Port OverlayWindow from XLib to XCB

With this change KWin core no longer depends on the XLib based
composite extension.

REVIEW: 107685
This commit is contained in:
Martin Gräßlin 2012-12-13 03:02:20 +01:00
parent aa34e8ec18
commit ccda10950b
3 changed files with 65 additions and 42 deletions

View file

@ -176,7 +176,7 @@ qt4_add_dbus_interface( kwin_KDEINIT_SRCS
qt4_add_resources( kwin_KDEINIT_SRCS resources.qrc )
set(kwinLibs ${KDE4_KDEUI_LIBS} ${KDE4_PLASMA_LIBS} ${QT_QTDECLARATIVE_LIBRARY} ${KDECLARATIVE_LIBRARIES} kdecorations kwineffects ${X11_LIBRARIES} ${X11_Xrandr_LIB} ${X11_Xcomposite_LIB} ${X11_Xdamage_LIB} ${X11_Xrender_LIB} ${X11_Xfixes_LIB} ${XCB_XCB_LIBRARIES} ${X11_XCB_LIBRARIES} ${XCB_XFIXES_LIBRARIES} ${XCB_DAMAGE_LIBRARIES} ${XCB_COMPOSITE_LIBRARIES})
set(kwinLibs ${KDE4_KDEUI_LIBS} ${KDE4_PLASMA_LIBS} ${QT_QTDECLARATIVE_LIBRARY} ${KDECLARATIVE_LIBRARIES} kdecorations kwineffects ${X11_LIBRARIES} ${X11_Xrandr_LIB} ${X11_Xdamage_LIB} ${X11_Xrender_LIB} ${X11_Xfixes_LIB} ${XCB_XCB_LIBRARIES} ${X11_XCB_LIBRARIES} ${XCB_XFIXES_LIBRARIES} ${XCB_DAMAGE_LIBRARIES} ${XCB_COMPOSITE_LIBRARIES} ${XCB_SHAPE_LIBRARIES})
find_library(XF86VM_LIBRARY Xxf86vm)
if (XF86VM_LIBRARY)

View file

@ -20,18 +20,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "overlaywindow.h"
#include <config-X11.h>
#include "kwinglobals.h"
#include "utils.h"
#include "assert.h"
#include <QtCore/QVector>
#include <X11/extensions/shape.h>
#include <X11/extensions/Xcomposite.h>
#if XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR >= 3
#include <xcb/composite.h>
#include <xcb/shape.h>
#if XCB_COMPOSITE_MAJOR_VERSION > 0 || XCB_COMPOSITE_MINOR_VERSION >= 3
#define KWIN_HAVE_XCOMPOSITE_OVERLAY
#endif
@ -39,7 +37,7 @@ namespace KWin {
OverlayWindow::OverlayWindow()
: m_visible(true)
, m_shown(false)
, m_window(None)
, m_window(XCB_WINDOW_NONE)
{
}
@ -49,50 +47,69 @@ OverlayWindow::~OverlayWindow()
bool OverlayWindow::create()
{
assert(m_window == None);
assert(m_window == XCB_WINDOW_NONE);
if (!Extensions::compositeOverlayAvailable())
return false;
if (!Extensions::shapeInputAvailable()) // needed in setupOverlay()
return false;
#ifdef KWIN_HAVE_XCOMPOSITE_OVERLAY
m_window = XCompositeGetOverlayWindow(display(), rootWindow());
if (m_window == None)
ScopedCPointer<xcb_composite_get_overlay_window_reply_t> overlay =
xcb_composite_get_overlay_window_reply(connection(),
xcb_composite_get_overlay_window(connection(), rootWindow()),
NULL);
if (overlay.isNull()) {
return false;
XResizeWindow(display(), m_window, displayWidth(), displayHeight());
}
m_window = overlay->overlay_win;
if (m_window == XCB_WINDOW_NONE)
return false;
resize(QSize(displayWidth(), displayHeight()));
return true;
#else
return false;
#endif
}
void OverlayWindow::setup(Window window)
void OverlayWindow::setup(xcb_window_t window)
{
assert(m_window != None);
assert(m_window != XCB_WINDOW_NONE);
assert(Extensions::shapeInputAvailable());
XSetWindowBackgroundPixmap(display(), m_window, None);
setNoneBackgroundPixmap(m_window);
m_shape = QRegion();
setShape(QRect(0, 0, displayWidth(), displayHeight()));
if (window != None) {
XSetWindowBackgroundPixmap(display(), window, None);
XShapeCombineRectangles(display(), window, ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted);
if (window != XCB_WINDOW_NONE) {
setNoneBackgroundPixmap(window);
setupInputShape(window);
}
XSelectInput(display(), m_window, VisibilityChangeMask);
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 != None);
assert(m_window != XCB_WINDOW_NONE);
if (m_shown)
return;
XMapSubwindows(display(), m_window);
XMapWindow(display(), m_window);
xcb_map_subwindows(connection(), m_window);
xcb_map_window(connection(), m_window);
m_shown = true;
}
void OverlayWindow::hide()
{
assert(m_window != None);
XUnmapWindow(display(), m_window);
assert(m_window != XCB_WINDOW_NONE);
xcb_unmap_window(connection(), m_window);
m_shown = false;
setShape(QRect(0, 0, displayWidth(), displayHeight()));
}
@ -104,7 +121,7 @@ void OverlayWindow::setShape(const QRegion& reg)
if (reg == m_shape)
return;
QVector< QRect > rects = reg.rects();
XRectangle* xrects = new XRectangle[ rects.count()];
xcb_rectangle_t *xrects = new xcb_rectangle_t[rects.count()];
for (int i = 0;
i < rects.count();
++i) {
@ -113,17 +130,21 @@ void OverlayWindow::setShape(const QRegion& reg)
xrects[ i ].width = rects[ i ].width();
xrects[ i ].height = rects[ i ].height();
}
XShapeCombineRectangles(display(), m_window, ShapeBounding, 0, 0,
xrects, rects.count(), ShapeSet, Unsorted);
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;
XShapeCombineRectangles(display(), m_window, ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted);
setupInputShape(m_window);
m_shape = reg;
}
void OverlayWindow::resize(const QSize &size)
{
assert(m_window != None);
XResizeWindow(display(), m_window, size.width(), size.height());
assert(m_window != XCB_WINDOW_NONE);
const uint32_t geometry[2] = {
static_cast<uint32_t>(size.width()),
static_cast<uint32_t>(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()));
}
@ -139,20 +160,20 @@ void OverlayWindow::setVisibility(bool visible)
void OverlayWindow::destroy()
{
if (m_window == None)
if (m_window == XCB_WINDOW_NONE)
return;
// reset the overlay shape
XRectangle rec = { 0, 0, static_cast<unsigned short>(displayWidth()), static_cast<unsigned short>(displayHeight()) };
XShapeCombineRectangles(display(), m_window, ShapeBounding, 0, 0, &rec, 1, ShapeSet, Unsorted);
XShapeCombineRectangles(display(), m_window, ShapeInput, 0, 0, &rec, 1, ShapeSet, Unsorted);
xcb_rectangle_t rec = { 0, 0, static_cast<uint16_t>(displayWidth()), static_cast<uint16_t>(displayHeight()) };
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
XCompositeReleaseOverlayWindow(display(), m_window);
xcb_composite_release_overlay_window(connection(), m_window);
#endif
m_window = None;
m_window = XCB_WINDOW_NONE;
m_shown = false;
}
Window OverlayWindow::window() const
xcb_window_t OverlayWindow::window() const
{
return m_window;
}

View file

@ -22,8 +22,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KWIN_OVERLAYWINDOW_H
#include <QRegion>
#include <X11/Xlib.h>
// xcb
#include <xcb/xcb.h>
namespace KWin {
class OverlayWindow {
@ -33,21 +33,23 @@ public:
/// Creates XComposite overlay window, call initOverlay() afterwards
bool create();
/// Init overlay and the destination window in it
void setup(Window window);
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);
/// Destroys XComposite overlay window
void destroy();
Window window() const;
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;
Window m_window;
xcb_window_t m_window;
};
} // namespace