diff --git a/client.cpp b/client.cpp index dfa43a5ee9..f2338d4893 100644 --- a/client.cpp +++ b/client.cpp @@ -141,7 +141,7 @@ Client::Client(Workspace* ws) #ifdef KWIN_BUILD_KAPPMENU , m_menuAvailable(false) #endif - , input_window(None) + , m_decoInputExtent() { // TODO: Do all as initialization #ifdef HAVE_XSYNC @@ -385,10 +385,7 @@ void Client::updateInputWindow() } if (region.isEmpty()) { - if (input_window) { - XDestroyWindow(display(), input_window); - input_window = None; - } + m_decoInputExtent.reset(); return; } @@ -401,23 +398,25 @@ void Client::updateInputWindow() // Move the region to input window coordinates region.translate(-input_offset); - if (!input_window) { - XSetWindowAttributes attr; - attr.event_mask = EnterWindowMask | LeaveWindowMask | - ButtonPressMask | ButtonReleaseMask | PointerMotionMask; - attr.override_redirect = True; - - input_window = XCreateWindow(display(), rootWindow(), bounds.x(), bounds.y(), - bounds.width(), bounds.height(), 0, 0, - InputOnly, 0, CWEventMask | CWOverrideRedirect, &attr); + if (!m_decoInputExtent.isValid()) { + const uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK; + const uint32_t values[] = {true, + XCB_EVENT_MASK_ENTER_WINDOW | + XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_POINTER_MOTION + }; + m_decoInputExtent.create(bounds, XCB_WINDOW_CLASS_INPUT_ONLY, mask, values); if (mapping_state == Mapped) - XMapWindow(display(), inputId()); + m_decoInputExtent.map(); } else { - XMoveResizeWindow(display(), input_window, bounds.x(), bounds.y(), - bounds.width(), bounds.height()); + m_decoInputExtent.setGeometry(bounds); } - XShapeCombineRegion(display(), input_window, ShapeInput, 0, 0, region.handle(), ShapeSet); + const QVector rects = Xcb::regionToRects(region); + xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, + m_decoInputExtent, 0, 0, rects.count(), rects.constData()); } void Client::updateDecoration(bool check_workspace_pos, bool force) @@ -484,10 +483,7 @@ void Client::destroyDecoration() emit geometryShapeChanged(this, oldgeom); } } - if (inputId()) { - XDestroyWindow(display(), input_window); - input_window = None; - } + m_decoInputExtent.reset(); } bool Client::checkBorderSizes(bool also_resize) @@ -1147,8 +1143,7 @@ void Client::internalShow(allowed_t) if (old == Unmapped || old == Withdrawn) map(Allowed); if (old == Kept) { - if (inputId()) - XMapWindow(display(), inputId()); + m_decoInputExtent.map(); updateHiddenPreview(); } if (Compositor::isCreated()) { @@ -1182,8 +1177,7 @@ void Client::internalKeep(allowed_t) mapping_state = Kept; if (old == Unmapped || old == Withdrawn) map(Allowed); - if (inputId()) - XUnmapWindow(display(), inputId()); + m_decoInputExtent.unmap(); updateHiddenPreview(); addWorkspaceRepaint(visibleRect()); workspace()->clientHidden(this); @@ -1210,8 +1204,7 @@ void Client::map(allowed_t) if (!isShade()) { XMapWindow(display(), wrapper); XMapWindow(display(), client); - if (inputId()) - XMapWindow(display(), inputId()); + m_decoInputExtent.map(); exportMappingState(NormalState); } else exportMappingState(IconicState); @@ -1232,8 +1225,7 @@ void Client::unmap(allowed_t) XUnmapWindow(display(), frameId()); XUnmapWindow(display(), wrapper); XUnmapWindow(display(), client); - if (inputId()) - XUnmapWindow(display(), inputId()); + m_decoInputExtent.unmap(); XSelectInput(display(), wrapper, ClientWinMask | SubstructureNotifyMask); if (decoration != NULL) decoration->widget()->hide(); // Not really necessary, but let it know the state @@ -2268,7 +2260,7 @@ void Client::updateCursor() if (decoration != NULL) decoration->widget()->setCursor(cursor); XDefineCursor(display(), frameId(), cursor.handle()); - if (inputId()) + if (m_decoInputExtent.isValid()) XDefineCursor(display(), inputId(), cursor.handle()); if (moveResizeMode) // XDefineCursor doesn't change cursor if there's pointer grab active XChangeActivePointerGrab(display(), diff --git a/client.h b/client.h index a078153fc7..0c9d1d24a6 100644 --- a/client.h +++ b/client.h @@ -44,6 +44,7 @@ along with this program. If not, see . #include "rules.h" #include "toplevel.h" #include "tabgroup.h" +#include "xcbutils.h" #ifdef HAVE_XSYNC #include @@ -284,7 +285,7 @@ public: explicit Client(Workspace* ws); Window wrapperId() const; Window decorationId() const; - Window inputId() const { return input_window; } + xcb_window_t inputId() const { return m_decoInputExtent; } const Client* transientFor() const; Client* transientFor(); @@ -995,7 +996,7 @@ private: #ifdef KWIN_BUILD_KAPPMENU bool m_menuAvailable; #endif - Window input_window; + Xcb::Window m_decoInputExtent; QPoint input_offset; }; diff --git a/geometry.cpp b/geometry.cpp index 682e013556..a6ff77352a 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -1892,10 +1892,7 @@ void Client::setGeometry(int x, int y, int w, int h, ForceGeometry_t force) } // Unconditionally move the input window: it won't affect rendering - if (inputId()) { - const QPoint pos = QPoint(x, y) + inputPos(); - XMoveWindow(display(), inputId(), pos.x(), pos.y()); - } + m_decoInputExtent.move(QPoint(x, y) + inputPos()); } updateWindowRules(Rules::Position|Rules::Size); diff --git a/xcbutils.h b/xcbutils.h index 488d746075..9d54803974 100644 --- a/xcbutils.h +++ b/xcbutils.h @@ -318,6 +318,8 @@ public: **/ void setGeometry(const QRect &geometry); 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 map(); void unmap(); /** @@ -426,6 +428,23 @@ void Window::setGeometry(uint32_t x, uint32_t y, uint32_t width, uint32_t height xcb_configure_window(connection(), m_window, mask, values); } +inline +void Window::move(const QPoint &pos) +{ + move(pos.x(), pos.y()); +} + +inline +void Window::move(uint32_t x, uint32_t y) +{ + if (!isValid()) { + return; + } + const uint16_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y; + const uint32_t values[] = { x, y }; + xcb_configure_window(connection(), m_window, mask, values); +} + inline void Window::map() { @@ -530,6 +549,26 @@ static inline int defaultDepth() return depth; } +static inline xcb_rectangle_t fromQt(const QRect &rect) +{ + xcb_rectangle_t rectangle; + rectangle.x = rect.x(); + rectangle.y = rect.y(); + rectangle.width = rect.width(); + rectangle.height = rect.height(); + return rectangle; +} + +static inline QVector regionToRects(const QRegion ®ion) +{ + const QVector regionRects = region.rects(); + QVector rects(regionRects.count()); + for (int i=0; i