Skip to content

Commit 1ff8162

Browse files
committed
#2462 shortcuts: try activate window with XDG_ACTIVATION_TOKEN
Signed-off-by: Patrizio Bekerle <[email protected]>
1 parent 51488a6 commit 1ff8162

File tree

4 files changed

+44
-6
lines changed

4 files changed

+44
-6
lines changed

src/mainwindow.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
#include <QTreeWidgetItem>
9898
#include <QUuid>
9999
#include <QWidgetAction>
100+
#include <QWindow>
100101
#include <QtConcurrent>
101102
#include <libraries/qttoolbareditor/src/toolbar_editor.hpp>
102103
#include <memory>
@@ -773,9 +774,10 @@ void MainWindow::initWaylandGlobalShortcuts(SettingsService &settings, const QSt
773774

774775
_xdgShortcutManager->setShortcuts(shortcuts);
775776

776-
// Connect the activation signal to trigger the corresponding action
777+
// Connect the activation signal to trigger the corresponding action.
778+
// The activationToken from the portal authorizes window activation on Wayland.
777779
connect(_xdgShortcutManager, &XdgGlobalShortcutManager::shortcutActivated, this,
778-
[this](const QString &shortcutId) {
780+
[this](const QString &shortcutId, const QString &activationToken) {
779781
QAction *action = findAction(shortcutId);
780782
if (action == nullptr) {
781783
qDebug() << "XDG GlobalShortcuts: failed to find action:" << shortcutId;
@@ -784,13 +786,19 @@ void MainWindow::initWaylandGlobalShortcuts(SettingsService &settings, const QSt
784786

785787
qDebug() << "XDG global shortcut action triggered:" << action->objectName();
786788

789+
// Set the activation token so that showWindow() can use it to
790+
// request window activation from the Wayland compositor
791+
_waylandActivationToken = activationToken;
792+
787793
// Don't call showWindow() for the "Show/Hide application" action
788794
// because it will call it itself
789795
if (action->objectName() != QStringLiteral("actionShow_Hide_application")) {
790796
showWindow();
791797
}
792798

793799
action->trigger();
800+
801+
_waylandActivationToken.clear();
794802
});
795803

796804
// Start the session creation and shortcut binding flow
@@ -6746,6 +6754,26 @@ void MainWindow::showWindow() {
67466754
// show the window in case we are using the system tray
67476755
show();
67486756

6757+
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
6758+
// On Wayland, use the XDG activation token (if available) to request
6759+
// window activation from the compositor. Without a valid token the
6760+
// compositor will refuse to raise/focus the window because Wayland
6761+
// does not allow applications to steal focus on their own.
6762+
if (!_waylandActivationToken.isEmpty() && windowHandle() != nullptr) {
6763+
qputenv("XDG_ACTIVATION_TOKEN", _waylandActivationToken.toUtf8());
6764+
windowHandle()->requestActivate();
6765+
qunsetenv("XDG_ACTIVATION_TOKEN");
6766+
6767+
// Still un-minimize if needed
6768+
if (windowState() & Qt::WindowMinimized) {
6769+
setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
6770+
}
6771+
6772+
startNavigationParser();
6773+
return;
6774+
}
6775+
#endif
6776+
67496777
// bring application window to the front
67506778
activateWindow(); // for Windows
67516779
setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);

src/mainwindow.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,9 @@ class MainWindow : public QMainWindow {
898898
QList<QHotkey *> _globalShortcuts;
899899
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
900900
XdgGlobalShortcutManager *_xdgShortcutManager = nullptr;
901+
// Activation token from the XDG GlobalShortcuts portal, used to authorize
902+
// window activation on Wayland compositors via xdg_activation_v1
903+
QString _waylandActivationToken;
901904
#endif
902905
int _lastNoteId = 0;
903906
bool _scriptUpdateFound = false;

src/services/xdgglobalshortcutmanager.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,14 +221,19 @@ void XdgGlobalShortcutManager::onShortcutActivated(QDBusObjectPath sessionHandle
221221
QString shortcutId, qulonglong timestamp,
222222
QVariantMap options) {
223223
Q_UNUSED(timestamp)
224-
Q_UNUSED(options)
225224

226225
if (sessionHandle.path() != _sessionHandle) {
227226
return;
228227
}
229228

230-
qDebug() << "XDG GlobalShortcuts: shortcut activated:" << shortcutId;
231-
emit shortcutActivated(shortcutId);
229+
// Extract the activation token from the portal options — this token
230+
// authorizes the application to activate (raise/focus) its window on
231+
// Wayland compositors that implement xdg_activation_v1
232+
const QString activationToken = options.value(QStringLiteral("activation_token")).toString();
233+
234+
qDebug() << "XDG GlobalShortcuts: shortcut activated:" << shortcutId << "activation_token:"
235+
<< (activationToken.isEmpty() ? QStringLiteral("(none)") : activationToken);
236+
emit shortcutActivated(shortcutId, activationToken);
232237
}
233238

234239
QString XdgGlobalShortcutManager::keySequenceToXdgTrigger(const QKeySequence &seq) {

src/services/xdgglobalshortcutmanager.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,10 @@ class XdgGlobalShortcutManager : public QObject {
8181
/**
8282
* Emitted when a global shortcut is activated by the user.
8383
* @param shortcutId The action object name of the triggered shortcut
84+
* @param activationToken The XDG activation token from the portal,
85+
* used to authorize window activation on Wayland compositors
8486
*/
85-
void shortcutActivated(const QString &shortcutId);
87+
void shortcutActivated(const QString &shortcutId, const QString &activationToken);
8688

8789
private slots:
8890
void onCreateSessionResponse(uint response, QVariantMap results);

0 commit comments

Comments
 (0)