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
})
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
})
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")
}
func (w *window) keyEvent(e js.Value) {
func (w *window) keyEvent(e js.Value, ks key.State) {
k := e.Get("key").String()
if n, ok := translateKey(k); ok {
cmd := key.Event{
Name: n,
Modifiers: modifiersFor(e),
State: ks,
}
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
s.disp.repeat.Stop(t)
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 {
return
}
kc := mapXKBKeycode(uint32(keyCode))
for _, e := range w.disp.xkb.DispatchKey(kc) {
w.w.Event(e)
}
if w.disp.xkb.IsRepeatKey(kc) {
w.disp.repeat.Start(w, kc, t)
}
@@ -981,6 +982,15 @@ func mapXKBKeycode(keyCode uint32) uint32 {
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) {
if r.rate <= 0 {
return
@@ -1046,7 +1056,7 @@ func (r *repeatState) Repeat(d *wlDisplay) {
if r.last+delay > now {
break
}
for _, e := range d.xkb.DispatchKey(r.key) {
for _, e := range d.xkb.DispatchKey(r.key, key.Press) {
r.win.Event(e)
}
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:
// Avoid flickering between GPU content and background color.
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 {
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:
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),
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))
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)
}
case C.KeyRelease:
case C.ButtonPress, C.ButtonRelease:
bevt := (*C.XButtonEvent)(unsafe.Pointer(xev))
ev := pointer.Event{
+1
View File
@@ -150,6 +150,7 @@ const (
WM_SHOWWINDOW = 0x0018
WM_SIZE = 0x0005
WM_SYSKEYDOWN = 0x0104
WM_SYSKEYUP = 0x0105
WM_RBUTTONDOWN = 0x0204
WM_RBUTTONUP = 0x0205
WM_TIMER = 0x0113
+3 -2
View File
@@ -150,7 +150,7 @@ func (x *Context) Modifiers() key.Modifiers {
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 {
return
}
@@ -163,6 +163,7 @@ func (x *Context) DispatchKey(keyCode uint32) (events []event.Event) {
cmd := key.Event{
Name: name,
Modifiers: x.Modifiers(),
State: state,
}
// Ensure that a physical backtab key is translated to
// Shift-Tab.
@@ -201,7 +202,7 @@ func (x *Context) DispatchKey(keyCode uint32) (events []event.Event) {
str = str[:len(str)-s]
}
}
if len(str) > 0 {
if state == key.Press && len(str) > 0 {
events = append(events, key.EditEvent{Text: string(str)})
}
return
+15
View File
@@ -46,6 +46,8 @@ type Event struct {
Name string
// Modifiers is the set of active modifiers when the key was pressed.
Modifiers Modifiers
// State is the state of the key when the event was fired.
State State
}
// An EditEvent is generated when text is input.
@@ -53,6 +55,19 @@ type EditEvent struct {
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
type Modifiers uint32