From cc154404d35bdce1042fcdd692a64b9365f7eb0d Mon Sep 17 00:00:00 2001 From: nnyyxxxx Date: Sat, 25 Jan 2025 02:26:45 -0500 Subject: [PATCH 1/2] fix(gtk): detect modifier keys without cursor movement --- src/apprt/gtk/winproto/wayland.zig | 15 +++++++++++++-- src/apprt/gtk/winproto/x11.zig | 14 ++++++++++++-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/apprt/gtk/winproto/wayland.zig b/src/apprt/gtk/winproto/wayland.zig index 8df3e57b32..ebbf237d17 100644 --- a/src/apprt/gtk/winproto/wayland.zig +++ b/src/apprt/gtk/winproto/wayland.zig @@ -76,10 +76,21 @@ pub const App = struct { } pub fn eventMods( - _: *App, - _: ?*c.GdkDevice, + _: App, + device: ?*c.GdkDevice, _: c.GdkModifierType, ) ?input.Mods { + if (device) |dev| { + const device_mods = c.gdk_device_get_modifier_state(dev); + return input.Mods{ + .shift = (device_mods & c.GDK_SHIFT_MASK) != 0, + .ctrl = (device_mods & c.GDK_CONTROL_MASK) != 0, + .alt = (device_mods & c.GDK_ALT_MASK) != 0, + .super = (device_mods & c.GDK_SUPER_MASK) != 0, + .caps_lock = (device_mods & c.GDK_LOCK_MASK) != 0, + }; + } + return null; } diff --git a/src/apprt/gtk/winproto/x11.zig b/src/apprt/gtk/winproto/x11.zig index 7a6b8b4c78..7ae35e25c8 100644 --- a/src/apprt/gtk/winproto/x11.zig +++ b/src/apprt/gtk/winproto/x11.zig @@ -122,8 +122,18 @@ pub const App = struct { device: ?*c.GdkDevice, gtk_mods: c.GdkModifierType, ) ?input.Mods { - _ = device; - _ = gtk_mods; + if (device) |dev| { + const device_mods = c.gdk_device_get_modifier_state(dev); + if (device_mods != gtk_mods) { + return input.Mods{ + .shift = (device_mods & c.GDK_SHIFT_MASK) != 0, + .ctrl = (device_mods & c.GDK_CONTROL_MASK) != 0, + .alt = (device_mods & c.GDK_ALT_MASK) != 0, + .super = (device_mods & c.GDK_SUPER_MASK) != 0, + .caps_lock = (device_mods & c.GDK_LOCK_MASK) != 0, + }; + } + } // Shoutout to Mozilla for figuring out a clean way to do this, this is // paraphrased from Firefox/Gecko in widget/gtk/nsGtkKeyUtils.cpp. From 862da9be90e8f98879eb1df54e0da0c89424ce46 Mon Sep 17 00:00:00 2001 From: nnyyxxxx Date: Sat, 25 Jan 2025 18:17:45 -0500 Subject: [PATCH 2/2] refactor(gtk): move device modifier state handling to key.zig --- src/apprt/gtk/key.zig | 16 ++++++++++++++++ src/apprt/gtk/winproto/wayland.zig | 16 +++------------- src/apprt/gtk/winproto/x11.zig | 14 +++----------- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/apprt/gtk/key.zig b/src/apprt/gtk/key.zig index 40c9ca9a4b..a62b0a16ab 100644 --- a/src/apprt/gtk/key.zig +++ b/src/apprt/gtk/key.zig @@ -49,6 +49,22 @@ pub fn translateMods(state: c.GdkModifierType) input.Mods { return mods; } +pub fn deviceMods(device: ?*c.GdkDevice, gtk_mods: c.GdkModifierType) ?input.Mods { + if (device) |dev| { + const device_mods = c.gdk_device_get_modifier_state(dev); + if (device_mods != gtk_mods) { + return input.Mods{ + .shift = (device_mods & c.GDK_SHIFT_MASK) != 0, + .ctrl = (device_mods & c.GDK_CONTROL_MASK) != 0, + .alt = (device_mods & c.GDK_ALT_MASK) != 0, + .super = (device_mods & c.GDK_SUPER_MASK) != 0, + .caps_lock = (device_mods & c.GDK_LOCK_MASK) != 0, + }; + } + } + return null; +} + // Get the unshifted unicode value of the keyval. This is used // by the Kitty keyboard protocol. pub fn keyvalUnicodeUnshifted( diff --git a/src/apprt/gtk/winproto/wayland.zig b/src/apprt/gtk/winproto/wayland.zig index ebbf237d17..c50409a592 100644 --- a/src/apprt/gtk/winproto/wayland.zig +++ b/src/apprt/gtk/winproto/wayland.zig @@ -5,6 +5,7 @@ const Allocator = std.mem.Allocator; const c = @import("../c.zig").c; const Config = @import("../../../config.zig").Config; const input = @import("../../../input.zig"); +const key = @import("../key.zig"); const wl = wayland.client.wl; const org = wayland.client.org; @@ -78,20 +79,9 @@ pub const App = struct { pub fn eventMods( _: App, device: ?*c.GdkDevice, - _: c.GdkModifierType, + gtk_mods: c.GdkModifierType, ) ?input.Mods { - if (device) |dev| { - const device_mods = c.gdk_device_get_modifier_state(dev); - return input.Mods{ - .shift = (device_mods & c.GDK_SHIFT_MASK) != 0, - .ctrl = (device_mods & c.GDK_CONTROL_MASK) != 0, - .alt = (device_mods & c.GDK_ALT_MASK) != 0, - .super = (device_mods & c.GDK_SUPER_MASK) != 0, - .caps_lock = (device_mods & c.GDK_LOCK_MASK) != 0, - }; - } - - return null; + return key.deviceMods(device, gtk_mods); } fn registryListener( diff --git a/src/apprt/gtk/winproto/x11.zig b/src/apprt/gtk/winproto/x11.zig index 7ae35e25c8..9afd3ff110 100644 --- a/src/apprt/gtk/winproto/x11.zig +++ b/src/apprt/gtk/winproto/x11.zig @@ -7,6 +7,7 @@ const c = @import("../c.zig").c; const input = @import("../../../input.zig"); const Config = @import("../../../config.zig").Config; const adwaita = @import("../adwaita.zig"); +const key = @import("../key.zig"); const log = std.log.scoped(.gtk_x11); @@ -122,17 +123,8 @@ pub const App = struct { device: ?*c.GdkDevice, gtk_mods: c.GdkModifierType, ) ?input.Mods { - if (device) |dev| { - const device_mods = c.gdk_device_get_modifier_state(dev); - if (device_mods != gtk_mods) { - return input.Mods{ - .shift = (device_mods & c.GDK_SHIFT_MASK) != 0, - .ctrl = (device_mods & c.GDK_CONTROL_MASK) != 0, - .alt = (device_mods & c.GDK_ALT_MASK) != 0, - .super = (device_mods & c.GDK_SUPER_MASK) != 0, - .caps_lock = (device_mods & c.GDK_LOCK_MASK) != 0, - }; - } + if (key.deviceMods(device, gtk_mods)) |mods| { + return mods; } // Shoutout to Mozilla for figuring out a clean way to do this, this is