Tim Clem : winemac.drv: Use Cocoa nonactivating panels for WS_EX_NOACTIVATE windows.

Alexandre Julliard julliard at winehq.org
Wed Jan 19 15:57:47 CST 2022


Module: wine
Branch: master
Commit: e58b1a2b395b56859157e7dd8d08cca4448f66c9
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=e58b1a2b395b56859157e7dd8d08cca4448f66c9

Author: Tim Clem <tclem at codeweavers.com>
Date:   Wed Jan 19 11:13:44 2022 -0800

winemac.drv: Use Cocoa nonactivating panels for WS_EX_NOACTIVATE windows.

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>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 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 2e15ec8ce72..6301b47143e 100644
--- a/dlls/winemac.drv/cocoa_window.m
+++ b/dlls/winemac.drv/cocoa_window.m
@@ -44,6 +44,16 @@ enum {
 #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 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
     - (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 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
             }
             [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 2304f771bfa..5c19b4f4e81 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -538,6 +538,7 @@ struct macdrv_window_features {
     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 6d735bb4ed2..4f3dbc08311 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;




More information about the wine-cvs mailing list