mirror of
https://github.com/lucannez64/darling-lol.git
synced 2026-10-27 19:54:38 +00:00
Merge branch 'main' into fix/cocoa-window-decorations
This commit is contained in:
2 files changed
+122
-25
No files matched your search
+95
-24
@@ -2764,7 +2764,7 @@ index 18189404..12cde429 100644
|
||||
+- (NSRect) frameForRootRect: (NSRect) rect;
|
||||
@end
|
||||
diff --git a/AppKit/X11.backend/X11Display.m b/AppKit/X11.backend/X11Display.m
|
||||
index 5ae29bf4..47fb6552 100644
|
||||
index 5ae29bf4..3a3c68f8 100644
|
||||
--- a/AppKit/X11.backend/X11Display.m
|
||||
+++ b/AppKit/X11.backend/X11Display.m
|
||||
@@ -48,12 +48,271 @@
|
||||
@@ -3652,7 +3652,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
}
|
||||
|
||||
- (NSEventModifierFlags) modifierFlagsForState: (unsigned int) state {
|
||||
@@ -1010,17 +1625,96 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1010,17 +1625,157 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -3660,15 +3660,37 @@ index 5ae29bf4..47fb6552 100644
|
||||
+ * carries the state AFTER it. Keep both sides separately so releasing one
|
||||
+ * Shift/Command key does not clear the other, and reconcile missed releases
|
||||
+ * when the compositor intercepts a shortcut or changes keyboard focus. */
|
||||
+static unsigned char rclolServerModifiers[256];
|
||||
+static BOOL rclolServerModifiersLoaded;
|
||||
+
|
||||
+/* Which modifier each keycode sets depends on the layout: Right Alt is Mod5
|
||||
+ * (AltGr) on most European layouts and Mod1 (Alt) on US. Ask the server. */
|
||||
+static void rclolLoadServerModifiers(Display *display) {
|
||||
+ if (rclolServerModifiersLoaded) return;
|
||||
+ rclolServerModifiersLoaded = YES;
|
||||
+ memset(rclolServerModifiers, 0, sizeof(rclolServerModifiers));
|
||||
+ XModifierKeymap *map = XGetModifierMapping(display);
|
||||
+ if (!map) return;
|
||||
+ for (int mod = 0; mod < 8; ++mod)
|
||||
+ for (int i = 0; i < map->max_keypermod; ++i) {
|
||||
+ KeyCode code = map->modifiermap[mod * map->max_keypermod + i];
|
||||
+ if (code) rclolServerModifiers[code] |= 1 << mod;
|
||||
+ }
|
||||
+ XFreeModifiermap(map);
|
||||
+}
|
||||
+
|
||||
+static unsigned int rclolModifierMask(unsigned int key) {
|
||||
+ unsigned int fallback;
|
||||
+ switch (key) {
|
||||
+ case 50: case 62: return ShiftMask;
|
||||
+ case 37: case 105: return ControlMask;
|
||||
+ case 64: return Mod1Mask;
|
||||
+ case 108: return Mod5Mask;
|
||||
+ case 133: case 134: return Mod4Mask;
|
||||
+ case 50: case 62: fallback = ShiftMask; break;
|
||||
+ case 37: case 105: fallback = ControlMask; break;
|
||||
+ case 64: fallback = Mod1Mask; break;
|
||||
+ case 108: fallback = Mod5Mask; break;
|
||||
+ case 133: case 134: fallback = Mod4Mask; break;
|
||||
+ default: return 0;
|
||||
+ }
|
||||
+ unsigned int server = rclolServerModifiers[key] & (Mod1Mask | Mod4Mask | Mod5Mask | ShiftMask | ControlMask);
|
||||
+ return server ? server : fallback;
|
||||
+}
|
||||
+
|
||||
+- (void) postModifierKey:(unsigned int)key state:(unsigned int)state window:(id)delegate {
|
||||
@@ -3696,6 +3718,26 @@ index 5ae29bf4..47fb6552 100644
|
||||
+ [self postModifierKey:key state:state window:delegate];
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* A compositor can eat a modifier release without moving focus: GNOME's
|
||||
+ * overview delivers Super's press, swallows its release and hands the
|
||||
+ * keyboard back with no FocusOut, leaving Command held in the guest. Every
|
||||
+ * input event carries the server's modifier state, so release any key we
|
||||
+ * think is held whose modifier is missing there. `except` is the key of a
|
||||
+ * modifier event, whose state predates its own transition. */
|
||||
+- (void) releaseModifierKeysMissingFromState:(unsigned int)state except:(unsigned int)except window:(id)delegate {
|
||||
+ static const unsigned char keys[] = { 50, 62, 37, 105, 64, 108, 133, 134 };
|
||||
+ for (unsigned int i = 0; i < sizeof(keys); ++i) {
|
||||
+ unsigned int key = keys[i];
|
||||
+ if (key == except || !_modifierKeysDown[key]) continue;
|
||||
+ if (state & rclolModifierMask(key)) continue;
|
||||
+ _modifierKeysDown[key] = 0;
|
||||
+ unsigned int now = state & ~(ShiftMask | ControlMask | Mod1Mask | Mod4Mask | Mod5Mask);
|
||||
+ for (unsigned int j = 0; j < sizeof(keys); ++j)
|
||||
+ if (_modifierKeysDown[keys[j]]) now |= rclolModifierMask(keys[j]);
|
||||
+ [self postModifierKey:key state:now window:delegate];
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
- (void) postXEvent: (XEvent *) ev {
|
||||
id event = nil;
|
||||
@@ -3703,6 +3745,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
X11Window* window = (X11Window*) [self windowForID: ev->xany.window];
|
||||
|
||||
id delegate = [window delegate];
|
||||
+ rclolLoadServerModifiers(_display);
|
||||
+ static int inputTrace = -1;
|
||||
+ if (inputTrace < 0) inputTrace = getenv("RCLOL_INPUT_TRACE") != NULL;
|
||||
+ if (inputTrace && (ev->type == KeyPress || ev->type == KeyRelease || ev->type == ButtonPress))
|
||||
@@ -3726,6 +3769,24 @@ index 5ae29bf4..47fb6552 100644
|
||||
+ /* Expected warp echoes are among the events queued when the warp was synced; motion ages them itself. */
|
||||
+ if (_relativeMouse.active && ev->type != MotionNotify)
|
||||
+ X11RelativeMouseTick(&_relativeMouse);
|
||||
+
|
||||
+ /* Events sent by other clients carry whatever state they chose. */
|
||||
+ switch (ev->xany.send_event ? 0 : ev->type) {
|
||||
+ case KeyPress: case KeyRelease:
|
||||
+ [self releaseModifierKeysMissingFromState:ev->xkey.state except:ev->xkey.keycode window:delegate];
|
||||
+ break;
|
||||
+ case ButtonPress: case ButtonRelease:
|
||||
+ [self releaseModifierKeysMissingFromState:ev->xbutton.state except:0 window:delegate];
|
||||
+ break;
|
||||
+ case MotionNotify:
|
||||
+ [self releaseModifierKeysMissingFromState:ev->xmotion.state except:0 window:delegate];
|
||||
+ break;
|
||||
+ case EnterNotify: case LeaveNotify:
|
||||
+ [self releaseModifierKeysMissingFromState:ev->xcrossing.state except:0 window:delegate];
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
switch (ev->type) {
|
||||
case KeyPress:
|
||||
@@ -3749,7 +3810,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
NSEventModifierFlags modifierFlags = [self modifierFlagsForState: ev->xkey.state];
|
||||
char buf[20] = {0};
|
||||
KeySym keySym;
|
||||
@@ -1030,7 +1724,11 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1030,7 +1785,11 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
break;
|
||||
|
||||
if (ev->type == KeyPress) {
|
||||
@@ -3762,7 +3823,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
buf[strLen] = 0;
|
||||
} else {
|
||||
// Xutf8LookupString() may not be used with KeyRelease
|
||||
@@ -1038,6 +1736,18 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1038,6 +1797,18 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
buf[strLen] = 0;
|
||||
}
|
||||
|
||||
@@ -3781,7 +3842,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
id str = [[NSString alloc] initWithCString: buf
|
||||
encoding: NSUTF8StringEncoding];
|
||||
NSPoint pos =
|
||||
@@ -1077,6 +1787,32 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1077,6 +1848,32 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
break;
|
||||
|
||||
case ButtonPress:;
|
||||
@@ -3814,7 +3875,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
NSTimeInterval now = [[NSDate date] timeIntervalSinceReferenceDate];
|
||||
|
||||
if (now - lastClickTimeStamp < [self doubleClickInterval]) {
|
||||
@@ -1086,8 +1822,8 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1086,8 +1883,8 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
}
|
||||
lastClickTimeStamp = now;
|
||||
|
||||
@@ -3825,7 +3886,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
|
||||
switch (ev->xbutton.button) {
|
||||
case Button1:
|
||||
@@ -1096,10 +1832,6 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1096,10 +1893,6 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
case Button3:
|
||||
type = NSRightMouseDown;
|
||||
break;
|
||||
@@ -3836,7 +3897,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
default:
|
||||
type = NSOtherMouseDown;
|
||||
}
|
||||
@@ -1113,14 +1845,22 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1113,14 +1906,22 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
clickCount: clickCount
|
||||
deltaX: 0.0
|
||||
deltaY: 0.0];
|
||||
@@ -3863,7 +3924,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
CGFloat deltaY = 0.0;
|
||||
|
||||
switch (ev->xbutton.button) {
|
||||
@@ -1130,14 +1870,6 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1130,14 +1931,6 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
case Button3:
|
||||
type = NSRightMouseUp;
|
||||
break;
|
||||
@@ -3878,7 +3939,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
default:
|
||||
type = NSOtherMouseUp;
|
||||
}
|
||||
@@ -1151,7 +1883,9 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1151,7 +1944,9 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
clickCount: clickCount
|
||||
deltaX: 0.0
|
||||
deltaY: deltaY];
|
||||
@@ -3889,7 +3950,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
[self postEvent: event atStart: NO];
|
||||
break;
|
||||
|
||||
@@ -1160,49 +1894,95 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1160,49 +1955,95 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
// ev->xmotion.x, ev->xmotion.y, ev->xmotion.x_root,
|
||||
// ev->xmotion.y_root);
|
||||
|
||||
@@ -4011,7 +4072,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
mouseEventWithType: type
|
||||
location: pos
|
||||
modifierFlags:
|
||||
@@ -1211,28 +1991,58 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1211,28 +2052,58 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
clickCount: 1
|
||||
deltaX: deltaX
|
||||
deltaY: deltaY];
|
||||
@@ -4072,7 +4133,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
NSLog(@"FocusIn");
|
||||
if ([delegate attachedSheet]) {
|
||||
[[delegate attachedSheet] makeKeyAndOrderFront: delegate];
|
||||
@@ -1243,28 +2053,62 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1243,28 +2114,62 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
checkForAppDeactivation: NO];
|
||||
lastFocusedWindow = nil;
|
||||
}
|
||||
@@ -4137,7 +4198,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
O2Rect rect = NSMakeRect(ev->xexpose.x, ev->xexpose.y,
|
||||
ev->xexpose.width, ev->xexpose.height);
|
||||
|
||||
@@ -1301,11 +2145,23 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1301,11 +2206,23 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
break;
|
||||
|
||||
case UnmapNotify:
|
||||
@@ -4165,7 +4226,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
break;
|
||||
|
||||
case MapRequest:
|
||||
@@ -1317,10 +2173,21 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1317,10 +2234,21 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
break;
|
||||
|
||||
case ConfigureNotify:
|
||||
@@ -4187,7 +4248,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
break;
|
||||
|
||||
case ConfigureRequest:
|
||||
@@ -1344,6 +2211,8 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1344,6 +2272,8 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
break;
|
||||
|
||||
case PropertyNotify:
|
||||
@@ -4196,7 +4257,17 @@ index 5ae29bf4..47fb6552 100644
|
||||
if ([window respondsToSelector: @selector(propertyNotify:)]) {
|
||||
[window propertyNotify: &ev->xproperty];
|
||||
}
|
||||
@@ -1399,7 +2268,9 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1392,6 +2322,9 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
|
||||
case MappingNotify:
|
||||
NSLog(@"MappingNotify");
|
||||
+ XRefreshKeyboardMapping(&ev->xmapping);
|
||||
+ if (ev->xmapping.request == MappingModifier)
|
||||
+ rclolServerModifiersLoaded = NO;
|
||||
break;
|
||||
|
||||
case GenericEvent:
|
||||
@@ -1399,7 +2332,9 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -4207,7 +4278,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
[self _invalidateRRCache];
|
||||
break;
|
||||
}
|
||||
@@ -1433,6 +2304,10 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
@@ -1433,6 +2368,10 @@ static NSDictionary *modeInfoToDictionary(const XRRModeInfo *mi, int depth) {
|
||||
NSLog(@"Request code: %d:%d", errorEvent->request_code,
|
||||
errorEvent->minor_code);
|
||||
NSLog(@"Error code: %d", errorEvent->error_code);
|
||||
@@ -4218,7 +4289,7 @@ index 5ae29bf4..47fb6552 100644
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1476,54 +2351,279 @@ void CGNativeBorderFrameWidthsForStyle(NSUInteger styleMask, CGFloat *top,
|
||||
@@ -1476,54 +2415,279 @@ void CGNativeBorderFrameWidthsForStyle(NSUInteger styleMask, CGFloat *top,
|
||||
return frame;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,8 +48,34 @@ int main(void) {
|
||||
XEvent map={0};map.type=KeymapNotify;[display postXEvent:&map];expectModifier(0x37,0);
|
||||
key(display,KeyPress,66,0);expectModifier(0x39,NSAlphaShiftKeyMask);
|
||||
key(display,KeyRelease,66,LockMask);expectModifier(0x39,NSAlphaShiftKeyMask);
|
||||
// GNOME overview: Super press delivered, release swallowed, no focus change.
|
||||
// The next event's server state lacks Mod4, so Command must be released first.
|
||||
key(display,KeyPress,133,LockMask);expectModifier(0x37,NSAlphaShiftKeyMask|NSCommandKeyMask);
|
||||
NSUInteger before=[events count];
|
||||
key(display,KeyPress,50,LockMask);
|
||||
assert([events count]==before+2);
|
||||
NSEvent *released=[events objectAtIndex:before];
|
||||
assert([released keyCode]==0x37 && [released modifierFlags]==NSAlphaShiftKeyMask);
|
||||
expectModifier(0x38,NSAlphaShiftKeyMask|NSShiftKeyMask);
|
||||
// A modifier that is still held stays held.
|
||||
key(display,KeyPress,133,LockMask|ShiftMask);expectModifier(0x37,NSAlphaShiftKeyMask|NSShiftKeyMask|NSCommandKeyMask);
|
||||
before=[events count];
|
||||
key(display,KeyRelease,50,LockMask|ShiftMask|Mod4Mask);
|
||||
assert([events count]==before+1);
|
||||
expectModifier(0x38,NSAlphaShiftKeyMask|NSCommandKeyMask);
|
||||
// Right Alt is Mod1 (Option) on US layouts and Mod5 (AltGr) elsewhere; the
|
||||
// backend reads the server map, so take whichever it reported and check it
|
||||
// is still held, and reported once, when Command goes up.
|
||||
key(display,KeyPress,108,LockMask|Mod4Mask);
|
||||
NSUInteger rightAlt=[[events lastObject] modifierFlags]&~(NSUInteger)(NSAlphaShiftKeyMask|NSCommandKeyMask);
|
||||
assert(rightAlt==NSAlternateKeyMask || rightAlt==NSFunctionKeyMask);
|
||||
unsigned int rightAltMask=rightAlt==NSAlternateKeyMask ? Mod1Mask : Mod5Mask;
|
||||
before=[events count];
|
||||
key(display,KeyRelease,133,LockMask|Mod4Mask|rightAltMask);
|
||||
assert([events count]==before+1);
|
||||
expectModifier(0x37,NSAlphaShiftKeyMask|rightAlt);
|
||||
method_setImplementation(method,original);
|
||||
puts("PASS Super=Command, Alt=Option, both Command keys, post-transition flags, focus-loss release, missed-release reconciliation, Caps Lock");
|
||||
puts("PASS Super=Command, Alt=Option, both Command keys, post-transition flags, focus-loss release, missed-release reconciliation, Caps Lock, swallowed Super release, layout-mapped Right Alt");
|
||||
[events release];
|
||||
}
|
||||
return 0;
|
||||
|
||||
Reference in new issue
Block a user