Port Client's shape handling to XCB

REVIEW: 108772
This commit is contained in:
Martin Gräßlin 2013-02-04 13:48:09 +01:00
parent 4a0a4bc27e
commit 0348a14a7d
3 changed files with 69 additions and 47 deletions

View file

@ -693,11 +693,12 @@ void Client::updateShape()
noborder = rules()->checkNoBorder(true); noborder = rules()->checkNoBorder(true);
updateDecoration(true); updateDecoration(true);
} }
if (noBorder()) if (noBorder()) {
XShapeCombineShape(display(), frameId(), ShapeBounding, xcb_shape_combine(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING,
clientPos().x(), clientPos().y(), window(), ShapeBounding, ShapeSet); frameId(), clientPos().x(), clientPos().y(), window());
}
} else if (app_noborder) { } else if (app_noborder) {
XShapeCombineMask(display(), frameId(), ShapeBounding, 0, 0, None, ShapeSet); xcb_shape_mask(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, frameId(), 0, 0, XCB_PIXMAP_NONE);
detectNoBorder(); detectNoBorder();
app_noborder = noborder = rules()->checkNoBorder(noborder); app_noborder = noborder = rules()->checkNoBorder(noborder);
updateDecoration(true); updateDecoration(true);
@ -713,7 +714,7 @@ void Client::updateShape()
emit geometryShapeChanged(this, geometry()); emit geometryShapeChanged(this, geometry());
} }
static Window shape_helper_window = None; static Xcb::Window shape_helper_window(XCB_WINDOW_NONE);
void Client::updateInputShape() void Client::updateInputShape()
{ {
@ -730,18 +731,18 @@ void Client::updateInputShape()
// until the real shape of the client is added and that can make // until the real shape of the client is added and that can make
// the window lose focus (which is a problem with mouse focus policies) // the window lose focus (which is a problem with mouse focus policies)
// TODO: It seems there is, after all - XShapeGetRectangles() - but maybe this is better // TODO: It seems there is, after all - XShapeGetRectangles() - but maybe this is better
if (shape_helper_window == None) if (!shape_helper_window.isValid())
shape_helper_window = XCreateSimpleWindow(display(), rootWindow(), shape_helper_window.create(QRect(0, 0, 1, 1));
0, 0, 1, 1, 0, 0, 0); shape_helper_window.resize(width(), height());
XResizeWindow(display(), shape_helper_window, width(), height()); xcb_connection_t *c = connection();
XShapeCombineShape(display(), shape_helper_window, ShapeInput, 0, 0, xcb_shape_combine(c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, XCB_SHAPE_SK_BOUNDING,
frameId(), ShapeBounding, ShapeSet); shape_helper_window, 0, 0, frameId());
XShapeCombineShape(display(), shape_helper_window, ShapeInput, xcb_shape_combine(c, XCB_SHAPE_SO_SUBTRACT, XCB_SHAPE_SK_INPUT, XCB_SHAPE_SK_BOUNDING,
clientPos().x(), clientPos().y(), window(), ShapeBounding, ShapeSubtract); shape_helper_window, clientPos().x(), clientPos().y(), window());
XShapeCombineShape(display(), shape_helper_window, ShapeInput, xcb_shape_combine(c, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_INPUT, XCB_SHAPE_SK_INPUT,
clientPos().x(), clientPos().y(), window(), ShapeInput, ShapeUnion); shape_helper_window, clientPos().x(), clientPos().y(), window());
XShapeCombineShape(display(), frameId(), ShapeInput, 0, 0, xcb_shape_combine(c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, XCB_SHAPE_SK_INPUT,
shape_helper_window, ShapeInput, ShapeSet); frameId(), 0, 0, shape_helper_window);
} }
} }
@ -751,41 +752,41 @@ void Client::setMask(const QRegion& reg, int mode)
if (_mask == r) if (_mask == r)
return; return;
_mask = r; _mask = r;
Window shape_window = frameId(); xcb_connection_t *c = connection();
xcb_window_t shape_window = frameId();
if (shape()) { if (shape()) {
// The same way of applying a shape without strange intermediate states like above // The same way of applying a shape without strange intermediate states like above
if (shape_helper_window == None) if (!shape_helper_window.isValid())
shape_helper_window = XCreateSimpleWindow(display(), rootWindow(), shape_helper_window.create(QRect(0, 0, 1, 1));
0, 0, 1, 1, 0, 0, 0);
shape_window = shape_helper_window; shape_window = shape_helper_window;
} }
if (_mask.isEmpty()) if (_mask.isEmpty()) {
XShapeCombineMask(display(), shape_window, ShapeBounding, 0, 0, None, ShapeSet); xcb_shape_mask(c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, shape_window, 0, 0, XCB_PIXMAP_NONE);
else if (mode == X::Unsorted) } else {
XShapeCombineRegion(display(), shape_window, ShapeBounding, 0, 0, _mask.handle(), ShapeSet); const QVector< QRect > rects = _mask.rects();
else { QVector< xcb_rectangle_t > xrects(rects.count());
QVector< QRect > rects = _mask.rects();
XRectangle* xrects = new XRectangle[rects.count()];
for (int i = 0; i < rects.count(); ++i) { for (int i = 0; i < rects.count(); ++i) {
xrects[i].x = rects[i].x(); const QRect &rect = rects.at(i);
xrects[i].y = rects[i].y(); xcb_rectangle_t xrect;
xrects[i].width = rects[i].width(); xrect.x = rect.x();
xrects[i].height = rects[i].height(); xrect.y = rect.y();
xrect.width = rect.width();
xrect.height = rect.height();
xrects[i] = xrect;
} }
XShapeCombineRectangles(display(), shape_window, ShapeBounding, 0, 0, xcb_shape_rectangles(c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, mode, shape_window,
xrects, rects.count(), ShapeSet, mode); 0, 0, xrects.count(), xrects.constData());
delete[] xrects;
} }
if (shape()) { if (shape()) {
// The rest of the applyign using a temporary window // The rest of the applying using a temporary window
XRectangle rec = { 0, 0, static_cast<unsigned short>(clientSize().width()), xcb_rectangle_t rec = { 0, 0, static_cast<uint16_t>(clientSize().width()),
static_cast<unsigned short>(clientSize().height()) }; static_cast<uint16_t>(clientSize().height()) };
XShapeCombineRectangles(display(), shape_helper_window, ShapeBounding, xcb_shape_rectangles(c, XCB_SHAPE_SO_SUBTRACT, XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED,
clientPos().x(), clientPos().y(), &rec, 1, ShapeSubtract, Unsorted); shape_helper_window, clientPos().x(), clientPos().y(), 1, &rec);
XShapeCombineShape(display(), shape_helper_window, ShapeBounding, xcb_shape_combine(c, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING,
clientPos().x(), clientPos().y(), window(), ShapeBounding, ShapeUnion); shape_helper_window, clientPos().x(), clientPos().y(), window());
XShapeCombineShape(display(), frameId(), ShapeBounding, 0, 0, xcb_shape_combine(c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING,
shape_helper_window, ShapeBounding, ShapeSet); frameId(), 0, 0, shape_helper_window);
} }
emit geometryShapeChanged(this, geometry()); emit geometryShapeChanged(this, geometry());
updateShape(); updateShape();
@ -1248,8 +1249,10 @@ void Client::updateHiddenPreview()
{ {
if (hiddenPreview()) { if (hiddenPreview()) {
workspace()->forceRestacking(); workspace()->forceRestacking();
if (Xcb::Extensions::self()->isShapeInputAvailable()) if (Xcb::Extensions::self()->isShapeInputAvailable()) {
XShapeCombineRectangles(display(), frameId(), ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted); xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT,
XCB_CLIP_ORDERING_UNSORTED, frameId(), 0, 0, 0, NULL);
}
} else { } else {
workspace()->forceRestacking(); workspace()->forceRestacking();
updateInputShape(); updateInputShape();

View file

@ -438,7 +438,7 @@ public:
} }
void demandAttention(bool set = true); void demandAttention(bool set = true);
void setMask(const QRegion& r, int mode = X::Unsorted); void setMask(const QRegion& r, int mode = XCB_CLIP_ORDERING_UNSORTED);
QRegion mask() const; QRegion mask() const;
void updateDecoration(bool check_workspace_pos, bool force = false); void updateDecoration(bool check_workspace_pos, bool force = false);

View file

@ -335,6 +335,8 @@ public:
void setGeometry(uint32_t x, uint32_t y, uint32_t width, uint32_t height); void setGeometry(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
void move(const QPoint &pos); void move(const QPoint &pos);
void move(uint32_t x, uint32_t y); void move(uint32_t x, uint32_t y);
void resize(const QSize &size);
void resize(uint32_t width, uint32_t height);
void map(); void map();
void unmap(); void unmap();
/** /**
@ -460,6 +462,23 @@ void Window::move(uint32_t x, uint32_t y)
xcb_configure_window(connection(), m_window, mask, values); xcb_configure_window(connection(), m_window, mask, values);
} }
inline
void Window::resize(const QSize &size)
{
resize(size.width(), size.height());
}
inline
void Window::resize(uint32_t width, uint32_t height)
{
if (!isValid()) {
return;
}
const uint16_t mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
const uint32_t values[] = { width, height };
xcb_configure_window(connection(), m_window, mask, values);
}
inline inline
void Window::map() void Window::map()
{ {