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;