File indexing completed on 2024-11-10 04:56:35
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org> 0006 SPDX-FileCopyrightText: 2010, 2011, 2017 Martin Gräßlin <mgraesslin@kde.org> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 #include "x11_standalone_effects.h" 0011 #include "cursor.h" 0012 #include "screenedge.h" 0013 #include "utils/common.h" 0014 #include "workspace.h" 0015 #include "x11_standalone_backend.h" 0016 #include "x11_standalone_effects_keyboard_interception_filter.h" 0017 #include "x11_standalone_effects_mouse_interception_filter.h" 0018 #include "x11_standalone_keyboard.h" 0019 0020 namespace KWin 0021 { 0022 0023 EffectsHandlerX11::EffectsHandlerX11(Compositor *compositor, WorkspaceScene *scene) 0024 : EffectsHandler(compositor, scene) 0025 { 0026 connect(this, &EffectsHandler::virtualScreenGeometryChanged, this, [this]() { 0027 if (m_mouseInterceptionWindow.isValid()) { 0028 m_mouseInterceptionWindow.setGeometry(virtualScreenGeometry()); 0029 } 0030 }); 0031 } 0032 0033 EffectsHandlerX11::~EffectsHandlerX11() 0034 { 0035 // EffectsHandler tries to unload all effects when it's destroyed. 0036 // The routine that unloads effects makes some calls (indirectly) to 0037 // doUngrabKeyboard and doStopMouseInterception, which are virtual. 0038 // Given that any call to a virtual function in the destructor of a base 0039 // class will never go to a derived class, we have to unload effects 0040 // here. Yeah, this is quite a bit ugly but it's fine; someday, X11 0041 // will be dead (or not?). 0042 unloadAllEffects(); 0043 } 0044 0045 bool EffectsHandlerX11::doGrabKeyboard() 0046 { 0047 auto keyboard = static_cast<X11StandaloneBackend *>(kwinApp()->outputBackend())->keyboard(); 0048 if (!keyboard->xkbKeymap()) { 0049 return false; 0050 } 0051 bool ret = grabXKeyboard(); 0052 if (!ret) { 0053 return false; 0054 } 0055 m_x11KeyboardInterception = std::make_unique<EffectsKeyboardInterceptionX11Filter>(this, keyboard); 0056 return ret; 0057 } 0058 0059 void EffectsHandlerX11::doUngrabKeyboard() 0060 { 0061 ungrabXKeyboard(); 0062 m_x11KeyboardInterception.reset(); 0063 } 0064 0065 void EffectsHandlerX11::doStartMouseInterception(Qt::CursorShape shape) 0066 { 0067 // NOTE: it is intended to not perform an XPointerGrab on X11. See documentation in kwineffects.h 0068 // The mouse grab is implemented by using a full screen input only window 0069 if (!m_mouseInterceptionWindow.isValid()) { 0070 const QSize &s = workspace()->geometry().size(); 0071 const QRect geo(0, 0, s.width(), s.height()); 0072 const uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK; 0073 const uint32_t values[] = { 0074 true, 0075 XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION}; 0076 m_mouseInterceptionWindow.reset(Xcb::createInputWindow(geo, mask, values)); 0077 defineCursor(shape); 0078 } else { 0079 defineCursor(shape); 0080 } 0081 m_mouseInterceptionWindow.map(); 0082 m_mouseInterceptionWindow.raise(); 0083 m_x11MouseInterception = std::make_unique<EffectsMouseInterceptionX11Filter>(m_mouseInterceptionWindow, this); 0084 // Raise electric border windows above the input windows 0085 // so they can still be triggered. 0086 workspace()->screenEdges()->ensureOnTop(); 0087 } 0088 0089 void EffectsHandlerX11::doStopMouseInterception() 0090 { 0091 m_mouseInterceptionWindow.unmap(); 0092 m_x11MouseInterception.reset(); 0093 Workspace::self()->stackScreenEdgesUnderOverrideRedirect(); 0094 } 0095 0096 void EffectsHandlerX11::defineCursor(Qt::CursorShape shape) 0097 { 0098 const xcb_cursor_t c = Cursors::self()->mouse()->x11Cursor(shape); 0099 if (c != XCB_CURSOR_NONE) { 0100 m_mouseInterceptionWindow.defineCursor(c); 0101 } 0102 } 0103 0104 void EffectsHandlerX11::doCheckInputWindowStacking() 0105 { 0106 m_mouseInterceptionWindow.raise(); 0107 // Raise electric border windows above the input windows 0108 // so they can still be triggered. TODO: Do both at once. 0109 workspace()->screenEdges()->ensureOnTop(); 0110 } 0111 0112 } 0113 0114 #include "moc_x11_standalone_effects.cpp"