The previous behavior denies any attempt to focus such windows, which is not in line with how they behave on Windows.
Rename the macdrv_window_state no_activate field to no_foreground so it more accurately reflects its meaning.
Signed-off-by: Tim Clem tclem@codeweavers.com --- dlls/winemac.drv/cocoa_app.m | 2 +- dlls/winemac.drv/cocoa_window.h | 4 ++-- dlls/winemac.drv/cocoa_window.m | 14 +++++++------- dlls/winemac.drv/macdrv_cocoa.h | 2 +- dlls/winemac.drv/window.c | 14 +++++++------- 5 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_app.m b/dlls/winemac.drv/cocoa_app.m index 1bb752d20b78..16a773e14703 100644 --- a/dlls/winemac.drv/cocoa_app.m +++ b/dlls/winemac.drv/cocoa_app.m @@ -1864,7 +1864,7 @@ - (void) handleMouseButton:(NSEvent*)theEvent break; } } - if (!process && ![windowBroughtForward isKeyWindow] && !windowBroughtForward.disabled && !windowBroughtForward.noActivate) + if (!process && ![windowBroughtForward isKeyWindow] && !windowBroughtForward.disabled && !windowBroughtForward.noForeground) [self windowGotFocus:windowBroughtForward]; }
diff --git a/dlls/winemac.drv/cocoa_window.h b/dlls/winemac.drv/cocoa_window.h index 9a8bbb5e2557..c7bcaedfd970 100644 --- a/dlls/winemac.drv/cocoa_window.h +++ b/dlls/winemac.drv/cocoa_window.h @@ -27,7 +27,7 @@ @interface WineWindow : NSPanel <NSWindowDelegate> { BOOL disabled; - BOOL noActivate; + BOOL noForeground; BOOL floating; BOOL resizable; BOOL maximized; @@ -90,7 +90,7 @@ @interface WineWindow : NSPanel <NSWindowDelegate>
@property (retain, readonly, nonatomic) WineEventQueue* queue; @property (readonly, nonatomic) BOOL disabled; -@property (readonly, nonatomic) BOOL noActivate; +@property (readonly, nonatomic) BOOL noForeground; @property (readonly, nonatomic) BOOL floating; @property (readonly, getter=isFullscreen, nonatomic) BOOL fullscreen; @property (readonly, getter=isFakingClose, nonatomic) BOOL fakingClose; diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index 7708157a9924..2e15ec8ce721 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -378,7 +378,7 @@ - (WineMetalView*) newMetalViewWithDevice:(id<MTLDevice>)device; @interface WineWindow ()
@property (readwrite, nonatomic) BOOL disabled; -@property (readwrite, nonatomic) BOOL noActivate; +@property (readwrite, nonatomic) BOOL noForeground; @property (readwrite, nonatomic) BOOL floating; @property (readwrite, nonatomic) BOOL drawnSinceShown; @property (readwrite, nonatomic) BOOL closing; @@ -942,7 +942,7 @@ @implementation WineWindow
static WineWindow* causing_becomeKeyWindow;
- @synthesize disabled, noActivate, floating, fullscreen, fakingClose, closing, latentParentWindow, hwnd, queue; + @synthesize disabled, noForeground, floating, fullscreen, fakingClose, closing, latentParentWindow, hwnd, queue; @synthesize drawnSinceShown; @synthesize surface, surface_mutex; @synthesize shapeChangedSinceLastDraw; @@ -1232,7 +1232,7 @@ - (void) setMacDrvState:(const struct macdrv_window_state*)state NSWindowCollectionBehavior behavior;
self.disabled = state->disabled; - self.noActivate = state->no_activate; + self.noForeground = state->no_foreground;
if (self.floating != state->floating) { @@ -2338,7 +2338,7 @@ - (void) checkEmptyShaped - (BOOL) canBecomeKeyWindow { if (causing_becomeKeyWindow == self) return YES; - if (self.disabled || self.noActivate) return NO; + if (self.disabled || self.noForeground) return NO; if ([self isKeyWindow]) return YES;
// If a window's collectionBehavior says it participates in cycling, @@ -2406,7 +2406,7 @@ - (BOOL) validateMenuItem:(NSMenuItem *)menuItem BOOL ret = [super validateMenuItem:menuItem];
if ([menuItem action] == @selector(makeKeyAndOrderFront:)) - ret = [self isKeyWindow] || (!self.disabled && !self.noActivate); + ret = [self isKeyWindow] || (!self.disabled && !self.noForeground); if ([menuItem action] == @selector(toggleFullScreen:) && (self.disabled || maximized)) ret = NO;
@@ -2421,7 +2421,7 @@ - (void) makeKeyAndOrderFront:(id)sender [self orderBelow:nil orAbove:nil activate:NO]; [[self ancestorWineWindow] postBroughtForwardEvent];
- if (![self isKeyWindow] && !self.disabled && !self.noActivate) + if (![self isKeyWindow] && !self.disabled && !self.noForeground) [[WineApplicationController sharedController] windowGotFocus:self]; }
@@ -2815,7 +2815,7 @@ - (void)windowDidDeminiaturize:(NSNotification *)notification if (![self parentWindow]) [self postBroughtForwardEvent];
- if (!self.disabled && !self.noActivate) + if (!self.disabled && !self.noForeground) { causing_becomeKeyWindow = self; [self makeKeyWindow]; diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index 2c903bfb12a3..2304f771bfa3 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -542,7 +542,7 @@ extern int macdrv_register_hot_key(macdrv_event_queue q, unsigned int vkey, unsi
struct macdrv_window_state { unsigned int disabled:1; - unsigned int no_activate:1; + unsigned int no_foreground:1; unsigned int floating:1; unsigned int excluded_by_expose:1; unsigned int excluded_by_cycle:1; diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index 07f04993ee81..6d735bb4ed22 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -90,17 +90,17 @@ static void get_cocoa_window_features(struct macdrv_win_data *data,
/******************************************************************* - * can_activate_window + * can_window_become_foreground * - * Check if we can activate the specified window. + * Check if the specified window can become the foreground/key + * window. */ -static inline BOOL can_activate_window(HWND hwnd) +static inline BOOL can_window_become_foreground(HWND hwnd) { LONG style = GetWindowLongW(hwnd, GWL_STYLE);
if (!(style & WS_VISIBLE)) return FALSE; if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE; - if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_NOACTIVATE) return FALSE; if (hwnd == GetDesktopWindow()) return FALSE; return !(style & WS_DISABLED); } @@ -115,7 +115,7 @@ static void get_cocoa_window_state(struct macdrv_win_data *data, { memset(state, 0, sizeof(*state)); state->disabled = (style & WS_DISABLED) != 0; - state->no_activate = !can_activate_window(data->hwnd); + state->no_foreground = !can_window_become_foreground(data->hwnd); state->floating = (ex_style & WS_EX_TOPMOST) != 0; state->excluded_by_expose = state->excluded_by_cycle = (!(ex_style & WS_EX_APPWINDOW) && @@ -2347,7 +2347,7 @@ void macdrv_window_got_focus(HWND hwnd, const macdrv_event *event) hwnd, event->window, event->window_got_focus.serial, IsWindowEnabled(hwnd), IsWindowVisible(hwnd), style, GetFocus(), GetActiveWindow(), GetForegroundWindow());
- if (can_activate_window(hwnd) && !(style & WS_MINIMIZE)) + if (can_window_become_foreground(hwnd) && !(style & WS_MINIMIZE)) { /* simulate a mouse click on the menu to find out * whether the window wants to be activated */ @@ -2570,7 +2570,7 @@ void macdrv_window_drag_begin(HWND hwnd, const macdrv_event *event) data->drag_event = drag_event; release_win_data(data);
- if (!event->window_drag_begin.no_activate && can_activate_window(hwnd) && GetForegroundWindow() != hwnd) + if (!event->window_drag_begin.no_activate && can_window_become_foreground(hwnd) && GetForegroundWindow() != hwnd) { /* ask whether the window wants to be activated */ LRESULT ma = SendMessageW(hwnd, WM_MOUSEACTIVATE, (WPARAM)GetAncestor(hwnd, GA_ROOT),
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;
This matches the behavior on Windows.
Signed-off-by: Tim Clem tclem@codeweavers.com --- dlls/winemac.drv/cocoa_app.h | 2 +- dlls/winemac.drv/cocoa_app.m | 9 ++++++--- dlls/winemac.drv/cocoa_window.h | 2 ++ dlls/winemac.drv/cocoa_window.m | 9 ++++++--- 4 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_app.h b/dlls/winemac.drv/cocoa_app.h index 0b70a2fd55b5..0689c22ec32a 100644 --- a/dlls/winemac.drv/cocoa_app.h +++ b/dlls/winemac.drv/cocoa_app.h @@ -142,7 +142,7 @@ @interface WineApplicationController : NSObject <NSApplicationDelegate>
+ (WineApplicationController*) sharedController;
- - (void) transformProcessToForeground; + - (void) transformProcessToForeground:(BOOL)activateIfTransformed;
- (BOOL) registerEventQueue:(WineEventQueue*)queue; - (void) unregisterEventQueue:(WineEventQueue*)queue; diff --git a/dlls/winemac.drv/cocoa_app.m b/dlls/winemac.drv/cocoa_app.m index 16a773e14703..8b6a1779b840 100644 --- a/dlls/winemac.drv/cocoa_app.m +++ b/dlls/winemac.drv/cocoa_app.m @@ -237,7 +237,7 @@ - (void) dealloc [super dealloc]; }
- - (void) transformProcessToForeground + - (void) transformProcessToForeground:(BOOL)activateIfTransformed { if ([NSApp activationPolicy] != NSApplicationActivationPolicyRegular) { @@ -248,7 +248,10 @@ - (void) transformProcessToForeground NSMenuItem* item;
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; - [NSApp activateIgnoringOtherApps:YES]; + + if (activateIfTransformed) + [NSApp activateIgnoringOtherApps:YES]; + #if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 if (!enable_app_nap && [NSProcessInfo instancesRespondToSelector:@selector(beginActivityWithOptions:reason:)]) { @@ -884,7 +887,7 @@ - (BOOL) setMode:(CGDisplayModeRef)mode forDisplay:(CGDirectDisplayID)displayID if (!modes.count) return FALSE;
- [self transformProcessToForeground]; + [self transformProcessToForeground:YES];
BOOL active = [NSApp isActive];
diff --git a/dlls/winemac.drv/cocoa_window.h b/dlls/winemac.drv/cocoa_window.h index c7bcaedfd970..a83f2aa803b6 100644 --- a/dlls/winemac.drv/cocoa_window.h +++ b/dlls/winemac.drv/cocoa_window.h @@ -28,6 +28,7 @@ @interface WineWindow : NSPanel <NSWindowDelegate> { BOOL disabled; BOOL noForeground; + BOOL preventsAppActivation; BOOL floating; BOOL resizable; BOOL maximized; @@ -91,6 +92,7 @@ @interface WineWindow : NSPanel <NSWindowDelegate> @property (retain, readonly, nonatomic) WineEventQueue* queue; @property (readonly, nonatomic) BOOL disabled; @property (readonly, nonatomic) BOOL noForeground; +@property (readonly, nonatomic) BOOL preventsAppActivation; @property (readonly, nonatomic) BOOL floating; @property (readonly, getter=isFullscreen, nonatomic) BOOL fullscreen; @property (readonly, getter=isFakingClose, nonatomic) BOOL fakingClose; diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index 6301b47143ea..bfa7e2fe8cc2 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -391,6 +391,7 @@ @interface WineWindow ()
@property (readwrite, nonatomic) BOOL disabled; @property (readwrite, nonatomic) BOOL noForeground; +@property (readwrite, nonatomic) BOOL preventsAppActivation; @property (readwrite, nonatomic) BOOL floating; @property (readwrite, nonatomic) BOOL drawnSinceShown; @property (readwrite, nonatomic) BOOL closing; @@ -954,7 +955,7 @@ @implementation WineWindow
static WineWindow* causing_becomeKeyWindow;
- @synthesize disabled, noForeground, floating, fullscreen, fakingClose, closing, latentParentWindow, hwnd, queue; + @synthesize disabled, noForeground, preventsAppActivation, floating, fullscreen, fakingClose, closing, latentParentWindow, hwnd, queue; @synthesize drawnSinceShown; @synthesize surface, surface_mutex; @synthesize shapeChangedSinceLastDraw; @@ -1143,6 +1144,8 @@ - (void) setWindowFeatures:(const struct macdrv_window_features*)wf NSUInteger currentStyle = [self styleMask]; NSUInteger newStyle = style_mask_for_features(wf) | (currentStyle & ~usedStyles);
+ self.preventsAppActivation = wf->prevents_app_activation; + if (newStyle != currentStyle) { NSString* title = [[[self title] copy] autorelease]; @@ -1686,7 +1689,7 @@ - (void) orderBelow:(WineWindow*)prev orAbove:(WineWindow*)next activate:(BOOL)a WineWindow* parent; WineWindow* child;
- [controller transformProcessToForeground]; + [controller transformProcessToForeground:!self.preventsAppActivation]; if ([NSApp isHidden]) [NSApp unhide:nil]; wasVisible = [self isVisible]; @@ -2056,7 +2059,7 @@ - (void) makeFocused:(BOOL)activate { if (activate) { - [[WineApplicationController sharedController] transformProcessToForeground]; + [[WineApplicationController sharedController] transformProcessToForeground:YES]; [NSApp activateIgnoringOtherApps:YES]; }