diff --git a/composite.cpp b/composite.cpp index 2fbf3e269c..99960b4af6 100644 --- a/composite.cpp +++ b/composite.cpp @@ -319,8 +319,6 @@ void Compositor::setupX11Support() return; } claimCompositorSelection(); - xcb_composite_redirect_subwindows(con, kwinApp()->x11RootWindow(), - XCB_COMPOSITE_REDIRECT_MANUAL); } void Compositor::startupWithWorkspace() @@ -429,10 +427,6 @@ void Compositor::stop() for (InternalClient *client : workspace()->internalClients()) { client->finishCompositing(); } - if (auto *con = kwinApp()->x11Connection()) { - xcb_composite_unredirect_subwindows(con, kwinApp()->x11RootWindow(), - XCB_COMPOSITE_REDIRECT_MANUAL); - } while (!workspace()->deletedList().isEmpty()) { workspace()->deletedList().first()->discard(); } diff --git a/deleted.cpp b/deleted.cpp index 2dbced2739..76c3bccd6f 100644 --- a/deleted.cpp +++ b/deleted.cpp @@ -3,6 +3,7 @@ This file is part of the KDE project. Copyright (C) 2006 Lubos Lunak +Copyright (C) 2019 Vlad Zahorodnii This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -95,7 +96,6 @@ void Deleted::copyToDeleted(Toplevel* c) Q_ASSERT(dynamic_cast< Deleted* >(c) == nullptr); Toplevel::copyToDeleted(c); m_bufferGeometry = c->bufferGeometry(); - m_bufferMargins = c->bufferMargins(); m_frameMargins = c->frameMargins(); m_bufferScale = c->bufferScale(); desk = c->desktop(); @@ -171,11 +171,6 @@ QRect Deleted::bufferGeometry() const return m_bufferGeometry; } -QMargins Deleted::bufferMargins() const -{ - return m_bufferMargins; -} - QMargins Deleted::frameMargins() const { return m_frameMargins; diff --git a/deleted.h b/deleted.h index bb7fe2f94c..d69e497664 100644 --- a/deleted.h +++ b/deleted.h @@ -3,6 +3,7 @@ This file is part of the KDE project. Copyright (C) 2006 Lubos Lunak +Copyright (C) 2019 Vlad Zahorodnii This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,7 +45,6 @@ public: void unrefWindow(); void discard(); QRect bufferGeometry() const override; - QMargins bufferMargins() const override; QMargins frameMargins() const override; qreal bufferScale() const override; int desktop() const override; @@ -202,7 +202,6 @@ private: void removeTransientFor(Deleted *parent); QRect m_bufferGeometry; - QMargins m_bufferMargins; QMargins m_frameMargins; int delete_refcount; diff --git a/effects.cpp b/effects.cpp index a64099dd0c..f9a604867a 100644 --- a/effects.cpp +++ b/effects.cpp @@ -4,6 +4,7 @@ Copyright (C) 2006 Lubos Lunak Copyright (C) 2010, 2011 Martin Gräßlin +Copyright (C) 2019 Vlad Zahorodnii This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1951,8 +1952,8 @@ void EffectWindowImpl::setSceneWindow(Scene::Window* w) QRegion EffectWindowImpl::shape() const { - if (isX11Client() && sceneWindow()) { - return sceneWindow()->bufferShape(); + if (sw) { + return sw->decorationShape() | sw->bufferShape().translated(toplevel->clientPos()); } return geometry(); } diff --git a/events.cpp b/events.cpp index cb30d74020..a3658de56d 100644 --- a/events.cpp +++ b/events.cpp @@ -581,7 +581,7 @@ bool X11Client::windowEvent(xcb_generic_event_t *e) detectShape(window()); // workaround for #19644 updateShape(); } - if (eventType == Xcb::Extensions::self()->damageNotifyEvent() && reinterpret_cast(e)->drawable == frameId()) + if (eventType == Xcb::Extensions::self()->damageNotifyEvent() && reinterpret_cast(e)->drawable == windowId()) damageNotifyEvent(); break; } diff --git a/geometry.cpp b/geometry.cpp index a106e93a27..ad84c04b40 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -1946,7 +1946,7 @@ void X11Client::setFrameGeometry(int x, int y, int w, int h, ForceGeometry_t for // for example using X11Client::clientSize() QRect frameGeometry(x, y, w, h); - QRect bufferGeometry; + QRect serverGeometry; if (shade_geometry_change) ; // nothing @@ -1961,18 +1961,18 @@ void X11Client::setFrameGeometry(int x, int y, int w, int h, ForceGeometry_t for m_clientGeometry = frameRectToClientRect(frameGeometry); } if (isDecorated()) { - bufferGeometry = frameGeometry; + serverGeometry = frameGeometry; } else { - bufferGeometry = m_clientGeometry; + serverGeometry = m_clientGeometry; } + geom = frameGeometry; if (!areGeometryUpdatesBlocked() && frameGeometry != rules()->checkGeometry(frameGeometry)) { qCDebug(KWIN_CORE) << "forced geometry fail:" << frameGeometry << ":" << rules()->checkGeometry(frameGeometry); } - if (!canUpdateGeometry(frameGeometry, bufferGeometry, force)) { + if (force == NormalGeometrySet && m_serverGeometry == serverGeometry && pendingGeometryUpdate() == PendingGeometryNone) { return; } - m_bufferGeometry = bufferGeometry; - geom = frameGeometry; + m_serverGeometry = serverGeometry; if (areGeometryUpdatesBlocked()) { if (pendingGeometryUpdate() == PendingGeometryForced) {} // maximum, nothing needed @@ -1982,35 +1982,7 @@ void X11Client::setFrameGeometry(int x, int y, int w, int h, ForceGeometry_t for setPendingGeometryUpdate(PendingGeometryNormal); return; } - const QRect oldBufferGeometry = bufferGeometryBeforeUpdateBlocking(); - bool resized = (oldBufferGeometry.size() != m_bufferGeometry.size() || pendingGeometryUpdate() == PendingGeometryForced); - if (resized) { - resizeDecoration(); - m_frame.setGeometry(m_bufferGeometry); - if (!isShade()) { - QSize cs = clientSize(); - m_wrapper.setGeometry(QRect(clientPos(), cs)); - if (!isResize() || syncRequest.counter == XCB_NONE) - m_client.setGeometry(0, 0, cs.width(), cs.height()); - // SELI - won't this be too expensive? - // THOMAS - yes, but gtk+ clients will not resize without ... - sendSyntheticConfigureNotify(); - } - updateShape(); - } else { - if (isMoveResize()) { - if (compositing()) // Defer the X update until we leave this mode - needsXWindowMove = true; - else - m_frame.move(m_bufferGeometry.topLeft()); // sendSyntheticConfigureNotify() on finish shall be sufficient - } else { - m_frame.move(m_bufferGeometry.topLeft()); - sendSyntheticConfigureNotify(); - } - - // Unconditionally move the input window: it won't affect rendering - m_decoInputExtent.move(QPoint(x, y) + inputPos()); - } + updateServerGeometry(); updateWindowRules(Rules::Position|Rules::Size); // keep track of old maximize mode @@ -2019,7 +1991,7 @@ void X11Client::setFrameGeometry(int x, int y, int w, int h, ForceGeometry_t for workspace()->updateStackingOrder(); // Need to regenerate decoration pixmaps when the buffer size is changed. - if (oldBufferGeometry.size() != m_bufferGeometry.size()) { + if (bufferGeometryBeforeUpdateBlocking().size() != bufferGeometry().size()) { discardWindowPixmap(); } emit geometryShapeChanged(this, frameGeometryBeforeUpdateBlocking()); @@ -2032,7 +2004,7 @@ void X11Client::setFrameGeometry(int x, int y, int w, int h, ForceGeometry_t for void X11Client::plainResize(int w, int h, ForceGeometry_t force) { QSize frameSize(w, h); - QSize bufferSize; + QSize serverSize; // this code is also duplicated in X11Client::setGeometry(), and it's also commented there if (shade_geometry_change) @@ -2048,20 +2020,20 @@ void X11Client::plainResize(int w, int h, ForceGeometry_t force) m_clientGeometry.setSize(frameSizeToClientSize(frameSize)); } if (isDecorated()) { - bufferSize = frameSize; + serverSize = frameSize; } else { - bufferSize = m_clientGeometry.size(); + serverSize = m_clientGeometry.size(); } if (!areGeometryUpdatesBlocked() && frameSize != rules()->checkSize(frameSize)) { qCDebug(KWIN_CORE) << "forced size fail:" << frameSize << ":" << rules()->checkSize(frameSize); } + geom.setSize(frameSize); // resuming geometry updates is handled only in setGeometry() Q_ASSERT(pendingGeometryUpdate() == PendingGeometryNone || areGeometryUpdatesBlocked()); - if (!canUpdateSize(frameSize, bufferSize, force)) { + if (force == NormalGeometrySet && m_serverGeometry.size() == serverSize) { return; } - m_bufferGeometry.setSize(bufferSize); - geom.setSize(frameSize); + m_serverGeometry.setSize(serverSize); if (areGeometryUpdatesBlocked()) { if (pendingGeometryUpdate() == PendingGeometryForced) {} // maximum, nothing needed @@ -2071,20 +2043,11 @@ void X11Client::plainResize(int w, int h, ForceGeometry_t force) setPendingGeometryUpdate(PendingGeometryNormal); return; } - resizeDecoration(); - m_frame.resize(m_bufferGeometry.size()); - if (!isShade()) { - QSize cs = clientSize(); - m_wrapper.setGeometry(QRect(clientPos(), cs)); - m_client.setGeometry(0, 0, cs.width(), cs.height()); - } - updateShape(); - - sendSyntheticConfigureNotify(); + updateServerGeometry(); updateWindowRules(Rules::Position|Rules::Size); screens()->setCurrent(this); workspace()->updateStackingOrder(); - if (bufferGeometryBeforeUpdateBlocking().size() != m_bufferGeometry.size()) { + if (bufferGeometryBeforeUpdateBlocking().size() != bufferGeometry().size()) { discardWindowPixmap(); } emit geometryShapeChanged(this, frameGeometryBeforeUpdateBlocking()); @@ -2094,6 +2057,39 @@ void X11Client::plainResize(int w, int h, ForceGeometry_t force) emit geometryChanged(); } +void X11Client::updateServerGeometry() +{ + const QRect previousServerGeometry = m_frame.geometry(); + const bool resized = (previousServerGeometry.size() != m_serverGeometry.size() || pendingGeometryUpdate() == PendingGeometryForced); + if (resized) { + resizeDecoration(); + m_frame.setGeometry(m_serverGeometry); + if (!isShade()) { + QSize cs = clientSize(); + m_wrapper.setGeometry(QRect(clientPos(), cs)); + if (!isResize() || syncRequest.counter == XCB_NONE) + m_client.setGeometry(0, 0, cs.width(), cs.height()); + // SELI - won't this be too expensive? + // THOMAS - yes, but gtk+ clients will not resize without ... + sendSyntheticConfigureNotify(); + } + updateShape(); + } else { + if (isMoveResize()) { + if (compositing()) // Defer the X update until we leave this mode + needsXWindowMove = true; + else + m_frame.move(m_serverGeometry.topLeft()); // sendSyntheticConfigureNotify() on finish shall be sufficient + } else { + m_frame.move(m_serverGeometry.topLeft()); + sendSyntheticConfigureNotify(); + } + + // Unconditionally move the input window: it won't affect rendering + m_decoInputExtent.move(pos() + inputPos()); + } +} + /** * Reimplemented to inform the client about the new window position. */ @@ -2673,7 +2669,7 @@ void X11Client::leaveMoveResize() { if (needsXWindowMove) { // Do the deferred move - m_frame.move(m_bufferGeometry.topLeft()); + m_frame.move(m_serverGeometry.topLeft()); needsXWindowMove = false; } if (!isResize()) diff --git a/plugins/scenes/opengl/scene_opengl.cpp b/plugins/scenes/opengl/scene_opengl.cpp index 1953ab4b38..f6f5d9c6c6 100644 --- a/plugins/scenes/opengl/scene_opengl.cpp +++ b/plugins/scenes/opengl/scene_opengl.cpp @@ -1433,7 +1433,6 @@ void SceneOpenGL2Window::performPaint(int mask, QRegion region, WindowPaintData if (data.crossFadeProgress() != 1.0) { OpenGLWindowPixmap *previous = previousWindowPixmap(); if (previous) { - const QRect &oldGeometry = previous->contentsRect(); for (const WindowQuad &quad : quads[ContentLeaf]) { // we need to create new window quads with normalize texture coordinates // normal quads divide the x/y position by width/height. This would not work as the texture @@ -1442,12 +1441,7 @@ void SceneOpenGL2Window::performPaint(int mask, QRegion region, WindowPaintData // the previous Client's content space. WindowQuad newQuad(WindowQuadContents); for (int i = 0; i < 4; ++i) { - const qreal xFactor = qreal(quad[i].textureX() - toplevel->clientPos().x())/qreal(toplevel->clientSize().width()); - const qreal yFactor = qreal(quad[i].textureY() - toplevel->clientPos().y())/qreal(toplevel->clientSize().height()); - WindowVertex vertex(quad[i].x(), quad[i].y(), - (xFactor * oldGeometry.width() + oldGeometry.x())/qreal(previous->size().width()), - (yFactor * oldGeometry.height() + oldGeometry.y())/qreal(previous->size().height())); - newQuad[i] = vertex; + newQuad[i] = WindowVertex(quad[i].x(), quad[i].y(), quad[i].u(), quad[i].v()); } quads[PreviousContentLeaf].append(newQuad); } diff --git a/scene.cpp b/scene.cpp index b466046b54..1c65625ef0 100644 --- a/scene.cpp +++ b/scene.cpp @@ -3,6 +3,7 @@ This file is part of the KDE project. Copyright (C) 2006 Lubos Lunak +Copyright (C) 2019 Vlad Zahorodnii This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -735,7 +736,7 @@ QRegion Scene::Window::bufferShape() const const QRect bufferGeometry = toplevel->bufferGeometry(); if (toplevel->shape()) { - auto cookie = xcb_shape_get_rectangles_unchecked(connection(), toplevel->frameId(), XCB_SHAPE_SK_BOUNDING); + auto cookie = xcb_shape_get_rectangles_unchecked(connection(), toplevel->windowId(), XCB_SHAPE_SK_BOUNDING); ScopedCPointer reply(xcb_shape_get_rectangles_reply(connection(), cookie, nullptr)); if (!reply.isNull()) { m_bufferShape = QRegion(); @@ -765,15 +766,7 @@ QRegion Scene::Window::clientShape() const return QRegion(); } } - - const QRegion shape = bufferShape(); - const QMargins bufferMargins = toplevel->bufferMargins(); - if (bufferMargins.isNull()) { - return shape; - } - - const QRect clippingRect = QRect(QPoint(0, 0), toplevel->bufferGeometry().size()) - toplevel->bufferMargins(); - return shape & clippingRect; + return bufferShape(); } QRegion Scene::Window::decorationShape() const @@ -1039,9 +1032,9 @@ void WindowPixmap::create() } XServerGrabber grabber; xcb_pixmap_t pix = xcb_generate_id(connection()); - xcb_void_cookie_t namePixmapCookie = xcb_composite_name_window_pixmap_checked(connection(), toplevel()->frameId(), pix); - Xcb::WindowAttributes windowAttributes(toplevel()->frameId()); - Xcb::WindowGeometry windowGeometry(toplevel()->frameId()); + xcb_void_cookie_t namePixmapCookie = xcb_composite_name_window_pixmap_checked(connection(), toplevel()->windowId(), pix); + Xcb::WindowAttributes windowAttributes(toplevel()->windowId()); + Xcb::WindowGeometry windowGeometry(toplevel()->windowId()); if (xcb_generic_error_t *error = xcb_request_check(connection(), namePixmapCookie)) { qCDebug(KWIN_CORE) << "Creating window pixmap failed: " << error->error_code; free(error); @@ -1062,7 +1055,6 @@ void WindowPixmap::create() } m_pixmap = pix; m_pixmapSize = bufferGeometry.size(); - m_contentsRect = QRect(toplevel()->clientPos(), toplevel()->clientSize()); m_window->unreferencePreviousPixmap(); } diff --git a/scene.h b/scene.h index 7e7aee5847..7444cdafca 100644 --- a/scene.h +++ b/scene.h @@ -3,6 +3,7 @@ This file is part of the KDE project. Copyright (C) 2006 Lubos Lunak +Copyright (C) 2019 Vlad Zahorodnii This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -448,12 +449,6 @@ public: * The size of the pixmap. */ const QSize &size() const; - /** - * The geometry of the Client's content inside the pixmap. In case of a decorated Client the - * pixmap also contains the decoration which is not rendered into this pixmap, though. This - * contentsRect tells where inside the complete pixmap the real content is. - */ - const QRect &contentsRect() const; /** * @brief Returns the Toplevel this WindowPixmap belongs to. * Note: the Toplevel can change over the lifetime of the WindowPixmap in case the Toplevel is copied to Deleted. @@ -513,7 +508,6 @@ private: xcb_pixmap_t m_pixmap; QSize m_pixmapSize; bool m_discarded; - QRect m_contentsRect; QPointer m_buffer; QSharedPointer m_fbo; QImage m_internalImage; @@ -679,12 +673,6 @@ void WindowPixmap::markAsDiscarded() m_window->referencePreviousPixmap(); } -inline -const QRect &WindowPixmap::contentsRect() const -{ - return m_contentsRect; -} - inline const QSize &WindowPixmap::size() const { diff --git a/toplevel.cpp b/toplevel.cpp index 3a11f30bd7..5666c8b3b4 100644 --- a/toplevel.cpp +++ b/toplevel.cpp @@ -3,6 +3,7 @@ This file is part of the KDE project. Copyright (C) 2006 Lubos Lunak +Copyright (C) 2019 Vlad Zahorodnii This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -256,12 +257,13 @@ bool Toplevel::setupCompositing() if (damage_handle != XCB_NONE) return false; - if (kwinApp()->operationMode() == Application::OperationModeX11 && !surface()) { + if (kwinApp()->operationMode() == Application::OperationModeX11) { damage_handle = xcb_generate_id(connection()); - xcb_damage_create(connection(), damage_handle, frameId(), XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY); + xcb_damage_create(connection(), damage_handle, windowId(), XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY); + xcb_composite_redirect_window(connection(), windowId(), XCB_COMPOSITE_REDIRECT_MANUAL); } - damage_region = QRegion(0, 0, width(), height()); + damage_region = QRegion(QRect(QPoint(), bufferGeometry().size())); effect_window = new EffectWindowImpl(this); Compositor::self()->scene()->addToplevel(this); @@ -278,6 +280,10 @@ void Toplevel::finishCompositing(ReleaseReason releaseReason) delete effect_window; } + if (kwinApp()->operationMode() == Application::OperationModeX11) { + xcb_composite_unredirect_window(connection(), windowId(), XCB_COMPOSITE_REDIRECT_MANUAL); + } + if (damage_handle != XCB_NONE && releaseReason != ReleaseReason::Destroyed) { xcb_damage_destroy(connection(), damage_handle); @@ -791,11 +797,6 @@ bool Toplevel::isLocalhost() const return m_clientMachine->isLocal(); } -QMargins Toplevel::bufferMargins() const -{ - return QMargins(); -} - QMargins Toplevel::frameMargins() const { return QMargins(); diff --git a/toplevel.h b/toplevel.h index a99556108d..3aa4960210 100644 --- a/toplevel.h +++ b/toplevel.h @@ -3,6 +3,7 @@ This file is part of the KDE project. Copyright (C) 2006 Lubos Lunak +Copyright (C) 2019 Vlad Zahorodnii This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -315,16 +316,6 @@ public: * occupies on the screen, in global screen coordinates. */ virtual QRect bufferGeometry() const = 0; - /** - * Returns the extents of invisible portions in the pixmap. - * - * An X11 pixmap may contain invisible space around the actual contents of the - * client. That space is reserved for server-side decoration, which we usually - * want to skip when building contents window quads. - * - * Default implementation returns a margins object with all margins set to 0. - */ - virtual QMargins bufferMargins() const; /** * Returns the geometry of the Toplevel, excluding invisible portions, e.g. * server-side and client-side drop shadows, etc. diff --git a/x11client.cpp b/x11client.cpp index 76a504c75e..d19967ced4 100644 --- a/x11client.cpp +++ b/x11client.cpp @@ -4,6 +4,7 @@ Copyright (C) 1999, 2000 Matthias Ettrich Copyright (C) 2003 Lubos Lunak +Copyright (C) 2019 Vlad Zahorodnii This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -255,7 +256,7 @@ void X11Client::releaseWindow(bool on_shutdown) m_client.deleteProperty(atoms->kde_net_wm_user_creation_time); m_client.deleteProperty(atoms->net_frame_extents); m_client.deleteProperty(atoms->kde_net_wm_frame_strut); - m_client.reparent(rootWindow(), m_bufferGeometry.x(), m_bufferGeometry.y()); + m_client.reparent(rootWindow(), m_serverGeometry.x(), m_serverGeometry.y()); xcb_change_save_set(c, XCB_SET_MODE_DELETE, m_client); m_client.selectInput(XCB_EVENT_MASK_NO_EVENT); if (on_shutdown) @@ -1985,12 +1986,7 @@ xcb_window_t X11Client::frameId() const QRect X11Client::bufferGeometry() const { - return m_bufferGeometry; -} - -QMargins X11Client::bufferMargins() const -{ - return QMargins(borderLeft(), borderTop(), borderRight(), borderBottom()); + return m_clientGeometry; } QPoint X11Client::framePosToClientPos(const QPoint &point) const @@ -2216,64 +2212,21 @@ void X11Client::handleSync() addRepaintFull(); } -bool X11Client::canUpdatePosition(const QPoint &frame, const QPoint &buffer, ForceGeometry_t force) const -{ - // Obey forced geometry updates. - if (force != NormalGeometrySet) { - return true; - } - // Server-side geometry and our geometry are out of sync. - if (bufferGeometry().topLeft() != buffer) { - return true; - } - if (frameGeometry().topLeft() != frame) { - return true; - } - return false; -} - -bool X11Client::canUpdateSize(const QSize &frame, const QSize &buffer, ForceGeometry_t force) const -{ - // Obey forced geometry updates. - if (force != NormalGeometrySet) { - return true; - } - // Server-side geometry and our geometry are out of sync. - if (bufferGeometry().size() != buffer) { - return true; - } - if (frameGeometry().size() != frame) { - return true; - } - return false; -} - -bool X11Client::canUpdateGeometry(const QRect &frame, const QRect &buffer, ForceGeometry_t force) const -{ - if (canUpdatePosition(frame.topLeft(), buffer.topLeft(), force)) { - return true; - } - if (canUpdateSize(frame.size(), buffer.size(), force)) { - return true; - } - return pendingGeometryUpdate() != PendingGeometryNone; -} - void X11Client::move(int x, int y, ForceGeometry_t force) { const QPoint framePosition(x, y); m_clientGeometry.moveTopLeft(framePosToClientPos(framePosition)); - const QPoint bufferPosition = isDecorated() ? framePosition : m_clientGeometry.topLeft(); + const QPoint serverPosition = isDecorated() ? framePosition : m_clientGeometry.topLeft(); // resuming geometry updates is handled only in setGeometry() Q_ASSERT(pendingGeometryUpdate() == PendingGeometryNone || areGeometryUpdatesBlocked()); if (!areGeometryUpdatesBlocked() && framePosition != rules()->checkPosition(framePosition)) { qCDebug(KWIN_CORE) << "forced position fail:" << framePosition << ":" << rules()->checkPosition(framePosition); } - if (!canUpdatePosition(framePosition, bufferPosition, force)) { + geom.moveTopLeft(framePosition); + if (force == NormalGeometrySet && m_serverGeometry.topLeft() == serverPosition) { return; } - m_bufferGeometry.moveTopLeft(bufferPosition); - geom.moveTopLeft(framePosition); + m_serverGeometry.moveTopLeft(serverPosition); if (areGeometryUpdatesBlocked()) { if (pendingGeometryUpdate() == PendingGeometryForced) { // Maximum, nothing needed. @@ -2284,8 +2237,7 @@ void X11Client::move(int x, int y, ForceGeometry_t force) } return; } - m_frame.move(m_bufferGeometry.topLeft()); - sendSyntheticConfigureNotify(); + updateServerGeometry(); updateWindowRules(Rules::Position); screens()->setCurrent(this); workspace()->updateStackingOrder(); diff --git a/x11client.h b/x11client.h index 34bb1371d7..df06e05d64 100644 --- a/x11client.h +++ b/x11client.h @@ -4,6 +4,7 @@ Copyright (C) 1999, 2000 Matthias Ettrich Copyright (C) 2003 Lubos Lunak +Copyright (C) 2019 Vlad Zahorodnii This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -57,6 +58,25 @@ enum class Predicate { InputIdMatch }; +/** + * The X11Client class represents a managed X11 client. + * + * Note that override-redirect clients are represented by instances of the Unmanaged class. + * + * Each X11 client has three geometries associated with it - frame, client, and server. The frame + * geometry is the most easiest one to understand, it specifies visible bounds of the window from + * the user's perspective. The frame geometry doesn't include server-side and client-side drop + * shadows. Window operations such resizing, snapping, tiling and so on must operate on this kind + * of geometry. The client geometry specifies a rectangle on the screen occupied by the client + * window. The server-side decoration, if any, must be put around the client geometry. The server + * geometry specifies the server-side geometry of the frame window. + * + * There is no strict order between the frame and the client geometry. Either one of them can be + * inside the other one. However, it's always guaranteed that both of them are inside the server + * geometry. + * + * The buffer geometry is an alias for the client geometry. + */ class KWIN_EXPORT X11Client : public AbstractClient { Q_OBJECT @@ -90,7 +110,6 @@ public: xcb_window_t frameId() const override; QRect bufferGeometry() const override; - QMargins bufferMargins() const override; QPoint framePosToClientPos(const QPoint &point) const override; QPoint clientPosToFramePos(const QPoint &point) const override; @@ -446,9 +465,6 @@ private: void destroyDecoration() override; void updateFrameExtents(); void setClientFrameExtents(const NETStrut &strut); - bool canUpdatePosition(const QPoint &frame, const QPoint &buffer, ForceGeometry_t force) const; - bool canUpdateSize(const QSize &frame, const QSize &buffer, ForceGeometry_t force) const; - bool canUpdateGeometry(const QRect &frame, const QRect &buffer, ForceGeometry_t force) const; void internalShow(); void internalHide(); @@ -456,7 +472,7 @@ private: void map(); void unmap(); void updateHiddenPreview(); - + void updateServerGeometry(); void updateInputShape(); xcb_timestamp_t readUserTimeMapTimestamp(const KStartupInfoId* asn_id, const KStartupInfoData* asn_data, @@ -522,7 +538,7 @@ private: } m_fullscreenMode; MaximizeMode max_mode; - QRect m_bufferGeometry = QRect(0, 0, 100, 100); + QRect m_serverGeometry = QRect(0, 0, 100, 100); QRect m_clientGeometry = QRect(0, 0, 100, 100); QRect geom_restore; QRect geom_fs_restore;