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@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Tim Clem 2022-01-19 11:13:44 -08:00 committed by Alexandre Julliard
parent 4b4ebef412
commit e58b1a2b39
3 changed files with 28 additions and 1 deletions

View File

@ -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])

View File

@ -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 {

View File

@ -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;