File indexing completed on 2024-05-19 05:32:51

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
0006     SPDX-FileCopyrightText: 2019 Roman Gilg <subdiff@gmail.com>
0007     SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0008 
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 */
0011 #include "xwayland.h"
0012 
0013 #include <config-kwin.h>
0014 
0015 #include "databridge.h"
0016 #include "dnd.h"
0017 #include "window.h"
0018 #include "xwaylandlauncher.h"
0019 #include "xwldrophandler.h"
0020 
0021 #include "core/output.h"
0022 #include "input_event_spy.h"
0023 #include "keyboard_input.h"
0024 #include "main_wayland.h"
0025 #include "utils/common.h"
0026 #include "utils/xcbutils.h"
0027 #include "wayland_server.h"
0028 #include "waylandwindow.h"
0029 #include "workspace.h"
0030 #include "x11eventfilter.h"
0031 #include "xkb.h"
0032 #include "xwayland_logging.h"
0033 
0034 #include <KSelectionOwner>
0035 #include <wayland/keyboard.h>
0036 #include <wayland/seat.h>
0037 #include <wayland/surface.h>
0038 
0039 #include <QAbstractEventDispatcher>
0040 #include <QDataStream>
0041 #include <QFile>
0042 #include <QRandomGenerator>
0043 #include <QScopeGuard>
0044 #include <QSocketNotifier>
0045 #include <QTimer>
0046 #include <QtConcurrentRun>
0047 
0048 #include <cerrno>
0049 #include <cstring>
0050 #include <input_event.h>
0051 #include <sys/socket.h>
0052 #include <unistd.h>
0053 #include <xkbcommon/xkbcommon-keysyms.h>
0054 
0055 namespace KWin
0056 {
0057 namespace Xwl
0058 {
0059 
0060 class XrandrEventFilter : public X11EventFilter
0061 {
0062 public:
0063     explicit XrandrEventFilter(Xwayland *backend);
0064 
0065     bool event(xcb_generic_event_t *event) override;
0066 
0067 private:
0068     Xwayland *const m_backend;
0069 };
0070 
0071 XrandrEventFilter::XrandrEventFilter(Xwayland *backend)
0072     : X11EventFilter(Xcb::Extensions::self()->randrNotifyEvent())
0073     , m_backend(backend)
0074 {
0075 }
0076 
0077 bool XrandrEventFilter::event(xcb_generic_event_t *event)
0078 {
0079     Q_ASSERT((event->response_type & ~0x80) == Xcb::Extensions::self()->randrNotifyEvent());
0080     m_backend->updatePrimary();
0081     return false;
0082 }
0083 
0084 class XwaylandInputSpy : public QObject, public KWin::InputEventSpy
0085 {
0086 public:
0087     XwaylandInputSpy()
0088     {
0089         connect(waylandServer()->seat(), &SeatInterface::focusedKeyboardSurfaceAboutToChange,
0090                 this, [this](SurfaceInterface *newSurface) {
0091                     auto keyboard = waylandServer()->seat()->keyboard();
0092                     if (!newSurface) {
0093                         return;
0094                     }
0095 
0096                     if (waylandServer()->xWaylandConnection() == newSurface->client()) {
0097                         // Since this is a spy but the keyboard interface gets its normal sendKey calls through filters,
0098                         // there can be a mismatch in both states.
0099                         // This loop makes sure all key press events are reset before we switch back to the
0100                         // Xwayland client and the state is correctly restored.
0101                         for (auto it = m_states.constBegin(); it != m_states.constEnd(); ++it) {
0102                             if (it.value() == KeyboardKeyState::Pressed) {
0103                                 keyboard->sendKey(it.key(), KeyboardKeyState::Released, waylandServer()->xWaylandConnection());
0104                             }
0105                         }
0106                         m_states.clear();
0107                     }
0108                 });
0109     }
0110 
0111     void setMode(XwaylandEavesdropsMode mode)
0112     {
0113         static const Qt::KeyboardModifiers modifierKeys = {
0114             Qt::ControlModifier,
0115             Qt::AltModifier,
0116             Qt::MetaModifier,
0117         };
0118 
0119         static const QSet<quint32> characterKeys = {
0120             Qt::Key_Any,
0121             Qt::Key_Space,
0122             Qt::Key_Exclam,
0123             Qt::Key_QuoteDbl,
0124             Qt::Key_NumberSign,
0125             Qt::Key_Dollar,
0126             Qt::Key_Percent,
0127             Qt::Key_Ampersand,
0128             Qt::Key_Apostrophe,
0129             Qt::Key_ParenLeft,
0130             Qt::Key_ParenRight,
0131             Qt::Key_Asterisk,
0132             Qt::Key_Plus,
0133             Qt::Key_Comma,
0134             Qt::Key_Minus,
0135             Qt::Key_Period,
0136             Qt::Key_Slash,
0137             Qt::Key_0,
0138             Qt::Key_1,
0139             Qt::Key_2,
0140             Qt::Key_3,
0141             Qt::Key_4,
0142             Qt::Key_5,
0143             Qt::Key_6,
0144             Qt::Key_7,
0145             Qt::Key_8,
0146             Qt::Key_9,
0147             Qt::Key_Colon,
0148             Qt::Key_Semicolon,
0149             Qt::Key_Less,
0150             Qt::Key_Equal,
0151             Qt::Key_Greater,
0152             Qt::Key_Question,
0153             Qt::Key_At,
0154             Qt::Key_A,
0155             Qt::Key_B,
0156             Qt::Key_C,
0157             Qt::Key_D,
0158             Qt::Key_E,
0159             Qt::Key_F,
0160             Qt::Key_G,
0161             Qt::Key_H,
0162             Qt::Key_I,
0163             Qt::Key_J,
0164             Qt::Key_K,
0165             Qt::Key_L,
0166             Qt::Key_M,
0167             Qt::Key_N,
0168             Qt::Key_O,
0169             Qt::Key_P,
0170             Qt::Key_Q,
0171             Qt::Key_R,
0172             Qt::Key_S,
0173             Qt::Key_T,
0174             Qt::Key_U,
0175             Qt::Key_V,
0176             Qt::Key_W,
0177             Qt::Key_X,
0178             Qt::Key_Y,
0179             Qt::Key_Z,
0180             Qt::Key_BracketLeft,
0181             Qt::Key_Backslash,
0182             Qt::Key_BracketRight,
0183             Qt::Key_AsciiCircum,
0184             Qt::Key_Underscore,
0185             Qt::Key_QuoteLeft,
0186             Qt::Key_BraceLeft,
0187             Qt::Key_Bar,
0188             Qt::Key_BraceRight,
0189             Qt::Key_AsciiTilde,
0190             Qt::Key_nobreakspace,
0191             Qt::Key_exclamdown,
0192             Qt::Key_cent,
0193             Qt::Key_sterling,
0194             Qt::Key_currency,
0195             Qt::Key_yen,
0196             Qt::Key_brokenbar,
0197             Qt::Key_section,
0198             Qt::Key_diaeresis,
0199             Qt::Key_copyright,
0200             Qt::Key_ordfeminine,
0201             Qt::Key_guillemotleft,
0202             Qt::Key_notsign,
0203             Qt::Key_hyphen,
0204             Qt::Key_registered,
0205             Qt::Key_macron,
0206             Qt::Key_degree,
0207             Qt::Key_plusminus,
0208             Qt::Key_twosuperior,
0209             Qt::Key_threesuperior,
0210             Qt::Key_acute,
0211             Qt::Key_mu,
0212             Qt::Key_paragraph,
0213             Qt::Key_periodcentered,
0214             Qt::Key_cedilla,
0215             Qt::Key_onesuperior,
0216             Qt::Key_masculine,
0217             Qt::Key_guillemotright,
0218             Qt::Key_onequarter,
0219             Qt::Key_onehalf,
0220             Qt::Key_threequarters,
0221             Qt::Key_questiondown,
0222             Qt::Key_Agrave,
0223             Qt::Key_Aacute,
0224             Qt::Key_Acircumflex,
0225             Qt::Key_Atilde,
0226             Qt::Key_Adiaeresis,
0227             Qt::Key_Aring,
0228             Qt::Key_AE,
0229             Qt::Key_Ccedilla,
0230             Qt::Key_Egrave,
0231             Qt::Key_Eacute,
0232             Qt::Key_Ecircumflex,
0233             Qt::Key_Ediaeresis,
0234             Qt::Key_Igrave,
0235             Qt::Key_Iacute,
0236             Qt::Key_Icircumflex,
0237             Qt::Key_Idiaeresis,
0238             Qt::Key_ETH,
0239             Qt::Key_Ntilde,
0240             Qt::Key_Ograve,
0241             Qt::Key_Oacute,
0242             Qt::Key_Ocircumflex,
0243             Qt::Key_Otilde,
0244             Qt::Key_Odiaeresis,
0245             Qt::Key_multiply,
0246             Qt::Key_Ooblique,
0247             Qt::Key_Ugrave,
0248             Qt::Key_Uacute,
0249             Qt::Key_Ucircumflex,
0250             Qt::Key_Udiaeresis,
0251             Qt::Key_Yacute,
0252             Qt::Key_THORN,
0253             Qt::Key_ssharp,
0254             Qt::Key_division,
0255             Qt::Key_ydiaeresis,
0256             Qt::Key_Multi_key,
0257             Qt::Key_Codeinput,
0258             Qt::Key_SingleCandidate,
0259             Qt::Key_MultipleCandidate,
0260             Qt::Key_PreviousCandidate,
0261             Qt::Key_Mode_switch,
0262             Qt::Key_Kanji,
0263             Qt::Key_Muhenkan,
0264             Qt::Key_Henkan,
0265             Qt::Key_Romaji,
0266             Qt::Key_Hiragana,
0267             Qt::Key_Katakana,
0268             Qt::Key_Hiragana_Katakana,
0269             Qt::Key_Zenkaku,
0270             Qt::Key_Hankaku,
0271             Qt::Key_Zenkaku_Hankaku,
0272             Qt::Key_Touroku,
0273             Qt::Key_Massyo,
0274             Qt::Key_Kana_Lock,
0275             Qt::Key_Kana_Shift,
0276             Qt::Key_Eisu_Shift,
0277             Qt::Key_Eisu_toggle,
0278             Qt::Key_Hangul,
0279             Qt::Key_Hangul_Start,
0280             Qt::Key_Hangul_End,
0281             Qt::Key_Hangul_Hanja,
0282             Qt::Key_Hangul_Jamo,
0283             Qt::Key_Hangul_Romaja,
0284             Qt::Key_Hangul_Jeonja,
0285             Qt::Key_Hangul_Banja,
0286             Qt::Key_Hangul_PreHanja,
0287             Qt::Key_Hangul_PostHanja,
0288             Qt::Key_Hangul_Special,
0289             Qt::Key_Dead_Grave,
0290             Qt::Key_Dead_Acute,
0291             Qt::Key_Dead_Circumflex,
0292             Qt::Key_Dead_Tilde,
0293             Qt::Key_Dead_Macron,
0294             Qt::Key_Dead_Breve,
0295             Qt::Key_Dead_Abovedot,
0296             Qt::Key_Dead_Diaeresis,
0297             Qt::Key_Dead_Abovering,
0298             Qt::Key_Dead_Doubleacute,
0299             Qt::Key_Dead_Caron,
0300             Qt::Key_Dead_Cedilla,
0301             Qt::Key_Dead_Ogonek,
0302             Qt::Key_Dead_Iota,
0303             Qt::Key_Dead_Voiced_Sound,
0304             Qt::Key_Dead_Semivoiced_Sound,
0305             Qt::Key_Dead_Belowdot,
0306             Qt::Key_Dead_Hook,
0307             Qt::Key_Dead_Horn,
0308             Qt::Key_Dead_Stroke,
0309             Qt::Key_Dead_Abovecomma,
0310             Qt::Key_Dead_Abovereversedcomma,
0311             Qt::Key_Dead_Doublegrave,
0312             Qt::Key_Dead_Belowring,
0313             Qt::Key_Dead_Belowmacron,
0314             Qt::Key_Dead_Belowcircumflex,
0315             Qt::Key_Dead_Belowtilde,
0316             Qt::Key_Dead_Belowbreve,
0317             Qt::Key_Dead_Belowdiaeresis,
0318             Qt::Key_Dead_Invertedbreve,
0319             Qt::Key_Dead_Belowcomma,
0320             Qt::Key_Dead_Currency,
0321             Qt::Key_Dead_a,
0322             Qt::Key_Dead_A,
0323             Qt::Key_Dead_e,
0324             Qt::Key_Dead_E,
0325             Qt::Key_Dead_i,
0326             Qt::Key_Dead_I,
0327             Qt::Key_Dead_o,
0328             Qt::Key_Dead_O,
0329             Qt::Key_Dead_u,
0330             Qt::Key_Dead_U,
0331             Qt::Key_Dead_Small_Schwa,
0332             Qt::Key_Dead_Capital_Schwa,
0333             Qt::Key_Dead_Greek,
0334             Qt::Key_Dead_Lowline,
0335             Qt::Key_Dead_Aboveverticalline,
0336             Qt::Key_Dead_Belowverticalline};
0337 
0338         switch (mode) {
0339         case None:
0340             m_filter = {};
0341             break;
0342         case NonCharacterKeys:
0343             m_filter = [](int key, Qt::KeyboardModifiers) {
0344                 return !characterKeys.contains(key);
0345             };
0346             break;
0347         case AllKeysWithModifier:
0348             m_filter = [](int key, Qt::KeyboardModifiers m) {
0349                 return m.testAnyFlags(modifierKeys) || !characterKeys.contains(key);
0350             };
0351             break;
0352         case All:
0353             m_filter = [](int, Qt::KeyboardModifiers) {
0354                 return true;
0355             };
0356             break;
0357         }
0358     }
0359 
0360     void keyEvent(KWin::KeyEvent *event) override
0361     {
0362         if (event->isAutoRepeat()) {
0363             return;
0364         }
0365 
0366         Window *window = workspace()->activeWindow();
0367         if (!m_filter || !m_filter(event->key(), event->modifiers()) || (window && window->isLockScreen())) {
0368             return;
0369         }
0370 
0371         auto keyboard = waylandServer()->seat()->keyboard();
0372         auto surface = keyboard->focusedSurface();
0373         if (!surface) {
0374             return;
0375         }
0376 
0377         ClientConnection *client = surface->client();
0378         ClientConnection *xwaylandClient = waylandServer()->xWaylandConnection();
0379         if (xwaylandClient && xwaylandClient != client) {
0380             KeyboardKeyState state{event->type() == QEvent::KeyPress};
0381             if (!updateKey(event->nativeScanCode(), state)) {
0382                 return;
0383             }
0384 
0385             auto xkb = input()->keyboard()->xkb();
0386             keyboard->sendModifiers(xkb->modifierState().depressed,
0387                                     xkb->modifierState().latched,
0388                                     xkb->modifierState().locked,
0389                                     xkb->currentLayout());
0390 
0391             waylandServer()->seat()->keyboard()->sendKey(event->nativeScanCode(), state, xwaylandClient);
0392         }
0393     }
0394 
0395     bool updateKey(quint32 key, KeyboardKeyState state)
0396     {
0397         auto it = m_states.find(key);
0398         if (it == m_states.end()) {
0399             m_states.insert(key, state);
0400             return true;
0401         }
0402         if (it.value() == state) {
0403             return false;
0404         }
0405         it.value() = state;
0406         return true;
0407     }
0408 
0409     QHash<quint32, KeyboardKeyState> m_states;
0410     std::function<bool(int key, Qt::KeyboardModifiers)> m_filter;
0411 };
0412 
0413 Xwayland::Xwayland(Application *app)
0414     : m_app(app)
0415     , m_launcher(new XwaylandLauncher(this))
0416 {
0417     connect(m_launcher, &XwaylandLauncher::started, this, &Xwayland::handleXwaylandReady);
0418     connect(m_launcher, &XwaylandLauncher::finished, this, &Xwayland::handleXwaylandFinished);
0419     connect(m_launcher, &XwaylandLauncher::errorOccurred, this, &Xwayland::errorOccurred);
0420 }
0421 
0422 Xwayland::~Xwayland()
0423 {
0424     m_launcher->stop();
0425 }
0426 
0427 void Xwayland::init()
0428 {
0429     m_launcher->enable();
0430 
0431     auto env = m_app->processStartupEnvironment();
0432     env.insert(QStringLiteral("DISPLAY"), m_launcher->displayName());
0433     env.insert(QStringLiteral("XAUTHORITY"), m_launcher->xauthority());
0434     qputenv("DISPLAY", m_launcher->displayName().toLatin1());
0435     qputenv("XAUTHORITY", m_launcher->xauthority().toLatin1());
0436     m_app->setProcessStartupEnvironment(env);
0437 }
0438 
0439 XwaylandLauncher *Xwayland::xwaylandLauncher() const
0440 {
0441     return m_launcher;
0442 }
0443 
0444 void Xwayland::dispatchEvents(DispatchEventsMode mode)
0445 {
0446     xcb_connection_t *connection = kwinApp()->x11Connection();
0447     if (!connection) {
0448         qCWarning(KWIN_XWL, "Attempting to dispatch X11 events with no connection");
0449         return;
0450     }
0451 
0452     const int connectionError = xcb_connection_has_error(connection);
0453     if (connectionError) {
0454         qCWarning(KWIN_XWL, "The X11 connection broke (error %d)", connectionError);
0455         m_launcher->stop();
0456         return;
0457     }
0458 
0459     auto pollEventFunc = mode == DispatchEventsMode::Poll ? xcb_poll_for_event : xcb_poll_for_queued_event;
0460 
0461     while (xcb_generic_event_t *event = pollEventFunc(connection)) {
0462         qintptr result = 0;
0463 
0464         QAbstractEventDispatcher *dispatcher = QCoreApplication::eventDispatcher();
0465         dispatcher->filterNativeEvent(QByteArrayLiteral("xcb_generic_event_t"), event, &result);
0466         free(event);
0467     }
0468 
0469     xcb_flush(connection);
0470 }
0471 
0472 void Xwayland::installSocketNotifier()
0473 {
0474     const int fileDescriptor = xcb_get_file_descriptor(kwinApp()->x11Connection());
0475 
0476     m_socketNotifier = new QSocketNotifier(fileDescriptor, QSocketNotifier::Read, this);
0477     connect(m_socketNotifier, &QSocketNotifier::activated, this, [this]() {
0478         dispatchEvents(DispatchEventsMode::Poll);
0479     });
0480 
0481     QAbstractEventDispatcher *dispatcher = QCoreApplication::eventDispatcher();
0482     connect(dispatcher, &QAbstractEventDispatcher::aboutToBlock, this, [this]() {
0483         dispatchEvents(DispatchEventsMode::EventQueue);
0484     });
0485     connect(dispatcher, &QAbstractEventDispatcher::awake, this, [this]() {
0486         dispatchEvents(DispatchEventsMode::EventQueue);
0487     });
0488 }
0489 
0490 void Xwayland::uninstallSocketNotifier()
0491 {
0492     QAbstractEventDispatcher *dispatcher = QCoreApplication::eventDispatcher();
0493     disconnect(dispatcher, nullptr, this, nullptr);
0494 
0495     delete m_socketNotifier;
0496     m_socketNotifier = nullptr;
0497 }
0498 
0499 void Xwayland::handleXwaylandFinished()
0500 {
0501     disconnect(workspace(), &Workspace::outputOrderChanged, this, &Xwayland::updatePrimary);
0502 
0503     delete m_xrandrEventsFilter;
0504     m_xrandrEventsFilter = nullptr;
0505 
0506     // If Xwayland has crashed, we must deactivate the socket notifier and ensure that no X11
0507     // events will be dispatched before blocking; otherwise we will simply hang...
0508     uninstallSocketNotifier();
0509 
0510     m_dataBridge.reset();
0511     m_compositingManagerSelectionOwner.reset();
0512     m_windowManagerSelectionOwner.reset();
0513 
0514     m_inputSpy.reset();
0515     disconnect(options, &Options::xwaylandEavesdropsChanged, this, &Xwayland::refreshEavesdropping);
0516 
0517     destroyX11Connection();
0518 }
0519 
0520 void Xwayland::handleXwaylandReady()
0521 {
0522     if (!createX11Connection()) {
0523         Q_EMIT errorOccurred();
0524         return;
0525     }
0526 
0527     qCInfo(KWIN_XWL) << "Xwayland server started on display" << m_launcher->displayName();
0528 
0529     m_compositingManagerSelectionOwner = std::make_unique<KSelectionOwner>("_NET_WM_CM_S0", kwinApp()->x11Connection(), kwinApp()->x11RootWindow());
0530     m_compositingManagerSelectionOwner->claim(true);
0531 
0532     xcb_composite_redirect_subwindows(kwinApp()->x11Connection(),
0533                                       kwinApp()->x11RootWindow(),
0534                                       XCB_COMPOSITE_REDIRECT_MANUAL);
0535 
0536     // create selection owner for WM_S0 - magic X display number expected by XWayland
0537     m_windowManagerSelectionOwner = std::make_unique<KSelectionOwner>("WM_S0", kwinApp()->x11Connection(), kwinApp()->x11RootWindow());
0538     connect(m_windowManagerSelectionOwner.get(), &KSelectionOwner::lostOwnership,
0539             this, &Xwayland::handleSelectionLostOwnership);
0540     connect(m_windowManagerSelectionOwner.get(), &KSelectionOwner::claimedOwnership,
0541             this, &Xwayland::handleSelectionClaimedOwnership);
0542     connect(m_windowManagerSelectionOwner.get(), &KSelectionOwner::failedToClaimOwnership,
0543             this, &Xwayland::handleSelectionFailedToClaimOwnership);
0544     m_windowManagerSelectionOwner->claim(true);
0545 
0546     m_dataBridge = std::make_unique<DataBridge>();
0547 
0548     connect(workspace(), &Workspace::outputOrderChanged, this, &Xwayland::updatePrimary);
0549     updatePrimary();
0550 
0551     Xcb::sync(); // Trigger possible errors, there's still a chance to abort
0552 
0553     delete m_xrandrEventsFilter;
0554     m_xrandrEventsFilter = new XrandrEventFilter(this);
0555 
0556     refreshEavesdropping();
0557     connect(options, &Options::xwaylandEavesdropsChanged, this, &Xwayland::refreshEavesdropping);
0558 }
0559 
0560 void Xwayland::refreshEavesdropping()
0561 {
0562     if (!waylandServer()->seat()->keyboard()) {
0563         return;
0564     }
0565 
0566     const bool enabled = options->xwaylandEavesdrops() != None;
0567     if (enabled == bool(m_inputSpy)) {
0568         if (m_inputSpy) {
0569             m_inputSpy->setMode(options->xwaylandEavesdrops());
0570         }
0571         return;
0572     }
0573 
0574     if (enabled) {
0575         m_inputSpy = std::make_unique<XwaylandInputSpy>();
0576         input()->installInputEventSpy(m_inputSpy.get());
0577         m_inputSpy->setMode(options->xwaylandEavesdrops());
0578     } else {
0579         input()->uninstallInputEventSpy(m_inputSpy.get());
0580         m_inputSpy.reset();
0581     }
0582 }
0583 
0584 void Xwayland::updatePrimary()
0585 {
0586     if (workspace()->outputOrder().empty()) {
0587         return;
0588     }
0589     Xcb::RandR::ScreenResources resources(kwinApp()->x11RootWindow());
0590     xcb_randr_crtc_t *crtcs = resources.crtcs();
0591     if (!crtcs) {
0592         return;
0593     }
0594 
0595     Output *const primaryOutput = workspace()->outputOrder().front();
0596     const QRect primaryOutputGeometry = Xcb::toXNative(primaryOutput->geometryF());
0597     for (int i = 0; i < resources->num_crtcs; ++i) {
0598         Xcb::RandR::CrtcInfo crtcInfo(crtcs[i], resources->config_timestamp);
0599         const QRect geometry = crtcInfo.rect();
0600         if (geometry.topLeft() == primaryOutputGeometry.topLeft()) {
0601             auto outputs = crtcInfo.outputs();
0602             if (outputs && crtcInfo->num_outputs > 0) {
0603                 qCDebug(KWIN_XWL) << "Setting primary" << primaryOutput << outputs[0];
0604                 xcb_randr_set_output_primary(kwinApp()->x11Connection(), kwinApp()->x11RootWindow(), outputs[0]);
0605                 break;
0606             }
0607         }
0608     }
0609 }
0610 
0611 void Xwayland::handleSelectionLostOwnership()
0612 {
0613     qCWarning(KWIN_XWL) << "Somebody else claimed ownership of WM_S0. This should never happen!";
0614     m_launcher->stop();
0615 }
0616 
0617 void Xwayland::handleSelectionFailedToClaimOwnership()
0618 {
0619     qCWarning(KWIN_XWL) << "Failed to claim ownership of WM_S0. This should never happen!";
0620     m_launcher->stop();
0621 }
0622 
0623 void Xwayland::handleSelectionClaimedOwnership()
0624 {
0625     Q_EMIT started();
0626 }
0627 
0628 bool Xwayland::createX11Connection()
0629 {
0630     xcb_connection_t *connection = xcb_connect_to_fd(m_launcher->xcbConnectionFd(), nullptr);
0631 
0632     const int errorCode = xcb_connection_has_error(connection);
0633     if (errorCode) {
0634         qCDebug(KWIN_XWL, "Failed to establish the XCB connection (error %d)", errorCode);
0635         return false;
0636     }
0637 
0638     xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data;
0639     Q_ASSERT(screen);
0640 
0641     m_app->setX11Connection(connection);
0642     m_app->setX11RootWindow(screen->root);
0643 
0644     m_app->createAtoms();
0645     m_app->installNativeX11EventFilter();
0646 
0647     installSocketNotifier();
0648 
0649     // Note that it's very important to have valid x11RootWindow(), and atoms when the
0650     // rest of kwin is notified about the new X11 connection.
0651     Q_EMIT m_app->x11ConnectionChanged();
0652 
0653     return true;
0654 }
0655 
0656 void Xwayland::destroyX11Connection()
0657 {
0658     if (!m_app->x11Connection()) {
0659         return;
0660     }
0661 
0662     Q_EMIT m_app->x11ConnectionAboutToBeDestroyed();
0663 
0664     Xcb::setInputFocus(XCB_INPUT_FOCUS_POINTER_ROOT);
0665     m_app->destroyAtoms();
0666     m_app->removeNativeX11EventFilter();
0667 
0668     xcb_disconnect(m_app->x11Connection());
0669 
0670     m_app->setX11Connection(nullptr);
0671     m_app->setX11RootWindow(XCB_WINDOW_NONE);
0672 
0673     Q_EMIT m_app->x11ConnectionChanged();
0674 }
0675 
0676 DragEventReply Xwayland::dragMoveFilter(Window *target)
0677 {
0678     if (m_dataBridge) {
0679         return m_dataBridge->dragMoveFilter(target);
0680     } else {
0681         return DragEventReply::Wayland;
0682     }
0683 }
0684 
0685 AbstractDropHandler *Xwayland::xwlDropHandler()
0686 {
0687     if (m_dataBridge) {
0688         return m_dataBridge->dnd()->dropHandler();
0689     } else {
0690         return nullptr;
0691     }
0692 }
0693 
0694 } // namespace Xwl
0695 } // namespace KWin
0696 
0697 #include "moc_xwayland.cpp"