From 0501c5d8c467346d419ceb91ae4abf0c8cbfe052 Mon Sep 17 00:00:00 2001 From: Nicolas Fella Date: Wed, 12 Oct 2022 12:44:17 +0200 Subject: [PATCH] Fix raising window when attaching to an existing instance on Wayland When the second instance is launched it receives an activation token per environment variable We need to pass that token to the first instance so that it can use it to raise itself Also properly use startup ids for this on X11 instead of relying on forceActiveWindow, which is a hack --- .gitlab-ci.yml | 4 ++-- CMakeLists.txt | 5 +++++ autotests/CMakeLists.txt | 8 ++++++++ config-okular.h.cmake | 3 +++ shell/CMakeLists.txt | 4 ++++ shell/okular_main.cpp | 24 ++++++++++++++++++++++-- shell/shell.cpp | 11 +++++++++-- shell/shell.h | 2 +- 8 files changed, 54 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b2c5be5ee..fba3796f9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -19,7 +19,7 @@ build_ubuntu_22_04: - apt-get update - apt-get install --yes eatmydata - eatmydata apt-get build-dep --yes --no-install-recommends okular - - eatmydata apt-get install --yes --no-install-recommends ninja-build qtbase5-private-dev + - eatmydata apt-get install --yes --no-install-recommends ninja-build qtbase5-private-dev libqt5x11extras5-dev script: - mkdir -p build && cd build - cmake -DOKULAR_UI=desktop -G Ninja .. @@ -37,7 +37,7 @@ build_clazy_clang_tidy: - apt-get update - apt-get install --yes eatmydata - eatmydata apt-get build-dep --yes --no-install-recommends okular - - eatmydata apt-get install --yes --no-install-recommends ninja-build clazy clang clang-tidy qtbase5-private-dev libkf5crash-dev libkf5purpose-dev kirigami2-dev libegl-dev jq + - eatmydata apt-get install --yes --no-install-recommends ninja-build clazy clang clang-tidy qtbase5-private-dev libqt5x11extras5-dev libkf5crash-dev libkf5purpose-dev kirigami2-dev libegl-dev jq script: - srcdir=`pwd` && mkdir -p /tmp/okular_build && cd /tmp/okular_build && CC=clang CXX=clazy CXXFLAGS="-Werror -Wno-deprecated-declarations" cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G Ninja $srcdir && cat compile_commands.json | jq '[.[] | select(.file | contains("'"$srcdir"'"))]' > compile_commands.aux.json && cat compile_commands.aux.json | jq '[.[] | select(.file | contains("/synctex/")| not)]' > compile_commands.json && cp "$srcdir/.clang-tidy" . diff --git a/CMakeLists.txt b/CMakeLists.txt index 39d32500b..15317fc31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -185,6 +185,11 @@ if(NOT WIN32 AND NOT ANDROID AND NOT APPLE) DESCRIPTION "Activities interface library" URL "https://api.kde.org/frameworks/kactivities/html/" PURPOSE "Required for Activities integration.") + + find_package(Qt5X11Extras REQUIRED) + set(HAVE_X11 TRUE) +else() + set(HAVE_X11 FALSE) endif() find_package(Phonon4Qt5 CONFIG REQUIRED) diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt index b2b8248a9..f1895bde7 100644 --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -115,6 +115,10 @@ if(KF5Activities_FOUND AND BUILD_DESKTOP) LINK_LIBRARIES Qt5::Test KF5::Activities okularpart okularcore ) target_compile_definitions(mainshelltest PRIVATE OKULAR_BINARY="$") + + if (HAVE_X11) + target_link_libraries(mainshelltest Qt5::X11Extras) + endif() endif() if(BUILD_DESKTOP) @@ -122,6 +126,10 @@ if(BUILD_DESKTOP) TEST_NAME "annotationtoolbartest" LINK_LIBRARIES Qt5::Test okularpart ) + + if (HAVE_X11) + target_link_libraries(annotationtoolbartest Qt5::X11Extras) + endif() endif() ecm_add_test(generatorstest.cpp diff --git a/config-okular.h.cmake b/config-okular.h.cmake index 905aac9cb..2bcf55a0d 100644 --- a/config-okular.h.cmake +++ b/config-okular.h.cmake @@ -6,3 +6,6 @@ /* Defines whether the malloc_trim method from malloc.h is available */ #cmakedefine01 HAVE_MALLOC_TRIM + +/* Defines whether we are building with X11 support */ +#cmakedefine01 HAVE_X11 diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt index fbd460322..597f0b74c 100644 --- a/shell/CMakeLists.txt +++ b/shell/CMakeLists.txt @@ -30,6 +30,10 @@ if(TARGET KF5::Activities) target_link_libraries(okular KF5::Activities) endif() +if (HAVE_X11) + target_link_libraries(okular Qt5::X11Extras) +endif() + install(TARGETS okular ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/shell/okular_main.cpp b/shell/okular_main.cpp index 8e64d2186..c23f46356 100644 --- a/shell/okular_main.cpp +++ b/shell/okular_main.cpp @@ -19,8 +19,28 @@ #include #include +#include "config-okular.h" +#if HAVE_X11 +#include +#endif + #include +static QString startupId() +{ + QString result; + if (KWindowSystem::isPlatformWayland()) { + result = qEnvironmentVariable("XDG_ACTIVATION_TOKEN"); + qunsetenv("XDG_ACTIVATION_TOKEN"); + } else if (KWindowSystem::isPlatformX11()) { +#if HAVE_X11 + result = QString::fromUtf8(QX11Info::nextStartupId()); +#endif + } + + return result; +} + static bool attachUniqueInstance(const QStringList &paths, const QString &serializedOptions) { if (!ShellUtils::unique(serializedOptions) || paths.count() != 1) { @@ -42,7 +62,7 @@ static bool attachUniqueInstance(const QStringList &paths, const QString &serial const QString page = ShellUtils::page(serializedOptions); iface.call(QStringLiteral("openDocument"), ShellUtils::urlFromArg(paths[0], ShellUtils::qfileExistFunc(), page).url(), serializedOptions); if (!ShellUtils::noRaise(serializedOptions)) { - iface.call(QStringLiteral("tryRaise")); + iface.call(QStringLiteral("tryRaise"), startupId()); } return true; @@ -136,7 +156,7 @@ static bool attachExistingInstance(const QStringList &paths, const QString &seri exit(1); } - bestService->call(QStringLiteral("tryRaise")); + bestService->call(QStringLiteral("tryRaise"), startupId()); return true; } diff --git a/shell/shell.cpp b/shell/shell.cpp index e87bdb33e..3685f6116 100644 --- a/shell/shell.cpp +++ b/shell/shell.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -660,9 +661,15 @@ void Shell::fileOpen() } } -void Shell::tryRaise() +void Shell::tryRaise(const QString &startupId) { - KWindowSystem::forceActiveWindow(window()->effectiveWinId()); + if (KWindowSystem::isPlatformWayland()) { + KWindowSystem::setCurrentXdgActivationToken(startupId); + } else if (KWindowSystem::isPlatformX11()) { + KStartupInfo::setNewStartupId(window()->windowHandle(), startupId.toUtf8()); + } + + KWindowSystem::activateWindow(window()->windowHandle()); } // only called when starting the program diff --git a/shell/shell.h b/shell/shell.h index 951371f53..facffe33b 100644 --- a/shell/shell.h +++ b/shell/shell.h @@ -74,7 +74,7 @@ public: bool openDocument(const QUrl &url, const QString &serializedOptions); public Q_SLOTS: - Q_SCRIPTABLE Q_NOREPLY void tryRaise(); + Q_SCRIPTABLE Q_NOREPLY void tryRaise(const QString &startupId); Q_SCRIPTABLE bool openDocument(const QString &urlString, const QString &serializedOptions = QString()); Q_SCRIPTABLE bool canOpenDocs(int numDocs, int desktop);