add a DBus slot to get an XDG activation token

Will check if the passed shellSessionId is the current one for safety.
Will try to generate a token and pass it back.

Allows e.g. Kate to properly activate existing instance windows

CCBUG: 442265
This commit is contained in:
Christoph Cullmann
2025-08-13 13:10:00 +02:00
parent 0e5043b783
commit fc6532e97e
2 changed files with 70 additions and 0 deletions

View File

@@ -34,12 +34,19 @@
#include <KNotification>
#include <KProcess>
#include <KSelectAction>
#include <KWindowSystem>
#ifndef Q_OS_WIN
#include <KPtyDevice>
#endif
#include <KShell>
// wayland window activation
#define HAVE_WAYLAND __has_include(<KWaylandExtras>)
#if HAVE_WAYLAND
#include <KWaylandExtras>
#endif
// Konsole
#if HAVE_DBUS
#include <sessionadaptor.h>
@@ -2161,4 +2168,49 @@ void Session::runCommandFromLayout(const QString &command) const
_emulation->sendText(command + QLatin1Char('\n'));
}
QString Session::activationToken(const QString &shellSessionIdForRequest) const
{
// safety check, only work if the caller knows our id
// they will read it from the SHELL_SESSION_ID env var inside this session
if (shellSessionIdForRequest != shellSessionId()) {
return {};
}
#if HAVE_DBUS && HAVE_WAYLAND
// no window active, no token
// same if we don't run wayland
const auto window = qApp->activeWindow();
if (!window || !window->window() || !KWindowSystem::isPlatformWayland()) {
return {};
}
// we will respond delayed, as the token needs to arrive
Q_ASSERT(calledFromDBus());
const auto msg = message();
setDelayedReply(true);
// we need to filter the response with the request serial
const int launchedSerial = KWaylandExtras::self()->lastInputSerial(window->window()->windowHandle());
connect(
KWaylandExtras::self(),
&KWaylandExtras::xdgActivationTokenArrived,
this,
[msg, launchedSerial](int tokenSerial, QString token) {
// if wrong token, ignore it, but we must always reply to not stall the caller
// we use here a SingleShotConnection, we will just be called once!
if (tokenSerial != launchedSerial) {
token.clear();
}
auto reply = msg.createReply(token);
QDBusConnection::sessionBus().send(reply);
},
Qt::SingleShotConnection);
KWaylandExtras::requestXdgActivationToken(window->window()->windowHandle(), launchedSerial, {});
#endif
return {};
}
#include "moc_Session.cpp"

View File

@@ -9,6 +9,8 @@
#ifndef SESSION_H
#define SESSION_H
#include "config-konsole.h"
// Qt
#include <QHash>
#include <QLoggingCategory>
@@ -19,6 +21,10 @@
#include <QUuid>
#include <QWidget>
#if HAVE_DBUS
#include <QDBusContext>
#endif
// Konsole
#include "Shortcut_p.h"
#include "config-konsole.h"
@@ -51,7 +57,11 @@ class SessionController;
* or send input to the program in the terminal in the form of keypresses and mouse
* activity.
*/
#if HAVE_DBUS
class KONSOLEPRIVATE_EXPORT Session : public QObject, protected QDBusContext
#else
class KONSOLEPRIVATE_EXPORT Session : public QObject
#endif
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.konsole.Session")
@@ -728,6 +738,14 @@ public Q_SLOTS:
*/
Q_SCRIPTABLE QStringList getDisplayedTextList(int startLineOffset, int endLineOffset);
/**
* DBus slot to get an XDG activation token.
* Will check if the passed shellSessionId is the current one for safety.
* Will try to generate a token and pass it back.
* Can only be called from DBus, will answer delayed.
*/
Q_SCRIPTABLE QString activationToken(const QString &shellSessionIdForRequest) const;
Q_SIGNALS:
/** Emitted when the terminal process starts. */