From 994fafa9120883642334e9e74435a1254bb74833 Mon Sep 17 00:00:00 2001 From: Roman Gilg Date: Sat, 22 Jun 2019 12:00:56 +0200 Subject: [PATCH] Move non-Compositor functions out of composite.cpp source file Summary: Compositing today is ubiquitous. There is no reason to keep compositing specific functions of Toplevel, Client and Workspace classes in the composite.cpp source file. Instead let these definitions be separated. Test Plan: Compiles Reviewers: #kwin, zzag Reviewed By: #kwin, zzag Subscribers: zzag, kwin Tags: #kwin Maniphest Tasks: T11071 Differential Revision: https://phabricator.kde.org/D21654 --- client.cpp | 17 +++ composite.cpp | 306 +++----------------------------------------------- toplevel.cpp | 240 ++++++++++++++++++++++++++++++++++++++- workspace.cpp | 5 + 4 files changed, 279 insertions(+), 289 deletions(-) diff --git a/client.cpp b/client.cpp index 8e78d9687c..81cc598588 100644 --- a/client.cpp +++ b/client.cpp @@ -704,6 +704,23 @@ void Client::hideClient(bool hide) updateVisibility(); } +bool Client::setupCompositing() +{ + if (!Toplevel::setupCompositing()){ + return false; + } + updateVisibility(); // for internalKeep() + return true; +} + +void Client::finishCompositing(ReleaseReason releaseReason) +{ + Toplevel::finishCompositing(releaseReason); + updateVisibility(); + // for safety in case KWin is just resizing the window + resetHaveResizeEffect(); +} + /** * Returns whether the window is minimizable or not **/ diff --git a/composite.cpp b/composite.cpp index 01ae756b27..7fb312eaaf 100644 --- a/composite.cpp +++ b/composite.cpp @@ -20,37 +20,27 @@ along with this program. If not, see . #include "composite.h" #include "dbusinterface.h" -#include "utils.h" -#include -#include "workspace.h" #include "client.h" -#include "unmanaged.h" +#include "decorations/decoratedclient.h" #include "deleted.h" #include "effects.h" #include "overlaywindow.h" +#include "platform.h" #include "scene.h" #include "screens.h" #include "shadow.h" -#include "useractions.h" -#include "xcbutils.h" -#include "platform.h" #include "shell_client.h" +#include "unmanaged.h" +#include "useractions.h" +#include "utils.h" #include "wayland_server.h" -#include "decorations/decoratedclient.h" +#include "workspace.h" +#include "xcbutils.h" #include #include -#include - -#include -#include -#include -#include -#include -#include -#include #include #include #include @@ -58,9 +48,20 @@ along with this program. If not, see . #include #include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include +#include + Q_DECLARE_METATYPE(KWin::Compositor::SuspendReason) namespace KWin @@ -918,275 +919,4 @@ bool Compositor::isOverlayWindowVisible() const return m_scene->overlayWindow()->isVisible(); } -/***************************************************** - * Workspace - ****************************************************/ - -bool Workspace::compositing() const -{ - return m_compositor && m_compositor->hasScene(); -} - -//**************************************** -// Toplevel -//**************************************** - -bool Toplevel::setupCompositing() -{ - if (!compositing()) - return false; - - if (damage_handle != XCB_NONE) - return false; - - if (kwinApp()->operationMode() == Application::OperationModeX11 && !surface()) { - damage_handle = xcb_generate_id(connection()); - xcb_damage_create(connection(), damage_handle, frameId(), XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY); - } - - damage_region = QRegion(0, 0, width(), height()); - effect_window = new EffectWindowImpl(this); - - Compositor::self()->scene()->addToplevel(this); - - return true; -} - -void Toplevel::finishCompositing(ReleaseReason releaseReason) -{ - if (kwinApp()->operationMode() == Application::OperationModeX11 && damage_handle == XCB_NONE) - return; - if (effect_window->window() == this) { // otherwise it's already passed to Deleted, don't free data - discardWindowPixmap(); - delete effect_window; - } - - if (damage_handle != XCB_NONE && - releaseReason != ReleaseReason::Destroyed) { - xcb_damage_destroy(connection(), damage_handle); - } - - damage_handle = XCB_NONE; - damage_region = QRegion(); - repaints_region = QRegion(); - effect_window = NULL; -} - -void Toplevel::discardWindowPixmap() -{ - addDamageFull(); - if (effectWindow() != NULL && effectWindow()->sceneWindow() != NULL) - effectWindow()->sceneWindow()->pixmapDiscarded(); -} - -void Toplevel::damageNotifyEvent() -{ - m_isDamaged = true; - - // Note: The rect is supposed to specify the damage extents, - // but we don't know it at this point. No one who connects - // to this signal uses the rect however. - emit damaged(this, QRect()); -} - -bool Toplevel::compositing() const -{ - if (!Workspace::self()) { - return false; - } - return Workspace::self()->compositing(); -} - -void Client::damageNotifyEvent() -{ - if (syncRequest.isPending && isResize()) { - emit damaged(this, QRect()); - m_isDamaged = true; - return; - } - - if (!ready_for_painting) { // avoid "setReadyForPainting()" function calling overhead - if (syncRequest.counter == XCB_NONE) { // cannot detect complete redraw, consider done now - setReadyForPainting(); - setupWindowManagementInterface(); - } - } - - Toplevel::damageNotifyEvent(); -} - -bool Toplevel::resetAndFetchDamage() -{ - if (!m_isDamaged) - return false; - - if (damage_handle == XCB_NONE) { - m_isDamaged = false; - return true; - } - - xcb_connection_t *conn = connection(); - - // Create a new region and copy the damage region to it, - // resetting the damaged state. - xcb_xfixes_region_t region = xcb_generate_id(conn); - xcb_xfixes_create_region(conn, region, 0, 0); - xcb_damage_subtract(conn, damage_handle, 0, region); - - // Send a fetch-region request and destroy the region - m_regionCookie = xcb_xfixes_fetch_region_unchecked(conn, region); - xcb_xfixes_destroy_region(conn, region); - - m_isDamaged = false; - m_damageReplyPending = true; - - return m_damageReplyPending; -} - -void Toplevel::getDamageRegionReply() -{ - if (!m_damageReplyPending) - return; - - m_damageReplyPending = false; - - // Get the fetch-region reply - xcb_xfixes_fetch_region_reply_t *reply = - xcb_xfixes_fetch_region_reply(connection(), m_regionCookie, 0); - - if (!reply) - return; - - // Convert the reply to a QRegion - int count = xcb_xfixes_fetch_region_rectangles_length(reply); - QRegion region; - - if (count > 1 && count < 16) { - xcb_rectangle_t *rects = xcb_xfixes_fetch_region_rectangles(reply); - - QVector qrects; - qrects.reserve(count); - - for (int i = 0; i < count; i++) - qrects << QRect(rects[i].x, rects[i].y, rects[i].width, rects[i].height); - - region.setRects(qrects.constData(), count); - } else - region += QRect(reply->extents.x, reply->extents.y, - reply->extents.width, reply->extents.height); - - damage_region += region; - repaints_region += region; - - free(reply); -} - -void Toplevel::addDamageFull() -{ - if (!compositing()) - return; - - damage_region = rect(); - repaints_region |= rect(); - - emit damaged(this, rect()); -} - -void Toplevel::resetDamage() -{ - damage_region = QRegion(); -} - -void Toplevel::addRepaint(const QRect& r) -{ - if (!compositing()) { - return; - } - repaints_region += r; - emit needsRepaint(); -} - -void Toplevel::addRepaint(int x, int y, int w, int h) -{ - QRect r(x, y, w, h); - addRepaint(r); -} - -void Toplevel::addRepaint(const QRegion& r) -{ - if (!compositing()) { - return; - } - repaints_region += r; - emit needsRepaint(); -} - -void Toplevel::addLayerRepaint(const QRect& r) -{ - if (!compositing()) { - return; - } - layer_repaints_region += r; - emit needsRepaint(); -} - -void Toplevel::addLayerRepaint(int x, int y, int w, int h) -{ - QRect r(x, y, w, h); - addLayerRepaint(r); -} - -void Toplevel::addLayerRepaint(const QRegion& r) -{ - if (!compositing()) - return; - layer_repaints_region += r; - emit needsRepaint(); -} - -void Toplevel::addRepaintFull() -{ - repaints_region = visibleRect().translated(-pos()); - emit needsRepaint(); -} - -void Toplevel::resetRepaints() -{ - repaints_region = QRegion(); - layer_repaints_region = QRegion(); -} - -void Toplevel::addWorkspaceRepaint(int x, int y, int w, int h) -{ - addWorkspaceRepaint(QRect(x, y, w, h)); -} - -void Toplevel::addWorkspaceRepaint(const QRect& r2) -{ - if (!compositing()) - return; - Compositor::self()->addRepaint(r2); -} - -//**************************************** -// Client -//**************************************** - -bool Client::setupCompositing() -{ - if (!Toplevel::setupCompositing()){ - return false; - } - updateVisibility(); // for internalKeep() - return true; -} - -void Client::finishCompositing(ReleaseReason releaseReason) -{ - Toplevel::finishCompositing(releaseReason); - updateVisibility(); - // for safety in case KWin is just resizing the window - resetHaveResizeEffect(); -} - } // namespace diff --git a/toplevel.cpp b/toplevel.cpp index de3a73c7dd..1bea1563c1 100644 --- a/toplevel.cpp +++ b/toplevel.cpp @@ -17,7 +17,6 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ - #include "toplevel.h" #ifdef KWIN_BUILD_ACTIVITIES @@ -26,9 +25,11 @@ along with this program. If not, see . #include "atoms.h" #include "client.h" #include "client_machine.h" +#include "composite.h" #include "effects.h" #include "screens.h" #include "shadow.h" +#include "workspace.h" #include "xcbutils.h" #include @@ -256,6 +257,243 @@ void Toplevel::setOpacity(double new_opacity) } } +bool Toplevel::setupCompositing() +{ + if (!compositing()) + return false; + + if (damage_handle != XCB_NONE) + return false; + + if (kwinApp()->operationMode() == Application::OperationModeX11 && !surface()) { + damage_handle = xcb_generate_id(connection()); + xcb_damage_create(connection(), damage_handle, frameId(), XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY); + } + + damage_region = QRegion(0, 0, width(), height()); + effect_window = new EffectWindowImpl(this); + + Compositor::self()->scene()->addToplevel(this); + + return true; +} + +void Toplevel::finishCompositing(ReleaseReason releaseReason) +{ + if (kwinApp()->operationMode() == Application::OperationModeX11 && damage_handle == XCB_NONE) + return; + if (effect_window->window() == this) { // otherwise it's already passed to Deleted, don't free data + discardWindowPixmap(); + delete effect_window; + } + + if (damage_handle != XCB_NONE && + releaseReason != ReleaseReason::Destroyed) { + xcb_damage_destroy(connection(), damage_handle); + } + + damage_handle = XCB_NONE; + damage_region = QRegion(); + repaints_region = QRegion(); + effect_window = NULL; +} + +void Toplevel::discardWindowPixmap() +{ + addDamageFull(); + if (effectWindow() != NULL && effectWindow()->sceneWindow() != NULL) + effectWindow()->sceneWindow()->pixmapDiscarded(); +} + +void Toplevel::damageNotifyEvent() +{ + m_isDamaged = true; + + // Note: The rect is supposed to specify the damage extents, + // but we don't know it at this point. No one who connects + // to this signal uses the rect however. + emit damaged(this, QRect()); +} + +bool Toplevel::compositing() const +{ + if (!Workspace::self()) { + return false; + } + return Workspace::self()->compositing(); +} + +void Client::damageNotifyEvent() +{ + if (syncRequest.isPending && isResize()) { + emit damaged(this, QRect()); + m_isDamaged = true; + return; + } + + if (!ready_for_painting) { // avoid "setReadyForPainting()" function calling overhead + if (syncRequest.counter == XCB_NONE) { // cannot detect complete redraw, consider done now + setReadyForPainting(); + setupWindowManagementInterface(); + } + } + + Toplevel::damageNotifyEvent(); +} + +bool Toplevel::resetAndFetchDamage() +{ + if (!m_isDamaged) + return false; + + if (damage_handle == XCB_NONE) { + m_isDamaged = false; + return true; + } + + xcb_connection_t *conn = connection(); + + // Create a new region and copy the damage region to it, + // resetting the damaged state. + xcb_xfixes_region_t region = xcb_generate_id(conn); + xcb_xfixes_create_region(conn, region, 0, 0); + xcb_damage_subtract(conn, damage_handle, 0, region); + + // Send a fetch-region request and destroy the region + m_regionCookie = xcb_xfixes_fetch_region_unchecked(conn, region); + xcb_xfixes_destroy_region(conn, region); + + m_isDamaged = false; + m_damageReplyPending = true; + + return m_damageReplyPending; +} + +void Toplevel::getDamageRegionReply() +{ + if (!m_damageReplyPending) + return; + + m_damageReplyPending = false; + + // Get the fetch-region reply + xcb_xfixes_fetch_region_reply_t *reply = + xcb_xfixes_fetch_region_reply(connection(), m_regionCookie, 0); + + if (!reply) + return; + + // Convert the reply to a QRegion + int count = xcb_xfixes_fetch_region_rectangles_length(reply); + QRegion region; + + if (count > 1 && count < 16) { + xcb_rectangle_t *rects = xcb_xfixes_fetch_region_rectangles(reply); + + QVector qrects; + qrects.reserve(count); + + for (int i = 0; i < count; i++) + qrects << QRect(rects[i].x, rects[i].y, rects[i].width, rects[i].height); + + region.setRects(qrects.constData(), count); + } else + region += QRect(reply->extents.x, reply->extents.y, + reply->extents.width, reply->extents.height); + + damage_region += region; + repaints_region += region; + + free(reply); +} + +void Toplevel::addDamageFull() +{ + if (!compositing()) + return; + + damage_region = rect(); + repaints_region |= rect(); + + emit damaged(this, rect()); +} + +void Toplevel::resetDamage() +{ + damage_region = QRegion(); +} + +void Toplevel::addRepaint(const QRect& r) +{ + if (!compositing()) { + return; + } + repaints_region += r; + emit needsRepaint(); +} + +void Toplevel::addRepaint(int x, int y, int w, int h) +{ + QRect r(x, y, w, h); + addRepaint(r); +} + +void Toplevel::addRepaint(const QRegion& r) +{ + if (!compositing()) { + return; + } + repaints_region += r; + emit needsRepaint(); +} + +void Toplevel::addLayerRepaint(const QRect& r) +{ + if (!compositing()) { + return; + } + layer_repaints_region += r; + emit needsRepaint(); +} + +void Toplevel::addLayerRepaint(int x, int y, int w, int h) +{ + QRect r(x, y, w, h); + addLayerRepaint(r); +} + +void Toplevel::addLayerRepaint(const QRegion& r) +{ + if (!compositing()) + return; + layer_repaints_region += r; + emit needsRepaint(); +} + +void Toplevel::addRepaintFull() +{ + repaints_region = visibleRect().translated(-pos()); + emit needsRepaint(); +} + +void Toplevel::resetRepaints() +{ + repaints_region = QRegion(); + layer_repaints_region = QRegion(); +} + +void Toplevel::addWorkspaceRepaint(int x, int y, int w, int h) +{ + addWorkspaceRepaint(QRect(x, y, w, h)); +} + +void Toplevel::addWorkspaceRepaint(const QRect& r2) +{ + if (!compositing()) + return; + Compositor::self()->addRepaint(r2); +} + void Toplevel::setReadyForPainting() { if (!ready_for_painting) { diff --git a/workspace.cpp b/workspace.cpp index 2adfa2edb0..c7aa162dfc 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -1748,6 +1748,11 @@ Toplevel *Workspace::findInternal(QWindow *w) const } } +bool Workspace::compositing() const +{ + return m_compositor && m_compositor->hasScene(); +} + void Workspace::markXStackingOrderAsDirty() { m_xStackingDirty = true;