11#include <config-kwin.h>
88#include <sys/socket.h>
93#if KWIN_BUILD_SCREENLOCKER
94#include <KScreenLocker/KsldApp>
118 const QSet<QByteArray> interfacesBlackList = {
119 QByteArrayLiteral(
"org_kde_kwin_remote_access_manager"),
120 QByteArrayLiteral(
"org_kde_plasma_window_management"),
121 QByteArrayLiteral(
"org_kde_kwin_fake_input"),
122 QByteArrayLiteral(
"org_kde_kwin_keystate"),
123 QByteArrayLiteral(
"zkde_screencast_unstable_v1"),
124 QByteArrayLiteral(
"org_kde_plasma_activation_feedback"),
125 QByteArrayLiteral(
"kde_lockscreen_overlay_v1"),
128 const QSet<QByteArray> inputmethodInterfaces = {
"zwp_input_panel_v1",
"zwp_input_method_v1"};
129 const QSet<QByteArray> xwaylandInterfaces = {
130 QByteArrayLiteral(
"zwp_xwayland_keyboard_grab_manager_v1"),
131 QByteArrayLiteral(
"xwayland_shell_v1"),
138 if (!client->
securityContextAppId().isEmpty() && interfaceName == QByteArrayLiteral(
"wp_security_context_manager_v1")) {
146 if (client !=
waylandServer()->inputMethodConnection() && inputmethodInterfaces.contains(interfaceName)) {
150 if (client !=
waylandServer()->xWaylandConnection() && xwaylandInterfaces.contains(interfaceName)) {
154 if (!interfacesBlackList.contains(interfaceName)) {
159 qCDebug(KWIN_CORE) <<
"Could not identify process with pid" << client->
processId();
163 static bool permissionCheckDisabled = qEnvironmentVariableIntValue(
"KWIN_WAYLAND_NO_PERMISSION_CHECKS") == 1;
164 if (!permissionCheckDisabled) {
165 auto requestedInterfaces = client->property(
"requestedInterfaces");
166 if (requestedInterfaces.isNull()) {
167 requestedInterfaces = fetchRequestedInterfaces(client);
168 client->setProperty(
"requestedInterfaces", requestedInterfaces);
170 if (!requestedInterfaces.toStringList().contains(QString::fromUtf8(interfaceName))) {
171 if (KWIN_CORE().isDebugEnabled()) {
172 const QString
id = client->
executablePath() + QLatin1Char(
'|') + QString::fromUtf8(interfaceName);
173 if (!m_reported.contains(
id)) {
174 m_reported.insert(
id);
175 qCDebug(KWIN_CORE) <<
"Interface" << interfaceName <<
"not in X-KDE-Wayland-Interfaces of" << client->
executablePath();
182 qCDebug(KWIN_CORE) <<
"authorized" << client->
executablePath() << interfaceName;
187WaylandServer::WaylandServer(QObject *parent)
189 , m_display(new KWinDisplay(this))
200 return m_xwaylandConnection;
205 return m_inputMethodServerConnection;
208void WaylandServer::registerWindow(
Window *window)
220void WaylandServer::registerXdgToplevelWindow(XdgToplevelWindow *window)
224 SurfaceInterface *surface = window->
surface();
226 registerWindow(window);
229 window->installPlasmaShellSurface(shellSurface);
232 window->installServerDecoration(decoration);
235 window->installXdgDecoration(decoration);
238 window->installAppMenu(menu);
241 window->installPalette(palette);
249void WaylandServer::registerXdgGenericWindow(
Window *window)
251 if (
auto toplevel = qobject_cast<XdgToplevelWindow *>(window)) {
252 registerXdgToplevelWindow(toplevel);
255 if (
auto popup = qobject_cast<XdgPopupWindow *>(window)) {
256 registerWindow(popup);
258 popup->installPlasmaShellSurface(shellSurface);
262 qCDebug(KWIN_CORE) <<
"Received invalid xdg shell window:" << window->surface();
265void WaylandServer::handleOutputAdded(Output *output)
267 if (!output->isPlaceholder() && !output->isNonDesktop()) {
268 m_waylandOutputDevices.insert(output,
new OutputDeviceV2Interface(m_display, output));
272void WaylandServer::handleOutputRemoved(Output *output)
274 if (
auto outputDevice = m_waylandOutputDevices.take(output)) {
275 outputDevice->remove();
279void WaylandServer::handleOutputEnabled(Output *output)
281 if (!output->isPlaceholder() && !output->isNonDesktop()) {
283 m_xdgOutputManagerV1->
offer(waylandOutput);
285 m_waylandOutputs.insert(output, waylandOutput);
289void WaylandServer::handleOutputDisabled(Output *output)
291 if (
auto waylandOutput = m_waylandOutputs.take(output)) {
298 return m_display->
start();
369 toplevel->installXdgDecoration(decoration);
385 const auto kwinConfig = kwinApp()->config();
386 if (kwinConfig->group(QStringLiteral(
"Wayland")).readEntry(
"EnablePrimarySelection",
true)) {
397 window->installPlasmaShellSurface(surface);
403 window->installAppMenu(appMenu);
409 window->installPalette(palette);
431 if (set ==
workspace()->showingDesktop()) {
438 m_windowManagement->setPlasmaVirtualDesktopManagementInterface(m_virtualDesktopManagement);
448 window->installServerDecoration(decoration);
461 auto init = [
this, activation] {
485 if (
auto window = qobject_cast<LayerShellV1Window *>(
findWindow(edge->
surface()))) {
486 window->installAutoHideScreenEdgeV1(edge);
492 if (qEnvironmentVariableIntValue(
"KWIN_ENABLE_XX_COLOR_MANAGEMENT")) {
508 if (!m_linuxDmabuf) {
511 return m_linuxDmabuf;
528 this, &WaylandServer::registerWindow);
532 this, &WaylandServer::registerXdgGenericWindow);
534 auto setPingTimeout = [xdgShellIntegration] {
542 this, &WaylandServer::registerWindow);
546 VirtualDesktopManager::self()->setVirtualDesktopManagement(m_virtualDesktopManagement);
548 if (m_windowManagement) {
556 QList<QString> uuids;
558 if (toplevel->windowManagementInterface()) {
559 ids << toplevel->windowManagementInterface()->internalId();
560 uuids << toplevel->windowManagementInterface()->uuid();
571 const auto availableOutputs = kwinApp()->outputBackend()->outputs();
572 for (
Output *output : availableOutputs) {
573 handleOutputAdded(output);
579 for (
Output *output : outputs) {
580 handleOutputEnabled(output);
589 if (
auto backend = qobject_cast<DrmBackend *>(kwinApp()->outputBackend())) {
602void WaylandServer::initScreenLocker()
604#if KWIN_BUILD_SCREENLOCKER
605 auto *screenLockerApp = ScreenLocker::KSldApp::self();
607 ScreenLocker::KSldApp::self()->setGreeterEnvironment(kwinApp()->processStartupEnvironment());
609 connect(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::aboutToLock,
this, [
this, screenLockerApp]() {
610 if (m_screenLockerClientConnection) {
614 int clientFd = createScreenLockerConnection();
618 ScreenLocker::KSldApp::self()->setWaylandFd(clientFd);
620 new LockScreenPresentationWatcher(
this);
622 const QList<SeatInterface *> seatIfaces = m_display->
seats();
623 for (
auto *
seat : seatIfaces) {
625 screenLockerApp, &ScreenLocker::KSldApp::userActivity);
629 connect(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::unlocked,
this, [
this, screenLockerApp]() {
630 if (m_screenLockerClientConnection) {
631 m_screenLockerClientConnection->
destroy();
632 delete m_screenLockerClientConnection;
633 m_screenLockerClientConnection =
nullptr;
636 const QList<SeatInterface *> seatIfaces = m_display->
seats();
637 for (
auto *
seat : seatIfaces) {
639 screenLockerApp, &ScreenLocker::KSldApp::userActivity);
641 ScreenLocker::KSldApp::self()->setWaylandFd(-1);
646 ScreenLocker::KSldApp::self()->initialize();
649 ScreenLocker::KSldApp::self()->lock(ScreenLocker::EstablishLock::Immediate);
658 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sx) < 0) {
659 qCWarning(KWIN_CORE) <<
"Could not create socket";
667int WaylandServer::createScreenLockerConnection()
670 if (!socket.connection) {
673 m_screenLockerClientConnection = socket.connection;
675 m_screenLockerClientConnection =
nullptr;
683 if (!socket.connection) {
686 m_xwaylandConnection = socket.connection;
688 m_xwaylandConnection->setScaleOverride(kwinApp()->xwaylandScale());
690 m_xwaylandConnection->setScaleOverride(kwinApp()->xwaylandScale());
698 if (!m_xwaylandConnection) {
701 m_xwaylandConnection->destroy();
702 m_xwaylandConnection =
nullptr;
708 if (!socket.connection) {
711 m_inputMethodServerConnection = socket.connection;
717 if (!m_inputMethodServerConnection) {
720 m_inputMethodServerConnection->destroy();
721 m_inputMethodServerConnection =
nullptr;
726 m_windows.removeAll(c);
734 auto it = std::find_if(windows.begin(), windows.end(), [surface](
Window *w) {
735 return w->surface() == surface;
737 if (it == windows.end()) {
748 if (
Window *c = findWindowInList(m_windows, surface)) {
756 return qobject_cast<XdgToplevelWindow *>(
findWindow(surface));
761 return qobject_cast<XdgSurfaceWindow *>(
findWindow(surface));
766#if KWIN_BUILD_SCREENLOCKER
770 return ScreenLocker::KSldApp::self()->lockState() == ScreenLocker::KSldApp::Locked || ScreenLocker::KSldApp::self()->lockState() == ScreenLocker::KSldApp::AcquiringLock;
778#if KWIN_BUILD_SCREENLOCKER
795 if (inhibitor && inhibitor->isActive()) {
798 if (m_xWaylandKeyboardGrabManager->
hasGrab(surface,
seat())) {
808 if (!socketNames.isEmpty()) {
809 return socketNames.first();
814#if KWIN_BUILD_SCREENLOCKER
815WaylandServer::LockScreenPresentationWatcher::LockScreenPresentationWatcher(
WaylandServer *server)
820 connect(window->output()->renderLoop(), &RenderLoop::framePresented, this, [this, windowGuard = QPointer(window)]() {
823 m_signaledOutputs << windowGuard->output();
824 if (m_signaledOutputs.size() == workspace()->outputs().size()) {
825 ScreenLocker::KSldApp::self()->lockScreenShown();
832 QTimer::singleShot(1000,
this, [
this]() {
833 ScreenLocker::KSldApp::self()->lockScreenShown();
840#include "moc_wayland_server.cpp"
void xwaylandScaleChanged()
SurfaceInterface * surface() const
Convenient Class which represents a wl_client.
QString executablePath() const
QString securityContextAppId() const
void disconnected(KWin::ClientConnection *)
void surfaceCreated(KWin::SurfaceInterface *surface)
Represents the Global for wl_data_device_manager interface.
ClientConnection * createClient(int fd)
QStringList socketNames() const
bool addSocketName(const QString &name=QString())
QList< SeatInterface * > seats() const
Global for server side Display Power Management Signaling interface.
Global representing the org_kde_kwin_idle interface.
KWinDisplay(QObject *parent)
QStringList fetchRequestedInterfaces(ClientConnection *client) const
bool allowInterface(ClientConnection *client, const QByteArray &interfaceName) override
QSet< QString > m_reported
Exposes key states to wayland clients.
KeyboardShortcutsInhibitorV1Interface * findInhibitor(SurfaceInterface *surface, SeatInterface *seat) const
void allowRequested(SurfaceInterface *surface)
Notifies about the surface being activated.
void killPingTimeoutChanged()
void outputAdded(Output *output)
void outputRemoved(Output *output)
void setOutputOrder(const QList< Output * > &outputOrder)
Global for the org_kde_plasma_shell interface.
void surfaceCreated(KWin::PlasmaShellSurfaceInterface *)
Resource for the org_kde_plasma_shell_surface interface.
static PlasmaShellSurfaceInterface * get(wl_resource *native)
Wrapper for the org_kde_plasma_virtual_desktop_management interface.
void setShowingDesktopState(ShowingDesktopState state)
void setStackingOrder(const QList< quint32 > &stackingOrder)
void setStackingOrderUuids(const QList< QString > &stackingOrderUuids)
void requestChangeShowingDesktop(ShowingDesktopState requestedState)
Represents the Global for zwp_primary_selection_manager_v1 interface.
void edgeRequested(AutoHideScreenEdgeV1Interface *edge)
Represents a Seat on the Wayland Display.
SurfaceInterface * focusedKeyboardSurface() const
Representing how a SurfaceInterface should be decorated.
static ServerSideDecorationInterface * get(SurfaceInterface *surface)
Manager to create ServerSideDecorationInterface.
void decorationCreated(KWin::ServerSideDecorationInterface *)
SurfaceInterface * surface() const
void paletteCreated(KWin::ServerSideDecorationPaletteInterface *)
ServerSideDecorationPaletteInterface * paletteForSurface(SurfaceInterface *)
Resource representing a wl_surface.
ClientConnection * client() const
bool hasGlobalShortcutSupport() const
bool isScreenLocked() const
XdgToplevelWindow * findXdgToplevelWindow(SurfaceInterface *surface) const
SurfaceInterface * findForeignTransientForSurface(SurfaceInterface *surface)
bool isKeyboardShortcutsInhibited() const
XdgSurfaceWindow * findXdgSurfaceWindow(SurfaceInterface *surface) const
bool init(const QString &socketName, InitializationFlags flags=InitializationFlag::NoOptions)
void windowRemoved(KWin::Window *)
int createInputMethodConnection()
bool hasScreenLockerIntegration() const
XdgExportedSurface * exportAsForeign(SurfaceInterface *surface)
SocketPairConnection createConnection()
LinuxDmaBufV1ClientBufferIntegration * linuxDmabuf()
void destroyInputMethodConnection()
Window * findWindow(const SurfaceInterface *surface) const
SeatInterface * seat() const
void destroyXWaylandConnection()
@ NoLockScreenIntegration
Display * display() const
KeyboardShortcutsInhibitManagerV1Interface * keyboardShortcutsInhibitManager() const
int createXWaylandConnection()
void removeWindow(Window *c)
QString socketName() const
ClientConnection * xWaylandConnection() const
void foreignTransientChanged(KWin::SurfaceInterface *child)
void windowAdded(KWin::Window *)
ClientConnection * inputMethodConnection() const
~WaylandServer() override
DrmClientBufferIntegration * drm()
void windowCreated(Window *window)
void setSurface(SurfaceInterface *surface)
SurfaceInterface * surface() const
void readyForPaintingChanged()
bool readyForPainting() const
virtual bool isLockScreen() const
void setLockScreenOverlay(bool allowed)
X11Window * findUnmanaged(std::function< bool(const X11Window *)> func) const
void outputOrderChanged()
void outputAdded(KWin::Output *)
X11Window * findClient(std::function< bool(const X11Window *)> func) const
Finds the first Client matching the condition expressed by passed in func.
const QList< Window * > & stackingOrder() const
void workspaceInitialized()
void stackingOrderChanged()
void showingDesktopChanged(bool showing, bool animated)
static Workspace * self()
QList< Output * > outputs() const
void setShowingDesktop(bool showing, bool animated=true)
void outputRemoved(KWin::Output *)
quint32 pendingSurfaceId() const
quint64 surfaceSerial() const
bool hasGrab(SurfaceInterface *surface, SeatInterface *seat) const
void decorationCreated(XdgToplevelDecorationV1Interface *decoration)
void transientChanged(KWin::SurfaceInterface *child, KWin::SurfaceInterface *parent)
XdgExportedSurface * exportSurface(SurfaceInterface *surface)
SurfaceInterface * transientFor(SurfaceInterface *surface)
void offer(OutputInterface *output)
XdgToplevelInterface * toplevel() const
static XdgToplevelDecorationV1Interface * get(XdgToplevelInterface *toplevel)
SurfaceInterface * surface() const
void surfaceAssociated(XwaylandSurfaceV1Interface *surface)
#define KWIN_SINGLETON_FACTORY(ClassName)
KWayland::Client::Output * waylandOutput(const QString &name)
WaylandServer * waylandServer()
ClientConnection * connection