Skip to content

Fix problems with the hide/restore functionality on the tray icon (issue #1595) (redone)#1703

Merged
TheZ3ro merged 6 commits intokeepassxreboot:release/2.3.2from
joanbm:release/2.3.2
Mar 12, 2018
Merged

Fix problems with the hide/restore functionality on the tray icon (issue #1595) (redone)#1703
TheZ3ro merged 6 commits intokeepassxreboot:release/2.3.2from
joanbm:release/2.3.2

Conversation

@joanbm
Copy link
Copy Markdown
Contributor

@joanbm joanbm commented Mar 11, 2018

Opening another PR since PR #1700 had the wrong source branch. Sorry for the annoyance...

Fix/work around tray issues on some Linux systems such as Arch Linux, and Windows. Fixes all cases explained in issue #1595.

Description

Basically there are two separate issues at play there:

  • The Linux issue: Sometimes instead of restoring, the KeePassXC window just flickers when restoring the window from the tray. This mostly happens if both the "minimize to tray" and "minimize at startup" options are enabled, and only on the first restore, though sometimes it's enough to set the "minimize to tray" option is enough and the flicker happens once per every restore, thus the tray having a flicker-restore-hide cycle instead of a restore-hide cycle. I'm not sure why it only happens on Arch but not on Ubuntu, and why it only happens sometimes, but I have found what seems to be the trigger of the issue: If one both minimizes and hides the window by code (or minimizes the window without showing it at all), it seems that a spurious changeEvent with isMinimized()=true is received sometimes when the main window is restored, which causes the bug. I imagine that, internally on the Qt Linux implementation, hiding the window causes further events to be enqueued or something similar, and when restoring the window some events from when the window was minimized are notified.

This can happen both on start (this is the case of the original bug report), if minimizeOnStartup=true and minimizeToTray=true, then the window is minimized but not shown:

    // start minimized if configured
    bool minimizeOnStartup = config()->get("GUI/MinimizeOnStartup").toBool();
    bool minimizeToTray    = config()->get("GUI/MinimizeToTray").toBool();
    if (minimizeOnStartup) {
        mainWindow.setWindowState(Qt::WindowMinimized); // --> MINIMIZE
    }
    if (!(minimizeOnStartup && minimizeToTray)) {
        mainWindow.show(); // --> NO SHOW
}

Or when clicking on the tray icon to hide the window, the window is both minimized and hidden by code on hideWindow() (this is what is causing my flicker-restore-minimize cycle sometimes):

void MainWindow::hideWindow()
{
    saveWindowInformation();
#ifndef Q_OS_MAC
    setWindowState(windowState() | Qt::WindowMinimized); // --> MINIMIZE
#endif
    QTimer::singleShot(0, this, SLOT(hide())); // --> HIDE

    if (config()->get("security/lockdatabaseminimize").toBool()) {
        m_ui->tabWidget->lockDatabases();
    }
}
  • The Windows issue: This is a completely separate issue. The flicker on restore issue explained previously doesn't happen on Windows, but on the other hand it seems impossible to hide the window by clicking on the tray icon on Windows. On toggleWindow(), there's a QApplication::activeWindow() == this check:
void MainWindow::toggleWindow()
{
    if ((QApplication::activeWindow() == this) && isVisible() && !isMinimized()) {
        hideWindow();
    } else {

On Windows, when clicking on the tray icon when the window is visible, QApplication::activeWindow() = NULL. I think this is due to differences in window focus behavior between Windows and Linux (I believe Windows removes the focus from the window when clicking on the tray).

Motivation and context

This change is required in order to avoid issues when hiding and restoring the KeePassXC windows from tray. One of those issues happen on Windows, and the other in some Linux systems (what exactly causes some systems and desktop environments to be affected and some not to be affected is not known, though it probably depends on the Qt version, but must also depend on some environment condition since on my system the bug only happens sometimes).

For the Linux issue, I avoid both minimizing and hiding the window at the same time by code. It should suffice to only hide the window if the event is caused by a tray icon click.

For the Windows issue, I just removed the check for QApplication::activeWindow() == this, I think it is unreliable and the other checks in the same line (which were added later) should suffice alone.

Fixes #1595

How has this been tested?

I set up some VMs for manual testing of the issue, and I found this:

  • Local Arch Linux + XFCE (Updated): I experience the flicker-restore-minimize cycle sometimes, and sometimes only the flicker on the first time like in the original report. No idea on what makes the difference. After applying the changes, the bug disappears and no regressions are found.

Environment details:

Libraries:
- Qt 5.10.1
- libgcrypt 1.8.2

Operating system: Arch Linux
CPU architecture: x86_64
Kernel: linux 4.15.7-1-ARCH

Enabled extensions:
- Auto-Type
- Browser Integration
- Legacy Browser Integration (KeePassHTTP)
- SSH Agent
- YubiKey
  • Local Arch Linux + LXDE (Updated): I experience the flicker like in the original report. After applying the changes, the bug disappears and no regressions are found.
  • VM Ubuntu 17.10 + Unity,KDE,LXDE (Updated clean install): No bug experienced. After applying the changes, no regressions are found.
  • VM Arch Linux + LXDE (Updated clean install): I experience the flicker like in the original report. After applying the changes, the bug disappears and no regressions are found.
  • Local Windows 10 (Updated): No flicker on restore, but the window cannot be hidden by clicking on the tray icon. After applying the changes, the bug disappears and no regressions are found.
  • VM Windows 7 (Updated clean install): No flicker on restore, but the window cannot be hidden by clicking on the tray icon. After applying the changes, the bug disappears and no regressions are found.

I also ran all the automatic tests on my local Arch Linux system and they passed.

Screenshots (if appropriate):

Windows issue: https://imgur.com/fJW62v7
Linux issue (flicker on first restore): https://imgur.com/cES8olj

Types of changes

  • ✅ Bug fix (non-breaking change which fixes an issue)

Checklist:

  • ✅ I have read the CONTRIBUTING document. [REQUIRED]
  • ✅ My code follows the code style of this project. [REQUIRED]
  • ✅ All new and existing tests passed. [REQUIRED]
  • ✅ I have compiled and verified my code with -DWITH_ASAN=ON. [REQUIRED]

@droidmonkey
Copy link
Copy Markdown
Member

Builds are failing

@joanbm
Copy link
Copy Markdown
Contributor Author

joanbm commented Mar 11, 2018

@droidmonkey They work on my Linux and Windows machines... not sure what's different in the CI environment.

PS: I have also noticed that there's a slight code style problem in the test, will fix.

EDIT: Think I may have found it...

@joanbm
Copy link
Copy Markdown
Contributor Author

joanbm commented Mar 11, 2018

Fixed, looks like the CI environment has no tray and therefore the tray icon can't be tested there, so it is now skipped.

Copy link
Copy Markdown
Member

@droidmonkey droidmonkey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@weslly did you confirm that this doesn't impact functionality on MacOS?

void MainWindow::hideWindow()
{
saveWindowInformation();
#ifndef Q_OS_MAC
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove this guard for MacOS?

Copy link
Copy Markdown
Contributor Author

@joanbm joanbm Mar 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch... @phoerious said in issue #1595 that isn't probably an ancient code from the time Mac didn't have a tray icon, and I remember doing a git blame, but it looks like I misread it, because it's rather the opposite... it was introduced in 8d6db27 when the tray icon on Mac was introduced... I will add it again, along with a TODO asking for further comments.


void MainWindow::toggleWindow()
{
if ((QApplication::activeWindow() == this) && isVisible() && !isMinimized()) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm afraid this will cause undesirable effects on MacOS

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@droidmonkey Can you elaborate? A priori I can't see it causing problems, since it looks like an old check (it was there before the other two conditions were implemented), it works on Windows and Linux, and it wasn't added specifically for Mac, though it would be nice for someone to check.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just saying that we edited it and thoroughly tested on Linux and Windows but not Mac. What I meant to say is "this needs to be tested on Mac to ensure no undesirable effects"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@droidmonkey I tested yesterday and saw no problems toggling the window from the tray icon on Mac.

@weslly
Copy link
Copy Markdown
Contributor

weslly commented Mar 11, 2018

I just noticed the "minimize on start" option doesn't work at all on macOS with or without this PR.

@TheZ3ro
Copy link
Copy Markdown
Contributor

TheZ3ro commented Mar 12, 2018

@weslly I think we can fix the mac minimize on start in a new PR

@joanbm please rebase

joanbm added 6 commits March 12, 2018 19:51
Fix/work around KeePassXC flickering and not restoring from tray on some Linux systems, which happens if the window is hidden and minimized by code at the same time (see issue #1595).
Fix unreliable check on toggleWindow() which causes Windows systems to be unable to hide the window by clicking on the tray icon (see issue #1595).
Add again the wrongly removed conditional macro for Mac, along with a TODO asking for further documentation on its significance.
@joanbm
Copy link
Copy Markdown
Contributor Author

joanbm commented Mar 12, 2018

@TheZ3ro Done, all commits in release/2.3.2 are now in my fork.

@TheZ3ro
Copy link
Copy Markdown
Contributor

TheZ3ro commented Mar 12, 2018

Thanks fot the contribution! 🎉

@TheZ3ro TheZ3ro merged commit 970cedf into keepassxreboot:release/2.3.2 Mar 12, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants