@@ -49,6 +49,24 @@ static io_connect_t _getAuxiliaryKeyDriver(void)
4949 }
5050 return sEventDrvrRef ;
5151}
52+
53+ static void postMacKeyEvent (MMKeyCode code , const bool down , CGEventFlags flags )
54+ {
55+ CGEventRef keyEvent = CGEventCreateKeyboardEvent (NULL ,
56+ (CGKeyCode )code , down );
57+ assert (keyEvent != NULL );
58+
59+ /* Hardware arrow-key events carry this flag. Mission Control ignores
60+ * synthetic Control+Arrow shortcuts without it. */
61+ if (code == K_UP || code == K_DOWN || code == K_LEFT || code == K_RIGHT ) {
62+ flags |= kCGEventFlagMaskSecondaryFn ;
63+ }
64+
65+ CGEventSetType (keyEvent , down ? kCGEventKeyDown : kCGEventKeyUp );
66+ CGEventSetFlags (keyEvent , flags );
67+ CGEventPost (kCGSessionEventTap , keyEvent );
68+ CFRelease (keyEvent );
69+ }
5270#endif
5371
5472#if defined(IS_WINDOWS )
@@ -125,22 +143,51 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags)
125143 event .compound .misc .L [0 ] = evtInfo ;
126144 kr = IOHIDPostEvent ( _getAuxiliaryKeyDriver (), NX_SYSDEFINED , loc , & event , kNXEventDataVersion , 0 , FALSE );
127145 assert ( KERN_SUCCESS == kr );
128- } else {
129- CGEventFlags eventFlags = (CGEventFlags )flags ;
130- CGEventRef keyEvent = CGEventCreateKeyboardEvent (NULL ,
131- (CGKeyCode )code , down );
132- assert (keyEvent != NULL );
133-
134- /* Hardware arrow-key events carry this flag. Mission Control ignores
135- * synthetic Control+Arrow shortcuts without it. */
136- if (code == K_UP || code == K_DOWN || code == K_LEFT || code == K_RIGHT ) {
137- eventFlags |= kCGEventFlagMaskSecondaryFn ;
146+ } else if (down ) {
147+ CGEventFlags activeFlags = 0 ;
148+
149+ /* Post real modifier events around the key. Chromium and other apps
150+ * ignore bare flag bits for some shortcuts, and explicit key-up events
151+ * prevent the modifier from remaining active after the key tap. */
152+ if (flags & MOD_META ) {
153+ activeFlags |= kCGEventFlagMaskCommand ;
154+ postMacKeyEvent (K_META , true, activeFlags );
155+ }
156+ if (flags & MOD_ALT ) {
157+ activeFlags |= kCGEventFlagMaskAlternate ;
158+ postMacKeyEvent (K_ALT , true, activeFlags );
138159 }
160+ if (flags & MOD_CONTROL ) {
161+ activeFlags |= kCGEventFlagMaskControl ;
162+ postMacKeyEvent (K_CONTROL , true, activeFlags );
163+ }
164+ if (flags & MOD_SHIFT ) {
165+ activeFlags |= kCGEventFlagMaskShift ;
166+ postMacKeyEvent (K_SHIFT , true, activeFlags );
167+ }
168+
169+ postMacKeyEvent (code , true, (CGEventFlags )flags );
170+ } else {
171+ CGEventFlags activeFlags = (CGEventFlags )flags ;
172+
173+ postMacKeyEvent (code , false, activeFlags );
139174
140- CGEventSetType (keyEvent , down ? kCGEventKeyDown : kCGEventKeyUp );
141- CGEventSetFlags (keyEvent , eventFlags );
142- CGEventPost (kCGSessionEventTap , keyEvent );
143- CFRelease (keyEvent );
175+ if (flags & MOD_SHIFT ) {
176+ activeFlags &= ~kCGEventFlagMaskShift ;
177+ postMacKeyEvent (K_SHIFT , false, activeFlags );
178+ }
179+ if (flags & MOD_CONTROL ) {
180+ activeFlags &= ~kCGEventFlagMaskControl ;
181+ postMacKeyEvent (K_CONTROL , false, activeFlags );
182+ }
183+ if (flags & MOD_ALT ) {
184+ activeFlags &= ~kCGEventFlagMaskAlternate ;
185+ postMacKeyEvent (K_ALT , false, activeFlags );
186+ }
187+ if (flags & MOD_META ) {
188+ activeFlags &= ~kCGEventFlagMaskCommand ;
189+ postMacKeyEvent (K_META , false, activeFlags );
190+ }
144191 }
145192#elif defined(IS_WINDOWS )
146193 const DWORD dwFlags = down ? 0 : KEYEVENTF_KEYUP ;
0 commit comments