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@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
+@interface NSWindow (PrivatePreventsActivation) + +/* Needed to ensure proper behavior after adding or removing + * NSWindowStyleMaskNonactivatingPanel. + * Available since at least macOS 10.6. */ +- (void)_setPreventsActivation:(BOOL)flag; + +@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;