File indexing completed on 2024-11-10 04:57:40
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"