diff --git a/atoms.h b/atoms.h --- a/atoms.h +++ b/atoms.h @@ -28,7 +28,7 @@ namespace KWin { -class Atoms +class KWIN_EXPORT Atoms { public: Atoms(); @@ -82,7 +82,7 @@ }; -extern Atoms* atoms; +extern KWIN_EXPORT Atoms* atoms; } // namespace diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -276,6 +276,7 @@ ../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) diff --git a/autotests/test_screen_edges.cpp b/autotests/test_screen_edges.cpp --- a/autotests/test_screen_edges.cpp +++ b/autotests/test_screen_edges.cpp @@ -94,11 +94,6 @@ { } -Application::OperationMode Application::operationMode() const -{ - return OperationModeX11; -} - class TestObject : public QObject { Q_OBJECT diff --git a/platform.h b/platform.h --- a/platform.h +++ b/platform.h @@ -34,9 +34,11 @@ namespace KWin { +class Edge; class OpenGLBackend; class QPainterBackend; class Screens; +class ScreenEdges; class WaylandCursorTheme; class KWIN_EXPORT Platform : public QObject @@ -49,6 +51,11 @@ virtual Screens *createScreens(QObject *parent = nullptr); virtual OpenGLBackend *createOpenGLBackend(); virtual QPainterBackend *createQPainterBackend(); + /** + * Allows the platform to create a platform specific screen edge. + * The default implementation creates a Edge. + **/ + virtual Edge *createScreenEdge(ScreenEdges *parent); virtual void warpPointer(const QPointF &globalPos); /** * Whether our Compositing EGL display allows a surface less context diff --git a/platform.cpp b/platform.cpp --- a/platform.cpp +++ b/platform.cpp @@ -25,6 +25,7 @@ #include "input.h" #include "pointer_input.h" #include "scene_opengl.h" +#include "screenedge.h" #include "wayland_server.h" namespace KWin @@ -65,6 +66,11 @@ return nullptr; } +Edge *Platform::createScreenEdge(ScreenEdges *edges) +{ + return new Edge(edges); +} + void Platform::configurationChangeRequested(KWayland::Server::OutputConfigurationInterface *config) { Q_UNUSED(config) diff --git a/plugins/platforms/x11/standalone/CMakeLists.txt b/plugins/platforms/x11/standalone/CMakeLists.txt --- a/plugins/platforms/x11/standalone/CMakeLists.txt +++ b/plugins/platforms/x11/standalone/CMakeLists.txt @@ -1,4 +1,5 @@ set(X11PLATFORM_SOURCES + edge.cpp logging.cpp x11_platform.cpp screens_xrandr.cpp diff --git a/plugins/platforms/x11/standalone/edge.h b/plugins/platforms/x11/standalone/edge.h new file mode 100644 --- /dev/null +++ b/plugins/platforms/x11/standalone/edge.h @@ -0,0 +1,78 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2011 Arthur Arlt +Copyright (C) 2013 Martin Gräßlin + +Since the functionality provided in this class has been moved from +class Workspace, it is not clear who exactly has written the code. +The list below contains the copyright holders of the class Workspace. + +Copyright (C) 1999, 2000 Matthias Ettrich +Copyright (C) 2003 Lubos Lunak +Copyright (C) 2009 Lucas Murray + +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_EDGE_H +#define KWIN_EDGE_H +#include "screenedge.h" +#include "xcbutils.h" + +namespace KWin +{ + +class WindowBasedEdge : public Edge +{ + Q_OBJECT +public: + explicit WindowBasedEdge(ScreenEdges *parent); + virtual ~WindowBasedEdge(); + + quint32 window() const override; + /** + * The approach window is a special window to notice when get close to the screen border but + * not yet triggering the border. + **/ + quint32 approachWindow() const override; + +protected: + virtual void doGeometryUpdate(); + virtual void activate(); + virtual void deactivate(); + virtual void doStartApproaching(); + virtual void doStopApproaching(); + virtual void doUpdateBlocking(); + +private: + void createWindow(); + void createApproachWindow(); + Xcb::Window m_window; + Xcb::Window m_approachWindow; +}; + +inline quint32 WindowBasedEdge::window() const +{ + return m_window; +} + +inline quint32 WindowBasedEdge::approachWindow() const +{ + return m_approachWindow; +} + +} + +#endif diff --git a/plugins/platforms/x11/standalone/edge.cpp b/plugins/platforms/x11/standalone/edge.cpp new file mode 100644 --- /dev/null +++ b/plugins/platforms/x11/standalone/edge.cpp @@ -0,0 +1,131 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2011 Arthur Arlt +Copyright (C) 2013 Martin Gräßlin + +Since the functionality provided in this class has been moved from +class Workspace, it is not clear who exactly has written the code. +The list below contains the copyright holders of the class Workspace. + +Copyright (C) 1999, 2000 Matthias Ettrich +Copyright (C) 2003 Lubos Lunak +Copyright (C) 2009 Lucas Murray + +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 "edge.h" +#include "atoms.h" +#include "cursor.h" + +namespace KWin +{ + +WindowBasedEdge::WindowBasedEdge(ScreenEdges *parent) + : Edge(parent) + , m_window(XCB_WINDOW_NONE) + , m_approachWindow(XCB_WINDOW_NONE) +{ +} + +WindowBasedEdge::~WindowBasedEdge() +{ +} + +void WindowBasedEdge::activate() +{ + createWindow(); + createApproachWindow(); + doUpdateBlocking(); +} + +void WindowBasedEdge::deactivate() +{ + m_window.reset(); + m_approachWindow.reset(); +} + +void WindowBasedEdge::createWindow() +{ + if (m_window.isValid()) { + return; + } + const uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK; + const uint32_t values[] = { + true, + XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_POINTER_MOTION + }; + m_window.create(geometry(), XCB_WINDOW_CLASS_INPUT_ONLY, mask, values); + m_window.map(); + // Set XdndAware on the windows, so that DND enter events are received (#86998) + xcb_atom_t version = 4; // XDND version + xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, m_window, + atoms->xdnd_aware, XCB_ATOM_ATOM, 32, 1, (unsigned char*)(&version)); +} + +void WindowBasedEdge::createApproachWindow() +{ + if (m_approachWindow.isValid()) { + return; + } + if (!approachGeometry().isValid()) { + return; + } + const uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK; + const uint32_t values[] = { + true, + XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_POINTER_MOTION + }; + m_approachWindow.create(approachGeometry(), XCB_WINDOW_CLASS_INPUT_ONLY, mask, values); + m_approachWindow.map(); +} + +void WindowBasedEdge::doGeometryUpdate() +{ + m_window.setGeometry(geometry()); + m_approachWindow.setGeometry(approachGeometry()); +} + +void WindowBasedEdge::doStartApproaching() +{ + m_approachWindow.unmap(); + Cursor *cursor = Cursor::self(); + connect(cursor, SIGNAL(posChanged(QPoint)), SLOT(updateApproaching(QPoint))); + cursor->startMousePolling(); +} + +void WindowBasedEdge::doStopApproaching() +{ + Cursor *cursor = Cursor::self(); + disconnect(cursor, SIGNAL(posChanged(QPoint)), this, SLOT(updateApproaching(QPoint))); + cursor->stopMousePolling(); + m_approachWindow.map(); +} + +void WindowBasedEdge::doUpdateBlocking() +{ + if (!isReserved()) { + return; + } + if (isBlocked()) { + m_window.unmap(); + m_approachWindow.unmap(); + } else { + m_window.map(); + m_approachWindow.map(); + } +} + +} diff --git a/plugins/platforms/x11/standalone/x11_platform.h b/plugins/platforms/x11/standalone/x11_platform.h --- a/plugins/platforms/x11/standalone/x11_platform.h +++ b/plugins/platforms/x11/standalone/x11_platform.h @@ -40,6 +40,7 @@ Screens *createScreens(QObject *parent = nullptr) override; OpenGLBackend *createOpenGLBackend() override; + Edge *createScreenEdge(ScreenEdges *parent) override; }; diff --git a/plugins/platforms/x11/standalone/x11_platform.cpp b/plugins/platforms/x11/standalone/x11_platform.cpp --- a/plugins/platforms/x11/standalone/x11_platform.cpp +++ b/plugins/platforms/x11/standalone/x11_platform.cpp @@ -18,6 +18,7 @@ along with this program. If not, see . *********************************************************************/ #include "x11_platform.h" +#include "edge.h" #include #if HAVE_EPOXY_GLX #include "glxbackend.h" @@ -68,4 +69,9 @@ } } +Edge *X11StandalonePlatform::createScreenEdge(ScreenEdges *edges) +{ + return new WindowBasedEdge(edges); +} + } diff --git a/screenedge.h b/screenedge.h --- a/screenedge.h +++ b/screenedge.h @@ -31,22 +31,22 @@ #define KWIN_SCREENEDGE_H // KWin #include "kwinglobals.h" -#include "xcbutils.h" // KDE includes #include // Qt #include #include #include +#include class QMouseEvent; namespace KWin { class Client; class ScreenEdges; -class Edge : public QObject +class KWIN_EXPORT Edge : public QObject { Q_OBJECT public: @@ -132,35 +132,6 @@ Client *m_client; }; -class WindowBasedEdge : public Edge -{ - Q_OBJECT -public: - explicit WindowBasedEdge(ScreenEdges *parent); - virtual ~WindowBasedEdge(); - - quint32 window() const override; - /** - * The approach window is a special window to notice when get close to the screen border but - * not yet triggering the border. - **/ - quint32 approachWindow() const override; - -protected: - virtual void doGeometryUpdate(); - virtual void activate(); - virtual void deactivate(); - virtual void doStartApproaching(); - virtual void doStopApproaching(); - virtual void doUpdateBlocking(); - -private: - void createWindow(); - void createApproachWindow(); - Xcb::Window m_window; - Xcb::Window m_approachWindow; -}; - /** * @short Class for controlling screen edges. * @@ -497,20 +468,6 @@ } /********************************************************** - * Inlines WindowBasedEdge - *********************************************************/ - -inline quint32 WindowBasedEdge::window() const -{ - return m_window; -} - -inline quint32 WindowBasedEdge::approachWindow() const -{ - return m_approachWindow; -} - -/********************************************************** * Inlines ScreenEdges *********************************************************/ inline void ScreenEdges::setConfig(KSharedConfig::Ptr config) diff --git a/screenedge.cpp b/screenedge.cpp --- a/screenedge.cpp +++ b/screenedge.cpp @@ -34,10 +34,14 @@ #include #include "cursor.h" #include "main.h" +#include "platform.h" #include "screens.h" #include "utils.h" #include #include "virtualdesktops.h" +#ifdef KWIN_UNIT_TEST +#include "plugins/platforms/x11/standalone/edge.h" +#endif // DBus generated #include "screenlocker_interface.h" // frameworks @@ -500,104 +504,6 @@ /********************************************************** * ScreenEdges *********************************************************/ -WindowBasedEdge::WindowBasedEdge(ScreenEdges *parent) - : Edge(parent) - , m_window(XCB_WINDOW_NONE) - , m_approachWindow(XCB_WINDOW_NONE) -{ -} - -WindowBasedEdge::~WindowBasedEdge() -{ -} - -void WindowBasedEdge::activate() -{ - createWindow(); - createApproachWindow(); - doUpdateBlocking(); -} - -void WindowBasedEdge::deactivate() -{ - m_window.reset(); - m_approachWindow.reset(); -} - -void WindowBasedEdge::createWindow() -{ - if (m_window.isValid()) { - return; - } - const uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK; - const uint32_t values[] = { - true, - XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_POINTER_MOTION - }; - m_window.create(geometry(), XCB_WINDOW_CLASS_INPUT_ONLY, mask, values); - m_window.map(); - // Set XdndAware on the windows, so that DND enter events are received (#86998) - xcb_atom_t version = 4; // XDND version - xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, m_window, - atoms->xdnd_aware, XCB_ATOM_ATOM, 32, 1, (unsigned char*)(&version)); -} - -void WindowBasedEdge::createApproachWindow() -{ - if (m_approachWindow.isValid()) { - return; - } - if (!approachGeometry().isValid()) { - return; - } - const uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK; - const uint32_t values[] = { - true, - XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_POINTER_MOTION - }; - m_approachWindow.create(approachGeometry(), XCB_WINDOW_CLASS_INPUT_ONLY, mask, values); - m_approachWindow.map(); -} - -void WindowBasedEdge::doGeometryUpdate() -{ - m_window.setGeometry(geometry()); - m_approachWindow.setGeometry(approachGeometry()); -} - -void WindowBasedEdge::doStartApproaching() -{ - m_approachWindow.unmap(); - Cursor *cursor = Cursor::self(); - connect(cursor, SIGNAL(posChanged(QPoint)), SLOT(updateApproaching(QPoint))); - cursor->startMousePolling(); -} - -void WindowBasedEdge::doStopApproaching() -{ - Cursor *cursor = Cursor::self(); - disconnect(cursor, SIGNAL(posChanged(QPoint)), this, SLOT(updateApproaching(QPoint))); - cursor->stopMousePolling(); - m_approachWindow.map(); -} - -void WindowBasedEdge::doUpdateBlocking() -{ - if (!isReserved()) { - return; - } - if (isBlocked()) { - m_window.unmap(); - m_approachWindow.unmap(); - } else { - m_window.map(); - m_approachWindow.map(); - } -} - -/********************************************************** - * ScreenEdges - *********************************************************/ KWIN_SINGLETON_FACTORY(ScreenEdges) ScreenEdges::ScreenEdges(QObject *parent) @@ -947,12 +853,11 @@ Edge *ScreenEdges::createEdge(ElectricBorder border, int x, int y, int width, int height, bool createAction) { - Edge *edge; - if (kwinApp()->operationMode() == Application::OperationModeX11) { - edge = new WindowBasedEdge(this); - } else { - edge = new Edge(this); - } +#ifdef KWIN_UNIT_TEST + Edge *edge = new WindowBasedEdge(this); +#else + Edge *edge = kwinApp()->platform()->createScreenEdge(this); +#endif edge->setBorder(border); edge->setGeometry(QRect(x, y, width, height)); if (createAction) {