qt: Clean up foreground window code
authorAndre Heinecke <aheinecke@intevation.de>
Wed, 28 Feb 2018 11:05:02 +0000 (12:05 +0100)
committerAndre Heinecke <aheinecke@intevation.de>
Wed, 28 Feb 2018 11:05:02 +0000 (12:05 +0100)
* qt/main.cpp (ForeignWidget): Remove. This did nothing
with Qt 5.
(setup_foreground_window): New helper to set parent and
window flags.
(qt_cmd_handler): Use setup_foreground_window.
* qt/pinentrydialog.cpp: Disable Windows API hacks.

--
This should hopefully work a bit cleaner then the old code.
Setting us as transient to the Desktop is the same what
Gtk 2 does.

qt/main.cpp
qt/pinentryconfirm.cpp
qt/pinentrydialog.cpp

index 70a009d..f236781 100644 (file)
 #include "pinentrydialog.h"
 #include "pinentry.h"
 
-#include <qapplication.h>
+#include <QApplication>
+#include <QDebug>
 #include <QIcon>
-#include <QString>
-#include <qwidget.h>
-#include <qmessagebox.h>
+#include <QMessageBox>
 #include <QPushButton>
+#include <QString>
+#include <QWidget>
+#include <QWindow>
 
 #include <stdio.h>
 #include <stdlib.h>
   #endif
 #endif
 
+#ifdef Q_OS_WIN
+#include <windows.h>
+#endif
+
 static QString escape_accel(const QString &s)
 {
 
@@ -97,22 +103,6 @@ static QString escape_accel(const QString &s)
     return result;
 }
 
-/* Hack for creating a QWidget with a "foreign" window ID */
-class ForeignWidget : public QWidget
-{
-public:
-    explicit ForeignWidget(WId wid) : QWidget(0)
-    {
-        QWidget::destroy();
-        create(wid, false, false);
-    }
-
-    ~ForeignWidget()
-    {
-        destroy(false, false);
-    }
-};
-
 namespace
 {
 class InvalidUtf8 : public std::invalid_argument
@@ -139,17 +129,44 @@ static QString from_utf8(const char *s)
     return result;
 }
 
+static void
+setup_foreground_window(QWidget *widget, WId parentWid)
+{
+    /* For windows set the desktop window as the transient parent */
+    QWindow *parentWindow = nullptr;
+    if (parentWid) {
+        parentWindow = QWindow::fromWinId(parentWid);
+    }
+#ifdef Q_OS_WIN
+    if (!parentWindow) {
+        HWND desktop = GetDesktopWindow();
+        if (desktop) {
+            parentWindow = QWindow::fromWinId((WId) desktop);
+        }
+    }
+#endif
+    if (parentWindow) {
+        // Ensure that we have a native wid
+        widget->winId();
+        QWindow *wndHandle = widget->windowHandle();
+
+        if (wndHandle) {
+            wndHandle->setTransientParent(parentWindow);
+        }
+    }
+    widget->setWindowFlags(Qt::Window |
+                           Qt::CustomizeWindowHint |
+                           Qt::WindowTitleHint |
+                           Qt::WindowCloseButtonHint |
+                           Qt::WindowStaysOnTopHint |
+                           Qt::WindowMinimizeButtonHint);
+}
+
 static int
 qt_cmd_handler(pinentry_t pe)
 {
-    QWidget *parent = 0;
     char *str;
 
-    /* FIXME: Add parent window ID to pinentry and GTK.  */
-    if (pe->parent_wid) {
-        parent = new ForeignWidget((WId) pe->parent_wid);
-    }
-
     int want_pass = !!pe->pin;
 
     const QString ok =
@@ -184,9 +201,9 @@ qt_cmd_handler(pinentry_t pe)
     if (want_pass) {
         char *str;
 
-        PinEntryDialog pinentry(parent, 0, pe->timeout, true, !!pe->quality_bar,
+        PinEntryDialog pinentry(nullptr, 0, pe->timeout, true, !!pe->quality_bar,
                                 repeatString, visibilityTT, hideTT);
-
+        setup_foreground_window(&pinentry, pe->parent_wid);
         pinentry.setPinentryInfo(pe);
         pinentry.setPrompt(escape_accel(from_utf8(pe->prompt)));
         pinentry.setDescription(from_utf8(pe->description));
@@ -247,7 +264,8 @@ qt_cmd_handler(pinentry_t pe)
             pe->notok      ? QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel :
             /* else */       QMessageBox::Ok | QMessageBox::Cancel ;
 
-        PinentryConfirm box(QMessageBox::Information, pe->timeout, title, desc, buttons, parent);
+        PinentryConfirm box(QMessageBox::Information, pe->timeout, title, desc, buttons, nullptr);
+        setup_foreground_window(&box, pe->parent_wid);
 
         const struct {
             QMessageBox::StandardButton button;
@@ -274,7 +292,7 @@ qt_cmd_handler(pinentry_t pe)
         }
 
         box.show();
-        raiseWindow(&box);
+        box.raise();
 
         const int rc = box.exec();
 
index 65b191c..e549e10 100644 (file)
@@ -38,7 +38,7 @@ PinentryConfirm::PinentryConfirm(Icon icon, int timeout, const QString &title,
     setAccessibleDescription(desc);
     setAccessibleName(title);
 #endif
-    raiseWindow(this);
+    raise();
 }
 
 bool PinentryConfirm::timedOut() const
@@ -61,7 +61,7 @@ void PinentryConfirm::showEvent(QShowEvent *event)
     }
 
     QDialog::showEvent(event);
-    raiseWindow(this);
+    raise();
 }
 
 void PinentryConfirm::slotTimeout()
index cb52d7c..9bff8d2 100644 (file)
@@ -41,6 +41,7 @@
 #include <windows.h>
 #endif
 
+#if 0
 /* I [wk] have no idea for what this code was supposed to do.
    Foregrounding a window is heavily restricted by modern Windows
    versions.  This is the reason why gpg-agent employs its
    a Window is so restricted that it AllowSetForegroundWindow
    does not always work (e.g. when the ForegroundWindow timeout
    has not expired.
+
+   [ah 2018-02-28] Disabled this again in favor of using
+   windows stays on top hint. The code that is in main
+   setup_foreground_window.
    */
 #ifdef Q_OS_WIN
 WINBOOL SetForegroundWindowEx(HWND hWnd)
@@ -103,6 +108,8 @@ void raiseWindow(QWidget *w)
 #endif
 }
 
+#endif
+
 QPixmap icon(QStyle::StandardPixmap which)
 {
     QPixmap pm = qApp->windowIcon().pixmap(48, 48);
@@ -129,7 +136,7 @@ PinEntryDialog::PinEntryDialog(QWidget *parent, const char *name,
                                const QString &repeatString,
                                const QString &visibilityTT,
                                const QString &hideTT)
-    : QDialog(parent, Qt::WindowStaysOnTopHint),
+    : QDialog(parent),
       mRepeat(NULL),
       _grabbed(false),
       mVisibilityTT(visibilityTT),
@@ -138,7 +145,6 @@ PinEntryDialog::PinEntryDialog(QWidget *parent, const char *name,
       mVisiCB(NULL)
 {
     _timed_out = false;
-    setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
 
     if (modal) {
         setWindowModality(Qt::ApplicationModal);
@@ -260,7 +266,7 @@ PinEntryDialog::PinEntryDialog(QWidget *parent, const char *name,
 void PinEntryDialog::showEvent(QShowEvent *event)
 {
     QDialog::showEvent(event);
-    raiseWindow(this);
+    raise();
 }
 
 void PinEntryDialog::setDescription(const QString &txt)