From 812b1d8f0bed026d145c791fcb0e404921a96370 Mon Sep 17 00:00:00 2001 From: Tuxx Date: Thu, 3 Apr 2025 22:49:47 +0200 Subject: [PATCH 1/3] Better keyboard handling for wayland --- go.mod | 1 + go.sum | 4 ++ internal/types.go | 87 ++++++++++++++++++----- internal/wayland.go | 165 +++++++++++++++++++++++++++++--------------- internal/xkb.go | 78 +++++++++++++++++++++ 5 files changed, 264 insertions(+), 71 deletions(-) create mode 100644 internal/xkb.go diff --git a/go.mod b/go.mod index 09ecd3f..2f76d0a 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( ) require ( + github.com/ebitengine/purego v0.8.2 // indirect github.com/yalue/native_endian v1.0.2 // indirect golang.org/x/text v0.23.0 // indirect ) diff --git a/go.sum b/go.sum index e4a2270..e329cb8 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,9 @@ github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc h1:7D+Bh06CRPCJO3gr2F7h1sriovOZ8BMhca2Rg85c2nk= github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/ebitengine/purego v0.7.1 h1:6/55d26lG3o9VCZX8lping+bZcmShseiqlh2bnUDiPA= +github.com/ebitengine/purego v0.7.1/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= +github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= +github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/msteinert/pam v1.2.0 h1:mYfjlvN2KYs2Pb9G6nb/1f/nPfAttT/Jee5Sq9r3bGE= diff --git a/internal/types.go b/internal/types.go index 75b7df8..0471a5a 100644 --- a/internal/types.go +++ b/internal/types.go @@ -3,6 +3,7 @@ package internal import ( "os/exec" "sync" + "time" "github.com/BurntSushi/xgb" "github.com/BurntSushi/xgb/xproto" @@ -179,9 +180,6 @@ type outputInfo struct { // RegistryHandler handles Wayland registry events type RegistryHandler struct { - wl.OutputGeometryHandler - wl.OutputModeHandler - registry *wl.Registry compositor *wl.Compositor lockManager *ext.SessionLockManager @@ -209,29 +207,84 @@ type handlerFunc func(wl.OutputGeometryEvent) // outputModeHandlerFunc is a function type for handling output mode events type outputModeHandlerFunc func(ev wl.OutputModeEvent) +// Config represents the configuration for the locker +type Config struct { + DebugExit bool + LockoutDuration time.Duration + LockoutAttempts int + MediaPlayerPath string + MediaPlayerArgs []string + MediaPlayerVolume int + MediaPlayerEnabled bool + MediaPlayerAutostart bool + MediaPlayerAutoplay bool + MediaPlayerAutoplayDelay time.Duration + MediaPlayerAutoplayVolume int + MediaPlayerAutoplayFadeIn time.Duration + MediaPlayerAutoplayFadeOut time.Duration + MediaPlayerAutoplayFadeStep int + MediaPlayerAutoplayFadeInterval time.Duration + MediaPlayerAutoplayFadeInStart bool + MediaPlayerAutoplayFadeOutEnd bool + MediaPlayerAutoplayFadeInEnd bool + MediaPlayerAutoplayFadeOutStart bool + MediaPlayerAutoplayFadeInStartVolume int + MediaPlayerAutoplayFadeOutStartVolume int + MediaPlayerAutoplayFadeInEndVolume int + MediaPlayerAutoplayFadeOutEndVolume int +} + +// WaylandLocker represents a Wayland-based screen locker type WaylandLocker struct { + // Wayland connection and display display *wl.Display registry *wl.Registry registryHandler *RegistryHandler compositor *wl.Compositor - lockManager *ext.SessionLockManager - lock *ext.SessionLock - keyboard *wl.Keyboard - seat *wl.Seat shm *wl.Shm - securePassword *SecurePassword - surfaces map[*wl.Output]struct { + seat *wl.Seat + keyboard *wl.Keyboard + pointer *wl.Pointer + output *wl.Output + lock *ext.SessionLock + lockSurface *wl.Surface + lockManager *ext.SessionLockManager + + // Session lock surfaces + surfaces map[*wl.Output]struct { wlSurface *wl.Surface lockSurface *ext.SessionLockSurface } - redrawCh chan int - outputs map[uint32]*wl.Output - mediaPlayer *MediaPlayer + outputs map[uint32]*wl.Output + + // State + mu sync.Mutex done chan struct{} - config Configuration - helper *LockHelper - lockActive bool + redrawCh chan int + securePassword *SecurePassword countdownActive bool - lockoutManager *LockoutManager // Use the shared lockout manager - mu sync.Mutex + countdownTimer *time.Timer + lockActive bool + mediaPlayer *MediaPlayer + lockoutManager *LockoutManager + + // Keymap data + keymapData []byte + keymapFormat uint32 + keymapSize uint32 + xkbContext uintptr + xkbState uintptr + xkbKeymap uintptr + + // Configuration + config Configuration + helper *LockHelper +} + +// updatePasswordDisplay updates the password display +func (l *WaylandLocker) updatePasswordDisplay() { + select { + case l.redrawCh <- l.securePassword.Length(): + default: + } } diff --git a/internal/wayland.go b/internal/wayland.go index 919da66..87f6fcf 100644 --- a/internal/wayland.go +++ b/internal/wayland.go @@ -131,6 +131,53 @@ func (l *WaylandLocker) HandleKeyboardLeave(ev wl.KeyboardLeaveEvent) { // Handle keyboard keymap events func (l *WaylandLocker) HandleKeyboardKeymap(ev wl.KeyboardKeymapEvent) { Info("Keyboard keymap event received: format=%d, size=%d\n", ev.Format, ev.Size) + + // Store keymap information + l.keymapFormat = ev.Format + l.keymapSize = ev.Size + + // Read the keymap data + if ev.Fd != 0 { + data, err := syscall.Mmap(int(ev.Fd), 0, int(ev.Size), syscall.PROT_READ, syscall.MAP_SHARED) + if err != nil { + Error("Failed to mmap keymap: %v", err) + return + } + defer syscall.Munmap(data) + + // Copy the keymap data + l.keymapData = make([]byte, ev.Size) + copy(l.keymapData, data) + + // Initialize XKB context if not already done + if l.xkbContext == 0 { + l.xkbContext = XkbContextNew(ContextNoFlags) + if l.xkbContext == 0 { + Error("Failed to create XKB context") + return + } + } + + // Create XKB keymap from the keymap data + if l.xkbKeymap != 0 { + XkbKeymapUnref(l.xkbKeymap) + } + l.xkbKeymap = XkbKeymapNewFromString(l.xkbContext, string(l.keymapData), KeymapFormatTextV1, ContextNoFlags) + if l.xkbKeymap == 0 { + Error("Failed to create XKB keymap") + return + } + + // Create XKB state + if l.xkbState != 0 { + XkbStateUnref(l.xkbState) + } + l.xkbState = XkbStateNew(l.xkbKeymap) + if l.xkbState == 0 { + Error("Failed to create XKB state") + return + } + } } // Handle keyboard modifier events @@ -272,82 +319,85 @@ func (l *WaylandLocker) shakePasswordDots() { } } +// Handle keyboard key events func (l *WaylandLocker) HandleKeyboardKey(ev wl.KeyboardKeyEvent) { l.mu.Lock() defer l.mu.Unlock() - if ev.State != 1 { + // Only handle key press events + if ev.State != wl.KeyboardKeyStatePressed { return } + // If countdown is active, ignore all keys except Escape if l.countdownActive { - // Only handle key if it's ESC and debug exit is enabled - if ev.Key == 1 && l.config.DebugExit { - Info("ESC pressed during countdown, triggering debug exit\n") - if l.lock != nil { - l.lock.UnlockAndDestroy() + if ev.Key == 1 { // Escape key + l.countdownActive = false + l.countdownTimer.Stop() + l.securePassword.Clear() + if l.config.DebugExit { + Info("ESC pressed during countdown, triggering debug exit\n") + if l.lock != nil { + l.lock.UnlockAndDestroy() + } + close(l.done) } - close(l.done) } - - // Ignore all other keys while countdown is active return } - charAdded := false - + // Handle special keys switch ev.Key { - case 1: // Escape + case 1: // Escape key Info("ESC pressed, clearing password\n") l.securePassword.Clear() - charAdded = true if l.config.DebugExit { Info("Debug exit triggered by ESC key\n") if l.lock != nil { l.lock.UnlockAndDestroy() } close(l.done) - return } - case 28, 96, 108, 65: // Enter + return + case 28: // Enter key Info("ENTER key detected (code=%d), authenticating\n", ev.Key) l.authenticate() return - case 14: // Backspace + case 14: // Backspace key Info("BACKSPACE pressed, removing last character\n") l.securePassword.RemoveLast() - charAdded = true - default: - if ev.Key >= 2 && ev.Key <= 11 { - if ev.Key == 11 { - l.securePassword.Append('0') - } else { - l.securePassword.Append('1' + byte(ev.Key-2)) - } - charAdded = true - } else if ev.Key >= 16 && ev.Key <= 25 { - chars := []byte{'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'} - l.securePassword.Append(chars[ev.Key-16]) - charAdded = true - } else if ev.Key >= 30 && ev.Key <= 38 { - chars := []byte{'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'} - l.securePassword.Append(chars[ev.Key-30]) - charAdded = true - } else if ev.Key >= 44 && ev.Key <= 50 { - chars := []byte{'z', 'x', 'c', 'v', 'b', 'n', 'm'} - l.securePassword.Append(chars[ev.Key-44]) - charAdded = true - } else { - Info("Unhandled key: %d\n", ev.Key) - } - } - - if charAdded { select { case l.redrawCh <- l.securePassword.Length(): default: } + return + } + + // Convert key code to character using XKB state + if l.xkbState != 0 && l.xkbKeymap != 0 { + // Get the key symbol + sym := XkbStateKeyGetSym(l.xkbState, ev.Key+8) // Add 8 to convert from evdev to XKB keycode + if sym != 0 { + // Convert the key symbol to a character + utf32 := XkbKeysymToUtf32(sym) + if utf32 != 0 { + // Convert UTF-32 to UTF-8 + r := rune(utf32) + if r >= 0x20 && r <= 0x7e { // Printable ASCII range + l.securePassword.Append(byte(r)) + select { + case l.redrawCh <- l.securePassword.Length(): + default: + } + //Debug("Key %d mapped to character '%c' (keysym: 0x%x)", ev.Key, r, sym) + return + } + } + } } + + // Log unhandled keys + Debug("Unhandled key: code=%d, state=%d", ev.Key, ev.State) } func (l *WaylandLocker) HandleSessionLockLocked(ev ext.SessionLockLockedEvent) { @@ -378,6 +428,21 @@ func (f outputModeHandlerFunc) HandleOutputMode(ev wl.OutputModeEvent) { f(ev) } +// HandleRegistryGlobalRemove handles registry global remove events +func (h *RegistryHandler) HandleRegistryGlobalRemove(ev wl.RegistryGlobalRemoveEvent) { + // Remove the output from our map if it exists + if output, ok := h.outputs[ev.Name]; ok { + delete(h.outputs, ev.Name) + delete(h.outputGeometries, output) + } +} + +// HandleKeyboardRepeatInfo handles keyboard repeat info events +func (l *WaylandLocker) HandleKeyboardRepeatInfo(ev wl.KeyboardRepeatInfoEvent) { + // We don't need to handle keyboard repeat info for our use case +} + +// HandleRegistryGlobal handles registry global events func (h *RegistryHandler) HandleRegistryGlobal(ev wl.RegistryGlobalEvent) { switch ev.Interface { case "wl_compositor": @@ -404,10 +469,6 @@ func (h *RegistryHandler) HandleRegistryGlobal(ev wl.RegistryGlobalEvent) { } // Add handlers for output geometry and mode - if h.outputGeometries == nil { - h.outputGeometries = make(map[*wl.Output]outputInfo) - } - output.AddGeometryHandler(struct{ wl.OutputGeometryHandler }{ OutputGeometryHandler: handlerFunc(func(ev wl.OutputGeometryEvent) { info := h.outputGeometries[output] @@ -953,7 +1014,7 @@ func (l *WaylandLocker) initWayland() error { l.display = conn // Get registry and set up registry handler - registry, err := conn.GetRegistry() + registry, err := wlclient.DisplayGetRegistry(conn) if err != nil { return fmt.Errorf("failed to get registry: %w", err) } @@ -967,7 +1028,7 @@ func (l *WaylandLocker) initWayland() error { l.registryHandler = regHandler // Add the registry handler - registry.AddGlobalHandler(regHandler) + wlclient.RegistryAddListener(registry, regHandler) // Process registry events err = wlclient.DisplayRoundtrip(conn) @@ -1046,11 +1107,7 @@ func (l *WaylandLocker) initWayland() error { keyboard, err := l.seat.GetKeyboard() if err == nil && keyboard != nil { l.keyboard = keyboard - l.keyboard.AddKeyHandler(l) - l.keyboard.AddEnterHandler(l) - l.keyboard.AddLeaveHandler(l) - l.keyboard.AddKeymapHandler(l) - l.keyboard.AddModifiersHandler(l) + wlclient.KeyboardAddListener(keyboard, l) } } diff --git a/internal/xkb.go b/internal/xkb.go new file mode 100644 index 0000000..878cba4 --- /dev/null +++ b/internal/xkb.go @@ -0,0 +1,78 @@ +package internal + +import ( + "fmt" + + "github.com/ebitengine/purego" +) + +// XKB constants +const ( + KeymapFormatTextV1 = 1 + ContextNoFlags = 0 +) + +var ( + libxkbcommon uintptr + xkbContextNew func(uint32) uintptr + xkbKeymapNewFromString func(uintptr, []byte, uint32, uint32) uintptr + xkbStateNew func(uintptr) uintptr + xkbStateKeyGetOneSym func(uintptr, uint) uintptr + xkbKeysymToUtf32 func(uint) uint + xkbKeymapUnref func(uintptr) + xkbStateUnref func(uintptr) + xkbContextUnref func(uintptr) +) + +func init() { + var err error + libxkbcommon, err = purego.Dlopen("libxkbcommon.so", purego.RTLD_NOW|purego.RTLD_GLOBAL) + if err != nil { + libxkbcommon, err = purego.Dlopen("libxkbcommon.so.0", purego.RTLD_NOW|purego.RTLD_GLOBAL) + if err != nil { + panic(fmt.Errorf("failed to load libxkbcommon: %v", err)) + } + } + + purego.RegisterLibFunc(&xkbContextNew, libxkbcommon, "xkb_context_new") + purego.RegisterLibFunc(&xkbKeymapNewFromString, libxkbcommon, "xkb_keymap_new_from_string") + purego.RegisterLibFunc(&xkbStateNew, libxkbcommon, "xkb_state_new") + purego.RegisterLibFunc(&xkbStateKeyGetOneSym, libxkbcommon, "xkb_state_key_get_one_sym") + purego.RegisterLibFunc(&xkbKeysymToUtf32, libxkbcommon, "xkb_keysym_to_utf32") + purego.RegisterLibFunc(&xkbKeymapUnref, libxkbcommon, "xkb_keymap_unref") + purego.RegisterLibFunc(&xkbStateUnref, libxkbcommon, "xkb_state_unref") + purego.RegisterLibFunc(&xkbContextUnref, libxkbcommon, "xkb_context_unref") +} + +// XKB wrapper functions +func XkbContextNew(flags uint32) uintptr { + return xkbContextNew(flags) +} + +func XkbKeymapNewFromString(context uintptr, str string, format uint32, flags uint32) uintptr { + return xkbKeymapNewFromString(context, []byte(str), format, flags) +} + +func XkbStateNew(keymap uintptr) uintptr { + return xkbStateNew(keymap) +} + +func XkbStateKeyGetSym(state uintptr, key uint32) uint32 { + return uint32(xkbStateKeyGetOneSym(state, uint(key))) +} + +func XkbKeysymToUtf32(keysym uint32) uint32 { + return uint32(xkbKeysymToUtf32(uint(keysym))) +} + +func XkbKeymapUnref(keymap uintptr) { + xkbKeymapUnref(keymap) +} + +func XkbStateUnref(state uintptr) { + xkbStateUnref(state) +} + +func XkbContextUnref(context uintptr) { + xkbContextUnref(context) +} From 395e77b2d72ddee801c99aac0aba88c071303238 Mon Sep 17 00:00:00 2001 From: Tuxx Date: Thu, 3 Apr 2025 23:00:08 +0200 Subject: [PATCH 2/3] Handle modifiers keys like Shift & Alt --- internal/types.go | 28 +--------- internal/wayland.go | 124 ++++++++++++++++++++++++++++++++++++-------- internal/xkb.go | 6 +++ 3 files changed, 108 insertions(+), 50 deletions(-) diff --git a/internal/types.go b/internal/types.go index 0471a5a..6025d09 100644 --- a/internal/types.go +++ b/internal/types.go @@ -187,6 +187,7 @@ type RegistryHandler struct { shm *wl.Shm outputs map[uint32]*wl.Output outputGeometries map[*wl.Output]outputInfo + locker *WaylandLocker } // Media file extension maps @@ -207,33 +208,6 @@ type handlerFunc func(wl.OutputGeometryEvent) // outputModeHandlerFunc is a function type for handling output mode events type outputModeHandlerFunc func(ev wl.OutputModeEvent) -// Config represents the configuration for the locker -type Config struct { - DebugExit bool - LockoutDuration time.Duration - LockoutAttempts int - MediaPlayerPath string - MediaPlayerArgs []string - MediaPlayerVolume int - MediaPlayerEnabled bool - MediaPlayerAutostart bool - MediaPlayerAutoplay bool - MediaPlayerAutoplayDelay time.Duration - MediaPlayerAutoplayVolume int - MediaPlayerAutoplayFadeIn time.Duration - MediaPlayerAutoplayFadeOut time.Duration - MediaPlayerAutoplayFadeStep int - MediaPlayerAutoplayFadeInterval time.Duration - MediaPlayerAutoplayFadeInStart bool - MediaPlayerAutoplayFadeOutEnd bool - MediaPlayerAutoplayFadeInEnd bool - MediaPlayerAutoplayFadeOutStart bool - MediaPlayerAutoplayFadeInStartVolume int - MediaPlayerAutoplayFadeOutStartVolume int - MediaPlayerAutoplayFadeInEndVolume int - MediaPlayerAutoplayFadeOutEndVolume int -} - // WaylandLocker represents a Wayland-based screen locker type WaylandLocker struct { // Wayland connection and display diff --git a/internal/wayland.go b/internal/wayland.go index 87f6fcf..a3c86cf 100644 --- a/internal/wayland.go +++ b/internal/wayland.go @@ -184,6 +184,13 @@ func (l *WaylandLocker) HandleKeyboardKeymap(ev wl.KeyboardKeymapEvent) { func (l *WaylandLocker) HandleKeyboardModifiers(ev wl.KeyboardModifiersEvent) { Info("Keyboard modifiers event received: mods=%d,%d,%d\n", ev.ModsDepressed, ev.ModsLatched, ev.ModsLocked) + + // Update XKB state with the new modifiers + if l.xkbState != 0 { + // Convert Wayland modifier masks to XKB modifier masks + mods := ev.ModsDepressed | ev.ModsLatched | ev.ModsLocked + XkbStateUpdateMask(l.xkbState, mods, 0, 0, 0, 0, 0) + } } func drawPasswordFeedback(l *WaylandLocker, surface *wl.Surface, count int, offsetX int) { @@ -349,27 +356,13 @@ func (l *WaylandLocker) HandleKeyboardKey(ev wl.KeyboardKeyEvent) { // Handle special keys switch ev.Key { case 1: // Escape key - Info("ESC pressed, clearing password\n") - l.securePassword.Clear() - if l.config.DebugExit { - Info("Debug exit triggered by ESC key\n") - if l.lock != nil { - l.lock.UnlockAndDestroy() - } - close(l.done) - } + l.handleEscape() return case 28: // Enter key - Info("ENTER key detected (code=%d), authenticating\n", ev.Key) - l.authenticate() + l.handleEnter() return case 14: // Backspace key - Info("BACKSPACE pressed, removing last character\n") - l.securePassword.RemoveLast() - select { - case l.redrawCh <- l.securePassword.Length(): - default: - } + l.handleBackspace() return } @@ -384,12 +377,7 @@ func (l *WaylandLocker) HandleKeyboardKey(ev wl.KeyboardKeyEvent) { // Convert UTF-32 to UTF-8 r := rune(utf32) if r >= 0x20 && r <= 0x7e { // Printable ASCII range - l.securePassword.Append(byte(r)) - select { - case l.redrawCh <- l.securePassword.Length(): - default: - } - //Debug("Key %d mapped to character '%c' (keysym: 0x%x)", ev.Key, r, sym) + l.handleChar(r) return } } @@ -1149,3 +1137,93 @@ func (l *WaylandLocker) initWayland() error { return nil } + +func (h *RegistryHandler) HandleKeyboardModifiers(keyboard *wl.Keyboard, serial uint32, modsDepressed, modsLatched, modsLocked, groupDepressed, groupLatched, groupLocked uint32) { + h.locker.mu.Lock() + defer h.locker.mu.Unlock() + + if h.locker.xkbState != 0 { + XkbStateUpdateMask(h.locker.xkbState, modsDepressed, modsLatched, modsLocked, groupDepressed, groupLatched, groupLocked) + } +} + +func (h *RegistryHandler) HandleKeyboardKey(keyboard *wl.Keyboard, serial uint32, time uint32, key uint32, state uint32) { + h.locker.mu.Lock() + defer h.locker.mu.Unlock() + + // Ignore key release events + if state != 1 { + return + } + + // Handle special keys + switch key { + case 1: // Escape + h.locker.handleEscape() + return + case 28: // Enter + h.locker.handleEnter() + return + case 14: // Backspace + h.locker.handleBackspace() + return + } + + // Convert key code to character using XKB state + if h.locker.xkbState != 0 { + sym := XkbStateKeyGetSym(h.locker.xkbState, key) + if sym != 0 { + char := XkbKeysymToUtf32(sym) + if char != 0 { + h.locker.handleChar(rune(char)) + return + } + } + } + + // Log unhandled keys + fmt.Printf("Unhandled key: %d\n", key) +} + +// handleEscape handles the Escape key press +func (l *WaylandLocker) handleEscape() { + Info("ESC pressed, clearing password\n") + l.securePassword.Clear() + if l.config.DebugExit { + Info("Debug exit triggered by ESC key\n") + if l.lock != nil { + l.lock.UnlockAndDestroy() + } + close(l.done) + } +} + +// handleEnter handles the Enter key press +func (l *WaylandLocker) handleEnter() { + Info("ENTER key detected, authenticating\n") + l.authenticate() +} + +// handleBackspace handles the Backspace key press +func (l *WaylandLocker) handleBackspace() { + Info("BACKSPACE pressed, removing last character\n") + l.securePassword.RemoveLast() + select { + case l.redrawCh <- l.securePassword.Length(): + default: + } +} + +// handleChar handles a character key press +func (l *WaylandLocker) handleChar(r rune) { + // Accept a wider range of characters, including those generated by Alt+key combinations + // This includes most Unicode characters that might be used in passwords + if r >= 0x20 && r <= 0x10FFFF { // Accept most Unicode characters + l.securePassword.Append(byte(r)) + select { + case l.redrawCh <- l.securePassword.Length(): + default: + } + Debug("Character '%c' (U+%04X) added to password", r, r) + } +} diff --git a/internal/xkb.go b/internal/xkb.go index 878cba4..41e8afc 100644 --- a/internal/xkb.go +++ b/internal/xkb.go @@ -22,6 +22,7 @@ var ( xkbKeymapUnref func(uintptr) xkbStateUnref func(uintptr) xkbContextUnref func(uintptr) + xkbStateUpdateMask func(uintptr, uint32, uint32, uint32, uint32, uint32, uint32) int ) func init() { @@ -42,6 +43,7 @@ func init() { purego.RegisterLibFunc(&xkbKeymapUnref, libxkbcommon, "xkb_keymap_unref") purego.RegisterLibFunc(&xkbStateUnref, libxkbcommon, "xkb_state_unref") purego.RegisterLibFunc(&xkbContextUnref, libxkbcommon, "xkb_context_unref") + purego.RegisterLibFunc(&xkbStateUpdateMask, libxkbcommon, "xkb_state_update_mask") } // XKB wrapper functions @@ -76,3 +78,7 @@ func XkbStateUnref(state uintptr) { func XkbContextUnref(context uintptr) { xkbContextUnref(context) } + +func XkbStateUpdateMask(state uintptr, depressed, latched, locked, depressed_group, latched_group, locked_group uint32) int { + return xkbStateUpdateMask(state, depressed, latched, locked, depressed_group, latched_group, locked_group) +} From 44d2882c3af34c8619811061c152153d55775763 Mon Sep 17 00:00:00 2001 From: Tuxx Date: Thu, 3 Apr 2025 23:05:46 +0200 Subject: [PATCH 3/3] Removed debug line for printing password characters to log --- internal/wayland.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/wayland.go b/internal/wayland.go index a3c86cf..e82b606 100644 --- a/internal/wayland.go +++ b/internal/wayland.go @@ -1224,6 +1224,6 @@ func (l *WaylandLocker) handleChar(r rune) { case l.redrawCh <- l.securePassword.Length(): default: } - Debug("Character '%c' (U+%04X) added to password", r, r) + //Debug("Character '%c' (U+%04X) added to password", r, r) // Let's not output password characters to any log. } }