From 236edae60b06808d0e835ebb4b2e1ccb28095b80 Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Sat, 12 Sep 2015 23:35:59 +0200 Subject: [PATCH 1/4] travis-ci: Backport OS X improvements from master. --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6e26860f1..fa33cf0a6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,11 +9,13 @@ install: - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq update; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq install cmake libqt4-dev libgcrypt11-dev zlib1g-dev libxtst-dev; fi - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; fi - - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install cmake qt libgcrypt; fi + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq cmake || brew install cmake; fi + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq qt || brew install qt; fi + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq libgcrypt || brew install libgcrypt; fi before_script: mkdir build && pushd build script: - cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_GUI_TESTS=ON .. - make - if [ "$TRAVIS_OS_NAME" = "linux" ]; then make test ARGS+="-E testgui --output-on-failure"; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then xvfb-run -a --server-args="-screen 0 800x600x24" make test ARGS+="-R testgui --output-on-failure"; fi - - if [ "$TRAVIS_OS_NAME" = "osx" ]; then make test; fi + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then make test ARGS+="--output-on-failure"; fi From f236c32063460edbf290d4d519f2c722a3ec7092 Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Sun, 13 Sep 2015 12:38:19 +0200 Subject: [PATCH 2/4] Clear clipboard when locking databases. Closes #342 --- src/gui/Clipboard.cpp | 18 +++++++++--------- src/gui/Clipboard.h | 4 +++- src/gui/DatabaseTabWidget.cpp | 3 +++ 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/gui/Clipboard.cpp b/src/gui/Clipboard.cpp index d4f34a187..698ca893e 100644 --- a/src/gui/Clipboard.cpp +++ b/src/gui/Clipboard.cpp @@ -31,7 +31,7 @@ Clipboard::Clipboard(QObject* parent) { m_timer->setSingleShot(true); connect(m_timer, SIGNAL(timeout()), SLOT(clearClipboard())); - connect(qApp, SIGNAL(aboutToQuit()), SLOT(cleanup())); + connect(qApp, SIGNAL(aboutToQuit()), SLOT(clearCopiedText())); } void Clipboard::setText(const QString& text) @@ -52,6 +52,14 @@ void Clipboard::setText(const QString& text) } } +void Clipboard::clearCopiedText() +{ + if (m_timer->isActive()) { + m_timer->stop(); + clearClipboard(); + } +} + void Clipboard::clearClipboard() { QClipboard* clipboard = QApplication::clipboard(); @@ -73,14 +81,6 @@ void Clipboard::clearClipboard() m_lastCopied.clear(); } -void Clipboard::cleanup() -{ - if (m_timer->isActive()) { - m_timer->stop(); - clearClipboard(); - } -} - Clipboard* Clipboard::instance() { if (!m_instance) { diff --git a/src/gui/Clipboard.h b/src/gui/Clipboard.h index 8b6ea69f5..8c234a2c5 100644 --- a/src/gui/Clipboard.h +++ b/src/gui/Clipboard.h @@ -33,9 +33,11 @@ public: static Clipboard* instance(); +public Q_SLOTS: + void clearCopiedText(); + private Q_SLOTS: void clearClipboard(); - void cleanup(); private: explicit Clipboard(QObject* parent = Q_NULLPTR); diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index 4c957a27f..3d03093d7 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -27,6 +27,7 @@ #include "core/Metadata.h" #include "core/qsavefile.h" #include "format/CsvExporter.h" +#include "gui/Clipboard.h" #include "gui/DatabaseWidget.h" #include "gui/DatabaseWidgetStateSync.h" #include "gui/DragTabBar.h" @@ -632,6 +633,8 @@ bool DatabaseTabWidget::hasLockableDatabases() const void DatabaseTabWidget::lockDatabases() { + clipboard()->clearCopiedText(); + for (int i = 0; i < count(); i++) { DatabaseWidget* dbWidget = static_cast(widget(i)); Database* db = databaseFromDatabaseWidget(dbWidget); From bb38be40f620b9e992514c37b61334d1b5da2e44 Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Sun, 13 Sep 2015 22:33:07 +0200 Subject: [PATCH 3/4] Enable Ctrl+M shortcut to minimize window on all platforms. Closes #329 --- src/gui/MainWindow.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index bfca42c98..77c34f12c 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -92,9 +92,7 @@ MainWindow::MainWindow() m_ui->actionEntryOpenUrl->setShortcut(Qt::CTRL + Qt::Key_U); m_ui->actionEntryCopyURL->setShortcut(Qt::CTRL + Qt::ALT + Qt::Key_U); -#ifdef Q_OS_MAC new QShortcut(Qt::CTRL + Qt::Key_M, this, SLOT(showMinimized())); -#endif m_ui->actionDatabaseNew->setIcon(filePath()->icon("actions", "document-new")); m_ui->actionDatabaseOpen->setIcon(filePath()->icon("actions", "document-open")); From 673dff2268a3cef5aab5d9a97505a995fd795a4c Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Mon, 21 Sep 2015 23:12:10 +0200 Subject: [PATCH 4/4] Auto-Type: Raise target window after showing the select dialog. kwin >= 5.4 (since commit cfa1d61) prefers to focus the main window instead of following the focus chain. We ask the window manager nicely to focus the window we want to type into. kwin seems to follow that (in the default configuration). --- src/autotype/AutoType.cpp | 2 ++ src/autotype/AutoTypePlatformPlugin.h | 1 + src/autotype/test/AutoTypeTest.cpp | 7 ++++++ src/autotype/test/AutoTypeTest.h | 1 + src/autotype/x11/AutoTypeX11.cpp | 35 +++++++++++++++++++++++++++ src/autotype/x11/AutoTypeX11.h | 2 ++ 6 files changed, 48 insertions(+) diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp index ce68ae471..5c3cac065 100644 --- a/src/autotype/AutoType.cpp +++ b/src/autotype/AutoType.cpp @@ -218,6 +218,8 @@ void AutoType::performAutoTypeFromGlobal(Entry* entry, const QString& sequence) { Q_ASSERT(m_inAutoType); + m_plugin->raiseWindow(m_windowFromGlobal); + m_inAutoType = false; performAutoType(entry, Q_NULLPTR, sequence, m_windowFromGlobal); } diff --git a/src/autotype/AutoTypePlatformPlugin.h b/src/autotype/AutoTypePlatformPlugin.h index 1e78f0d28..614c8060b 100644 --- a/src/autotype/AutoTypePlatformPlugin.h +++ b/src/autotype/AutoTypePlatformPlugin.h @@ -33,6 +33,7 @@ public: virtual void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) = 0; virtual int platformEventFilter(void* event) = 0; virtual int initialTimeout() = 0; + virtual bool raiseWindow(WId window) = 0; virtual void unload() {} virtual AutoTypeExecutor* createExecutor() = 0; diff --git a/src/autotype/test/AutoTypeTest.cpp b/src/autotype/test/AutoTypeTest.cpp index d48d17fe0..f12014668 100644 --- a/src/autotype/test/AutoTypeTest.cpp +++ b/src/autotype/test/AutoTypeTest.cpp @@ -103,6 +103,13 @@ int AutoTypePlatformTest::initialTimeout() return 0; } +bool AutoTypePlatformTest::raiseWindow(WId window) +{ + Q_UNUSED(window); + + return false; +} + AutoTypeExecturorTest::AutoTypeExecturorTest(AutoTypePlatformTest* platform) : m_platform(platform) { diff --git a/src/autotype/test/AutoTypeTest.h b/src/autotype/test/AutoTypeTest.h index a39269b01..c21ff3beb 100644 --- a/src/autotype/test/AutoTypeTest.h +++ b/src/autotype/test/AutoTypeTest.h @@ -42,6 +42,7 @@ public: void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers); int platformEventFilter(void* event); int initialTimeout(); + bool raiseWindow(WId window); AutoTypeExecutor* createExecutor(); void setActiveWindowTitle(const QString& title); diff --git a/src/autotype/x11/AutoTypeX11.cpp b/src/autotype/x11/AutoTypeX11.cpp index 876be3fd3..870002220 100644 --- a/src/autotype/x11/AutoTypeX11.cpp +++ b/src/autotype/x11/AutoTypeX11.cpp @@ -35,6 +35,7 @@ AutoTypePlatformX11::AutoTypePlatformX11() m_atomNetWmName = XInternAtom(m_dpy, "_NET_WM_NAME", true); m_atomString = XInternAtom(m_dpy, "STRING", true); m_atomUtf8String = XInternAtom(m_dpy, "UTF8_STRING", true); + m_atomNetActiveWindow = XInternAtom(m_dpy, "_NET_ACTIVE_WINDOW", true); m_classBlacklist << "desktop_window" << "gnome-panel"; // Gnome m_classBlacklist << "kdesktop" << "kicker"; // KDE 3 @@ -770,4 +771,38 @@ int AutoTypePlatformX11::initialTimeout() return 500; } +bool AutoTypePlatformX11::raiseWindow(WId window) +{ + if (m_atomNetActiveWindow == None) { + return false; + } + + XRaiseWindow(m_dpy, window); + + XEvent event; + event.xclient.type = ClientMessage; + event.xclient.serial = 0; + event.xclient.send_event = True; + event.xclient.window = window; + event.xclient.message_type = m_atomNetActiveWindow; + event.xclient.format = 32; + event.xclient.data.l[0] = 1; // FromApplication + event.xclient.data.l[1] = QX11Info::appUserTime(); + QWidget* activeWindow = QApplication::activeWindow(); + if (activeWindow) { + event.xclient.data.l[2] = activeWindow->internalWinId(); + } + else { + event.xclient.data.l[2] = 0; + } + event.xclient.data.l[3] = 0; + event.xclient.data.l[4] = 0; + XSendEvent(m_dpy, m_rootWindow, False, + SubstructureRedirectMask | SubstructureNotifyMask, + &event); + XFlush(m_dpy); + + return true; +} + Q_EXPORT_PLUGIN2(keepassx-autotype-x11, AutoTypePlatformX11) diff --git a/src/autotype/x11/AutoTypeX11.h b/src/autotype/x11/AutoTypeX11.h index 1fa455035..a1d6e9ff5 100644 --- a/src/autotype/x11/AutoTypeX11.h +++ b/src/autotype/x11/AutoTypeX11.h @@ -50,6 +50,7 @@ public: void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers); int platformEventFilter(void* event); int initialTimeout(); + bool raiseWindow(WId window); AutoTypeExecutor* createExecutor(); KeySym charToKeySym(const QChar& ch); @@ -89,6 +90,7 @@ private: Atom m_atomNetWmName; Atom m_atomString; Atom m_atomUtf8String; + Atom m_atomNetActiveWindow; QSet m_classBlacklist; Qt::Key m_currentGlobalKey; Qt::KeyboardModifiers m_currentGlobalModifiers;