KWin
Loading...
Searching...
No Matches
wayland_server.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9#include "wayland_server.h"
10
11#include <config-kwin.h>
12
14#include "core/output.h"
15#include "core/outputbackend.h"
16#include "idle_inhibition.h"
19#include "layershellv1window.h"
20#include "main.h"
21#include "options.h"
22#include "utils/serviceutils.h"
23#include "virtualdesktops.h"
24#include "wayland/appmenu.h"
26#include "wayland/compositor.h"
31#include "wayland/display.h"
32#include "wayland/dpms.h"
34#include "wayland/drmlease_v1.h"
38#include "wayland/idle.h"
43#include "wayland/keystate.h"
46#include "wayland/output.h"
50#include "wayland/plasmashell.h"
59#include "wayland/seat.h"
63#include "wayland/shadow.h"
65#include "wayland/tablet_v2.h"
67#include "wayland/viewporter.h"
72#include "wayland/xdgshell.h"
77#include "workspace.h"
78#include "x11window.h"
79#include "xdgactivationv1.h"
80#include "xdgshellintegration.h"
81#include "xdgshellwindow.h"
82
83// Qt
84#include <QDir>
85#include <QFileInfo>
86
87// system
88#include <sys/socket.h>
89#include <sys/types.h>
90#include <unistd.h>
91
92// screenlocker
93#if KWIN_BUILD_SCREENLOCKER
94#include <KScreenLocker/KsldApp>
95#endif
96
97namespace KWin
98{
99
100KWIN_SINGLETON_FACTORY(WaylandServer)
101
103{
104public:
105 KWinDisplay(QObject *parent)
106 : FilteredDisplay(parent)
107 {
108 }
109
111 {
112 if (!client->securityContextAppId().isEmpty()) {
113 return KWin::fetchRequestedInterfacesForDesktopId(client->securityContextAppId());
114 }
115 return KWin::fetchRequestedInterfaces(client->executablePath());
116 }
117
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"),
126 };
127
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"),
132 };
133
134 QSet<QString> m_reported;
135
136 bool allowInterface(ClientConnection *client, const QByteArray &interfaceName) override
137 {
138 if (!client->securityContextAppId().isEmpty() && interfaceName == QByteArrayLiteral("wp_security_context_manager_v1")) {
139 return false;
140 }
141
142 if (client->processId() == getpid()) {
143 return true;
144 }
145
146 if (client != waylandServer()->inputMethodConnection() && inputmethodInterfaces.contains(interfaceName)) {
147 return false;
148 }
149
150 if (client != waylandServer()->xWaylandConnection() && xwaylandInterfaces.contains(interfaceName)) {
151 return false;
152 }
153
154 if (!interfacesBlackList.contains(interfaceName)) {
155 return true;
156 }
157
158 if (client->executablePath().isEmpty()) {
159 qCDebug(KWIN_CORE) << "Could not identify process with pid" << client->processId();
160 return false;
161 }
162
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);
169 }
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();
176 }
177 }
178 return false;
179 }
180 }
181
182 qCDebug(KWIN_CORE) << "authorized" << client->executablePath() << interfaceName;
183 return true;
184 }
185};
186
187WaylandServer::WaylandServer(QObject *parent)
188 : QObject(parent)
189 , m_display(new KWinDisplay(this))
190{
191}
192
194{
195 s_self = nullptr;
196}
197
199{
200 return m_xwaylandConnection;
201}
202
204{
205 return m_inputMethodServerConnection;
206}
207
208void WaylandServer::registerWindow(Window *window)
209{
210 if (window->readyForPainting()) {
211 Q_EMIT windowAdded(window);
212 } else {
213 connect(window, &Window::readyForPaintingChanged, this, [this, window]() {
214 Q_EMIT windowAdded(window);
215 });
216 }
217 m_windows << window;
218}
219
220void WaylandServer::registerXdgToplevelWindow(XdgToplevelWindow *window)
221{
222 // TODO: Find a better way and more generic to install extensions.
223
224 SurfaceInterface *surface = window->surface();
225
226 registerWindow(window);
227
228 if (auto shellSurface = PlasmaShellSurfaceInterface::get(surface)) {
229 window->installPlasmaShellSurface(shellSurface);
230 }
231 if (auto decoration = ServerSideDecorationInterface::get(surface)) {
232 window->installServerDecoration(decoration);
233 }
234 if (auto decoration = XdgToplevelDecorationV1Interface::get(window->shellSurface())) {
235 window->installXdgDecoration(decoration);
236 }
237 if (auto menu = m_appMenuManager->appMenuForSurface(surface)) {
238 window->installAppMenu(menu);
239 }
240 if (auto palette = m_paletteManager->paletteForSurface(surface)) {
241 window->installPalette(palette);
242 }
243
244 connect(m_XdgForeign, &XdgForeignV2Interface::transientChanged, window, [this](SurfaceInterface *child) {
245 Q_EMIT foreignTransientChanged(child);
246 });
247}
248
249void WaylandServer::registerXdgGenericWindow(Window *window)
250{
251 if (auto toplevel = qobject_cast<XdgToplevelWindow *>(window)) {
252 registerXdgToplevelWindow(toplevel);
253 return;
254 }
255 if (auto popup = qobject_cast<XdgPopupWindow *>(window)) {
256 registerWindow(popup);
257 if (auto shellSurface = PlasmaShellSurfaceInterface::get(popup->surface())) {
258 popup->installPlasmaShellSurface(shellSurface);
259 }
260 return;
261 }
262 qCDebug(KWIN_CORE) << "Received invalid xdg shell window:" << window->surface();
263}
264
265void WaylandServer::handleOutputAdded(Output *output)
266{
267 if (!output->isPlaceholder() && !output->isNonDesktop()) {
268 m_waylandOutputDevices.insert(output, new OutputDeviceV2Interface(m_display, output));
269 }
270}
271
272void WaylandServer::handleOutputRemoved(Output *output)
273{
274 if (auto outputDevice = m_waylandOutputDevices.take(output)) {
275 outputDevice->remove();
276 }
277}
278
279void WaylandServer::handleOutputEnabled(Output *output)
280{
281 if (!output->isPlaceholder() && !output->isNonDesktop()) {
282 auto waylandOutput = new OutputInterface(waylandServer()->display(), output);
283 m_xdgOutputManagerV1->offer(waylandOutput);
284
285 m_waylandOutputs.insert(output, waylandOutput);
286 }
287}
288
289void WaylandServer::handleOutputDisabled(Output *output)
290{
291 if (auto waylandOutput = m_waylandOutputs.take(output)) {
292 waylandOutput->remove();
293 }
294}
295
297{
298 return m_display->start();
299}
300
301bool WaylandServer::init(const QString &socketName, InitializationFlags flags)
302{
303 if (!m_display->addSocketName(socketName)) {
304 return false;
305 }
306 return init(flags);
307}
308
309bool WaylandServer::init(InitializationFlags flags)
310{
311 m_initFlags = flags;
312 m_compositor = new CompositorInterface(m_display, m_display);
313 connect(m_compositor, &CompositorInterface::surfaceCreated, this, [this](SurfaceInterface *surface) {
314 // check whether we have a Window with the Surface's id
316 if (!ws) {
317 // it's possible that a Surface gets created before Workspace is created
318 return;
319 }
320 if (surface->client() != xWaylandConnection()) {
321 // setting surface is only relevant for Xwayland clients
322 return;
323 }
324
325 X11Window *window = ws->findClient([surface](const X11Window *window) {
326 return window->pendingSurfaceId() == surface->id();
327 });
328 if (window) {
329 window->setSurface(surface);
330 return;
331 }
332
333 X11Window *unmanaged = ws->findUnmanaged([surface](const X11Window *unmanaged) {
334 return unmanaged->pendingSurfaceId() == surface->id();
335 });
336 if (unmanaged) {
337 unmanaged->setSurface(surface);
338 return;
339 }
340
341 // The surface will be bound later when a WL_SURFACE_ID message is received.
342 });
343
344 m_xwaylandShell = new XwaylandShellV1Interface(m_display, m_display);
345 connect(m_xwaylandShell, &XwaylandShellV1Interface::surfaceAssociated, this, [](XwaylandSurfaceV1Interface *surface) {
346 X11Window *window = workspace()->findClient([&surface](const X11Window *window) {
347 return window->surfaceSerial() == surface->serial();
348 });
349 if (window) {
350 window->setSurface(surface->surface());
351 return;
352 }
353
354 X11Window *unmanaged = workspace()->findUnmanaged([&surface](const X11Window *window) {
355 return window->surfaceSerial() == surface->serial();
356 });
357 if (unmanaged) {
358 unmanaged->setSurface(surface->surface());
359 return;
360 }
361 });
362
363 m_tabletManagerV2 = new TabletManagerV2Interface(m_display, m_display);
364 m_keyboardShortcutsInhibitManager = new KeyboardShortcutsInhibitManagerV1Interface(m_display, m_display);
365
366 m_xdgDecorationManagerV1 = new XdgDecorationManagerV1Interface(m_display, m_display);
367 connect(m_xdgDecorationManagerV1, &XdgDecorationManagerV1Interface::decorationCreated, this, [this](XdgToplevelDecorationV1Interface *decoration) {
368 if (XdgToplevelWindow *toplevel = findXdgToplevelWindow(decoration->toplevel()->surface())) {
369 toplevel->installXdgDecoration(decoration);
370 }
371 });
372
373 new ViewporterInterface(m_display, m_display);
374 new SecurityContextManagerV1Interface(m_display, m_display);
375 new FractionalScaleManagerV1Interface(m_display, m_display);
376 m_display->createShm();
377 m_seat = new SeatInterface(m_display, m_display);
378 new PointerGesturesV1Interface(m_display, m_display);
379 new PointerConstraintsV1Interface(m_display, m_display);
380 new RelativePointerManagerV1Interface(m_display, m_display);
381 m_dataDeviceManager = new DataDeviceManagerInterface(m_display, m_display);
382 new DataControlDeviceManagerV1Interface(m_display, m_display);
383 new CursorShapeManagerV1Interface(m_display, m_display);
384
385 const auto kwinConfig = kwinApp()->config();
386 if (kwinConfig->group(QStringLiteral("Wayland")).readEntry("EnablePrimarySelection", true)) {
387 new PrimarySelectionDeviceManagerV1Interface(m_display, m_display);
388 }
389
390 m_idle = new IdleInterface(m_display, m_display);
391 new IdleInhibition(m_idle);
392 new IdleInhibitManagerV1Interface(m_display, m_display);
393 new IdleNotifyV1Interface(m_display, m_display);
394 m_plasmaShell = new PlasmaShellInterface(m_display, m_display);
395 connect(m_plasmaShell, &PlasmaShellInterface::surfaceCreated, this, [this](PlasmaShellSurfaceInterface *surface) {
396 if (XdgSurfaceWindow *window = findXdgSurfaceWindow(surface->surface())) {
397 window->installPlasmaShellSurface(surface);
398 }
399 });
400 m_appMenuManager = new AppMenuManagerInterface(m_display, m_display);
401 connect(m_appMenuManager, &AppMenuManagerInterface::appMenuCreated, this, [this](AppMenuInterface *appMenu) {
402 if (XdgToplevelWindow *window = findXdgToplevelWindow(appMenu->surface())) {
403 window->installAppMenu(appMenu);
404 }
405 });
406 m_paletteManager = new ServerSideDecorationPaletteManagerInterface(m_display, m_display);
408 if (XdgToplevelWindow *window = findXdgToplevelWindow(palette->surface())) {
409 window->installPalette(palette);
410 }
411 });
412
413 m_windowManagement = new PlasmaWindowManagementInterface(m_display, m_display);
414 m_windowManagement->setShowingDesktopState(PlasmaWindowManagementInterface::ShowingDesktopState::Disabled);
416 if (!workspace()) {
417 return;
418 }
419 bool set = false;
420 switch (state) {
422 set = false;
423 break;
425 set = true;
426 break;
427 default:
428 Q_UNREACHABLE();
429 break;
430 }
431 if (set == workspace()->showingDesktop()) {
432 return;
433 }
435 });
436
437 m_virtualDesktopManagement = new PlasmaVirtualDesktopManagementInterface(m_display, m_display);
438 m_windowManagement->setPlasmaVirtualDesktopManagementInterface(m_virtualDesktopManagement);
439
440 m_plasmaActivationFeedback = new PlasmaWindowActivationFeedbackInterface(m_display, m_display);
441
442 new ShadowManagerInterface(m_display, m_display);
443 new DpmsManagerInterface(m_display, m_display);
444
445 m_decorationManager = new ServerSideDecorationManagerInterface(m_display, m_display);
446 connect(m_decorationManager, &ServerSideDecorationManagerInterface::decorationCreated, this, [this](ServerSideDecorationInterface *decoration) {
447 if (XdgToplevelWindow *window = findXdgToplevelWindow(decoration->surface())) {
448 window->installServerDecoration(decoration);
449 }
450 });
451
452 m_outputManagement = new OutputManagementV2Interface(m_display, m_display);
453
454 m_xdgOutputManagerV1 = new XdgOutputManagerV1Interface(m_display, m_display);
455 new SubCompositorInterface(m_display, m_display);
456 m_XdgForeign = new XdgForeignV2Interface(m_display, m_display);
457 m_inputMethod = new InputMethodV1Interface(m_display, m_display);
458 m_xWaylandKeyboardGrabManager = new XWaylandKeyboardGrabManagerV1Interface(m_display, m_display);
459
460 auto activation = new XdgActivationV1Interface(m_display, this);
461 auto init = [this, activation] {
462 m_xdgActivationIntegration = new XdgActivationV1Integration(activation, this);
463 };
464 if (Workspace::self()) {
465 init();
466 } else {
467 connect(static_cast<Application *>(qApp), &Application::workspaceCreated, this, init);
468 }
469
470 auto aboveLockscreen = new LockscreenOverlayV1Interface(m_display, this);
471 connect(aboveLockscreen, &LockscreenOverlayV1Interface::allowRequested, this, [](SurfaceInterface *surface) {
472 auto w = waylandServer()->findWindow(surface);
473 if (!w) {
474 return;
475 }
476 w->setLockScreenOverlay(true);
477 });
478
479 m_contentTypeManager = new ContentTypeManagerV1Interface(m_display, m_display);
480 m_tearingControlInterface = new TearingControlManagerV1Interface(m_display, m_display);
481 new XdgToplevelDragManagerV1Interface(m_display, this);
482
483 auto screenEdgeManager = new ScreenEdgeManagerV1Interface(m_display, m_display);
484 connect(screenEdgeManager, &ScreenEdgeManagerV1Interface::edgeRequested, this, [this](AutoHideScreenEdgeV1Interface *edge) {
485 if (auto window = qobject_cast<LayerShellV1Window *>(findWindow(edge->surface()))) {
486 window->installAutoHideScreenEdgeV1(edge);
487 }
488 });
489
490 new FrogColorManagementV1(m_display, m_display);
491 new PresentationTime(m_display, m_display);
492 if (qEnvironmentVariableIntValue("KWIN_ENABLE_XX_COLOR_MANAGEMENT")) {
493 m_xxColorManager = new XXColorManagerV2(m_display, m_display);
494 }
495 return true;
496}
497
499{
500 if (!m_drm) {
501 m_drm = new DrmClientBufferIntegration(m_display);
502 }
503 return m_drm;
504}
505
507{
508 if (!m_linuxDmabuf) {
509 m_linuxDmabuf = new LinuxDmaBufV1ClientBufferIntegration(m_display);
510 }
511 return m_linuxDmabuf;
512}
513
518
520{
521 return m_XdgForeign->exportSurface(surface);
522}
523
525{
526 auto inputPanelV1Integration = new InputPanelV1Integration(this);
527 connect(inputPanelV1Integration, &InputPanelV1Integration::windowCreated,
528 this, &WaylandServer::registerWindow);
529
530 auto xdgShellIntegration = new XdgShellIntegration(this);
531 connect(xdgShellIntegration, &XdgShellIntegration::windowCreated,
532 this, &WaylandServer::registerXdgGenericWindow);
533
534 auto setPingTimeout = [xdgShellIntegration] {
535 xdgShellIntegration->setPingTimeout(std::chrono::milliseconds(options->killPingTimeout()));
536 };
537 connect(options, &Options::killPingTimeoutChanged, xdgShellIntegration, setPingTimeout);
538 setPingTimeout();
539
540 auto layerShellV1Integration = new LayerShellV1Integration(this);
541 connect(layerShellV1Integration, &LayerShellV1Integration::windowCreated,
542 this, &WaylandServer::registerWindow);
543
544 new KeyStateInterface(m_display, m_display);
545
546 VirtualDesktopManager::self()->setVirtualDesktopManagement(m_virtualDesktopManagement);
547
548 if (m_windowManagement) {
549 connect(workspace(), &Workspace::showingDesktopChanged, this, [this](bool set) {
551 });
552
553 connect(workspace(), &Workspace::workspaceInitialized, this, [this] {
554 auto f = [this]() {
555 QList<quint32> ids;
556 QList<QString> uuids;
557 for (Window *toplevel : workspace()->stackingOrder()) {
558 if (toplevel->windowManagementInterface()) {
559 ids << toplevel->windowManagementInterface()->internalId();
560 uuids << toplevel->windowManagementInterface()->uuid();
561 }
562 }
563 m_windowManagement->setStackingOrder(ids);
564 m_windowManagement->setStackingOrderUuids(uuids);
565 };
566 f();
567 connect(workspace(), &Workspace::stackingOrderChanged, this, f);
568 });
569 }
570
571 const auto availableOutputs = kwinApp()->outputBackend()->outputs();
572 for (Output *output : availableOutputs) {
573 handleOutputAdded(output);
574 }
575 connect(kwinApp()->outputBackend(), &OutputBackend::outputAdded, this, &WaylandServer::handleOutputAdded);
576 connect(kwinApp()->outputBackend(), &OutputBackend::outputRemoved, this, &WaylandServer::handleOutputRemoved);
577
578 const auto outputs = workspace()->outputs();
579 for (Output *output : outputs) {
580 handleOutputEnabled(output);
581 }
582 connect(workspace(), &Workspace::outputAdded, this, &WaylandServer::handleOutputEnabled);
583 connect(workspace(), &Workspace::outputRemoved, this, &WaylandServer::handleOutputDisabled);
584
586 initScreenLocker();
587 }
588
589 if (auto backend = qobject_cast<DrmBackend *>(kwinApp()->outputBackend())) {
590 m_leaseManager = new DrmLeaseManagerV1(backend, m_display, m_display);
591 }
592
593 m_outputOrder = new OutputOrderV1Interface(m_display, m_display);
594 m_outputOrder->setOutputOrder(workspace()->outputOrder());
595 connect(workspace(), &Workspace::outputOrderChanged, m_outputOrder, [this]() {
596 m_outputOrder->setOutputOrder(workspace()->outputOrder());
597 });
598
599 Q_EMIT initialized();
600}
601
602void WaylandServer::initScreenLocker()
603{
604#if KWIN_BUILD_SCREENLOCKER
605 auto *screenLockerApp = ScreenLocker::KSldApp::self();
606
607 ScreenLocker::KSldApp::self()->setGreeterEnvironment(kwinApp()->processStartupEnvironment());
608
609 connect(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::aboutToLock, this, [this, screenLockerApp]() {
610 if (m_screenLockerClientConnection) {
611 // Already sent data to KScreenLocker.
612 return;
613 }
614 int clientFd = createScreenLockerConnection();
615 if (clientFd < 0) {
616 return;
617 }
618 ScreenLocker::KSldApp::self()->setWaylandFd(clientFd);
619
620 new LockScreenPresentationWatcher(this);
621
622 const QList<SeatInterface *> seatIfaces = m_display->seats();
623 for (auto *seat : seatIfaces) {
625 screenLockerApp, &ScreenLocker::KSldApp::userActivity);
626 }
627 });
628
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;
634 }
635
636 const QList<SeatInterface *> seatIfaces = m_display->seats();
637 for (auto *seat : seatIfaces) {
639 screenLockerApp, &ScreenLocker::KSldApp::userActivity);
640 }
641 ScreenLocker::KSldApp::self()->setWaylandFd(-1);
642 });
643
644 connect(screenLockerApp, &ScreenLocker::KSldApp::lockStateChanged, this, &WaylandServer::lockStateChanged);
645
646 ScreenLocker::KSldApp::self()->initialize();
647
648 if (m_initFlags.testFlag(InitializationFlag::LockScreen)) {
649 ScreenLocker::KSldApp::self()->lock(ScreenLocker::EstablishLock::Immediate);
650 }
651#endif
652}
653
655{
657 int sx[2];
658 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sx) < 0) {
659 qCWarning(KWIN_CORE) << "Could not create socket";
660 return ret;
661 }
662 ret.connection = m_display->createClient(sx[0]);
663 ret.fd = sx[1];
664 return ret;
665}
666
667int WaylandServer::createScreenLockerConnection()
668{
669 const auto socket = createConnection();
670 if (!socket.connection) {
671 return -1;
672 }
673 m_screenLockerClientConnection = socket.connection;
674 connect(m_screenLockerClientConnection, &ClientConnection::disconnected, this, [this]() {
675 m_screenLockerClientConnection = nullptr;
676 });
677 return socket.fd;
678}
679
681{
682 const auto socket = createConnection();
683 if (!socket.connection) {
684 return -1;
685 }
686 m_xwaylandConnection = socket.connection;
687
688 m_xwaylandConnection->setScaleOverride(kwinApp()->xwaylandScale());
689 connect(kwinApp(), &Application::xwaylandScaleChanged, m_xwaylandConnection, [this]() {
690 m_xwaylandConnection->setScaleOverride(kwinApp()->xwaylandScale());
691 });
692
693 return socket.fd;
694}
695
697{
698 if (!m_xwaylandConnection) {
699 return;
700 }
701 m_xwaylandConnection->destroy();
702 m_xwaylandConnection = nullptr;
703}
704
706{
707 const auto socket = createConnection();
708 if (!socket.connection) {
709 return -1;
710 }
711 m_inputMethodServerConnection = socket.connection;
712 return socket.fd;
713}
714
716{
717 if (!m_inputMethodServerConnection) {
718 return;
719 }
720 m_inputMethodServerConnection->destroy();
721 m_inputMethodServerConnection = nullptr;
722}
723
725{
726 m_windows.removeAll(c);
727 if (c->readyForPainting()) {
728 Q_EMIT windowRemoved(c);
729 }
730}
731
732static Window *findWindowInList(const QList<Window *> &windows, const SurfaceInterface *surface)
733{
734 auto it = std::find_if(windows.begin(), windows.end(), [surface](Window *w) {
735 return w->surface() == surface;
736 });
737 if (it == windows.end()) {
738 return nullptr;
739 }
740 return *it;
741}
742
744{
745 if (!surface) {
746 return nullptr;
747 }
748 if (Window *c = findWindowInList(m_windows, surface)) {
749 return c;
750 }
751 return nullptr;
752}
753
755{
756 return qobject_cast<XdgToplevelWindow *>(findWindow(surface));
757}
758
760{
761 return qobject_cast<XdgSurfaceWindow *>(findWindow(surface));
762}
763
765{
766#if KWIN_BUILD_SCREENLOCKER
768 return false;
769 }
770 return ScreenLocker::KSldApp::self()->lockState() == ScreenLocker::KSldApp::Locked || ScreenLocker::KSldApp::self()->lockState() == ScreenLocker::KSldApp::AcquiringLock;
771#else
772 return false;
773#endif
774}
775
777{
778#if KWIN_BUILD_SCREENLOCKER
779 return !m_initFlags.testFlag(InitializationFlag::NoLockScreenIntegration);
780#else
781 return false;
782#endif
783}
784
786{
787 return !m_initFlags.testFlag(InitializationFlag::NoGlobalShortcuts);
788}
789
791{
792 auto surface = seat()->focusedKeyboardSurface();
793 if (surface) {
794 auto inhibitor = keyboardShortcutsInhibitManager()->findInhibitor(surface, seat());
795 if (inhibitor && inhibitor->isActive()) {
796 return true;
797 }
798 if (m_xWaylandKeyboardGrabManager->hasGrab(surface, seat())) {
799 return true;
800 }
801 }
802 return false;
803}
804
806{
807 const QStringList socketNames = display()->socketNames();
808 if (!socketNames.isEmpty()) {
809 return socketNames.first();
810 }
811 return QString();
812}
813
814#if KWIN_BUILD_SCREENLOCKER
815WaylandServer::LockScreenPresentationWatcher::LockScreenPresentationWatcher(WaylandServer *server)
816{
817 connect(server, &WaylandServer::windowAdded, this, [this](Window *window) {
818 if (window->isLockScreen()) {
819 // only signal lockScreenShown once all outputs have been presented at least once
820 connect(window->output()->renderLoop(), &RenderLoop::framePresented, this, [this, windowGuard = QPointer(window)]() {
821 // window might be destroyed before a frame is presented, so it's wrapped in QPointer
822 if (windowGuard) {
823 m_signaledOutputs << windowGuard->output();
824 if (m_signaledOutputs.size() == workspace()->outputs().size()) {
825 ScreenLocker::KSldApp::self()->lockScreenShown();
826 delete this;
827 }
828 }
829 });
830 }
831 });
832 QTimer::singleShot(1000, this, [this]() {
833 ScreenLocker::KSldApp::self()->lockScreenShown();
834 delete this;
835 });
836}
837#endif
838}
839
840#include "moc_wayland_server.cpp"
AppMenuInterface * appMenuForSurface(SurfaceInterface *)
Definition appmenu.cpp:111
void appMenuCreated(KWin::AppMenuInterface *)
void xwaylandScaleChanged()
SurfaceInterface * surface() const
Convenient Class which represents a wl_client.
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)
Definition display.cpp:228
void createShm()
Definition display.cpp:128
QStringList socketNames() const
Definition display.cpp:87
bool addSocketName(const QString &name=QString())
Definition display.cpp:68
QList< SeatInterface * > seats() const
Definition display.cpp:195
bool start()
Definition display.cpp:92
Global for server side Display Power Management Signaling interface.
Definition dpms.h:52
Global representing the org_kde_kwin_idle interface.
Definition idle.h:38
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.
Definition keystate.h:23
KeyboardShortcutsInhibitorV1Interface * findInhibitor(SurfaceInterface *surface, SeatInterface *seat) const
void allowRequested(SurfaceInterface *surface)
Notifies about the surface being activated.
void killPingTimeoutChanged()
int killPingTimeout
Definition options.h:176
void outputAdded(Output *output)
void outputRemoved(Output *output)
void setOutputOrder(const QList< Output * > &outputOrder)
Global for the org_kde_plasma_shell interface.
Definition plasmashell.h:37
void surfaceCreated(KWin::PlasmaShellSurfaceInterface *)
Resource for the org_kde_plasma_shell_surface interface.
Definition plasmashell.h:60
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.
Definition seat.h:134
SurfaceInterface * focusedKeyboardSurface() const
Definition seat.cpp:910
Representing how a SurfaceInterface should be decorated.
static ServerSideDecorationInterface * get(SurfaceInterface *surface)
Manager to create ServerSideDecorationInterface.
void decorationCreated(KWin::ServerSideDecorationInterface *)
void paletteCreated(KWin::ServerSideDecorationPaletteInterface *)
ServerSideDecorationPaletteInterface * paletteForSurface(SurfaceInterface *)
Resource representing a wl_surface.
Definition surface.h:80
ClientConnection * client() const
Definition surface.cpp:444
uint32_t id() const
Definition surface.cpp:439
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 *)
bool hasScreenLockerIntegration() const
XdgExportedSurface * exportAsForeign(SurfaceInterface *surface)
SocketPairConnection createConnection()
LinuxDmaBufV1ClientBufferIntegration * linuxDmabuf()
Window * findWindow(const SurfaceInterface *surface) const
SeatInterface * seat() const
Display * display() const
KeyboardShortcutsInhibitManagerV1Interface * keyboardShortcutsInhibitManager() const
void removeWindow(Window *c)
QString socketName() const
ClientConnection * xWaylandConnection() const
void foreignTransientChanged(KWin::SurfaceInterface *child)
void windowAdded(KWin::Window *)
ClientConnection * inputMethodConnection() const
DrmClientBufferIntegration * drm()
void windowCreated(Window *window)
void setSurface(SurfaceInterface *surface)
Definition window.cpp:347
SurfaceInterface * surface() const
Definition window.cpp:342
void readyForPaintingChanged()
bool readyForPainting() const
Definition window.h:1917
virtual bool isLockScreen() const
Definition window.h:2007
void setLockScreenOverlay(bool allowed)
Definition window.cpp:4172
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
Definition workspace.h:788
void workspaceInitialized()
void stackingOrderChanged()
void showingDesktopChanged(bool showing, bool animated)
static Workspace * self()
Definition workspace.h:91
QList< Output * > outputs() const
Definition workspace.h:762
void setShowingDesktop(bool showing, bool animated=true)
void outputRemoved(KWin::Output *)
quint32 pendingSurfaceId() const
Definition x11window.h:630
quint64 surfaceSerial() const
Definition x11window.h:625
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
Definition xdgshell.cpp:552
void surfaceAssociated(XwaylandSurfaceV1Interface *surface)
#define KWIN_SINGLETON_FACTORY(ClassName)
Definition globals.h:335
KWayland::Client::Output * waylandOutput(const QString &name)
WaylandServer * waylandServer()
Workspace * workspace()
Definition workspace.h:830
Options * options
Definition main.cpp:73