macos: fix window activation during shadow click-through
authorChristian Hergert <christian@hergert.me>
Fri, 11 Mar 2022 01:26:56 +0000 (17:26 -0800)
committerChristian Hergert <chergert@redhat.com>
Wed, 16 Mar 2022 19:25:10 +0000 (12:25 -0700)
If we are clicking through the shadow of a window, we need to take special
care to not raise the old window on mouseUp. This is normally done by the
display server for us, so we need to use the proper API that is public to
handle this (rather than CGSSetWindowTags()). Doing so requires us to
dispatch the event to the NSView and then cancel the activcation from
the mouseDown: event there.

gdk/macos/GdkMacosView.c
gdk/macos/GdkMacosWindow.c
gdk/macos/GdkMacosWindow.h
gdk/macos/gdkmacosdisplay-translate.c

index 52a55a7cefee063c402cc41a9474da5232c62c4e..18de78aa1935b9952a22e4be9a44284c5d90a27a 100644 (file)
@@ -24,6 +24,7 @@
 
 #import "GdkMacosLayer.h"
 #import "GdkMacosView.h"
+#import "GdkMacosWindow.h"
 
 @implementation GdkMacosView
 
   return NO;
 }
 
+-(void)mouseDown:(NSEvent *)nsevent
+{
+  if ([(GdkMacosWindow *)[self window] needsMouseDownQuirk])
+    /* We should only hit this when we are trying to click through
+     * the shadow of a window into another window. Just request
+     * that the application not activate this window on mouseUp.
+     * See gdkmacosdisplay-translate.c for the other half of this.
+     */
+    [NSApp preventWindowOrdering];
+  else
+    [super mouseDown:nsevent];
+}
+
 -(void)setFrame:(NSRect)rect
 {
   [super setFrame:rect];
index c93be7f49e00c729d281f9a0c5afde6c9fb66170..23b3f5a3f3bd451463ed4889d7d6f1ad6eef2e41 100644 (file)
@@ -262,9 +262,9 @@ typedef NSString *CALayerContentsGravity;
   inShowOrHide = YES;
 
   if (makeKey && [self canBecomeKeyWindow])
-    [self makeKeyAndOrderFront:nil];
+    [self makeKeyAndOrderFront:self];
   else
-    [self orderFront:nil];
+    [self orderFront:self];
 
   if (makeKey && [self canBecomeMainWindow])
     [self makeMainWindow];
@@ -830,4 +830,10 @@ typedef NSString *CALayerContentsGravity;
   [(GdkMacosView *)[self contentView] swapBuffer:buffer withDamage:damage];
 }
 
+-(BOOL)needsMouseDownQuirk
+{
+  return GDK_IS_MACOS_TOPLEVEL_SURFACE (gdk_surface) &&
+    !GDK_MACOS_TOPLEVEL_SURFACE (gdk_surface)->decorated;
+}
+
 @end
index cb8b2efad1f081e20f27e0a406bf9faf13951313..3a514ea85707ae1123f75a52f8c36e04b2134d76 100644 (file)
@@ -69,5 +69,6 @@
 -(BOOL)trackManualResize;
 -(void)setDecorated:(BOOL)decorated;
 -(void)swapBuffer:(GdkMacosBuffer *)buffer withDamage:(const cairo_region_t *)damage;
+-(BOOL)needsMouseDownQuirk;
 
 @end
index 4ad12ba7781b6d379d1a4bc931bbb85e7f026159..9caddca811c6ad39f83f6f0b615019f834e7602d 100644 (file)
@@ -1159,15 +1159,31 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
   if (test_resize (nsevent, surface, x, y))
     return NULL;
 
-  if ((event_type == NSEventTypeRightMouseDown ||
-       event_type == NSEventTypeOtherMouseDown ||
-       event_type == NSEventTypeLeftMouseDown))
+  if (event_type == NSEventTypeRightMouseDown ||
+      event_type == NSEventTypeOtherMouseDown ||
+      event_type == NSEventTypeLeftMouseDown)
     {
       if (![NSApp isActive])
         [NSApp activateIgnoringOtherApps:YES];
 
       if (![window isKeyWindow])
-        [window makeKeyWindow];
+        {
+          NSWindow *orig_window = [nsevent window];
+
+          /* To get NSApp to supress activating the window we might
+           * have clicked through the shadow of, we need to dispatch
+           * the event and handle it in GdkMacosView:mouseDown to call
+           * [NSApp preventWindowOrdering]. Calling it here will not
+           * do anything as the event is not registered.
+           */
+          if (orig_window &&
+              GDK_IS_MACOS_WINDOW (orig_window) &&
+              [(GdkMacosWindow *)orig_window needsMouseDownQuirk])
+            [NSApp sendEvent:nsevent];
+
+          [window showAndMakeKey:YES];
+          _gdk_macos_display_clear_sorting (self);
+        }
     }
 
   switch ((int)event_type)