Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hide window and dock icon on macOS when tray enabled #4782

Merged
merged 1 commit into from
May 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 28 additions & 19 deletions src/gui/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1368,6 +1368,16 @@ void MainWindow::trayIconTriggered(QSystemTrayIcon::ActivationReason reason)

void MainWindow::processTrayIconTrigger()
{
#ifdef Q_OS_MACOS
// Do not toggle the window on macOS and just show the context menu instead.
// Right click detection doesn't seem to be working anyway
// and anything else will only trigger the context menu AND
// toggle the window at the same time, which is confusing at best.
// Showing only a context menu for tray icons seems to be best
// practice on macOS anyway, so this is probably fine.
return;
#endif

if (m_trayIconTriggerReason == QSystemTrayIcon::DoubleClick) {
// Always toggle window on double click
toggleWindow();
Expand All @@ -1379,7 +1389,7 @@ void MainWindow::processTrayIconTrigger()
// clicking the tray icon removes focus from main window.
if (isHidden() || (Clock::currentMilliSecondsSinceEpoch() - m_lastFocusOutTime) <= 500) {
#else
// If on Linux or macOS, check if the window has focus.
// If on Linux, check if the window has focus.
if (hasFocus() || isHidden() || windowHandle()->isActive()) {
#endif
toggleWindow();
Expand All @@ -1393,41 +1403,40 @@ void MainWindow::show()
{
#ifndef Q_OS_WIN
m_lastShowTime = Clock::currentMilliSecondsSinceEpoch();
#endif
#ifdef Q_OS_MACOS
// Unset minimize state to avoid weird fly-in effects
setWindowState(windowState() & ~Qt::WindowMinimized);
macUtils()->toggleForegroundApp(true);
#endif
QMainWindow::show();
}

bool MainWindow::shouldHide()
void MainWindow::hide()
{
#ifndef Q_OS_WIN
qint64 current_time = Clock::currentMilliSecondsSinceEpoch();

if (current_time - m_lastShowTime < 50) {
return false;
return;
}
#endif
return true;
}

void MainWindow::hide()
{
if (shouldHide()) {
QMainWindow::hide();
}
QMainWindow::hide();
#ifdef Q_OS_MACOS
macUtils()->toggleForegroundApp(false);
#endif
}

void MainWindow::hideWindow()
{
saveWindowInformation();
if (QGuiApplication::platformName() != "xcb") {
// In X11 the window should NOT be minimized and hidden (i.e. not
// shown) at the same time (which would happen if both minimize on
// startup and minimize to tray are set) since otherwise it causes
// problems on restore as seen on issue #1595. Hiding it is enough.
setWindowState(windowState() | Qt::WindowMinimized);
}

// Only hide if tray icon is active, otherwise window will be gone forever
if (isTrayIconEnabled()) {
// On X11, the window should NOT be minimized and hidden at the same time. See issue #1595.
// On macOS, we are skipping minimization as well to avoid playing the magic lamp animation.
if (QGuiApplication::platformName() != "xcb" && QGuiApplication::platformName() != "cocoa") {
setWindowState(windowState() | Qt::WindowMinimized);
}
hide();
} else {
showMinimized();
Expand Down
1 change: 0 additions & 1 deletion src/gui/MainWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ private slots:

static const QString BaseWindowTitle;

bool shouldHide();
void saveWindowInformation();
bool saveLastDatabases();
void updateTrayIcon();
Expand Down
1 change: 1 addition & 0 deletions src/gui/osutils/macutils/AppKit.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class AppKit : public QObject
bool isDarkMode();
bool enableAccessibility();
bool enableScreenRecording();
void toggleForegroundApp(bool foreground);

signals:
void lockDatabases();
Expand Down
1 change: 1 addition & 0 deletions src/gui/osutils/macutils/AppKitImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,6 @@
- (void) userSwitchHandler:(NSNotification*) notification;
- (bool) enableAccessibility;
- (bool) enableScreenRecording;
- (void) toggleForegroundApp:(bool) foreground;

@end
15 changes: 15 additions & 0 deletions src/gui/osutils/macutils/AppKitImpl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,16 @@ - (bool) enableScreenRecording
return YES;
}

- (void) toggleForegroundApp:(bool) foreground
{
ProcessSerialNumber psn = {0, kCurrentProcess};
if (foreground) {
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
} else {
TransformProcessType(&psn, kProcessTransformToUIElementApplication);
}
}

@end

//
Expand Down Expand Up @@ -215,3 +225,8 @@ - (bool) enableScreenRecording
{
return [static_cast<id>(self) enableScreenRecording];
}

void AppKit::toggleForegroundApp(bool foreground)
{
[static_cast<id>(self) toggleForegroundApp:foreground];
}
11 changes: 11 additions & 0 deletions src/gui/osutils/macutils/MacUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,14 @@ bool MacUtils::isCapslockEnabled()
{
return (CGEventSourceFlagsState(kCGEventSourceStateHIDSystemState) & kCGEventFlagMaskAlphaShift) != 0;
}

/**
* Toggle application state between foreground app and UIElement app.
* Foreground apps have dock icons, UIElement apps do not.
*
* @param foreground whether app is foreground app
*/
void MacUtils::toggleForegroundApp(bool foreground)
{
m_appkit->toggleForegroundApp(foreground);
}
1 change: 1 addition & 0 deletions src/gui/osutils/macutils/MacUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class MacUtils : public OSUtilsBase
bool isHidden();
bool enableAccessibility();
bool enableScreenRecording();
void toggleForegroundApp(bool foreground);

signals:
void lockDatabases();
Expand Down