akiyosi.goneovim/editor/input.go
thjbbvlt d54e48beb8 Add Hyper_L/R to the list of non-input keys
The current list of modifiers keys inside editor/input.go doesn't handle
the keys Hyper_L or Hyper_R, typically mapped to Linux window manager
actions. As now, at least on a Debian 12 with DWM setup, it insert a `�`
character. This commit add the `Hyper_L` and `Hyper_R` keys to the list
to avoid this behaviour.

This is only made possible by the fact that the
akiyosi's version of Qt bindings add these modifiers.
2025-06-16 10:51:13 +02:00

400 lines
10 KiB
Go

package editor
import (
"fmt"
"runtime"
"strings"
"unicode"
"github.com/akiyosi/qt/core"
"github.com/akiyosi/qt/gui"
)
func (e *Editor) keyRelease(event *gui.QKeyEvent) {
if !e.isKeyAutoRepeating {
return
}
// if editor.config.Editor.SmoothScroll {
// ws := e.workspaces[e.active]
// win, ok := ws.screen.getWindow(ws.cursor.gridid)
// if !ok {
// return
// }
// if win.scrollPixels2 != 0 {
// return
// }
// win.grabScreenSnapshot()
// }
e.isKeyAutoRepeating = false
}
func (e *Editor) keyPress(event *gui.QKeyEvent) {
if len(e.workspaces) <= e.active {
return
}
ws := e.workspaces[e.active]
if ws.nvim == nil {
return
}
if event.IsAutoRepeat() {
e.isKeyAutoRepeating = true
}
// if !e.isKeyAutoRepeating {
// ws.getSnapshot()
// }
if !e.isHideMouse && e.config.Editor.HideMouseWhenTyping {
bc := gui.NewQCursor2(core.Qt__BlankCursor)
gui.QGuiApplication_SetOverrideCursor(bc)
gui.QGuiApplication_ChangeOverrideCursor(bc)
e.isHideMouse = true
}
input := e.convertKey(event)
e.putLog("key input for nvim::", "input:", input)
if input != "" {
ws.nvim.Input(input)
}
}
func keyToText(key int, mod core.Qt__KeyboardModifier) string {
text := string(rune(key))
if !(mod&core.Qt__ShiftModifier > 0) {
text = strings.ToLower(text)
}
return text
}
// controlModifier is
func controlModifier() (controlModifier core.Qt__KeyboardModifier) {
if runtime.GOOS == "windows" {
controlModifier = core.Qt__ControlModifier
}
if runtime.GOOS == "linux" {
controlModifier = core.Qt__ControlModifier
}
if runtime.GOOS == "darwin" {
controlModifier = core.Qt__MetaModifier
}
return
}
// cmdModifier is
func cmdModifier() (cmdModifier core.Qt__KeyboardModifier) {
if runtime.GOOS == "windows" {
cmdModifier = core.Qt__NoModifier
}
if runtime.GOOS == "linux" {
cmdModifier = core.Qt__MetaModifier
}
if runtime.GOOS == "darwin" {
cmdModifier = core.Qt__ControlModifier
}
return
}
func isAsciiCharRequiringAlt(key int, mod core.Qt__KeyboardModifier, c rune) bool {
// Ignore all key events where Alt is not pressed
if !(mod&core.Qt__AltModifier > 0) {
return false
}
// These low-ascii characters may require AltModifier on MacOS
if (c == '[' /* && key != int(core.Qt__Key_BracketLeft) */) ||
(c == ']' && key != int(core.Qt__Key_BracketRight)) ||
(c == '{' /* && key != int(core.Qt__Key_BraceLeft) */) ||
(c == '}' && key != int(core.Qt__Key_BraceRight)) ||
(c == '|' && key != int(core.Qt__Key_Bar)) ||
(c == '~' && key != int(core.Qt__Key_AsciiTilde)) ||
(c == '@' && key != int(core.Qt__Key_At)) ||
(c == '#' && key != int(core.Qt__Key_NumberSign)) {
return true
}
return false
}
func isControlCaretKeyEvent(key int, mod core.Qt__KeyboardModifier, text string) bool {
if key != int(core.Qt__Key_6) && key != int(core.Qt__Key_AsciiCircum) {
return false
}
if !(mod&controlModifier() > 0) {
return false
}
if text != "\u001E" && text != "^" && text != "6" && text != "" {
return false
}
return true
}
func (e *Editor) convertKey(event *gui.QKeyEvent) string {
text := event.Text()
key := event.Key()
mod := event.Modifiers()
if e.opts.Debug != "" {
e.putLog("key input(raw)::", fmt.Sprintf("text: %s, key: %d, mod: %v", text, key, mod))
}
// this is macmeta alternatively
if e.config.Editor.Macmeta {
if mod&core.Qt__AltModifier > 0 && mod&core.Qt__ShiftModifier > 0 {
text = string(rune(key))
} else if mod&core.Qt__AltModifier > 0 && !(mod&core.Qt__ShiftModifier > 0) {
text = strings.ToLower(string(rune(key)))
}
}
keypadKeys := map[core.Qt__Key]string{
core.Qt__Key_Home: "kHome",
core.Qt__Key_End: "kEnd",
core.Qt__Key_PageUp: "kPageUp",
core.Qt__Key_PageDown: "kPageDown",
core.Qt__Key_Plus: "kPlus",
core.Qt__Key_Minus: "kMinus",
core.Qt__Key_multiply: "kMultiply",
core.Qt__Key_division: "kDivide",
core.Qt__Key_Enter: "kEnter",
core.Qt__Key_Period: "kPoint",
core.Qt__Key_0: "k0",
core.Qt__Key_1: "k1",
core.Qt__Key_2: "k2",
core.Qt__Key_3: "k3",
core.Qt__Key_4: "k4",
core.Qt__Key_5: "k5",
core.Qt__Key_6: "k6",
core.Qt__Key_7: "k7",
core.Qt__Key_8: "k8",
core.Qt__Key_9: "k9",
}
if mod&core.Qt__KeypadModifier > 0 {
if value, ok := keypadKeys[core.Qt__Key(key)]; ok {
return fmt.Sprintf("<%s%s>", e.modPrefix(mod), value)
}
}
if key == int(core.Qt__Key_Space) && len([]rune(text)) > 0 && !unicode.IsPrint([]rune(text)[0]) {
text = " "
}
if key == int(core.Qt__Key_Space) && len([]rune(text)) > 0 && text != " " {
if mod != core.Qt__NoModifier {
return fmt.Sprintf("<%s%s>", e.modPrefix(mod), text)
}
}
specialKey, ok := e.specialKeys[core.Qt__Key(key)]
if ok {
if key == int(core.Qt__Key_Space) && text != " " {
return text
}
if key == int(core.Qt__Key_Space) || key == int(core.Qt__Key_Backspace) {
mod &= ^core.Qt__ShiftModifier
}
return fmt.Sprintf("<%s%s>", e.modPrefix(mod), specialKey)
}
if text == "<" {
modNoShift := mod & ^core.Qt__ShiftModifier
return fmt.Sprintf("<%s%s>", e.modPrefix(modNoShift), "lt")
}
// neovim-qt issue#720
if key == int(core.Qt__Key_AsciiCircum) && text == "[" {
modNoAlt := mod & ^core.Qt__AltModifier
if modNoAlt == core.Qt__NoModifier {
return "["
}
return fmt.Sprintf("<%s%s>", e.modPrefix(modNoAlt), "[")
}
// Normalize modifiers, CTRL+^ always sends as <C-^>
if isControlCaretKeyEvent(key, mod, text) {
modNoShiftMeta := mod & ^core.Qt__ShiftModifier & ^cmdModifier()
return fmt.Sprintf("<%s%s>", e.modPrefix(modNoShiftMeta), "^")
}
if text == "\\" {
// If key code is yen and text is backslash, return backslash. #534
if key == 165 {
return "<Bslash>"
}
return fmt.Sprintf("<%s%s>", e.modPrefix(mod), "Bslash")
}
rtext := []rune(text)
isGraphic := false
if len(rtext) > 0 {
isGraphic = unicode.IsGraphic(rtext[0])
}
if text == "" || !isGraphic {
if key == int(core.Qt__Key_Alt) ||
key == int(core.Qt__Key_AltGr) ||
key == int(core.Qt__Key_CapsLock) ||
key == int(core.Qt__Key_Control) ||
key == int(core.Qt__Key_Meta) ||
key == int(core.Qt__Key_Shift) ||
key == int(core.Qt__Key_Hyper_L) ||
key == int(core.Qt__Key_Hyper_R) ||
key == int(core.Qt__Key_Super_L) ||
key == int(core.Qt__Key_Super_R) {
return ""
}
// Ignore special keys
if key == int(core.Qt__Key_VolumeDown) ||
key == int(core.Qt__Key_VolumeMute) ||
key == int(core.Qt__Key_VolumeUp) {
return ""
}
text = keyToText(key, mod)
}
c := text
if c == "" {
return ""
}
char := []rune(c)[0]
// char := core.NewQChar11(c)
// Remove SHIFT
if (int(char) >= 0x80 || unicode.IsPrint(char)) && !(mod&controlModifier() > 0) && !(mod&cmdModifier() > 0) {
mod &= ^core.Qt__ShiftModifier
}
// if (char.Unicode() >= 0x80 || char.IsPrint()) && !(mod&controlModifier() > 0) && !(mod&cmdModifier() > 0) {
// mod &= ^core.Qt__ShiftModifier
// }
// Remove CTRL
if int(char) < 0x20 {
text = keyToText(key, mod)
}
// if char.Unicode() < 0x20 {
// text = keyToText(key, mod)
// }
if runtime.GOOS == "darwin" {
// Remove ALT/OPTION
if int(char) >= 0x80 && unicode.IsPrint(char) {
mod &= ^core.Qt__AltModifier
}
// if char.Unicode() >= 0x80 && char.IsPrint() {
// mod &= ^core.Qt__AltModifier
// }
// Some locales require Alt for basic low-ascii characters,
// remove AltModifer. Ex) German layouts use Alt for "{".
if isAsciiCharRequiringAlt(key, mod, []rune(c)[0]) {
mod &= ^core.Qt__AltModifier
}
}
prefix := e.modPrefix(mod)
if prefix != "" {
return fmt.Sprintf("<%s%s>", prefix, c)
}
return c
}
func (e *Editor) modPrefix(mod core.Qt__KeyboardModifier) string {
prefix := ""
if runtime.GOOS == "windows" {
if mod&controlModifier() > 0 && !(mod&core.Qt__AltModifier > 0) {
prefix += "C-"
}
if mod&core.Qt__ShiftModifier > 0 {
prefix += "S-"
}
if mod&core.Qt__AltModifier > 0 && !(mod&controlModifier() > 0) {
prefix += e.prefixToMapMetaKey
}
} else {
if mod&cmdModifier() > 0 {
prefix += "D-"
}
if mod&controlModifier() > 0 {
prefix += "C-"
}
if mod&core.Qt__ShiftModifier > 0 {
prefix += "S-"
}
if mod&core.Qt__AltModifier > 0 {
prefix += e.prefixToMapMetaKey
}
}
return prefix
}
func (e *Editor) initSpecialKeys() {
e.specialKeys = map[core.Qt__Key]string{}
e.specialKeys[core.Qt__Key_Up] = "Up"
e.specialKeys[core.Qt__Key_Down] = "Down"
e.specialKeys[core.Qt__Key_Left] = "Left"
e.specialKeys[core.Qt__Key_Right] = "Right"
e.specialKeys[core.Qt__Key_F1] = "F1"
e.specialKeys[core.Qt__Key_F2] = "F2"
e.specialKeys[core.Qt__Key_F3] = "F3"
e.specialKeys[core.Qt__Key_F4] = "F4"
e.specialKeys[core.Qt__Key_F5] = "F5"
e.specialKeys[core.Qt__Key_F6] = "F6"
e.specialKeys[core.Qt__Key_F7] = "F7"
e.specialKeys[core.Qt__Key_F8] = "F8"
e.specialKeys[core.Qt__Key_F9] = "F9"
e.specialKeys[core.Qt__Key_F10] = "F10"
e.specialKeys[core.Qt__Key_F11] = "F11"
e.specialKeys[core.Qt__Key_F12] = "F12"
e.specialKeys[core.Qt__Key_F13] = "F13"
e.specialKeys[core.Qt__Key_F14] = "F14"
e.specialKeys[core.Qt__Key_F15] = "F15"
e.specialKeys[core.Qt__Key_F16] = "F16"
e.specialKeys[core.Qt__Key_F17] = "F17"
e.specialKeys[core.Qt__Key_F18] = "F18"
e.specialKeys[core.Qt__Key_F19] = "F19"
e.specialKeys[core.Qt__Key_F20] = "F20"
e.specialKeys[core.Qt__Key_F21] = "F21"
e.specialKeys[core.Qt__Key_F22] = "F22"
e.specialKeys[core.Qt__Key_F23] = "F23"
e.specialKeys[core.Qt__Key_F24] = "F24"
e.specialKeys[core.Qt__Key_Backspace] = "BS"
e.specialKeys[core.Qt__Key_Delete] = "Del"
e.specialKeys[core.Qt__Key_Insert] = "Insert"
e.specialKeys[core.Qt__Key_Home] = "Home"
e.specialKeys[core.Qt__Key_End] = "End"
e.specialKeys[core.Qt__Key_PageUp] = "PageUp"
e.specialKeys[core.Qt__Key_PageDown] = "PageDown"
e.specialKeys[core.Qt__Key_Return] = "Enter"
e.specialKeys[core.Qt__Key_Enter] = "Enter"
e.specialKeys[core.Qt__Key_Tab] = "Tab"
e.specialKeys[core.Qt__Key_Backtab] = "Tab"
e.specialKeys[core.Qt__Key_Escape] = "Esc"
e.specialKeys[core.Qt__Key_Backslash] = "Bslash"
e.specialKeys[core.Qt__Key_Space] = "Space"
if runtime.GOOS == "darwin" {
e.keyControl = core.Qt__Key_Meta
e.keyCmd = core.Qt__Key_Control
} else if runtime.GOOS == "windows" {
e.keyControl = core.Qt__Key_Control
e.keyCmd = (core.Qt__Key)(0)
} else {
e.keyControl = core.Qt__Key_Control
e.keyCmd = core.Qt__Key_Meta
}
e.prefixToMapMetaKey = "A-"
}