[PATCH 2/3] winemac.drv: Use Cocoa nonactivating panels for WS_EX_NOACTIVATE windows.

Tim Clem tclem at codeweavers.com
Wed Jan 19 13:13:44 CST 2022


NSWindowStyleMaskNonactivatingPanel is almost exactly the same behavior
as WS_EX_NOACTIVATE on Windows: it prevents the window from activating
the app, but does not prevent it from being focused if the app is
already active.

Signed-off-by: Tim Clem <tclem at codeweavers.com>
---
 dlls/winemac.drv/cocoa_window.m | 26 +++++++++++++++++++++++++-
 dlls/winemac.drv/macdrv_cocoa.h |  1 +
 dlls/winemac.drv/window.c       |  2 ++
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m
index 2e15ec8ce721..6301b47143ea 100644
--- a/dlls/winemac.drv/cocoa_window.m
+++ b/dlls/winemac.drv/cocoa_window.m
@@ -44,6 +44,16 @@
 #endif
 
 
+ at interface NSWindow (PrivatePreventsActivation)
+
+/* Needed to ensure proper behavior after adding or removing
+ * NSWindowStyleMaskNonactivatingPanel.
+ * Available since at least macOS 10.6. */
+- (void)_setPreventsActivation:(BOOL)flag;
+
+ at end
+
+
 static NSUInteger style_mask_for_features(const struct macdrv_window_features* wf)
 {
     NSUInteger style_mask;
@@ -58,6 +68,8 @@ static NSUInteger style_mask_for_features(const struct macdrv_window_features* w
     }
     else style_mask = NSWindowStyleMaskBorderless;
 
+    if (wf->prevents_app_activation) style_mask |= NSWindowStyleMaskNonactivatingPanel;
+
     return style_mask;
 }
 
@@ -1126,7 +1138,8 @@ - (void) adjustFullScreenBehavior:(NSWindowCollectionBehavior)behavior
     - (void) setWindowFeatures:(const struct macdrv_window_features*)wf
     {
         static const NSUInteger usedStyles = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable |
-                                             NSWindowStyleMaskResizable | NSWindowStyleMaskUtilityWindow | NSWindowStyleMaskBorderless;
+                                             NSWindowStyleMaskResizable | NSWindowStyleMaskUtilityWindow | NSWindowStyleMaskBorderless |
+                                             NSWindowStyleMaskNonactivatingPanel;
         NSUInteger currentStyle = [self styleMask];
         NSUInteger newStyle = style_mask_for_features(wf) | (currentStyle & ~usedStyles);
 
@@ -1146,6 +1159,17 @@ - (void) setWindowFeatures:(const struct macdrv_window_features*)wf
             }
             [self setStyleMask:newStyle];
 
+            BOOL isNonActivating = (currentStyle & NSWindowStyleMaskNonactivatingPanel) != 0;
+            BOOL shouldBeNonActivating = (newStyle & NSWindowStyleMaskNonactivatingPanel) != 0;
+            if (isNonActivating != shouldBeNonActivating) {
+                // Changing NSWindowStyleMaskNonactivatingPanel with -setStyleMask is also
+                // buggy. If it's added, clicking the title bar will still activate the
+                // app. If it's removed, nothing changes at all.
+                // This private method ensures the correct behavior.
+                if ([self respondsToSelector:@selector(_setPreventsActivation:)])
+                    [self _setPreventsActivation:shouldBeNonActivating];
+            }
+
             // -setStyleMask: resets the firstResponder to the window.  Set it
             // back to the content view.
             if ([[self contentView] acceptsFirstResponder])
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index 2304f771bfa3..5c19b4f4e817 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -538,6 +538,7 @@ extern int macdrv_register_hot_key(macdrv_event_queue q, unsigned int vkey, unsi
     unsigned int    maximize_button:1;
     unsigned int    utility:1;
     unsigned int    shadow:1;
+    unsigned int    prevents_app_activation:1;
 };
 
 struct macdrv_window_state {
diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c
index 6d735bb4ed22..4f3dbc08311f 100644
--- a/dlls/winemac.drv/window.c
+++ b/dlls/winemac.drv/window.c
@@ -63,6 +63,8 @@ static void get_cocoa_window_features(struct macdrv_win_data *data,
 {
     memset(wf, 0, sizeof(*wf));
 
+    if (ex_style & WS_EX_NOACTIVATE) wf->prevents_app_activation = TRUE;
+
     if (disable_window_decorations) return;
     if (IsRectEmpty(window_rect)) return;
     if (EqualRect(window_rect, client_rect)) return;
-- 
2.34.1




More information about the wine-devel mailing list