mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-05 18:01:34 +00:00
winemac.drv: Hide app's dock icon when it wouldn't have a taskbar item on Windows.
Hide the icon when an app has no visible windows, or when all of its visible windows would have no taskbar entry (i.e., they are owned or have WS_EX_TOOLWINDOW or WS_EX_NOACTIVATE, but not WS_EX_APPWINDOW). The dock icon returns if those conditions are no longer satisfied. This behavior is behind a Mac Driver registry key, EagerDockIconHiding (defaulting to true), to allow toggling it on a per-app or global basis.
This commit is contained in:
parent
d6e39da995
commit
f0efb2e46a
7 changed files with 112 additions and 2 deletions
|
@ -157,6 +157,7 @@ - (void) noteKey:(uint16_t)keyCode pressed:(BOOL)pressed;
|
|||
|
||||
- (void) window:(WineWindow*)window isBeingDragged:(BOOL)dragged;
|
||||
- (void) windowWillOrderOut:(WineWindow*)window;
|
||||
- (void) maybeHideDockIconDueToWindowOrderingOut:(NSWindow *)window;
|
||||
|
||||
- (void) flipRect:(NSRect*)rect;
|
||||
- (NSPoint) flippedMouseLocation:(NSPoint)point;
|
||||
|
|
|
@ -1300,6 +1300,78 @@ - (void) window:(WineWindow*)window isBeingDragged:(BOOL)dragged
|
|||
[windowsBeingDragged removeObject:window];
|
||||
}
|
||||
|
||||
/* Checks if, discounting the given window, there are any visible windows
|
||||
that should make the app have a dock icon. window may be nil. anyVisible
|
||||
will be set to reflect whether any window other than the given one is
|
||||
visible. */
|
||||
- (BOOL) shouldHaveDockIconAfterWindowOrdersOut:(NSWindow *)window
|
||||
anyWindowIsVisible:(BOOL *)anyVisible
|
||||
{
|
||||
BOOL foundVisibleWindow = NO;
|
||||
|
||||
if (!eager_dock_icon_hiding)
|
||||
return YES;
|
||||
|
||||
for (NSWindow *w in [NSApp windows])
|
||||
{
|
||||
if (w != window && (w.isVisible || w.isMiniaturized))
|
||||
{
|
||||
foundVisibleWindow = YES;
|
||||
|
||||
if ([w isKindOfClass:[WineWindow class]] && !((WineWindow *)w).needsDockIcon)
|
||||
continue;
|
||||
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
if (anyVisible)
|
||||
*anyVisible = foundVisibleWindow;
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
/* If there are no visible windows that should make the app have a dock icon
|
||||
(other than the provided one), hides the dock icon. window may be nil. */
|
||||
- (void) maybeHideDockIconDueToWindowOrderingOut:(NSWindow *)window
|
||||
{
|
||||
BOOL anyVisibleWindows;
|
||||
static int isMontereyOrLater = -1;
|
||||
|
||||
if (isMontereyOrLater == -1)
|
||||
{
|
||||
isMontereyOrLater = 0;
|
||||
if ([NSProcessInfo instancesRespondToSelector:@selector(isOperatingSystemAtLeastVersion:)])
|
||||
{
|
||||
NSOperatingSystemVersion requiredVersion = { 12, 0, 0 };
|
||||
isMontereyOrLater = [[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:requiredVersion];
|
||||
}
|
||||
}
|
||||
|
||||
if (!eager_dock_icon_hiding)
|
||||
return;
|
||||
|
||||
if (window &&
|
||||
((!window.isVisible && !window.isMiniaturized) ||
|
||||
([window isKindOfClass:[WineWindow class]] && !((WineWindow *)window).needsDockIcon)))
|
||||
{
|
||||
/* Nothing to do; that window couldn't have changed anything. */
|
||||
return;
|
||||
}
|
||||
|
||||
if ([NSApp activationPolicy] == NSApplicationActivationPolicyRegular &&
|
||||
![self shouldHaveDockIconAfterWindowOrdersOut:window
|
||||
anyWindowIsVisible:&anyVisibleWindows])
|
||||
{
|
||||
/* Before macOS 12 Monterey, hiding the dock icon while there are
|
||||
visible windows makes those windows disappear until they are
|
||||
programmatically ordered back in. So we don't do that transition
|
||||
(which should be rather uncommon) on older OSes. */
|
||||
if (isMontereyOrLater || !anyVisibleWindows)
|
||||
NSApp.activationPolicy = NSApplicationActivationPolicyAccessory;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) windowWillOrderOut:(WineWindow*)window
|
||||
{
|
||||
if ([windowsBeingDragged containsObject:window])
|
||||
|
@ -1310,6 +1382,8 @@ - (void) windowWillOrderOut:(WineWindow*)window
|
|||
[window.queue postEvent:event];
|
||||
macdrv_release_event(event);
|
||||
}
|
||||
|
||||
[self maybeHideDockIconDueToWindowOrderingOut:window];
|
||||
}
|
||||
|
||||
- (BOOL) isAnyWineWindowVisible
|
||||
|
|
|
@ -29,6 +29,7 @@ @interface WineWindow : NSPanel <NSWindowDelegate>
|
|||
BOOL disabled;
|
||||
BOOL noForeground;
|
||||
BOOL preventsAppActivation;
|
||||
BOOL needsDockIcon;
|
||||
BOOL floating;
|
||||
BOOL resizable;
|
||||
BOOL maximized;
|
||||
|
@ -93,6 +94,7 @@ @interface WineWindow : NSPanel <NSWindowDelegate>
|
|||
@property (readonly, nonatomic) BOOL disabled;
|
||||
@property (readonly, nonatomic) BOOL noForeground;
|
||||
@property (readonly, nonatomic) BOOL preventsAppActivation;
|
||||
@property (readonly, nonatomic) BOOL needsDockIcon;
|
||||
@property (readonly, nonatomic) BOOL floating;
|
||||
@property (readonly, getter=isFullscreen, nonatomic) BOOL fullscreen;
|
||||
@property (readonly, getter=isFakingClose, nonatomic) BOOL fakingClose;
|
||||
|
|
|
@ -1009,6 +1009,7 @@ @implementation WineWindow
|
|||
@synthesize colorKeyed, colorKeyRed, colorKeyGreen, colorKeyBlue;
|
||||
@synthesize usePerPixelAlpha;
|
||||
@synthesize himc, commandDone;
|
||||
@synthesize needsDockIcon;
|
||||
|
||||
+ (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)wf
|
||||
windowFrame:(NSRect)window_frame
|
||||
|
@ -1048,6 +1049,7 @@ + (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)w
|
|||
window->savedContentMaxSize = NSMakeSize(FLT_MAX, FLT_MAX);
|
||||
window->resizable = wf->resizable;
|
||||
window->_lastDisplayTime = [[NSDate distantPast] timeIntervalSinceReferenceDate];
|
||||
window->needsDockIcon = wf->dock_icon;
|
||||
|
||||
[window registerForDraggedTypes:@[(NSString*)kUTTypeData, (NSString*)kUTTypeContent]];
|
||||
|
||||
|
@ -1183,6 +1185,7 @@ - (void) setWindowFeatures:(const struct macdrv_window_features*)wf
|
|||
NSWindowStyleMaskNonactivatingPanel;
|
||||
NSUInteger currentStyle = [self styleMask];
|
||||
NSUInteger newStyle = style_mask_for_features(wf) | (currentStyle & ~usedStyles);
|
||||
int neededDockIcon;
|
||||
|
||||
self.preventsAppActivation = wf->prevents_app_activation;
|
||||
|
||||
|
@ -1227,6 +1230,17 @@ - (void) setWindowFeatures:(const struct macdrv_window_features*)wf
|
|||
resizable = wf->resizable;
|
||||
[self adjustFeaturesForState];
|
||||
[self setHasShadow:wf->shadow];
|
||||
|
||||
// We may need to hide or show our dock icon in response to changes.
|
||||
neededDockIcon = needsDockIcon;
|
||||
needsDockIcon = wf->dock_icon; // Need to update this before calling maybeHideDockIcon
|
||||
if ([self isOrderedIn])
|
||||
{
|
||||
if (neededDockIcon && !needsDockIcon)
|
||||
[[WineApplicationController sharedController] maybeHideDockIconDueToWindowOrderingOut:nil];
|
||||
else if(!neededDockIcon && needsDockIcon)
|
||||
[[WineApplicationController sharedController] transformProcessToForeground:!self.preventsAppActivation];
|
||||
}
|
||||
}
|
||||
|
||||
// Indicates if the window would be visible if the app were not hidden.
|
||||
|
@ -1739,7 +1753,9 @@ - (void) orderBelow:(WineWindow*)prev orAbove:(WineWindow*)next activate:(BOOL)a
|
|||
WineWindow* parent;
|
||||
WineWindow* child;
|
||||
|
||||
[controller transformProcessToForeground:!self.preventsAppActivation];
|
||||
if (!eager_dock_icon_hiding || self.needsDockIcon)
|
||||
[controller transformProcessToForeground:!self.preventsAppActivation];
|
||||
|
||||
if ([NSApp isHidden])
|
||||
[NSApp unhide:nil];
|
||||
wasVisible = [self isVisible];
|
||||
|
@ -2110,7 +2126,10 @@ - (void) makeFocused:(BOOL)activate
|
|||
if (activate)
|
||||
{
|
||||
WineApplicationController *controller = [WineApplicationController sharedController];
|
||||
[controller transformProcessToForeground:YES];
|
||||
|
||||
if (!eager_dock_icon_hiding || self.needsDockIcon)
|
||||
[controller transformProcessToForeground:YES];
|
||||
|
||||
[controller tryToActivateIgnoringOtherApps:YES];
|
||||
}
|
||||
|
||||
|
|
|
@ -158,6 +158,7 @@
|
|||
extern int retina_enabled; /* Whether Retina mode is enabled via registry setting. */
|
||||
extern int retina_on; /* Whether Retina mode is currently active (enabled and display is in default mode). */
|
||||
extern int enable_app_nap;
|
||||
extern int eager_dock_icon_hiding;
|
||||
|
||||
static inline CGRect cgrect_mac_from_win(CGRect rect)
|
||||
{
|
||||
|
@ -521,6 +522,7 @@ extern int macdrv_register_hot_key(macdrv_event_queue q, unsigned int vkey, unsi
|
|||
unsigned int utility:1;
|
||||
unsigned int shadow:1;
|
||||
unsigned int prevents_app_activation:1;
|
||||
unsigned int dock_icon:1;
|
||||
};
|
||||
|
||||
struct macdrv_window_state {
|
||||
|
|
|
@ -60,6 +60,7 @@ int use_precise_scrolling = TRUE;
|
|||
int gl_surface_mode = GL_SURFACE_IN_FRONT_OPAQUE;
|
||||
int retina_enabled = FALSE;
|
||||
int enable_app_nap = FALSE;
|
||||
int eager_dock_icon_hiding = TRUE;
|
||||
|
||||
CFDictionaryRef localized_strings;
|
||||
|
||||
|
@ -378,6 +379,9 @@ static void setup_options(void)
|
|||
if (!get_config_key(hkey, appkey, "EnableAppNap", buffer, sizeof(buffer)))
|
||||
enable_app_nap = IS_OPTION_TRUE(buffer[0]);
|
||||
|
||||
if (!get_config_key(hkey, appkey, "EagerDockIconHiding", buffer, sizeof(buffer)))
|
||||
eager_dock_icon_hiding = IS_OPTION_TRUE(buffer[0]);
|
||||
|
||||
/* Don't use appkey. The DPI and monitor sizes should be consistent for all
|
||||
processes in the prefix. */
|
||||
if (!get_config_key(hkey, NULL, "RetinaMode", buffer, sizeof(buffer)))
|
||||
|
|
|
@ -59,6 +59,14 @@ static void get_cocoa_window_features(struct macdrv_win_data *data,
|
|||
|
||||
if (ex_style & WS_EX_NOACTIVATE) wf->prevents_app_activation = TRUE;
|
||||
|
||||
/* The dock_icon flag is only relevant when the window is visible, so we
|
||||
don't need to worry about any other styles or the window rect. */
|
||||
if (NtUserGetWindowRelative(data->hwnd, GW_OWNER))
|
||||
wf->dock_icon = FALSE;
|
||||
else
|
||||
wf->dock_icon = (ex_style & WS_EX_APPWINDOW) ||
|
||||
((ex_style & (WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE)) == 0);
|
||||
|
||||
if (disable_window_decorations) return;
|
||||
if (IsRectEmpty(window_rect)) return;
|
||||
if (EqualRect(window_rect, client_rect)) return;
|
||||
|
|
Loading…
Reference in a new issue