This thread contains a patchset. You're looking at the original emails,
but you may wish to use the patch review UI.
Review patch
2
2
[PATCH v2] gio: app: send keypress events for modifier keys in macos
This change generates keypress and release events for modifier keys in
MacOS. Specifically the Control, Alt, Shift and Command keys.
---
app/os_macos.go | 50 +++++++++++++++++++++++++++++++++++++++++++++++++
app/os_macos.m | 4 ++++
2 files changed, 54 insertions(+)
diff --git a/app/os_macos.go b/app/os_macos.go
index d62bb645..77d69e1b 100644
--- a/app/os_macos.go
+++ b/app/os_macos.go
@@ -561,6 +561,56 @@ func gio_onKeys(h C.uintptr_t, cstr C.CFTypeRef, ti C.double, mods C.NSUInteger,
}
}
+ var lastModsOnFlagsChanged C.NSUInteger
+
+ type onFlagsChangedLogicTableEntry struct {
+ modKeyMask C.NSUInteger
+ modKeyName key.Name
+ }
+
+ var onFlagsChangedLogicTable = []onFlagsChangedLogicTableEntry{
+ onFlagsChangedLogicTableEntry{
+ C.NSControlKeyMask,
+ key.NameCtrl,
+ },
+ onFlagsChangedLogicTableEntry{
+ C.NSAlternateKeyMask,
+ key.NameAlt,
+ },
+ onFlagsChangedLogicTableEntry{
+ C.NSShiftKeyMask,
+ key.NameShift,
+ },
+ onFlagsChangedLogicTableEntry{
+ C.NSCommandKeyMask,
+ key.NameCommand,
+ },
+ }
+
+ //export gio_onFlagsChanged
+ func gio_onFlagsChanged(h C.uintptr_t, mods C.NSUInteger) {
+ w := windowFor(h)
+ for _, e := range onFlagsChangedLogicTable {
+ if mods&e.modKeyMask != 0 {
+ if lastModsOnFlagsChanged&e.modKeyMask == 0 {
+ w.ProcessEvent(key.Event{Name: e.modKeyName,
+ State: key.Press,
+ })
+ }
+
+ continue
+ }
+
+ if lastModsOnFlagsChanged&e.modKeyMask != 0 {
+ w.ProcessEvent(key.Event{Name: e.modKeyName,
+ State: key.Release,
+ })
+ }
+ }
+
+ lastModsOnFlagsChanged = mods
+ }
+
//export gio_onText
func gio_onText(h C.uintptr_t, cstr C.CFTypeRef) {
str := nsstringToString(cstr)
diff --git a/app/os_macos.m b/app/os_macos.m
index 9c895148..6e3438e3 100644
--- a/app/os_macos.m
+++ b/app/os_macos.m
@@ -136,6 +136,10 @@ static void handleMouse(GioView *view, NSEvent *event, int typ, CGFloat dx, CGFl
NSString *keys = [event charactersIgnoringModifiers];
gio_onKeys(self.handle, (__bridge CFTypeRef)keys, [event timestamp], [event modifierFlags], true);
}
+ - (void)flagsChanged:(NSEvent *)event {
+ [self interpretKeyEvents:[NSArray arrayWithObject:event]];
+ gio_onFlagsChanged(self.handle, [event modifierFlags]);
+ }
- (void)keyUp:(NSEvent *)event {
NSString *keys = [event charactersIgnoringModifiers];
gio_onKeys(self.handle, (__bridge CFTypeRef)keys, [event timestamp], [event modifierFlags], false);
--
2.30.2
On Tue Oct 1, 2024 at 4:17 AM CEST, Jeff Williams wrote:
> This change generates keypress and release events for modifier keys in
> MacOS. Specifically the Control, Alt, Shift and Command keys.
> ---
Thank you for working on this. I've been more than usually busy and I apologize
for the delayed review.
> app/os_macos.go | 50 +++++++++++++++++++++++++++++++++++++++++++++++++
> app/os_macos.m | 4 ++++
> 2 files changed, 54 insertions(+)
>
> diff --git a/app/os_macos.go b/app/os_macos.go
> index d62bb645..77d69e1b 100644
> --- a/app/os_macos.go
> +++ b/app/os_macos.go
> @@ -561,6 +561,56 @@ func gio_onKeys(h C.uintptr_t, cstr C.CFTypeRef, ti C.double, mods C.NSUInteger,
> }
> }
>
> +var lastModsOnFlagsChanged C.NSUInteger
This global variable probably belongs to the window type as a struct field.
Perhaps shorten its name to `lastMods`.
> +
> +type onFlagsChangedLogicTableEntry struct {
> + modKeyMask C.NSUInteger
> + modKeyName key.Name
> +}
> +
> +var onFlagsChangedLogicTable = []onFlagsChangedLogicTableEntry{
> + onFlagsChangedLogicTableEntry{
> + C.NSControlKeyMask,
> + key.NameCtrl,
> + },
> + onFlagsChangedLogicTableEntry{
> + C.NSAlternateKeyMask,
> + key.NameAlt,
> + },
> + onFlagsChangedLogicTableEntry{
> + C.NSShiftKeyMask,
> + key.NameShift,
> + },
> + onFlagsChangedLogicTableEntry{
> + C.NSCommandKeyMask,
> + key.NameCommand,
> + },
> +}
> +
> +//export gio_onFlagsChanged
> +func gio_onFlagsChanged(h C.uintptr_t, mods C.NSUInteger) {
> + w := windowFor(h)
> + for _, e := range onFlagsChangedLogicTable {
> + if mods&e.modKeyMask != 0 {
> + if lastModsOnFlagsChanged&e.modKeyMask == 0 {
> + w.ProcessEvent(key.Event{Name: e.modKeyName,
> + State: key.Press,
> + })
> + }
> +
> + continue
> + }
> +
> + if lastModsOnFlagsChanged&e.modKeyMask != 0 {
> + w.ProcessEvent(key.Event{Name: e.modKeyName,
> + State: key.Release,
> + })
> + }
> + }
How about dropping the onFlagsChangedLogicTable and then
mods := []C.NSUInteger{C.NSShiftKeyMask, ...}
keys := []key.Name{key.NameShift, ...}
for i, mod := range mods {
wasPressed := w.lastMods&mod != 0
isPressed := mods&mod != 0
if wasPressed != isPressed {
st := key.Release
if isPressed {
st = key.Press
}
w.ProcessEvent(key.Event{
Name: keys[i],
State: st,
})
}
}
?
> +
> + lastModsOnFlagsChanged = mods
> +}
> +
> //export gio_onText
> func gio_onText(h C.uintptr_t, cstr C.CFTypeRef) {
> str := nsstringToString(cstr)
> diff --git a/app/os_macos.m b/app/os_macos.m
> index 9c895148..6e3438e3 100644
> --- a/app/os_macos.m
> +++ b/app/os_macos.m
> @@ -136,6 +136,10 @@ static void handleMouse(GioView *view, NSEvent *event, int typ, CGFloat dx, CGFl
> NSString *keys = [event charactersIgnoringModifiers];
> gio_onKeys(self.handle, (__bridge CFTypeRef)keys, [event timestamp], [event modifierFlags], true);
> }
> +- (void)flagsChanged:(NSEvent *)event {
> + [self interpretKeyEvents:[NSArray arrayWithObject:event]];
> + gio_onFlagsChanged(self.handle, [event modifierFlags]);
> +}
> - (void)keyUp:(NSEvent *)event {
> NSString *keys = [event charactersIgnoringModifiers];
> gio_onKeys(self.handle, (__bridge CFTypeRef)keys, [event timestamp], [event modifierFlags], false);
> Thank you for working on this. I've been more than usually busy and I apologize
> for the delayed review.
I completely understand, it's no problem at all! Thanks for reviewing it.
> > +var lastModsOnFlagsChanged C.NSUInteger
>
> This global variable probably belongs to the window type as a struct field.
> Perhaps shorten its name to `lastMods`.
Good suggestion, I'll do that.
> How about dropping the onFlagsChangedLogicTable and then ...
Yes, that's much cleaner. I'll make that change too, and then send
another patch.
Thanks!