From 9f85f7f59741dc808ce72c0d303b826735d0ce71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Mon, 28 Jan 2013 14:17:12 +0100 Subject: [PATCH] Port non-composited Outline to XCB Use xcb to create and manage the X11 backend of Outline. In addition the used background pixmaps are rendered with XRender instead of using a QPainter on a QPixmap. This is done because QPixmap is no longer bound to an X Pixmap. To create the XRender Picture the available functionality from kwinxrenderutils is used. To be able to use it in KWin core the compile option to build without XRender is removed for kwinxrenderutils, but still supported for effects. Obviously the port to XCB is not complete as xremderutils itself is still on XLib. REVIEW: 108642 --- libkwineffects/kwinxrenderutils.cpp | 4 - libkwineffects/kwinxrenderutils.h | 4 - outline.cpp | 229 ++++++++++++++-------------- outline.h | 30 ++-- tabbox/tabbox.cpp | 2 +- tabbox/tabbox.h | 2 +- tabbox/tabboxhandler.cpp | 2 +- tabbox/tabboxhandler.h | 3 +- tabbox/tests/mock_tabboxhandler.h | 4 +- 9 files changed, 139 insertions(+), 141 deletions(-) diff --git a/libkwineffects/kwinxrenderutils.cpp b/libkwineffects/kwinxrenderutils.cpp index 835240a235..bae0c21dcb 100644 --- a/libkwineffects/kwinxrenderutils.cpp +++ b/libkwineffects/kwinxrenderutils.cpp @@ -21,8 +21,6 @@ along with this program. If not, see . #include "kwinxrenderutils.h" #include "kwinglobals.h" -#ifdef KWIN_HAVE_XRENDER_COMPOSITING - #include #include #include @@ -263,5 +261,3 @@ QPixmap *xRenderOffscreenTarget() } } // namespace - -#endif diff --git a/libkwineffects/kwinxrenderutils.h b/libkwineffects/kwinxrenderutils.h index 5b7a95326e..9a9a8bc7ee 100644 --- a/libkwineffects/kwinxrenderutils.h +++ b/libkwineffects/kwinxrenderutils.h @@ -23,8 +23,6 @@ along with this program. If not, see . #include -#ifdef KWIN_HAVE_XRENDER_COMPOSITING - #include #include #include @@ -164,8 +162,6 @@ KWIN_EXPORT XRenderPicture *scene_xRenderOffscreenTarget(); } // namespace -#endif - /** @} */ #endif diff --git a/outline.cpp b/outline.cpp index 7819eba969..708ceb42f9 100644 --- a/outline.cpp +++ b/outline.cpp @@ -3,6 +3,7 @@ This file is part of the KDE project. Copyright (C) 2011 Arthur Arlt +Copyright (C) 2013 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 @@ -17,13 +18,14 @@ 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 . *********************************************************************/ - +// own #include "outline.h" +// KWin #include "effects.h" -#include -#include -#include -#include +// KWin libs +#include +// xcb +#include namespace KWin { @@ -35,12 +37,6 @@ Outline::Outline() Outline::~Outline() { - if (m_initialized) { - XDestroyWindow(QX11Info::display(), m_leftOutline); - XDestroyWindow(QX11Info::display(), m_rightOutline); - XDestroyWindow(QX11Info::display(), m_topOutline); - XDestroyWindow(QX11Info::display(), m_bottomOutline); - } } void Outline::show() @@ -63,7 +59,7 @@ void Outline::hide() static_cast(effects)->slotHideOutline(); return; // done by effect } - hideWithX(); + forEachWindow(&Xcb::Window::unmap); } void Outline::show(const QRect& outlineGeometry) @@ -77,9 +73,9 @@ void Outline::setGeometry(const QRect& outlineGeometry) m_outlineGeometry = outlineGeometry; } -QVector< Window > Outline::windowIds() const +QVector< xcb_window_t > Outline::windowIds() const { - QVector windows; + QVector windows; if (m_initialized) { windows.reserve(4); windows << m_leftOutline << m_topOutline << m_rightOutline << m_bottomOutline; @@ -90,113 +86,114 @@ QVector< Window > Outline::windowIds() const void Outline::showWithX() { if (!m_initialized) { - XSetWindowAttributes attr; - attr.override_redirect = 1; - m_leftOutline = XCreateWindow(QX11Info::display(), QX11Info::appRootWindow(), 0, 0, 1, 1, 0, - CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr); - m_rightOutline = XCreateWindow(QX11Info::display(), QX11Info::appRootWindow(), 0, 0, 1, 1, 0, - CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr); - m_topOutline = XCreateWindow(QX11Info::display(), QX11Info::appRootWindow(), 0, 0, 1, 1, 0, - CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr); - m_bottomOutline = XCreateWindow(QX11Info::display(), QX11Info::appRootWindow(), 0, 0, 1, 1, 0, - CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr); - m_initialized = true; + const QRect geo(0, 0, 1, 1); + const uint32_t values[] = {true}; + // TODO: use template variant + m_leftOutline.create(geo, XCB_CW_OVERRIDE_REDIRECT, values); + m_rightOutline.create(geo, XCB_CW_OVERRIDE_REDIRECT, values); + m_topOutline.create(geo, XCB_CW_OVERRIDE_REDIRECT, values); + m_bottomOutline.create(geo, XCB_CW_OVERRIDE_REDIRECT, values); + m_initialized = true; } - int defaultDepth = XDefaultDepth(QX11Info::display(), QX11Info::appScreen()); + int screen = QX11Info::appScreen(); + int defaultDepth = 0; + // TODO: move into xcbutils or maybe kwinglobals + for (xcb_screen_iterator_t it = xcb_setup_roots_iterator(xcb_get_setup(connection())); + it.rem; + --screen, xcb_screen_next(&it)) { + if (screen == 0) { + defaultDepth = it.data->root_depth; + break; + } + } // left/right parts are between top/bottom, they don't reach as far as the corners - XMoveResizeWindow(QX11Info::display(), m_leftOutline, m_outlineGeometry.x(), m_outlineGeometry.y() + 5, 5, m_outlineGeometry.height() - 10); - XMoveResizeWindow(QX11Info::display(), m_rightOutline, m_outlineGeometry.x() + m_outlineGeometry.width() - 5, m_outlineGeometry.y() + 5, 5, m_outlineGeometry.height() - 10); - XMoveResizeWindow(QX11Info::display(), m_topOutline, m_outlineGeometry.x(), m_outlineGeometry.y(), m_outlineGeometry.width(), 5); - XMoveResizeWindow(QX11Info::display(), m_bottomOutline, m_outlineGeometry.x(), m_outlineGeometry.y() + m_outlineGeometry.height() - 5, m_outlineGeometry.width(), 5); - { - Pixmap xpix = XCreatePixmap(display(), rootWindow(), 5, - m_outlineGeometry.height() - 10, defaultDepth); - QPixmap pix = QPixmap::fromX11Pixmap(xpix, QPixmap::ExplicitlyShared); - QPainter p(&pix); - p.setPen(Qt::white); - p.drawLine(0, 0, 0, pix.height() - 1); - p.drawLine(4, 0, 4, pix.height() - 1); - p.setPen(Qt::gray); - p.drawLine(1, 0, 1, pix.height() - 1); - p.drawLine(3, 0, 3, pix.height() - 1); - p.setPen(Qt::black); - p.drawLine(2, 0, 2, pix.height() - 1); - p.end(); - XSetWindowBackgroundPixmap(QX11Info::display(), m_leftOutline, pix.handle()); - XSetWindowBackgroundPixmap(QX11Info::display(), m_rightOutline, pix.handle()); - // According to the XSetWindowBackgroundPixmap documentation the pixmap can be freed. - XFreePixmap (display(), xpix); - } - { - Pixmap xpix = XCreatePixmap(display(), rootWindow(), m_outlineGeometry.width(), - 5, defaultDepth); - QPixmap pix = QPixmap::fromX11Pixmap(xpix, QPixmap::ExplicitlyShared); - QPainter p(&pix); - p.setPen(Qt::white); - p.drawLine(0, 0, pix.width() - 1 - 0, 0); - p.drawLine(4, 4, pix.width() - 1 - 4, 4); - p.drawLine(0, 0, 0, 4); - p.drawLine(pix.width() - 1 - 0, 0, pix.width() - 1 - 0, 4); - p.setPen(Qt::gray); - p.drawLine(1, 1, pix.width() - 1 - 1, 1); - p.drawLine(3, 3, pix.width() - 1 - 3, 3); - p.drawLine(1, 1, 1, 4); - p.drawLine(3, 3, 3, 4); - p.drawLine(pix.width() - 1 - 1, 1, pix.width() - 1 - 1, 4); - p.drawLine(pix.width() - 1 - 3, 3, pix.width() - 1 - 3, 4); - p.setPen(Qt::black); - p.drawLine(2, 2, pix.width() - 1 - 2, 2); - p.drawLine(2, 2, 2, 4); - p.drawLine(pix.width() - 1 - 2, 2, pix.width() - 1 - 2, 4); - p.end(); - XSetWindowBackgroundPixmap(QX11Info::display(), m_topOutline, pix.handle()); - // According to the XSetWindowBackgroundPixmap documentation the pixmap can be freed. - XFreePixmap (display(), xpix); - } - { - Pixmap xpix = XCreatePixmap(display(), rootWindow(), m_outlineGeometry.width(), - 5, defaultDepth); - QPixmap pix = QPixmap::fromX11Pixmap(xpix, QPixmap::ExplicitlyShared); - QPainter p(&pix); - p.setPen(Qt::white); - p.drawLine(4, 0, pix.width() - 1 - 4, 0); - p.drawLine(0, 4, pix.width() - 1 - 0, 4); - p.drawLine(0, 4, 0, 0); - p.drawLine(pix.width() - 1 - 0, 4, pix.width() - 1 - 0, 0); - p.setPen(Qt::gray); - p.drawLine(3, 1, pix.width() - 1 - 3, 1); - p.drawLine(1, 3, pix.width() - 1 - 1, 3); - p.drawLine(3, 1, 3, 0); - p.drawLine(1, 3, 1, 0); - p.drawLine(pix.width() - 1 - 3, 1, pix.width() - 1 - 3, 0); - p.drawLine(pix.width() - 1 - 1, 3, pix.width() - 1 - 1, 0); - p.setPen(Qt::black); - p.drawLine(2, 2, pix.width() - 1 - 2, 2); - p.drawLine(2, 0, 2, 2); - p.drawLine(pix.width() - 1 - 2, 0, pix.width() - 1 - 2, 2); - p.end(); - XSetWindowBackgroundPixmap(QX11Info::display(), m_bottomOutline, pix.handle()); - // According to the XSetWindowBackgroundPixmap documentation the pixmap can be freed. - XFreePixmap (display(), xpix); - } - XClearWindow(QX11Info::display(), m_leftOutline); - XClearWindow(QX11Info::display(), m_rightOutline); - XClearWindow(QX11Info::display(), m_topOutline); - XClearWindow(QX11Info::display(), m_bottomOutline); - XMapWindow(QX11Info::display(), m_leftOutline); - XMapWindow(QX11Info::display(), m_rightOutline); - XMapWindow(QX11Info::display(), m_topOutline); - XMapWindow(QX11Info::display(), m_bottomOutline); -} + const uint16_t verticalWidth = 5; + const uint16_t verticalHeight = m_outlineGeometry.height() - 10; + const uint16_t horizontalWidth = m_outlineGeometry.width(); + const uint horizontalHeight = 5; + m_leftOutline.setGeometry(m_outlineGeometry.x(), m_outlineGeometry.y() + 5, verticalWidth, verticalHeight); + m_rightOutline.setGeometry(m_outlineGeometry.x() + m_outlineGeometry.width() - 5, m_outlineGeometry.y() + 5, verticalWidth, verticalHeight); + m_topOutline.setGeometry(m_outlineGeometry.x(), m_outlineGeometry.y(), horizontalWidth, horizontalHeight); + m_bottomOutline.setGeometry(m_outlineGeometry.x(), m_outlineGeometry.y() + m_outlineGeometry.height() - 5, horizontalWidth, horizontalHeight); -void Outline::hideWithX() -{ - XUnmapWindow(QX11Info::display(), m_leftOutline); - XUnmapWindow(QX11Info::display(), m_rightOutline); - XUnmapWindow(QX11Info::display(), m_topOutline); - XUnmapWindow(QX11Info::display(), m_bottomOutline); + const xcb_render_color_t white = {0xffff, 0xffff, 0xffff, 0xffff}; + QColor qGray(Qt::gray); + const xcb_render_color_t gray = { + uint16_t(0xffff * qGray.redF()), + uint16_t(0xffff * qGray.greenF()), + uint16_t(0xffff * qGray.blueF()), + 0xffff + }; + const xcb_render_color_t black = {0, 0, 0, 0xffff}; + { + xcb_pixmap_t xpix = xcb_generate_id(connection()); + xcb_create_pixmap(connection(), defaultDepth, xpix, rootWindow(), verticalWidth, verticalHeight); + XRenderPicture pic(xpix, defaultDepth); + + xcb_rectangle_t rect = {0, 0, 5, verticalHeight}; + xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, white, 1, &rect); + rect.x = 1; + rect.width = 3; + xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, gray, 1, &rect); + rect.x = 2; + rect.width = 1; + xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, black, 1, &rect); + + m_leftOutline.setBackgroundPixmap(xpix); + m_rightOutline.setBackgroundPixmap(xpix); + // According to the XSetWindowBackgroundPixmap documentation the pixmap can be freed. + xcb_free_pixmap(connection(), xpix); + } + { + xcb_pixmap_t xpix = xcb_generate_id(connection()); + xcb_create_pixmap(connection(), defaultDepth, xpix, rootWindow(), horizontalWidth, horizontalHeight); + XRenderPicture pic(xpix, defaultDepth); + + xcb_rectangle_t rect = {0, 0, horizontalWidth, horizontalHeight}; + xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, white, 1, &rect); + xcb_rectangle_t grayRects[] = { + {1, 1, uint16_t(horizontalWidth -2), 3}, + {1, 4, 3, 1}, + {int16_t(horizontalWidth - 4), 4, 3, 1} + }; + xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, gray, 3, grayRects); + xcb_rectangle_t blackRects[] = { + {2, 2, uint16_t(horizontalWidth -4), 1}, + {2, 3, 1, 2}, + {int16_t(horizontalWidth - 3), 3, 1, 2} + }; + xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, black, 3, blackRects); + m_topOutline.setBackgroundPixmap(xpix); + // According to the XSetWindowBackgroundPixmap documentation the pixmap can be freed. + xcb_free_pixmap(connection(), xpix); + } + { + xcb_pixmap_t xpix = xcb_generate_id(connection()); + xcb_create_pixmap(connection(), defaultDepth, xpix, rootWindow(), m_outlineGeometry.width(), 5); + XRenderPicture pic(xpix, defaultDepth); + + xcb_rectangle_t rect = {0, 0, horizontalWidth, horizontalHeight}; + xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, white, 1, &rect); + xcb_rectangle_t grayRects[] = { + {1, 1, uint16_t(horizontalWidth -2), 3}, + {1, 0, 3, 1}, + {int16_t(horizontalWidth - 4), 0, 3, 1} + }; + xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, gray, 3, grayRects); + xcb_rectangle_t blackRects[] = { + {2, 2, uint16_t(horizontalWidth -4), 1}, + {2, 0, 1, 2}, + {int16_t(horizontalWidth - 3), 0, 1, 2} + }; + xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, black, 3, blackRects); + m_bottomOutline.setBackgroundPixmap(xpix); + // According to the XSetWindowBackgroundPixmap documentation the pixmap can be freed. + xcb_free_pixmap(connection(), xpix); + } + forEachWindow(&Xcb::Window::clear); + forEachWindow(&Xcb::Window::map); } } // namespace diff --git a/outline.h b/outline.h index 20e7a8668b..81b1abd3bb 100644 --- a/outline.h +++ b/outline.h @@ -20,8 +20,7 @@ along with this program. If not, see . #ifndef KWIN_OUTLINE_H #define KWIN_OUTLINE_H -#include -#include +#include "xcbutils.h" #include #include @@ -77,7 +76,7 @@ public: * Return outline window ids * @return The window ids created to represent the outline */ - QVector windowIds() const; + QVector windowIds() const; private: /** @@ -85,20 +84,29 @@ private: */ void showWithX(); - /** - * Hide previously shown outline used the X implementation - */ - void hideWithX(); + // TODO: variadic template arguments for adding method arguments + template + void forEachWindow(T method); - Window m_topOutline; - Window m_rightOutline; - Window m_bottomOutline; - Window m_leftOutline; + Xcb::Window m_topOutline; + Xcb::Window m_rightOutline; + Xcb::Window m_bottomOutline; + Xcb::Window m_leftOutline; QRect m_outlineGeometry; bool m_initialized; bool m_active; }; +template +inline +void Outline::forEachWindow(T method) +{ + (m_topOutline.*method)(); + (m_rightOutline.*method)(); + (m_bottomOutline.*method)(); + (m_leftOutline.*method)(); +} + } #endif diff --git a/tabbox/tabbox.cpp b/tabbox/tabbox.cpp index 8a3b364b0b..cb2120f53f 100644 --- a/tabbox/tabbox.cpp +++ b/tabbox/tabbox.cpp @@ -326,7 +326,7 @@ void TabBoxHandlerImpl::hideOutline() Workspace::self()->outline()->hide(); } -QVector< Window > TabBoxHandlerImpl::outlineWindowIds() const +QVector< xcb_window_t > TabBoxHandlerImpl::outlineWindowIds() const { return Workspace::self()->outline()->windowIds(); } diff --git a/tabbox/tabbox.h b/tabbox/tabbox.h index a17494456d..1a54a96158 100644 --- a/tabbox/tabbox.h +++ b/tabbox/tabbox.h @@ -64,7 +64,7 @@ public: virtual QWeakPointer< TabBoxClient > desktopClient() const; virtual void hideOutline(); virtual void showOutline(const QRect &outline); - virtual QVector< Window > outlineWindowIds() const; + virtual QVector< xcb_window_t > outlineWindowIds() const; virtual void activateAndClose(); private: diff --git a/tabbox/tabboxhandler.cpp b/tabbox/tabboxhandler.cpp index ad3919aa03..d84d2d338f 100644 --- a/tabbox/tabboxhandler.cpp +++ b/tabbox/tabboxhandler.cpp @@ -186,7 +186,7 @@ void TabBoxHandlerPrivate::updateHighlightWindows() } data[ 0 ] = currentClient ? currentClient->window() : 0L; if (config.isShowOutline()) { - QVector outlineWindows = q->outlineWindowIds(); + QVector outlineWindows = q->outlineWindowIds(); data.resize(2+outlineWindows.size()); for (int i=0; i. #include #include #include +#include /** * @file @@ -351,7 +352,7 @@ protected: * @return The outline window ids given in the order left, top, right, bottom * @since 4.7 **/ - virtual QVector outlineWindowIds() const = 0; + virtual QVector outlineWindowIds() const = 0; signals: /** diff --git a/tabbox/tests/mock_tabboxhandler.h b/tabbox/tests/mock_tabboxhandler.h index 5578001a01..78ee542bf1 100644 --- a/tabbox/tests/mock_tabboxhandler.h +++ b/tabbox/tests/mock_tabboxhandler.h @@ -68,8 +68,8 @@ public: virtual int numberOfDesktops() const { return 1; } - virtual QVector< Window > outlineWindowIds() const { - return QVector(); + virtual QVector< xcb_window_t > outlineWindowIds() const { + return QVector(); } virtual void raiseClient(TabBox::TabBoxClient *c) const { Q_UNUSED(c)