admin管理员组文章数量:1387356
I have a Mac menubar app that tries to show/hide the Emoji picker (Character palette) in the frontmost app via a menu item.
The best way I found to do this was to trigger the Emoji picker's system keyboard shortcut — fn-E
(Globe-E) — via simulated key press sent to the frontmost app:
pid_t psn = NSWorkspace.sharedWorkspace.frontmostApplication.processIdentifier;
CGEventRef keyup, keydown;
CGEventFlags flags = kCGEventFlagMaskSecondaryFn;
keydown = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)kVK_ANSI_E, true);
CGEventSetFlags(keydown, flags);
keyup = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)kVK_ANSI_E, false);
CGEventSetFlags(keyup, flags);
CGEventPostToPid(psn, keydown);
CGEventPostToPid(psn, keyup);
CFRelease(keydown);
CFRelease(keyup);
This no longer works in macOS 15 Sequoia. The code above simply fails without error.
I found one similar question on StackOverflow, with a suggestion from @Rudolfs-Bundulis to set timestamps on the events before posting them, e.g. add these lines:
CGEventSetTimestamp(keydown, clock_gettime_nsec_np(CLOCK_UPTIME_RAW));
CGEventSetTimestamp(keyup, clock_gettime_nsec_np(CLOCK_UPTIME_RAW));
This still doesn't work. I also tried creating an NSEvent key event with a timestamp and windowId, but that also doesn't work. Am I doing something wrong with the timestamps, or is there something else I'm missing?
I have a Mac menubar app that tries to show/hide the Emoji picker (Character palette) in the frontmost app via a menu item.
The best way I found to do this was to trigger the Emoji picker's system keyboard shortcut — fn-E
(Globe-E) — via simulated key press sent to the frontmost app:
pid_t psn = NSWorkspace.sharedWorkspace.frontmostApplication.processIdentifier;
CGEventRef keyup, keydown;
CGEventFlags flags = kCGEventFlagMaskSecondaryFn;
keydown = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)kVK_ANSI_E, true);
CGEventSetFlags(keydown, flags);
keyup = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)kVK_ANSI_E, false);
CGEventSetFlags(keyup, flags);
CGEventPostToPid(psn, keydown);
CGEventPostToPid(psn, keyup);
CFRelease(keydown);
CFRelease(keyup);
This no longer works in macOS 15 Sequoia. The code above simply fails without error.
I found one similar question on StackOverflow, with a suggestion from @Rudolfs-Bundulis to set timestamps on the events before posting them, e.g. add these lines:
CGEventSetTimestamp(keydown, clock_gettime_nsec_np(CLOCK_UPTIME_RAW));
CGEventSetTimestamp(keyup, clock_gettime_nsec_np(CLOCK_UPTIME_RAW));
This still doesn't work. I also tried creating an NSEvent key event with a timestamp and windowId, but that also doesn't work. Am I doing something wrong with the timestamps, or is there something else I'm missing?
Share Improve this question edited Mar 21 at 22:02 HangarRash 15.1k5 gold badges20 silver badges55 bronze badges asked Mar 18 at 17:45 AdamAdam 5,17522 silver badges30 bronze badges 6 | Show 1 more comment1 Answer
Reset to default 0Okay, with a little help I have figured out what was going on. There were two issues:
First, I needed to reset permissions. That is, I had to go to System Settings > Privacy & Security > Accessibility, remove my app, then add it back again (toggling the switch was insufficient). In my app, calling AXIsProcessTrusted()
returned true
both before and after the reset. This seems to me to be a macOS bug.
Second, I was not accounting for how fn+e works as compared to many other hotkeys. Many hotkeys are remapped when you switch keyboard layouts, but fn+e is not, meaning I need to send the key code for the current layout's E key. kVK_ANSI_E
is the virtual key code that represents the ANSI keyboard layout's E key.
So the solution was to figure out which CGKeyCode
corresponds to the current keyboard layout's E key and use that instead of hard-coding kVK_ANSI_E
. I used the Sauce library to do this.
本文标签: objective cPosting keypress CGEvent fails in macOS 15 SequoiaStack Overflow
版权声明:本文标题:objective c - Posting key-press CGEvent fails in macOS 15 Sequoia - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744498526a2609178.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
psn
is confusing. – Willeke Commented Mar 19 at 6:04CGEventPostToPSN
is deprecated in CGEvent.h. How do you get a psn nowadays?. – Willeke Commented Mar 19 at 11:53