Port Client's decoration resize extend input window to XCB

Using Xcb::Window to manage the xcb_window_t and simplify the code - no
longer need to check whether the input_window is valid before calling e.g.
map, as that's handled in Xcb::Window.

One XLib usage for setting cursor is still present. This will be ported
once all the QCursor::handle() get removed.

REVIEW: 108771
icc-effect-5.14.5
Martin Gräßlin 2013-02-04 11:20:15 +01:00
parent 3d5f962566
commit 74097e7d29
4 changed files with 66 additions and 37 deletions

View File

@ -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<xcb_rectangle_t> 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(),

View File

@ -44,6 +44,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "rules.h"
#include "toplevel.h"
#include "tabgroup.h"
#include "xcbutils.h"
#ifdef HAVE_XSYNC
#include <X11/extensions/sync.h>
@ -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;
};

View File

@ -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);

View File

@ -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<xcb_rectangle_t> regionToRects(const QRegion &region)
{
const QVector<QRect> regionRects = region.rects();
QVector<xcb_rectangle_t> rects(regionRects.count());
for (int i=0; i<regionRects.count(); ++i) {
rects[i] = Xcb::fromQt(regionRects.at(i));
}
return rects;
}
} // namespace X11
} // namespace KWin