Repeated keys are detected properly

The repeated bool was removed and instead key release events are
*only* sent when the key is actually let go. If an element wants to
listen to repeat presses, it can just listen to press events.
This commit is contained in:
Sasha Koshka 2023-01-20 17:40:28 -05:00
parent 2f53c942ac
commit 72f604e819
7 changed files with 56 additions and 64 deletions

View File

@ -67,6 +67,23 @@ func (window *Window) handleConfigureNotify (
}
}
func (window *Window) modifiersFromState (
state uint16,
) (
modifiers tomo.Modifiers,
) {
return tomo.Modifiers {
Shift:
(state & xproto.ModMaskShift) > 0 ||
(state & window.backend.modifierMasks.shiftLock) > 0,
Control: (state & xproto.ModMaskControl) > 0,
Alt: (state & window.backend.modifierMasks.alt) > 0,
Meta: (state & window.backend.modifierMasks.meta) > 0,
Super: (state & window.backend.modifierMasks.super) > 0,
Hyper: (state & window.backend.modifierMasks.hyper) > 0,
}
}
func (window *Window) handleKeyPress (
connection *xgbutil.XUtil,
event xevent.KeyPressEvent,
@ -75,17 +92,8 @@ func (window *Window) handleKeyPress (
keyEvent := *event.KeyPressEvent
key, numberPad := window.backend.keycodeToKey(keyEvent.Detail, keyEvent.State)
modifiers := tomo.Modifiers {
Shift:
(keyEvent.State & xproto.ModMaskShift) > 0 ||
(keyEvent.State & window.backend.modifierMasks.shiftLock) > 0,
Control: (keyEvent.State & xproto.ModMaskControl) > 0,
Alt: (keyEvent.State & window.backend.modifierMasks.alt) > 0,
Meta: (keyEvent.State & window.backend.modifierMasks.meta) > 0,
Super: (keyEvent.State & window.backend.modifierMasks.super) > 0,
Hyper: (keyEvent.State & window.backend.modifierMasks.hyper) > 0,
NumberPad: numberPad,
}
modifiers := window.modifiersFromState(keyEvent.State)
modifiers.NumberPad = numberPad
if key == tomo.KeyTab && modifiers.Alt {
if child, ok := window.child.(tomo.Selectable); ok {
@ -99,8 +107,7 @@ func (window *Window) handleKeyPress (
}
}
} else if child, ok := window.child.(tomo.KeyboardTarget); ok {
// FIXME: pass correct value for repeated
child.HandleKeyDown(key, modifiers, false)
child.HandleKeyDown(key, modifiers)
}
}
@ -111,19 +118,28 @@ func (window *Window) handleKeyRelease (
if window.child == nil { return }
keyEvent := *event.KeyReleaseEvent
key, numberPad := window.backend.keycodeToKey(keyEvent.Detail, keyEvent.State)
modifiers := tomo.Modifiers {
Shift:
(keyEvent.State & xproto.ModMaskShift) > 0 ||
(keyEvent.State & window.backend.modifierMasks.shiftLock) > 0,
Control: (keyEvent.State & xproto.ModMaskControl) > 0,
Alt: (keyEvent.State & window.backend.modifierMasks.alt) > 0,
Meta: (keyEvent.State & window.backend.modifierMasks.meta) > 0,
Super: (keyEvent.State & window.backend.modifierMasks.super) > 0,
Hyper: (keyEvent.State & window.backend.modifierMasks.hyper) > 0,
NumberPad: numberPad,
// do not process this event if it was generated from a key repeat
nextEvents := xevent.Peek(window.backend.connection)
if len(nextEvents) > 0 {
untypedEvent := nextEvents[0]
if untypedEvent.Err == nil {
typedEvent, ok :=
untypedEvent.Event.(xproto.KeyReleaseEvent)
if ok && typedEvent.Detail == keyEvent.Detail &&
typedEvent.Event == keyEvent.Event &&
typedEvent.State == keyEvent.State {
return
}
}
}
key, numberPad := window.backend.keycodeToKey(keyEvent.Detail, keyEvent.State)
modifiers := window.modifiersFromState(keyEvent.State)
modifiers.NumberPad = numberPad
if child, ok := window.child.(tomo.KeyboardTarget); ok {
child.HandleKeyUp(key, modifiers)
}

View File

@ -86,12 +86,12 @@ type Selectable interface {
type KeyboardTarget interface {
Element
// HandleKeyDown is called when a key is pressed down while this element
// has keyboard focus. It is important to note that not every key down
// event is guaranteed to be paired with exactly one key up event. This
// is the reason a list of modifier keys held down at the time of the
// key press is given.
HandleKeyDown (key Key, modifiers Modifiers, repeated bool)
// HandleKeyDown is called when a key is pressed down or repeated while
// this element has keyboard focus. It is important to note that not
// every key down event is guaranteed to be paired with exactly one key
// up event. This is the reason a list of modifier keys held down at the
// time of the key press is given.
HandleKeyDown (key Key, modifiers Modifiers)
// HandleKeyUp is called when a key is released while this element has
// keyboard focus.

View File

@ -68,11 +68,7 @@ func (element *Button) HandleMouseUp (x, y int, button tomo.Button) {
func (element *Button) HandleMouseMove (x, y int) { }
func (element *Button) HandleMouseScroll (x, y int, deltaX, deltaY float64) { }
func (element *Button) HandleKeyDown (
key tomo.Key,
modifiers tomo.Modifiers,
repeated bool,
) {
func (element *Button) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) {
if !element.enabled { return }
if key == tomo.KeyEnter {
element.pressed = true

View File

@ -70,11 +70,7 @@ func (element *Checkbox) HandleMouseUp (x, y int, button tomo.Button) {
func (element *Checkbox) HandleMouseMove (x, y int) { }
func (element *Checkbox) HandleMouseScroll (x, y int, deltaX, deltaY float64) { }
func (element *Checkbox) HandleKeyDown (
key tomo.Key,
modifiers tomo.Modifiers,
repeated bool,
) {
func (element *Checkbox) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) {
if key == tomo.KeyEnter {
element.pressed = true
if element.core.HasImage() {

View File

@ -235,15 +235,11 @@ func (element *Container) HandleMouseScroll (x, y int, deltaX, deltaY float64) {
child.HandleMouseScroll(x - childPosition.X, y - childPosition.Y, deltaX, deltaY)
}
func (element *Container) HandleKeyDown (
key tomo.Key,
modifiers tomo.Modifiers,
repeated bool,
) {
func (element *Container) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) {
element.forSelected (func (child tomo.Selectable) bool {
child0, handlesKeyboard := child.(tomo.KeyboardTarget)
if handlesKeyboard {
child0.HandleKeyDown(key, modifiers, repeated)
child0.HandleKeyDown(key, modifiers)
}
return true
})

View File

@ -93,13 +93,9 @@ func (element *ScrollContainer) Adopt (child tomo.Scrollable) {
}
}
func (element *ScrollContainer) HandleKeyDown (
key tomo.Key,
modifiers tomo.Modifiers,
repeated bool,
) {
func (element *ScrollContainer) HandleKeyDown (key tomo.Key, modifiers tomo.Modifiers) {
if child, ok := element.child.(tomo.KeyboardTarget); ok {
child.HandleKeyDown(key, modifiers, repeated)
child.HandleKeyDown(key, modifiers)
}
}

View File

@ -23,7 +23,7 @@ type TextBox struct {
placeholderDrawer artist.TextDrawer
valueDrawer artist.TextDrawer
onKeyDown func (tomo.Key, tomo.Modifiers, bool) (bool)
onKeyDown func (key tomo.Key, modifiers tomo.Modifiers) (handled bool)
onChange func ()
onSelectionRequest func () (granted bool)
onSelectionMotionRequest func (tomo.SelectionDirection) (granted bool)
@ -63,12 +63,8 @@ func (element *TextBox) HandleMouseUp (x, y int, button tomo.Button) { }
func (element *TextBox) HandleMouseMove (x, y int) { }
func (element *TextBox) HandleMouseScroll (x, y int, deltaX, deltaY float64) { }
func (element *TextBox) HandleKeyDown (
key tomo.Key,
modifiers tomo.Modifiers,
repeated bool,
) {
if element.onKeyDown != nil && element.onKeyDown(key, modifiers, repeated) {
func (element *TextBox) HandleKeyDown(key tomo.Key, modifiers tomo.Modifiers) {
if element.onKeyDown != nil && element.onKeyDown(key, modifiers) {
return
}
@ -232,11 +228,7 @@ func (element *TextBox) Filled () (filled bool) {
}
func (element *TextBox) OnKeyDown (
callback func (
key tomo.Key, modifiers tomo.Modifiers, repeated bool,
) (
handled bool,
),
callback func (key tomo.Key, modifiers tomo.Modifiers) (handled bool),
) {
element.onKeyDown = callback
}