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

View file

@ -438,7 +438,7 @@ public:
}
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;
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 move(const QPoint &pos);
void move(uint32_t x, uint32_t y);
void resize(const QSize &size);
void resize(uint32_t width, uint32_t height);
void map();
void unmap();
/**
@ -460,6 +462,23 @@ void Window::move(uint32_t x, uint32_t y)
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
void Window::map()
{