author | Antonio Rojas
<arojas@archlinux.org> 2015-09-30 19:28:53 UTC |
committer | Antonio Rojas
<arojas@archlinux.org> 2015-09-30 19:28:53 UTC |
parent | 1debaecc4dbd62d5765276f227d1b071c296da35 |
PKGBUILD | +8 | -3 |
bug350758.patch | +245 | -0 |
diff --git a/PKGBUILD b/PKGBUILD index 58d9bd1..46b9e62 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -3,7 +3,7 @@ pkgname=frameworkintegration pkgver=5.14.0 -pkgrel=1 +pkgrel=2 pkgdesc='Framework providing components to allow applications to integrate with a KDE Workspace' arch=('i686' 'x86_64') url='https://projects.kde.org/projects/frameworks/frameworkintegration' @@ -11,11 +11,16 @@ license=('LGPL') depends=('kio' 'ttf-oxygen' 'libxcursor') makedepends=('extra-cmake-modules') groups=('kf5') -source=("http://download.kde.org/stable/frameworks/${pkgver%.*}/${pkgname}-${pkgver}.tar.xz") -md5sums=('d5094cba8ca4d280d6e817d334fb2dc1') +source=("http://download.kde.org/stable/frameworks/${pkgver%.*}/${pkgname}-${pkgver}.tar.xz" bug350758.patch) +md5sums=('d5094cba8ca4d280d6e817d334fb2dc1' + '83e03a5a5f79de524e290b691efbbd77') prepare() { mkdir -p build + +# Fix file dialogs sometimes freezing applications https://bugs.kde.org/show_bug.cgi?id=350758 + cd $pkgname-$pkgver + patch -p1 -i ../bug350758.patch } build() { diff --git a/bug350758.patch b/bug350758.patch new file mode 100644 index 0000000..357bf76 --- /dev/null +++ b/bug350758.patch @@ -0,0 +1,245 @@ +From 6ae74671ca68e9444db618207d662ad5d1c16f31 Mon Sep 17 00:00:00 2001 +From: Weng Xuetian <wengxt@gmail.com> +Date: Wed, 30 Sep 2015 10:40:35 -0700 +Subject: [PATCH] Fix random file dialog not showing up problem. + +When using QDialog to implement QPlatformDialog there will be a issue, +that QDialog will use a dummy invisible to make Qt aware that a modal +dialog exists. But for our usecase, this invisible dialog will show up +after our own qdialog and cause our dialog not accept any input. + +The original workaround is to hide our dialog and show it again, but +this will hit QTBUG-48248 and our dialog will not show up at all +randomly. To avoid this, we delegate the call to show() on our +QDialog with a timer. + +BUG: 350758 +REVIEW: 125208 +--- + autotests/kfiledialog_unittest.cpp | 10 +++++++ + autotests/kfiledialogqml_unittest.cpp | 4 +++ + src/platformtheme/kdeplatformfiledialogbase.cpp | 16 ++++++++++- + src/platformtheme/kdeplatformfiledialogbase_p.h | 5 ++++ + src/platformtheme/kdeplatformfiledialoghelper.cpp | 35 +++++++++++++++-------- + src/platformtheme/kdeplatformfiledialoghelper.h | 1 + + 6 files changed, 58 insertions(+), 13 deletions(-) + +diff --git a/autotests/kfiledialog_unittest.cpp b/autotests/kfiledialog_unittest.cpp +index 0d4c816..6abd98a 100644 +--- a/autotests/kfiledialog_unittest.cpp ++++ b/autotests/kfiledialog_unittest.cpp +@@ -92,6 +92,8 @@ private Q_SLOTS: + + KFileWidget *fw = findFileWidget(); + QVERIFY(fw); ++ // real show() is delayed to next event. ++ QTest::qWaitForWindowExposed(fw->window()); + KDirOperator *op = fw->dirOperator(); + QCOMPARE(fileViewToString(op->viewMode()), fileViewToString(KFile::Tree)); + fw->setViewMode(KFile::Simple); +@@ -120,6 +122,8 @@ private Q_SLOTS: + + KFileWidget *fw = findFileWidget(); + QVERIFY(fw); ++ // real show() is delayed to next event. ++ QTest::qWaitForWindowExposed(fw->window()); + QCOMPARE(fw->isVisible(), true); + fw->slotCancel(); + } +@@ -133,6 +137,8 @@ private Q_SLOTS: + + KFileWidget *fw = findFileWidget(); + QVERIFY(fw); ++ // real show() is delayed to next event. ++ QTest::qWaitForWindowExposed(fw->window()); + QCOMPARE(fw->isVisible(), true); + fw->slotCancel(); + } +@@ -147,6 +153,8 @@ private Q_SLOTS: + + KFileWidget *fw = findFileWidget(); + QVERIFY(fw); ++ // real show() is delayed to next event. ++ QTest::qWaitForWindowExposed(fw->window()); + QCOMPARE(fw->isVisible(), true); + fw->slotCancel(); + } +@@ -160,6 +168,8 @@ private Q_SLOTS: + + KFileWidget *fw = findFileWidget(); + QVERIFY(fw); ++ // real show() is delayed to next event. ++ QTest::qWaitForWindowExposed(fw->window()); + QCOMPARE(fw->isVisible(), true); + fw->slotCancel(); + } +diff --git a/autotests/kfiledialogqml_unittest.cpp b/autotests/kfiledialogqml_unittest.cpp +index f805ef2..eb7dfc5 100644 +--- a/autotests/kfiledialogqml_unittest.cpp ++++ b/autotests/kfiledialogqml_unittest.cpp +@@ -48,6 +48,8 @@ private Q_SLOTS: + + fw = findFileWidget(); + QVERIFY(fw); ++ // real show() is delayed to next event. ++ QTest::qWaitForWindowExposed(fw->window()); + QCOMPARE(fw->isVisible(), true); + fw->slotCancel(); + } +@@ -65,6 +67,8 @@ private Q_SLOTS: + + fw = findFileWidget(); + QVERIFY(fw); ++ // real show() is delayed to next event. ++ QTest::qWaitForWindowExposed(fw->window()); + QCOMPARE(fw->isVisible(), true); + fw->slotCancel(); + } +diff --git a/src/platformtheme/kdeplatformfiledialogbase.cpp b/src/platformtheme/kdeplatformfiledialogbase.cpp +index 8e696bd..856c052 100644 +--- a/src/platformtheme/kdeplatformfiledialogbase.cpp ++++ b/src/platformtheme/kdeplatformfiledialogbase.cpp +@@ -22,6 +22,20 @@ + + KDEPlatformFileDialogBase::KDEPlatformFileDialogBase() + { ++ m_timer.setInterval(0); ++ m_timer.setSingleShot(true); ++ connect(&m_timer, &QTimer::timeout, this, &KDEPlatformFileDialogBase::show); ++} ++ ++void KDEPlatformFileDialogBase::delayedShow() ++{ ++ m_timer.start(); ++} ++ ++void KDEPlatformFileDialogBase::discardDelayedShow() ++{ ++ // this is used when hide() is called before timer triggers. ++ m_timer.stop(); + } + + void KDEPlatformFileDialogBase::closeEvent(QCloseEvent *e) +@@ -30,4 +44,4 @@ void KDEPlatformFileDialogBase::closeEvent(QCloseEvent *e) + QDialog::closeEvent(e); + } + +-#include "moc_kdeplatformfiledialogbase_p.cpp" +\ No newline at end of file ++#include "moc_kdeplatformfiledialogbase_p.cpp" +diff --git a/src/platformtheme/kdeplatformfiledialogbase_p.h b/src/platformtheme/kdeplatformfiledialogbase_p.h +index 5936dfb..3191027 100644 +--- a/src/platformtheme/kdeplatformfiledialogbase_p.h ++++ b/src/platformtheme/kdeplatformfiledialogbase_p.h +@@ -23,6 +23,7 @@ + + #include <QDialog> + #include <QUrl> ++#include <QTimer> + + class KFileWidget; + class QDialogButtonBox; +@@ -40,6 +41,9 @@ public: + virtual QString selectedNameFilter() = 0; + virtual QList<QUrl> selectedFiles() = 0; + ++ void delayedShow(); ++ void discardDelayedShow(); ++ + Q_SIGNALS: + void closed(); + void fileSelected(const QUrl &file); +@@ -51,6 +55,7 @@ Q_SIGNALS: + protected: + void closeEvent(QCloseEvent *e) Q_DECL_OVERRIDE; + QDialogButtonBox *m_buttons; ++ QTimer m_timer; + }; + + #endif +diff --git a/src/platformtheme/kdeplatformfiledialoghelper.cpp b/src/platformtheme/kdeplatformfiledialoghelper.cpp +index 94f2059..11e7efb 100644 +--- a/src/platformtheme/kdeplatformfiledialoghelper.cpp ++++ b/src/platformtheme/kdeplatformfiledialoghelper.cpp +@@ -37,7 +37,6 @@ + #include <QWindow> + + #include <QTextStream> +-#include <QEventLoop> + + namespace + { +@@ -281,19 +280,17 @@ void KDEPlatformFileDialogHelper::initializeDialog() + + void KDEPlatformFileDialogHelper::exec() + { +- m_dialog->hide(); // ensure dialog is not shown (exec would block input) +- m_dialog->winId(); // ensure there's a window created +- KSharedConfig::Ptr conf = KSharedConfig::openConfig(); +- KWindowConfig::restoreWindowSize(m_dialog->windowHandle(), conf->group("FileDialogSize")); +- // NOTICE: QWindow::setGeometry() does NOT impact the backing QWidget geometry even if the platform +- // window was created -> QTBUG-40584. We therefore copy the size here. +- // TODO: remove once this was resolved in QWidget QPA +- m_dialog->resize(m_dialog->windowHandle()->size()); ++ restoreSize(); ++ // KDEPlatformFileDialog::show() will always be called during QFileDialog::exec() ++ // discard the delayed show() it and use exec() and it will call show() for us. ++ // We can't hide and show it here because of https://bugreports.qt.io/browse/QTBUG-48248 ++ m_dialog->discardDelayedShow(); + m_dialog->exec(); + } + + void KDEPlatformFileDialogHelper::hide() + { ++ m_dialog->discardDelayedShow(); + m_dialog->hide(); + } + +@@ -304,15 +301,29 @@ void KDEPlatformFileDialogHelper::saveSize() + KWindowConfig::saveWindowSize(m_dialog->windowHandle(), group); + } + ++void KDEPlatformFileDialogHelper::restoreSize() ++{ ++ m_dialog->winId(); // ensure there's a window created ++ KSharedConfig::Ptr conf = KSharedConfig::openConfig(); ++ KWindowConfig::restoreWindowSize(m_dialog->windowHandle(), conf->group("FileDialogSize")); ++ // NOTICE: QWindow::setGeometry() does NOT impact the backing QWidget geometry even if the platform ++ // window was created -> QTBUG-40584. We therefore copy the size here. ++ // TODO: remove once this was resolved in QWidget QPA ++ m_dialog->resize(m_dialog->windowHandle()->size()); ++} ++ + bool KDEPlatformFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) + { + Q_UNUSED(parent) + initializeDialog(); + m_dialog->setWindowFlags(windowFlags); + m_dialog->setWindowModality(windowModality); +- m_dialog->show(); +- KSharedConfig::Ptr conf = KSharedConfig::openConfig(); +- KWindowConfig::restoreWindowSize(m_dialog->windowHandle(), conf->group("FileDialogSize")); ++ restoreSize(); ++ // Use a delayed show here to delay show() after the internal Qt invisible QDialog. ++ // The delayed call shouldn't matter, because for other "real" native QPlatformDialog ++ // implementation like Mac and Windows, the native dialog is not necessarily ++ // show up immediately. ++ m_dialog->delayedShow(); + return true; + } + +diff --git a/src/platformtheme/kdeplatformfiledialoghelper.h b/src/platformtheme/kdeplatformfiledialoghelper.h +index dfbbed1..f80b8c7 100644 +--- a/src/platformtheme/kdeplatformfiledialoghelper.h ++++ b/src/platformtheme/kdeplatformfiledialoghelper.h +@@ -74,6 +74,7 @@ private Q_SLOTS: + void saveSize(); + + private: ++ void restoreSize(); + KDEPlatformFileDialogBase *m_dialog; + }; + +-- +2.5.3 +