diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt index 2974d9664..d4fdc79ff 100644 --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -1,312 +1,323 @@ add_definitions(-DKWIN_UNIT_TEST) remove_definitions(-DQT_USE_QSTRINGBUILDER) add_subdirectory(libkwineffects) add_subdirectory(libxrenderutils) add_subdirectory(integration) if (HAVE_INPUT) add_subdirectory(libinput) endif() add_subdirectory(tabbox) ######################################################## # Test ScreenPaintData ######################################################## set( testScreenPaintData_SRCS test_screen_paint_data.cpp ) add_executable(testScreenPaintData ${testScreenPaintData_SRCS}) target_link_libraries( testScreenPaintData kwineffects Qt5::Test Qt5::Widgets KF5::WindowSystem) add_test(kwin-testScreenPaintData testScreenPaintData) ecm_mark_as_test(testScreenPaintData) ######################################################## # Test WindowPaintData ######################################################## set( testWindowPaintData_SRCS test_window_paint_data.cpp ) add_executable(testWindowPaintData ${testWindowPaintData_SRCS}) target_link_libraries( testWindowPaintData kwineffects Qt5::Widgets Qt5::Test ) add_test(kwin-testWindowPaintData testWindowPaintData) ecm_mark_as_test(testWindowPaintData) ######################################################## # Test VirtualDesktopManager ######################################################## set( testVirtualDesktops_SRCS test_virtual_desktops.cpp ../virtualdesktops.cpp ) add_executable(testVirtualDesktops ${testVirtualDesktops_SRCS}) target_link_libraries( testVirtualDesktops Qt5::Test Qt5::Widgets KF5::I18n KF5::GlobalAccel KF5::ConfigCore KF5::WindowSystem ) add_test(kwin-testVirtualDesktops testVirtualDesktops) ecm_mark_as_test(testVirtualDesktops) ######################################################## # Test ClientMachine ######################################################## set( testClientMachine_SRCS test_client_machine.cpp ../client_machine.cpp ) add_executable( testClientMachine ${testClientMachine_SRCS} ) target_link_libraries( testClientMachine Qt5::Concurrent Qt5::Test Qt5::X11Extras Qt5::Widgets KF5::ConfigCore KF5::WindowSystem XCB::XCB XCB::XFIXES ${X11_X11_LIB} # to make jenkins happy ) add_test(kwin-testClientMachine testClientMachine) ecm_mark_as_test(testClientMachine) ######################################################## # Test XcbWrapper ######################################################## set( testXcbWrapper_SRCS test_xcb_wrapper.cpp ) add_executable( testXcbWrapper ${testXcbWrapper_SRCS} ) target_link_libraries( testXcbWrapper Qt5::Test Qt5::X11Extras Qt5::Widgets KF5::ConfigCore KF5::WindowSystem XCB::XCB ) add_test(kwin-testXcbWrapper testXcbWrapper) ecm_mark_as_test(testXcbWrapper) if (XCB_ICCCM_FOUND) add_executable( testXcbSizeHints test_xcb_size_hints.cpp ) target_link_libraries( testXcbSizeHints Qt5::Test Qt5::X11Extras KF5::ConfigCore KF5::WindowSystem XCB::XCB XCB::ICCCM ) add_test(kwin-testXcbSizeHints testXcbSizeHints) ecm_mark_as_test(testXcbSizeHints) endif() ######################################################## # Test XcbWindow ######################################################## set( testXcbWindow_SRCS test_xcb_window.cpp ) add_executable( testXcbWindow ${testXcbWindow_SRCS} ) target_link_libraries( testXcbWindow Qt5::Test Qt5::X11Extras Qt5::Widgets KF5::ConfigCore KF5::WindowSystem XCB::XCB ) add_test(kwin-testXcbWindow testXcbWindow) ecm_mark_as_test(testXcbWindow) ######################################################## # Test BuiltInEffectLoader ######################################################## set( testBuiltInEffectLoader_SRCS test_builtin_effectloader.cpp mock_effectshandler.cpp ../effectloader.cpp ) add_executable( testBuiltInEffectLoader ${testBuiltInEffectLoader_SRCS}) target_link_libraries(testBuiltInEffectLoader Qt5::Concurrent Qt5::Test KF5::Package kwineffects kwin4_effect_builtins ) add_test(kwin-testBuiltInEffectLoader testBuiltInEffectLoader) ecm_mark_as_test(testBuiltInEffectLoader) ######################################################## # Test ScriptedEffectLoader ######################################################## include_directories(${KWIN_SOURCE_DIR}) set( testScriptedEffectLoader_SRCS test_scripted_effectloader.cpp mock_effectshandler.cpp ../effectloader.cpp ../scripting/scriptedeffect.cpp ../scripting/scriptingutils.cpp ../scripting/scripting_logging.cpp ) add_executable( testScriptedEffectLoader ${testScriptedEffectLoader_SRCS}) target_link_libraries(testScriptedEffectLoader Qt5::Concurrent Qt5::Script Qt5::Test KF5::ConfigGui KF5::GlobalAccel KF5::I18n KF5::Package kwineffects kwin4_effect_builtins ) add_test(kwin-testScriptedEffectLoader testScriptedEffectLoader) ecm_mark_as_test(testScriptedEffectLoader) ######################################################## # Test PluginEffectLoader ######################################################## set( testPluginEffectLoader_SRCS test_plugin_effectloader.cpp mock_effectshandler.cpp ../effectloader.cpp ) add_executable( testPluginEffectLoader ${testPluginEffectLoader_SRCS}) target_link_libraries(testPluginEffectLoader Qt5::Concurrent Qt5::Test KF5::Package kwineffects kwin4_effect_builtins ) add_test(kwin-testPluginEffectLoader testPluginEffectLoader) ecm_mark_as_test(testPluginEffectLoader) ######################################################## # FakeEffectPlugin ######################################################## add_library(fakeeffectplugin MODULE fakeeffectplugin.cpp) set_target_properties(fakeeffectplugin PROPERTIES PREFIX "") target_link_libraries(fakeeffectplugin kwineffects) ######################################################## # FakeEffectPlugin-Version ######################################################## add_library(effectversionplugin MODULE fakeeffectplugin_version.cpp) set_target_properties(effectversionplugin PROPERTIES PREFIX "") target_link_libraries(effectversionplugin kwineffects) ######################################################## # Test Screens ######################################################## set( testScreens_SRCS test_screens.cpp mock_abstract_client.cpp mock_client.cpp mock_screens.cpp mock_workspace.cpp ../screens.cpp ../x11eventfilter.cpp ) kconfig_add_kcfg_files(testScreens_SRCS ../settings.kcfgc) add_executable( testScreens ${testScreens_SRCS}) target_include_directories(testScreens BEFORE PRIVATE ./) target_link_libraries(testScreens Qt5::Test Qt5::X11Extras KF5::ConfigCore KF5::ConfigGui KF5::WindowSystem ) add_test(kwin_testScreens testScreens) ecm_mark_as_test(testScreens) ######################################################## # Test XrandRScreens ######################################################## set( testXRandRScreens_SRCS test_xrandr_screens.cpp mock_abstract_client.cpp mock_client.cpp mock_screens.cpp mock_workspace.cpp ../screens.cpp ../plugins/platforms/x11/standalone/screens_xrandr.cpp ../xcbutils.cpp # init of extensions ../x11eventfilter.cpp ) kconfig_add_kcfg_files(testXRandRScreens_SRCS ../settings.kcfgc) add_executable( testXRandRScreens ${testXRandRScreens_SRCS} ) target_link_libraries( testXRandRScreens Qt5::Test Qt5::Gui KF5::ConfigCore KF5::ConfigGui KF5::WindowSystem XCB::XCB XCB::RANDR XCB::XFIXES XCB::SYNC XCB::COMPOSITE XCB::DAMAGE XCB::GLX XCB::SHM ) add_test(kwin-testXRandRScreens testXRandRScreens) ecm_mark_as_test(testXRandRScreens) ######################################################## # Test ScreenEdges ######################################################## set( testScreenEdges_SRCS test_screen_edges.cpp mock_abstract_client.cpp mock_client.cpp mock_screens.cpp mock_workspace.cpp ../atoms.cpp ../screens.cpp ../screenedge.cpp ../virtualdesktops.cpp ../xcbutils.cpp # init of extensions ../plugins/platforms/x11/standalone/edge.cpp ) kconfig_add_kcfg_files(testScreenEdges_SRCS ../settings.kcfgc) qt5_add_dbus_interface( testScreenEdges_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/../org.freedesktop.ScreenSaver.xml screenlocker_interface) add_executable( testScreenEdges ${testScreenEdges_SRCS}) target_include_directories(testScreenEdges BEFORE PRIVATE ./) target_link_libraries(testScreenEdges Qt5::DBus Qt5::Test Qt5::X11Extras KF5::ConfigCore KF5::ConfigGui KF5::I18n KF5::GlobalAccel KF5::WindowSystem XCB::XCB XCB::RANDR XCB::XFIXES XCB::SYNC XCB::COMPOSITE XCB::DAMAGE XCB::GLX XCB::SHM ) add_test(kwin_testScreenEdges testScreenEdges) ecm_mark_as_test(testScreenEdges) + +######################################################## +# Test X11 TimestampUpdate +######################################################## +add_executable(testX11TimestampUpdate test_x11_timestamp_update.cpp) +target_link_libraries(testX11TimestampUpdate + Qt5::Test + kwin +) +add_test(kwin-testX11TimestampUpdate testX11TimestampUpdate) +ecm_mark_as_test(testX11TimestampUpdate) diff --git a/autotests/test_x11_timestamp_update.cpp b/autotests/test_x11_timestamp_update.cpp new file mode 100644 index 000000000..50ba151d3 --- /dev/null +++ b/autotests/test_x11_timestamp_update.cpp @@ -0,0 +1,123 @@ +/******************************************************************** +KWin - the KDE window manager +This file is part of the KDE project. + +Copyright (C) 2017 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#include +#include + +#include "main.h" +#include "utils.h" + +namespace KWin +{ + +class X11TestApplication : public Application +{ + Q_OBJECT +public: + X11TestApplication(int &argc, char **argv); + virtual ~X11TestApplication(); + +protected: + void performStartup() override; + +}; + +X11TestApplication::X11TestApplication(int &argc, char **argv) + : Application(OperationModeX11, argc, argv) +{ + setX11Connection(QX11Info::connection()); + setX11RootWindow(QX11Info::appRootWindow()); +} + +X11TestApplication::~X11TestApplication() +{ +} + +void X11TestApplication::performStartup() +{ +} + +} + +class X11TimestampUpdateTest : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void testGrabAfterServerTime(); + void testBeforeLastGrabTime(); +}; + +void X11TimestampUpdateTest::testGrabAfterServerTime() +{ + // this test tries to grab the X keyboard with a timestamp in future + // that should fail, but after updating the X11 timestamp, it should + // work again + KWin::updateXTime(); + QCOMPARE(KWin::grabXKeyboard(), true); + KWin::ungrabXKeyboard(); + + // now let's change the timestamp + KWin::kwinApp()->setX11Time(KWin::xTime() + 5 * 60 * 1000); + + // now grab keyboard should fail + QCOMPARE(KWin::grabXKeyboard(), false); + + // let's update timestamp, now it should work again + KWin::updateXTime(); + QCOMPARE(KWin::grabXKeyboard(), true); + KWin::ungrabXKeyboard(); +} + +void X11TimestampUpdateTest::testBeforeLastGrabTime() +{ + // this test tries to grab the X keyboard with a timestamp before the + // last grab time on the server. That should fail, but after updating the X11 + // timestamp it should work again + + // first set the grab timestamp + KWin::updateXTime(); + QCOMPARE(KWin::grabXKeyboard(), true); + KWin::ungrabXKeyboard(); + + // now go to past + const auto timestamp = KWin::xTime(); + KWin::kwinApp()->setX11Time(KWin::xTime() - 5 * 60 * 1000, KWin::Application::TimestampUpdate::Always); + QCOMPARE(KWin::xTime(), timestamp - 5 * 60 * 1000); + + // now grab keyboard should fail + QCOMPARE(KWin::grabXKeyboard(), false); + + // let's update timestamp, now it should work again + KWin::updateXTime(); + QVERIFY(KWin::xTime() >= timestamp); + QCOMPARE(KWin::grabXKeyboard(), true); + KWin::ungrabXKeyboard(); +} + +int main(int argc, char *argv[]) +{ + setenv("QT_QPA_PLATFORM", "xcb", true); + KWin::X11TestApplication app(argc, argv); + app.setAttribute(Qt::AA_Use96Dpi, true); + X11TimestampUpdateTest tc; + return QTest::qExec(&tc, argc, argv); +} + +#include "test_x11_timestamp_update.moc" diff --git a/main.h b/main.h index a7dd47dd6..6706c0faf 100644 --- a/main.h +++ b/main.h @@ -1,242 +1,246 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 1999, 2000 Matthias Ettrich Copyright (C) 2003 Lubos Lunak This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #ifndef MAIN_H #define MAIN_H #include #include #include #include #include // Qt #include #include #include class KPluginMetaData; class QCommandLineParser; namespace KWin { class Platform; class XcbEventFilter : public QAbstractNativeEventFilter { public: virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long int *result) override; }; class KWIN_EXPORT Application : public QApplication { Q_OBJECT Q_PROPERTY(quint32 x11Time READ x11Time WRITE setX11Time) Q_PROPERTY(quint32 x11RootWindow READ x11RootWindow CONSTANT) Q_PROPERTY(void *x11Connection READ x11Connection NOTIFY x11ConnectionChanged) Q_PROPERTY(int x11ScreenNumber READ x11ScreenNumber CONSTANT) public: /** * @brief This enum provides the various operation modes of KWin depending on the available * Windowing Systems at startup. For example whether KWin only talks to X11 or also to a Wayland * Compositor. * */ enum OperationMode { /** * @brief KWin uses only X11 for managing windows and compositing */ OperationModeX11, /** * @brief KWin uses X11 for managing windows, but renders to a Wayland compositor. * Input is received from the Wayland compositor. */ OperationModeWaylandAndX11, /** * @brief KWin uses Wayland and controls a nested Xwayland server. **/ OperationModeXwayland }; virtual ~Application(); void setConfigLock(bool lock); KSharedConfigPtr config() const { return m_config; } void setConfig(KSharedConfigPtr config) { m_config = config; } void start(); /** * @brief The operation mode used by KWin. * * @return OperationMode */ OperationMode operationMode() const; void setOperationMode(OperationMode mode); bool shouldUseWaylandForCompositing() const; void setupTranslator(); void setupCommandLine(QCommandLineParser *parser); void processCommandLine(QCommandLineParser *parser); xcb_timestamp_t x11Time() const { return m_x11Time; } - void setX11Time(xcb_timestamp_t timestamp) { - if (timestamp > m_x11Time) { + enum class TimestampUpdate { + OnlyIfLarger, + Always + }; + void setX11Time(xcb_timestamp_t timestamp, TimestampUpdate force = TimestampUpdate::OnlyIfLarger) { + if (timestamp > m_x11Time || force == TimestampUpdate::Always) { m_x11Time = timestamp; } } void updateX11Time(xcb_generic_event_t *event); void createScreens(); static void setCrashCount(int count); static bool wasCrash(); /** * Creates the KAboutData object for the KWin instance and registers it as * KAboutData::setApplicationData. **/ static void createAboutData(); /** * @returns the X11 Screen number. If not applicable it's set to @c -1. **/ static int x11ScreenNumber(); /** * Sets the X11 screen number of this KWin instance to @p screenNumber. **/ static void setX11ScreenNumber(int screenNumber); /** * @returns whether this is a multi head setup on X11. **/ static bool isX11MultiHead(); /** * Sets whether this is a multi head setup on X11. */ static void setX11MultiHead(bool multiHead); /** * @returns the X11 root window. **/ xcb_window_t x11RootWindow() const { return m_rootWindow; } /** * @returns the X11 xcb connection **/ xcb_connection_t *x11Connection() const { return m_connection; } #ifdef KWIN_BUILD_ACTIVITIES bool usesKActivities() const { return m_useKActivities; } void setUseKActivities(bool use) { m_useKActivities = use; } #endif virtual QProcessEnvironment processStartupEnvironment() const; void initPlatform(const KPluginMetaData &plugin); Platform *platform() const { return m_platform; } static void setupMalloc(); static void setupLocalizedString(); static bool usesLibinput(); static void setUseLibinput(bool use); Q_SIGNALS: void x11ConnectionChanged(); void x11ConnectionAboutToBeDestroyed(); void workspaceCreated(); void screensCreated(); void virtualTerminalCreated(); protected: Application(OperationMode mode, int &argc, char **argv); virtual void performStartup() = 0; void notifyKSplash(); void createInput(); void createWorkspace(); void createAtoms(); void createOptions(); void createCompositor(); void setupEventFilters(); void destroyWorkspace(); void destroyCompositor(); /** * Inheriting classes should use this method to set the X11 root window * before accessing any X11 specific code pathes. **/ void setX11RootWindow(xcb_window_t root) { m_rootWindow = root; } /** * Inheriting classes should use this method to set the xcb connection * before accessing any X11 specific code pathes. **/ void setX11Connection(xcb_connection_t *c) { m_connection = c; emit x11ConnectionChanged(); } void destroyAtoms(); protected: QString m_originalSessionKey; static int crashes; private Q_SLOTS: void resetCrashesCount(); private: QScopedPointer m_eventFilter; bool m_configLock; KSharedConfigPtr m_config; OperationMode m_operationMode; xcb_timestamp_t m_x11Time = XCB_TIME_CURRENT_TIME; xcb_window_t m_rootWindow = XCB_WINDOW_NONE; xcb_connection_t *m_connection = nullptr; #ifdef KWIN_BUILD_ACTIVITIES bool m_useKActivities = true; #endif Platform *m_platform = nullptr; }; inline static Application *kwinApp() { return static_cast(QCoreApplication::instance()); } } // namespace #endif diff --git a/utils.cpp b/utils.cpp index ad45406e5..8d3f2ffbe 100644 --- a/utils.cpp +++ b/utils.cpp @@ -1,246 +1,246 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 1999, 2000 Matthias Ettrich Copyright (C) 2003 Lubos Lunak This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ /* This file is for (very) small utility functions/classes. */ #include "utils.h" #include #include #ifndef KCMRULES #include #include #include #include #include #include "atoms.h" #include "workspace.h" #include #endif Q_LOGGING_CATEGORY(KWIN_CORE, "kwin_core", QtCriticalMsg) namespace KWin { #ifndef KCMRULES //************************************ // StrutRect //************************************ StrutRect::StrutRect(QRect rect, StrutArea area) : QRect(rect) , m_area(area) { } StrutRect::StrutRect(const StrutRect& other) : QRect(other) , m_area(other.area()) { } #endif #ifndef KCMRULES /* Updates xTime(). This used to simply fetch current timestamp from the server, but that can cause xTime() to be newer than timestamp of events that are still in our events queue, thus e.g. making XSetInputFocus() caused by such event to be ignored. Therefore events queue is searched for first event with timestamp, and extra PropertyNotify is generated in order to make sure such event is found. */ void updateXTime() { // NOTE: QX11Info::getTimestamp does not yet search the event queue as the old // solution did. This means there might be regressions currently. See the // documentation above on how it should be done properly. - kwinApp()->setX11Time(QX11Info::getTimestamp()); + kwinApp()->setX11Time(QX11Info::getTimestamp(), Application::TimestampUpdate::Always); } static int server_grab_count = 0; void grabXServer() { if (++server_grab_count == 1) xcb_grab_server(connection()); } void ungrabXServer() { assert(server_grab_count > 0); if (--server_grab_count == 0) { xcb_ungrab_server(connection()); xcb_flush(connection()); } } bool grabbedXServer() { return server_grab_count > 0; } static bool keyboard_grabbed = false; bool grabXKeyboard(xcb_window_t w) { if (QWidget::keyboardGrabber() != NULL) return false; if (keyboard_grabbed) return false; if (qApp->activePopupWidget() != NULL) return false; if (w == XCB_WINDOW_NONE) w = rootWindow(); const xcb_grab_keyboard_cookie_t c = xcb_grab_keyboard_unchecked(connection(), false, w, xTime(), XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); ScopedCPointer grab(xcb_grab_keyboard_reply(connection(), c, NULL)); if (grab.isNull()) { return false; } if (grab->status != XCB_GRAB_STATUS_SUCCESS) { return false; } keyboard_grabbed = true; return true; } void ungrabXKeyboard() { if (!keyboard_grabbed) { // grabXKeyboard() may fail sometimes, so don't fail, but at least warn anyway qCDebug(KWIN_CORE) << "ungrabXKeyboard() called but keyboard not grabbed!"; } keyboard_grabbed = false; xcb_ungrab_keyboard(connection(), XCB_TIME_CURRENT_TIME); } Process::Process(QObject *parent) : QProcess(parent) { } Process::~Process() = default; void Process::setupChildProcess() { sigset_t userSiganls; sigemptyset(&userSiganls); sigaddset(&userSiganls, SIGUSR1); sigaddset(&userSiganls, SIGUSR2); pthread_sigmask(SIG_UNBLOCK, &userSiganls, nullptr); } #endif // converting between X11 mouse/keyboard state mask and Qt button/keyboard states int qtToX11Button(Qt::MouseButton button) { if (button == Qt::LeftButton) return XCB_BUTTON_INDEX_1; else if (button == Qt::MidButton) return XCB_BUTTON_INDEX_2; else if (button == Qt::RightButton) return XCB_BUTTON_INDEX_3; return XCB_BUTTON_INDEX_ANY; // 0 } Qt::MouseButton x11ToQtMouseButton(int button) { if (button == XCB_BUTTON_INDEX_1) return Qt::LeftButton; if (button == XCB_BUTTON_INDEX_2) return Qt::MidButton; if (button == XCB_BUTTON_INDEX_3) return Qt::RightButton; if (button == XCB_BUTTON_INDEX_4) return Qt::XButton1; if (button == XCB_BUTTON_INDEX_5) return Qt::XButton2; return Qt::NoButton; } int qtToX11State(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) { int ret = 0; if (buttons & Qt::LeftButton) ret |= XCB_KEY_BUT_MASK_BUTTON_1; if (buttons & Qt::MidButton) ret |= XCB_KEY_BUT_MASK_BUTTON_2; if (buttons & Qt::RightButton) ret |= XCB_KEY_BUT_MASK_BUTTON_3; if (modifiers & Qt::ShiftModifier) ret |= XCB_KEY_BUT_MASK_SHIFT; if (modifiers & Qt::ControlModifier) ret |= XCB_KEY_BUT_MASK_CONTROL; if (modifiers & Qt::AltModifier) ret |= KKeyServer::modXAlt(); if (modifiers & Qt::MetaModifier) ret |= KKeyServer::modXMeta(); return ret; } Qt::MouseButtons x11ToQtMouseButtons(int state) { Qt::MouseButtons ret = 0; if (state & XCB_KEY_BUT_MASK_BUTTON_1) ret |= Qt::LeftButton; if (state & XCB_KEY_BUT_MASK_BUTTON_2) ret |= Qt::MidButton; if (state & XCB_KEY_BUT_MASK_BUTTON_3) ret |= Qt::RightButton; if (state & XCB_KEY_BUT_MASK_BUTTON_4) ret |= Qt::XButton1; if (state & XCB_KEY_BUT_MASK_BUTTON_5) ret |= Qt::XButton2; return ret; } Qt::KeyboardModifiers x11ToQtKeyboardModifiers(int state) { Qt::KeyboardModifiers ret = 0; if (state & XCB_KEY_BUT_MASK_SHIFT) ret |= Qt::ShiftModifier; if (state & XCB_KEY_BUT_MASK_CONTROL) ret |= Qt::ControlModifier; if (state & KKeyServer::modXAlt()) ret |= Qt::AltModifier; if (state & KKeyServer::modXMeta()) ret |= Qt::MetaModifier; return ret; } } // namespace #ifndef KCMRULES #endif diff --git a/utils.h b/utils.h index e9fa91232..06980fd64 100644 --- a/utils.h +++ b/utils.h @@ -1,250 +1,250 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 1999, 2000 Matthias Ettrich Copyright (C) 2003 Lubos Lunak This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #ifndef KWIN_UTILS_H #define KWIN_UTILS_H // cmake stuff #include #include // kwin #include // KDE #include // Qt #include #include #include #include #include #include // system #include Q_DECLARE_LOGGING_CATEGORY(KWIN_CORE) namespace KWin { // window types that are supported as normal windows (i.e. KWin actually manages them) const NET::WindowTypes SUPPORTED_MANAGED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask /*| NET::OverrideMask*/ | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask | NET::NotificationMask | NET::OnScreenDisplayMask; // window types that are supported as unmanaged (mainly for compositing) const NET::WindowTypes SUPPORTED_UNMANAGED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask /*| NET::OverrideMask*/ | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask | NET::DropdownMenuMask | NET::PopupMenuMask | NET::TooltipMask | NET::NotificationMask | NET::ComboBoxMask | NET::DNDIconMask | NET::OnScreenDisplayMask; const QPoint invalidPoint(INT_MIN, INT_MIN); class Toplevel; class Client; class Unmanaged; class Deleted; class Group; class Options; typedef QList< Toplevel* > ToplevelList; typedef QList< Client* > ClientList; typedef QList< const Client* > ConstClientList; typedef QList< Unmanaged* > UnmanagedList; typedef QList< Deleted* > DeletedList; typedef QList< Group* > GroupList; extern Options* options; enum Layer { UnknownLayer = -1, FirstLayer = 0, DesktopLayer = FirstLayer, BelowLayer, NormalLayer, DockLayer, AboveLayer, NotificationLayer, // layer for windows of type notification ActiveLayer, // active fullscreen, or active dialog OnScreenDisplayLayer, // layer for On Screen Display windows such as volume feedback UnmanagedLayer, // layer for override redirect windows. NumLayers // number of layers, must be last }; // yes, I know this is not 100% like standard operator++ inline void operator++(Layer& lay) { lay = static_cast< Layer >(lay + 1); } enum StrutArea { StrutAreaInvalid = 0, // Null StrutAreaTop = 1 << 0, StrutAreaRight = 1 << 1, StrutAreaBottom = 1 << 2, StrutAreaLeft = 1 << 3, StrutAreaAll = StrutAreaTop | StrutAreaRight | StrutAreaBottom | StrutAreaLeft }; Q_DECLARE_FLAGS(StrutAreas, StrutArea) class StrutRect : public QRect { public: explicit StrutRect(QRect rect = QRect(), StrutArea area = StrutAreaInvalid); StrutRect(const StrutRect& other); inline StrutArea area() const { return m_area; }; private: StrutArea m_area; }; typedef QVector StrutRects; enum ShadeMode { ShadeNone, // not shaded ShadeNormal, // normally shaded - isShade() is true only here ShadeHover, // "shaded", but visible due to hover unshade ShadeActivated // "shaded", but visible due to alt+tab to the window }; /** * Maximize mode. These values specify how a window is maximized. */ // these values are written to session files, don't change the order enum MaximizeMode { MaximizeRestore = 0, ///< The window is not maximized in any direction. MaximizeVertical = 1, ///< The window is maximized vertically. MaximizeHorizontal = 2, ///< The window is maximized horizontally. /// Equal to @p MaximizeVertical | @p MaximizeHorizontal MaximizeFull = MaximizeVertical | MaximizeHorizontal }; inline MaximizeMode operator^(MaximizeMode m1, MaximizeMode m2) { return MaximizeMode(int(m1) ^ int(m2)); } template using ScopedCPointer = QScopedPointer; -void updateXTime(); +void KWIN_EXPORT updateXTime(); void grabXServer(); void ungrabXServer(); bool grabbedXServer(); -bool grabXKeyboard(xcb_window_t w = rootWindow()); -void ungrabXKeyboard(); +bool KWIN_EXPORT grabXKeyboard(xcb_window_t w = rootWindow()); +void KWIN_EXPORT ungrabXKeyboard(); /** * Small helper class which performs @link grabXServer in the ctor and * @link ungrabXServer in the dtor. Use this class to ensure that grab and * ungrab are matched. * * To simplify usage consider using the macro GRAB_SERVER_DURING_CONTEXT **/ class XServerGrabber { public: XServerGrabber() { grabXServer(); } ~XServerGrabber() { ungrabXServer(); } }; #define GRAB_SERVER_DURING_CONTEXT XServerGrabber xserverGrabber; // the docs say it's UrgencyHint, but it's often #defined as XUrgencyHint #ifndef UrgencyHint #define UrgencyHint XUrgencyHint #endif // converting between X11 mouse/keyboard state mask and Qt button/keyboard states int qtToX11Button(Qt::MouseButton button); Qt::MouseButton x11ToQtMouseButton(int button); int qtToX11State(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers); Qt::MouseButtons KWIN_EXPORT x11ToQtMouseButtons(int state); Qt::KeyboardModifiers KWIN_EXPORT x11ToQtKeyboardModifiers(int state); void checkNonExistentClients(); static inline int bitCount(uint32_t mask) { #if defined(__GNUC__) return __builtin_popcount(mask); #else int count = 0; while (mask) { count += (mask & 1); mask >>= 1; } return count; #endif } /** * Separate the concept of an unet QPoint and 0,0 */ class ClearablePoint { public: inline bool isValid() const { return m_valid; } inline void clear(){ m_valid = false; } inline void setPoint(const QPoint &point) { m_point = point; m_valid = true; } inline QPoint point() const { return m_point; } private: QPoint m_point; bool m_valid = false; }; /** * QProcess subclass which unblocks SIGUSR in the child process. **/ class KWIN_EXPORT Process : public QProcess { Q_OBJECT public: explicit Process(QObject *parent = nullptr); virtual ~Process(); protected: void setupChildProcess() override; }; } // namespace // Must be outside namespace Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::StrutAreas) #endif