io/key: implement key.Release state

Implement key state for the following platforms:
js, wayland, windows, x11.

Unsupported platforms will continue to function as before, sending
key.Press for all key events.

Signed-off-by: Josiah Niedrauer <josiah@niedrauer.com>
This commit is contained in:
Josiah Niedrauer
2020-10-29 15:46:41 -07:00
committed by Elias Naur
parent ef652f4922
commit 42e568775c
7 changed files with 57 additions and 14 deletions
+7 -2
View File
@@ -180,7 +180,11 @@ func (w *window) addEventListeners() {
return nil return nil
}) })
w.addEventListener(w.tarea, "keydown", func(this js.Value, args []js.Value) interface{} { w.addEventListener(w.tarea, "keydown", func(this js.Value, args []js.Value) interface{} {
w.keyEvent(args[0]) w.keyEvent(args[0], key.Press)
return nil
})
w.addEventListener(w.tarea, "keyup", func(this js.Value, args []js.Value) interface{} {
w.keyEvent(args[0], key.Release)
return nil return nil
}) })
w.addEventListener(w.tarea, "compositionstart", func(this js.Value, args []js.Value) interface{} { w.addEventListener(w.tarea, "compositionstart", func(this js.Value, args []js.Value) interface{} {
@@ -215,12 +219,13 @@ func (w *window) focus() {
w.tarea.Call("focus") w.tarea.Call("focus")
} }
func (w *window) keyEvent(e js.Value) { func (w *window) keyEvent(e js.Value, ks key.State) {
k := e.Get("key").String() k := e.Get("key").String()
if n, ok := translateKey(k); ok { if n, ok := translateKey(k); ok {
cmd := key.Event{ cmd := key.Event{
Name: n, Name: n,
Modifiers: modifiersFor(e), Modifiers: modifiersFor(e),
State: ks,
} }
w.w.Event(cmd) w.w.Event(cmd)
} }
+15 -5
View File
@@ -964,13 +964,14 @@ func gio_onKeyboardKey(data unsafe.Pointer, keyboard *C.struct_wl_keyboard, seri
t := time.Duration(timestamp) * time.Millisecond t := time.Duration(timestamp) * time.Millisecond
s.disp.repeat.Stop(t) s.disp.repeat.Stop(t)
w.resetFling() w.resetFling()
kc := mapXKBKeycode(uint32(keyCode))
ks := mapXKBKeyState(uint32(state))
for _, e := range w.disp.xkb.DispatchKey(kc, ks) {
w.w.Event(e)
}
if state != C.WL_KEYBOARD_KEY_STATE_PRESSED { if state != C.WL_KEYBOARD_KEY_STATE_PRESSED {
return return
} }
kc := mapXKBKeycode(uint32(keyCode))
for _, e := range w.disp.xkb.DispatchKey(kc) {
w.w.Event(e)
}
if w.disp.xkb.IsRepeatKey(kc) { if w.disp.xkb.IsRepeatKey(kc) {
w.disp.repeat.Start(w, kc, t) w.disp.repeat.Start(w, kc, t)
} }
@@ -981,6 +982,15 @@ func mapXKBKeycode(keyCode uint32) uint32 {
return keyCode + 8 return keyCode + 8
} }
func mapXKBKeyState(state uint32) key.State {
switch state {
case C.WL_KEYBOARD_KEY_STATE_RELEASED:
return key.Release
default:
return key.Press
}
}
func (r *repeatState) Start(w *window, keyCode uint32, t time.Duration) { func (r *repeatState) Start(w *window, keyCode uint32, t time.Duration) {
if r.rate <= 0 { if r.rate <= 0 {
return return
@@ -1046,7 +1056,7 @@ func (r *repeatState) Repeat(d *wlDisplay) {
if r.last+delay > now { if r.last+delay > now {
break break
} }
for _, e := range d.xkb.DispatchKey(r.key) { for _, e := range d.xkb.DispatchKey(r.key, key.Press) {
r.win.Event(e) r.win.Event(e)
} }
r.last += delay r.last += delay
+10 -2
View File
@@ -228,9 +228,17 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr
case windows.WM_ERASEBKGND: case windows.WM_ERASEBKGND:
// Avoid flickering between GPU content and background color. // Avoid flickering between GPU content and background color.
return 1 return 1
case windows.WM_KEYDOWN, windows.WM_SYSKEYDOWN: case windows.WM_KEYDOWN, windows.WM_KEYUP, windows.WM_SYSKEYDOWN, windows.WM_SYSKEYUP:
if n, ok := convertKeyCode(wParam); ok { if n, ok := convertKeyCode(wParam); ok {
w.w.Event(key.Event{Name: n, Modifiers: getModifiers()}) e := key.Event{
Name: n,
Modifiers: getModifiers(),
State: key.Press,
}
if msg == windows.WM_KEYUP || msg == windows.WM_SYSKEYUP {
e.State = key.Release
}
w.w.Event(e)
} }
case windows.WM_LBUTTONDOWN: case windows.WM_LBUTTONDOWN:
w.pointerButton(pointer.ButtonLeft, true, lParam, getModifiers()) w.pointerButton(pointer.ButtonLeft, true, lParam, getModifiers())
+6 -3
View File
@@ -305,12 +305,15 @@ func (h *x11EventHandler) handleEvents() bool {
h.w.xkb.UpdateMask(uint32(state.base_mods), uint32(state.latched_mods), uint32(state.locked_mods), h.w.xkb.UpdateMask(uint32(state.base_mods), uint32(state.latched_mods), uint32(state.locked_mods),
uint32(state.base_group), uint32(state.latched_group), uint32(state.locked_group)) uint32(state.base_group), uint32(state.latched_group), uint32(state.locked_group))
} }
case C.KeyPress: case C.KeyPress, C.KeyRelease:
ks := key.Press
if _type == C.KeyRelease {
ks = key.Release
}
kevt := (*C.XKeyPressedEvent)(unsafe.Pointer(xev)) kevt := (*C.XKeyPressedEvent)(unsafe.Pointer(xev))
for _, e := range h.w.xkb.DispatchKey(uint32(kevt.keycode)) { for _, e := range h.w.xkb.DispatchKey(uint32(kevt.keycode), ks) {
w.w.Event(e) w.w.Event(e)
} }
case C.KeyRelease:
case C.ButtonPress, C.ButtonRelease: case C.ButtonPress, C.ButtonRelease:
bevt := (*C.XButtonEvent)(unsafe.Pointer(xev)) bevt := (*C.XButtonEvent)(unsafe.Pointer(xev))
ev := pointer.Event{ ev := pointer.Event{
+1
View File
@@ -150,6 +150,7 @@ const (
WM_SHOWWINDOW = 0x0018 WM_SHOWWINDOW = 0x0018
WM_SIZE = 0x0005 WM_SIZE = 0x0005
WM_SYSKEYDOWN = 0x0104 WM_SYSKEYDOWN = 0x0104
WM_SYSKEYUP = 0x0105
WM_RBUTTONDOWN = 0x0204 WM_RBUTTONDOWN = 0x0204
WM_RBUTTONUP = 0x0205 WM_RBUTTONUP = 0x0205
WM_TIMER = 0x0113 WM_TIMER = 0x0113
+3 -2
View File
@@ -150,7 +150,7 @@ func (x *Context) Modifiers() key.Modifiers {
return mods return mods
} }
func (x *Context) DispatchKey(keyCode uint32) (events []event.Event) { func (x *Context) DispatchKey(keyCode uint32, state key.State) (events []event.Event) {
if x.state == nil { if x.state == nil {
return return
} }
@@ -163,6 +163,7 @@ func (x *Context) DispatchKey(keyCode uint32) (events []event.Event) {
cmd := key.Event{ cmd := key.Event{
Name: name, Name: name,
Modifiers: x.Modifiers(), Modifiers: x.Modifiers(),
State: state,
} }
// Ensure that a physical backtab key is translated to // Ensure that a physical backtab key is translated to
// Shift-Tab. // Shift-Tab.
@@ -201,7 +202,7 @@ func (x *Context) DispatchKey(keyCode uint32) (events []event.Event) {
str = str[:len(str)-s] str = str[:len(str)-s]
} }
} }
if len(str) > 0 { if state == key.Press && len(str) > 0 {
events = append(events, key.EditEvent{Text: string(str)}) events = append(events, key.EditEvent{Text: string(str)})
} }
return return
+15
View File
@@ -46,6 +46,8 @@ type Event struct {
Name string Name string
// Modifiers is the set of active modifiers when the key was pressed. // Modifiers is the set of active modifiers when the key was pressed.
Modifiers Modifiers Modifiers Modifiers
// State is the state of the key when the event was fired.
State State
} }
// An EditEvent is generated when text is input. // An EditEvent is generated when text is input.
@@ -53,6 +55,19 @@ type EditEvent struct {
Text string Text string
} }
// State is the state of a key during an event.
type State uint8
const (
// Press is the state of a pressed key.
Press State = iota
// Release is the state of a key that has been released.
//
// Note: release events are only implemented on the following platforms:
// Linux, Windows, WebAssembly.
Release
)
// Modifiers // Modifiers
type Modifiers uint32 type Modifiers uint32