diff --git a/app/internal/window/os_js.go b/app/internal/window/os_js.go index e537eb96..5aef3350 100644 --- a/app/internal/window/os_js.go +++ b/app/internal/window/os_js.go @@ -210,8 +210,11 @@ func (w *window) keyEvent(e js.Value) { k := e.Get("key").String() if n, ok := translateKey(k); ok { cmd := key.Event{Name: n} + if e.Call("getModifierState", "Alt").Bool() { + cmd.Modifiers |= key.ModAlt + } if e.Call("getModifierState", "Control").Bool() { - cmd.Modifiers |= key.ModCommand + cmd.Modifiers |= key.ModCtrl } if e.Call("getModifierState", "Shift").Bool() { cmd.Modifiers |= key.ModShift diff --git a/app/internal/window/os_macos.go b/app/internal/window/os_macos.go index ed4edb2c..152d8e8c 100644 --- a/app/internal/window/os_macos.go +++ b/app/internal/window/os_macos.go @@ -119,6 +119,12 @@ func gio_onFrameCallback(view C.CFTypeRef) { func gio_onKeys(view C.CFTypeRef, cstr *C.char, ti C.double, mods C.NSUInteger) { str := C.GoString(cstr) var kmods key.Modifiers + if mods&C.NSAlternateKeyMask != 0 { + kmods |= key.ModAlt + } + if mods&C.NSControlKeyMask != 0 { + kmods |= key.ModCtrl + } if mods&C.NSCommandKeyMask != 0 { kmods |= key.ModCommand } diff --git a/app/internal/window/os_windows.go b/app/internal/window/os_windows.go index 58d53c76..41fc92f4 100644 --- a/app/internal/window/os_windows.go +++ b/app/internal/window/os_windows.go @@ -94,6 +94,9 @@ const ( _USER_TIMER_MINIMUM = 0x0000000A _VK_CONTROL = 0x11 + _VK_LWIN = 0x5B + _VK_MENU = 0x12 + _VK_RWIN = 0x5C _VK_SHIFT = 0x10 _VK_BACK = 0x08 @@ -280,6 +283,12 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr case _WM_KEYDOWN, _WM_SYSKEYDOWN: if n, ok := convertKeyCode(wParam); ok { cmd := key.Event{Name: n} + if getKeyState(_VK_LWIN)&0x1000 != 0 || getKeyState(_VK_RWIN)&0x1000 != 0 { + cmd.Modifiers |= key.ModSuper + } + if getKeyState(_VK_MENU)&0x1000 != 0 { + cmd.Modifiers |= key.ModAlt + } if getKeyState(_VK_CONTROL)&0x1000 != 0 { cmd.Modifiers |= key.ModCtrl } diff --git a/app/internal/window/os_x11.go b/app/internal/window/os_x11.go index 00458ca9..81edf1c9 100644 --- a/app/internal/window/os_x11.go +++ b/app/internal/window/os_x11.go @@ -334,6 +334,12 @@ func (h *x11EventHandler) handleEvents() bool { func x11KeyStateToModifiers(s C.uint) key.Modifiers { var m key.Modifiers + if s&C.Mod1Mask != 0 { + m |= key.ModAlt + } + if s&C.Mod4Mask != 0 { + m |= key.ModSuper + } if s&C.ControlMask != 0 { m |= key.ModCtrl } diff --git a/app/internal/xkb/xkb_unix.go b/app/internal/xkb/xkb_unix.go index 398348ed..1d024e7f 100644 --- a/app/internal/xkb/xkb_unix.go +++ b/app/internal/xkb/xkb_unix.go @@ -42,6 +42,8 @@ type Context struct { var ( _XKB_MOD_NAME_CTRL = []byte("Control\x00") _XKB_MOD_NAME_SHIFT = []byte("Shift\x00") + _XKB_MOD_NAME_ALT = []byte("Mod1\x00") + _XKB_MOD_NAME_LOGO = []byte("Mod4\x00") ) func (x *Context) Destroy() { @@ -129,6 +131,12 @@ func (x *Context) DispatchKey(keyCode uint32) (events []event.Event) { if C.xkb_state_mod_name_is_active(x.state, (*C.char)(unsafe.Pointer(&_XKB_MOD_NAME_SHIFT[0])), C.XKB_STATE_MODS_EFFECTIVE) == 1 { cmd.Modifiers |= key.ModShift } + if C.xkb_state_mod_name_is_active(x.state, (*C.char)(unsafe.Pointer(&_XKB_MOD_NAME_ALT[0])), C.XKB_STATE_MODS_EFFECTIVE) == 1 { + cmd.Modifiers |= key.ModAlt + } + if C.xkb_state_mod_name_is_active(x.state, (*C.char)(unsafe.Pointer(&_XKB_MOD_NAME_LOGO[0])), C.XKB_STATE_MODS_EFFECTIVE) == 1 { + cmd.Modifiers |= key.ModSuper + } events = append(events, cmd) } C.xkb_compose_state_feed(x.compState, sym) diff --git a/io/key/key.go b/io/key/key.go index bca97812..f33bfde5 100644 --- a/io/key/key.go +++ b/io/key/key.go @@ -64,6 +64,12 @@ const ( ModCommand // ModShift is the shift modifier key. ModShift + // ModAlt is the alt modifier key, or the option + // key on Apple keyboards. + ModAlt + // ModSuper is the "logo" modifier key, often + // represented by a Windows logo. + ModSuper ) const ( @@ -121,5 +127,11 @@ func (m Modifiers) String() string { if m.Contain(ModShift) { strs = append(strs, "ModShift") } + if m.Contain(ModAlt) { + strs = append(strs, "ModAlt") + } + if m.Contain(ModSuper) { + strs = append(strs, "ModSuper") + } return strings.Join(strs, "|") }