[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