File indexing completed on 2024-11-10 04:57:49
0001 /* 0002 * SPDX-FileCopyrightText: 2023 Kai Uwe Broulik <kde@broulik.de> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "killprompt.h" 0008 0009 #include "client_machine.h" 0010 #include "wayland/display.h" 0011 #include "wayland/seat.h" 0012 #include "wayland/xdgforeign_v2.h" 0013 #include "wayland_server.h" 0014 #include "x11window.h" 0015 #include "xdgactivationv1.h" 0016 #include "xdgshellwindow.h" 0017 0018 #include <QDir> 0019 #include <QFileInfo> 0020 #include <QString> 0021 0022 namespace KWin 0023 { 0024 0025 KillPrompt::KillPrompt(Window *window) 0026 : m_window(window) 0027 { 0028 Q_ASSERT(qobject_cast<X11Window *>(window) || qobject_cast<XdgToplevelWindow *>(window)); 0029 0030 m_process.setProcessChannelMode(QProcess::ForwardedChannels); 0031 0032 const QFileInfo binaryInfo(KWIN_KILLER_BIN); 0033 const QFileInfo buildDirBinary{QDir{QCoreApplication::applicationDirPath()}, binaryInfo.fileName()}; 0034 0035 if (buildDirBinary.exists()) { 0036 m_process.setProgram(buildDirBinary.absoluteFilePath()); 0037 } else { 0038 m_process.setProgram(KWIN_KILLER_BIN); 0039 } 0040 } 0041 0042 bool KillPrompt::isRunning() const 0043 { 0044 return m_process.state() == QProcess::Running; 0045 } 0046 0047 void KillPrompt::start(quint32 timestamp) 0048 { 0049 if (isRunning()) { 0050 return; 0051 } 0052 0053 QProcessEnvironment env = kwinApp()->processStartupEnvironment(); 0054 0055 QString wid; 0056 QString timestampString; 0057 QString hostname = QStringLiteral("localhost"); 0058 QString appId = !m_window->desktopFileName().isEmpty() ? m_window->desktopFileName() : m_window->resourceClass(); 0059 QString platform; 0060 0061 if (auto *x11Window = qobject_cast<X11Window *>(m_window)) { 0062 platform = QStringLiteral("xcb"); 0063 wid = QString::number(x11Window->window()); 0064 timestampString = QString::number(timestamp); 0065 if (!x11Window->clientMachine()->isLocal()) { 0066 hostname = x11Window->clientMachine()->hostName(); 0067 } 0068 } else if (auto *xdgToplevel = qobject_cast<XdgToplevelWindow *>(m_window)) { 0069 platform = QStringLiteral("wayland"); 0070 auto *exported = waylandServer()->exportAsForeign(xdgToplevel->surface()); 0071 wid = exported->handle(); 0072 0073 auto *seat = waylandServer()->seat(); 0074 const QString token = waylandServer()->xdgActivationIntegration()->requestPrivilegedToken(nullptr, seat->display()->serial(), seat, QStringLiteral("org.kde.kwin.killer")); 0075 env.insert(QStringLiteral("XDG_ACTIVATION_TOKEN"), token); 0076 0077 env.remove(QStringLiteral("QT_WAYLAND_RECONNECT")); 0078 } 0079 0080 QStringList args{ 0081 QStringLiteral("-platform"), 0082 platform, 0083 QStringLiteral("--pid"), 0084 QString::number(m_window->pid()), 0085 QStringLiteral("--windowname"), 0086 m_window->captionNormal(), 0087 QStringLiteral("--applicationname"), 0088 appId, 0089 QStringLiteral("--wid"), 0090 wid, 0091 QStringLiteral("--hostname"), 0092 hostname, 0093 QStringLiteral("--timestamp"), 0094 timestampString, 0095 }; 0096 0097 m_process.setArguments(args); 0098 m_process.setProcessEnvironment(env); 0099 m_process.start(); 0100 } 0101 0102 void KillPrompt::quit() 0103 { 0104 m_process.terminate(); 0105 } 0106 0107 } // namespace KWin