diff --git a/overlaywindow.cpp b/overlaywindow.cpp index 91642786e2..ac697519fd 100644 --- a/overlaywindow.cpp +++ b/overlaywindow.cpp @@ -20,26 +20,8 @@ along with this program. If not, see . #include "overlaywindow.h" -#include "kwinglobals.h" -#include "screens.h" -#include "utils.h" -#include "xcbutils.h" - -#include "assert.h" - -#include - -#include -#include -#if XCB_COMPOSITE_MAJOR_VERSION > 0 || XCB_COMPOSITE_MINOR_VERSION >= 3 -#define KWIN_HAVE_XCOMPOSITE_OVERLAY -#endif - namespace KWin { OverlayWindow::OverlayWindow() - : m_visible(true) - , m_shown(false) - , m_window(XCB_WINDOW_NONE) { } @@ -47,137 +29,4 @@ OverlayWindow::~OverlayWindow() { } -bool OverlayWindow::create() -{ - assert(m_window == XCB_WINDOW_NONE); - if (!Xcb::Extensions::self()->isCompositeOverlayAvailable()) - return false; - if (!Xcb::Extensions::self()->isShapeInputAvailable()) // needed in setupOverlay() - return false; -#ifdef KWIN_HAVE_XCOMPOSITE_OVERLAY - Xcb::OverlayWindow overlay(rootWindow()); - if (overlay.isNull()) { - return false; - } - m_window = overlay->overlay_win; - if (m_window == XCB_WINDOW_NONE) - return false; - resize(screens()->size()); - return true; -#else - return false; -#endif -} - -void OverlayWindow::setup(xcb_window_t window) -{ - assert(m_window != XCB_WINDOW_NONE); - assert(Xcb::Extensions::self()->isShapeInputAvailable()); - setNoneBackgroundPixmap(m_window); - m_shape = QRegion(); - const QSize &s = screens()->size(); - setShape(QRect(0, 0, s.width(), s.height())); - if (window != XCB_WINDOW_NONE) { - setNoneBackgroundPixmap(window); - setupInputShape(window); - } - const uint32_t eventMask = XCB_EVENT_MASK_VISIBILITY_CHANGE; - xcb_change_window_attributes(connection(), m_window, XCB_CW_EVENT_MASK, &eventMask); -} - -void OverlayWindow::setupInputShape(xcb_window_t window) -{ - xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, window, 0, 0, 0, NULL); -} - -void OverlayWindow::setNoneBackgroundPixmap(xcb_window_t window) -{ - const uint32_t mask = XCB_BACK_PIXMAP_NONE; - xcb_change_window_attributes(connection(), window, XCB_CW_BACK_PIXMAP, &mask); -} - -void OverlayWindow::show() -{ - assert(m_window != XCB_WINDOW_NONE); - if (m_shown) - return; - xcb_map_subwindows(connection(), m_window); - xcb_map_window(connection(), m_window); - m_shown = true; -} - -void OverlayWindow::hide() -{ - assert(m_window != XCB_WINDOW_NONE); - xcb_unmap_window(connection(), m_window); - m_shown = false; - const QSize &s = screens()->size(); - setShape(QRect(0, 0, s.width(), s.height())); -} - -void OverlayWindow::setShape(const QRegion& reg) -{ - // Avoid setting the same shape again, it causes flicker (apparently it is not a no-op - // and triggers something). - if (reg == m_shape) - return; - QVector< QRect > rects = reg.rects(); - xcb_rectangle_t *xrects = new xcb_rectangle_t[rects.count()]; - for (int i = 0; - i < rects.count(); - ++i) { - xrects[ i ].x = rects[ i ].x(); - xrects[ i ].y = rects[ i ].y(); - xrects[ i ].width = rects[ i ].width(); - xrects[ i ].height = rects[ i ].height(); - } - xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, - m_window, 0, 0, rects.count(), xrects); - delete[] xrects; - setupInputShape(m_window); - m_shape = reg; -} - -void OverlayWindow::resize(const QSize &size) -{ - assert(m_window != XCB_WINDOW_NONE); - const uint32_t geometry[2] = { - static_cast(size.width()), - static_cast(size.height()) - }; - xcb_configure_window(connection(), m_window, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, geometry); - setShape(QRegion(0, 0, size.width(), size.height())); -} - -bool OverlayWindow::isVisible() const -{ - return m_visible; -} - -void OverlayWindow::setVisibility(bool visible) -{ - m_visible = visible; -} - -void OverlayWindow::destroy() -{ - if (m_window == XCB_WINDOW_NONE) - return; - // reset the overlay shape - const QSize &s = screens()->size(); - xcb_rectangle_t rec = { 0, 0, static_cast(s.width()), static_cast(s.height()) }; - xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, m_window, 0, 0, 1, &rec); - xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, m_window, 0, 0, 1, &rec); -#ifdef KWIN_HAVE_XCOMPOSITE_OVERLAY - xcb_composite_release_overlay_window(connection(), m_window); -#endif - m_window = XCB_WINDOW_NONE; - m_shown = false; -} - -xcb_window_t OverlayWindow::window() const -{ - return m_window; -} - } // namespace KWin diff --git a/overlaywindow.h b/overlaywindow.h index e1ec3ec2f5..0afff215d1 100644 --- a/overlaywindow.h +++ b/overlaywindow.h @@ -30,28 +30,22 @@ along with this program. If not, see . namespace KWin { class KWIN_EXPORT OverlayWindow { public: - OverlayWindow(); - ~OverlayWindow(); + virtual ~OverlayWindow(); /// Creates XComposite overlay window, call initOverlay() afterwards - bool create(); + virtual bool create() = 0; /// Init overlay and the destination window in it - void setup(xcb_window_t window); - void show(); - void hide(); // hides and resets overlay window - void setShape(const QRegion& reg); - void resize(const QSize &size); + virtual void setup(xcb_window_t window) = 0; + virtual void show() = 0; + virtual void hide() = 0; // hides and resets overlay window + virtual void setShape(const QRegion& reg) = 0; + virtual void resize(const QSize &size) = 0; /// Destroys XComposite overlay window - void destroy(); - xcb_window_t window() const; - bool isVisible() const; - void setVisibility(bool visible); -private: - void setNoneBackgroundPixmap(xcb_window_t window); - void setupInputShape(xcb_window_t window); - bool m_visible; - bool m_shown; // For showOverlay() - QRegion m_shape; - xcb_window_t m_window; + virtual void destroy() = 0; + virtual xcb_window_t window() const = 0; + virtual bool isVisible() const = 0; + virtual void setVisibility(bool visible) = 0; +protected: + OverlayWindow(); }; } // namespace diff --git a/platform.cpp b/platform.cpp index afd3e65532..91ac210c55 100644 --- a/platform.cpp +++ b/platform.cpp @@ -23,6 +23,7 @@ along with this program. If not, see . #include "composite.h" #include "cursor.h" #include "input.h" +#include "overlaywindow.h" #include "pointer_input.h" #include "scene_opengl.h" #include "screenedge.h" @@ -460,4 +461,9 @@ void Platform::setupActionForGlobalAccel(QAction *action) Q_UNUSED(action) } +OverlayWindow *Platform::createOverlayWindow() +{ + return nullptr; +} + } diff --git a/platform.h b/platform.h index f27feda837..35392bf5d5 100644 --- a/platform.h +++ b/platform.h @@ -40,6 +40,7 @@ namespace KWin { class Edge; +class OverlayWindow; class OpenGLBackend; class QPainterBackend; class Screens; @@ -301,6 +302,12 @@ public: m_initialOutputScale = scale; } + /** + * Creates the OverlayWindow required for X11 based compositors. + * Default implementation returns @c nullptr. + **/ + virtual OverlayWindow *createOverlayWindow(); + public Q_SLOTS: void pointerMotion(const QPointF &position, quint32 time); void pointerButtonPressed(quint32 button, quint32 time); diff --git a/plugins/platforms/x11/common/eglonxbackend.cpp b/plugins/platforms/x11/common/eglonxbackend.cpp index 49e23578d0..6eaf518a37 100644 --- a/plugins/platforms/x11/common/eglonxbackend.cpp +++ b/plugins/platforms/x11/common/eglonxbackend.cpp @@ -40,7 +40,7 @@ namespace KWin EglOnXBackend::EglOnXBackend(Display *display) : AbstractEglBackend() - , m_overlayWindow(new OverlayWindow()) + , m_overlayWindow(kwinApp()->platform()->createOverlayWindow()) , surfaceHasSubPost(0) , m_bufferAge(0) , m_usesOverlayWindow(true) diff --git a/plugins/platforms/x11/standalone/CMakeLists.txt b/plugins/platforms/x11/standalone/CMakeLists.txt index 98daa12208..c2cc0191a1 100644 --- a/plugins/platforms/x11/standalone/CMakeLists.txt +++ b/plugins/platforms/x11/standalone/CMakeLists.txt @@ -5,6 +5,7 @@ set(X11PLATFORM_SOURCES x11_platform.cpp screens_xrandr.cpp windowselector.cpp + overlaywindow_x11.cpp ) if(X11_Xinput_FOUND) diff --git a/plugins/platforms/x11/standalone/glxbackend.cpp b/plugins/platforms/x11/standalone/glxbackend.cpp index 438052fb40..ee86434c50 100644 --- a/plugins/platforms/x11/standalone/glxbackend.cpp +++ b/plugins/platforms/x11/standalone/glxbackend.cpp @@ -29,6 +29,7 @@ along with this program. If not, see . #include "options.h" #include "overlaywindow.h" #include "composite.h" +#include "platform.h" #include "screens.h" #include "xcbutils.h" // kwin libs @@ -104,7 +105,7 @@ bool SwapEventFilter::event(xcb_generic_event_t *event) GlxBackend::GlxBackend(Display *display) : OpenGLBackend() - , m_overlayWindow(new OverlayWindow()) + , m_overlayWindow(kwinApp()->platform()->createOverlayWindow()) , window(None) , fbconfig(NULL) , glxWindow(None) diff --git a/plugins/platforms/x11/standalone/overlaywindow_x11.cpp b/plugins/platforms/x11/standalone/overlaywindow_x11.cpp new file mode 100644 index 0000000000..c1e4fe9dae --- /dev/null +++ b/plugins/platforms/x11/standalone/overlaywindow_x11.cpp @@ -0,0 +1,185 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2011 Arthur Arlt + +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 "overlaywindow_x11.h" + +#include "kwinglobals.h" +#include "screens.h" +#include "utils.h" +#include "xcbutils.h" + +#include "assert.h" + +#include + +#include +#include +#if XCB_COMPOSITE_MAJOR_VERSION > 0 || XCB_COMPOSITE_MINOR_VERSION >= 3 +#define KWIN_HAVE_XCOMPOSITE_OVERLAY +#endif + +namespace KWin { +OverlayWindowX11::OverlayWindowX11() + : OverlayWindow() + , m_visible(true) + , m_shown(false) + , m_window(XCB_WINDOW_NONE) +{ +} + +OverlayWindowX11::~OverlayWindowX11() +{ +} + +bool OverlayWindowX11::create() +{ + assert(m_window == XCB_WINDOW_NONE); + if (!Xcb::Extensions::self()->isCompositeOverlayAvailable()) + return false; + if (!Xcb::Extensions::self()->isShapeInputAvailable()) // needed in setupOverlay() + return false; +#ifdef KWIN_HAVE_XCOMPOSITE_OVERLAY + Xcb::OverlayWindow overlay(rootWindow()); + if (overlay.isNull()) { + return false; + } + m_window = overlay->overlay_win; + if (m_window == XCB_WINDOW_NONE) + return false; + resize(screens()->size()); + return true; +#else + return false; +#endif +} + +void OverlayWindowX11::setup(xcb_window_t window) +{ + assert(m_window != XCB_WINDOW_NONE); + assert(Xcb::Extensions::self()->isShapeInputAvailable()); + setNoneBackgroundPixmap(m_window); + m_shape = QRegion(); + const QSize &s = screens()->size(); + setShape(QRect(0, 0, s.width(), s.height())); + if (window != XCB_WINDOW_NONE) { + setNoneBackgroundPixmap(window); + setupInputShape(window); + } + const uint32_t eventMask = XCB_EVENT_MASK_VISIBILITY_CHANGE; + xcb_change_window_attributes(connection(), m_window, XCB_CW_EVENT_MASK, &eventMask); +} + +void OverlayWindowX11::setupInputShape(xcb_window_t window) +{ + xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, window, 0, 0, 0, NULL); +} + +void OverlayWindowX11::setNoneBackgroundPixmap(xcb_window_t window) +{ + const uint32_t mask = XCB_BACK_PIXMAP_NONE; + xcb_change_window_attributes(connection(), window, XCB_CW_BACK_PIXMAP, &mask); +} + +void OverlayWindowX11::show() +{ + assert(m_window != XCB_WINDOW_NONE); + if (m_shown) + return; + xcb_map_subwindows(connection(), m_window); + xcb_map_window(connection(), m_window); + m_shown = true; +} + +void OverlayWindowX11::hide() +{ + assert(m_window != XCB_WINDOW_NONE); + xcb_unmap_window(connection(), m_window); + m_shown = false; + const QSize &s = screens()->size(); + setShape(QRect(0, 0, s.width(), s.height())); +} + +void OverlayWindowX11::setShape(const QRegion& reg) +{ + // Avoid setting the same shape again, it causes flicker (apparently it is not a no-op + // and triggers something). + if (reg == m_shape) + return; + QVector< QRect > rects = reg.rects(); + xcb_rectangle_t *xrects = new xcb_rectangle_t[rects.count()]; + for (int i = 0; + i < rects.count(); + ++i) { + xrects[ i ].x = rects[ i ].x(); + xrects[ i ].y = rects[ i ].y(); + xrects[ i ].width = rects[ i ].width(); + xrects[ i ].height = rects[ i ].height(); + } + xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, + m_window, 0, 0, rects.count(), xrects); + delete[] xrects; + setupInputShape(m_window); + m_shape = reg; +} + +void OverlayWindowX11::resize(const QSize &size) +{ + assert(m_window != XCB_WINDOW_NONE); + const uint32_t geometry[2] = { + static_cast(size.width()), + static_cast(size.height()) + }; + xcb_configure_window(connection(), m_window, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, geometry); + setShape(QRegion(0, 0, size.width(), size.height())); +} + +bool OverlayWindowX11::isVisible() const +{ + return m_visible; +} + +void OverlayWindowX11::setVisibility(bool visible) +{ + m_visible = visible; +} + +void OverlayWindowX11::destroy() +{ + if (m_window == XCB_WINDOW_NONE) + return; + // reset the overlay shape + const QSize &s = screens()->size(); + xcb_rectangle_t rec = { 0, 0, static_cast(s.width()), static_cast(s.height()) }; + xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, m_window, 0, 0, 1, &rec); + xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, m_window, 0, 0, 1, &rec); +#ifdef KWIN_HAVE_XCOMPOSITE_OVERLAY + xcb_composite_release_overlay_window(connection(), m_window); +#endif + m_window = XCB_WINDOW_NONE; + m_shown = false; +} + +xcb_window_t OverlayWindowX11::window() const +{ + return m_window; +} + +} // namespace KWin + diff --git a/plugins/platforms/x11/standalone/overlaywindow_x11.h b/plugins/platforms/x11/standalone/overlaywindow_x11.h new file mode 100644 index 0000000000..2cb562ae55 --- /dev/null +++ b/plugins/platforms/x11/standalone/overlaywindow_x11.h @@ -0,0 +1,54 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2011 Arthur Arlt + +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_OVERLAYWINDOW_X11_H +#define KWIN_OVERLAYWINDOW_X11_H + +#include "../../../../overlaywindow.h" + +namespace KWin { +class KWIN_EXPORT OverlayWindowX11 : public OverlayWindow { +public: + OverlayWindowX11(); + ~OverlayWindowX11(); + /// Creates XComposite overlay window, call initOverlay() afterwards + bool create() override; + /// Init overlay and the destination window in it + void setup(xcb_window_t window) override; + void show() override; + void hide() override; // hides and resets overlay window + void setShape(const QRegion& reg) override; + void resize(const QSize &size) override; + /// Destroys XComposite overlay window + void destroy() override; + xcb_window_t window() const override; + bool isVisible() const override; + void setVisibility(bool visible) override; +private: + void setNoneBackgroundPixmap(xcb_window_t window); + void setupInputShape(xcb_window_t window); + bool m_visible; + bool m_shown; // For showOverlay() + QRegion m_shape; + xcb_window_t m_window; +}; +} // namespace + +#endif //KWIN_OVERLAYWINDOW_H diff --git a/plugins/platforms/x11/standalone/x11_platform.cpp b/plugins/platforms/x11/standalone/x11_platform.cpp index b6a9150c1e..0a938b20e7 100644 --- a/plugins/platforms/x11/standalone/x11_platform.cpp +++ b/plugins/platforms/x11/standalone/x11_platform.cpp @@ -34,6 +34,7 @@ along with this program. If not, see . #include "logging.h" #include "screens_xrandr.h" #include "options.h" +#include "overlaywindow_x11.h" #include #include @@ -309,4 +310,9 @@ void X11StandalonePlatform::setupActionForGlobalAccel(QAction *action) }); } +OverlayWindow *X11StandalonePlatform::createOverlayWindow() +{ + return new OverlayWindowX11(); +} + } diff --git a/plugins/platforms/x11/standalone/x11_platform.h b/plugins/platforms/x11/standalone/x11_platform.h index 7fa55261d8..861b2bf10a 100644 --- a/plugins/platforms/x11/standalone/x11_platform.h +++ b/plugins/platforms/x11/standalone/x11_platform.h @@ -55,6 +55,8 @@ public: void setupActionForGlobalAccel(QAction *action) override; + OverlayWindow *createOverlayWindow() override; + protected: void doHideCursor() override; void doShowCursor() override; diff --git a/scene_xrender.cpp b/scene_xrender.cpp index 263c75f14f..ead00b8c5b 100644 --- a/scene_xrender.cpp +++ b/scene_xrender.cpp @@ -32,6 +32,7 @@ along with this program. If not, see . #include "effects.h" #include "main.h" #include "overlaywindow.h" +#include "platform.h" #include "xcbutils.h" #include "kwinxrenderutils.h" #include "decorations/decoratedclient.h" @@ -109,7 +110,7 @@ void XRenderBackend::screenGeometryChanged(const QSize &size) //**************************************** X11XRenderBackend::X11XRenderBackend() : XRenderBackend() - , m_overlayWindow(new OverlayWindow()) + , m_overlayWindow(kwinApp()->platform()->createOverlayWindow()) , m_front(XCB_RENDER_PICTURE_NONE) , m_format(0) {