From 71e8fad1f60996bcc1a7e5974f0a21b194214db0 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Thu, 25 May 2023 10:57:36 +0300 Subject: [PATCH] Delegate screen edge reservation error handling to user Window screen edge reservation relies on Window::showOnScreenEdge() getting called when the screen edge can't be reserved. That makes screen edge code not easy to follow. This change makes ScreenEdges::reserve() indicate if a screen edge has been successfully reserved and delegate error handling to the user. In most cases, if a screen edge has not been successfully hidden, you just need to avoid calling hideClient() and wait until the next moment when the window can be hidden again. Note that it differs from the current behavior but it's for a good reason. If the panel can't be hidden now, the panel has no idea how to handle it; only the compositor knows when it can be hidden again. --- src/layershellv1window.cpp | 7 +++++-- src/screenedge.cpp | 16 +++++++--------- src/screenedge.h | 4 ++-- src/x11window.cpp | 27 ++++++++++++--------------- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/layershellv1window.cpp b/src/layershellv1window.cpp index 546ef820f8..631e26f2d3 100644 --- a/src/layershellv1window.cpp +++ b/src/layershellv1window.cpp @@ -322,8 +322,11 @@ void LayerShellV1Window::installAutoHideScreenEdgeV1(KWaylandServer::AutoHideScr void LayerShellV1Window::reserveScreenEdge() { - hideClient(); - workspace()->screenEdges()->reserve(this, m_screenEdge->border()); + if (workspace()->screenEdges()->reserve(this, m_screenEdge->border())) { + hideClient(); + } else { + showClient(); + } } void LayerShellV1Window::unreserveScreenEdge() diff --git a/src/screenedge.cpp b/src/screenedge.cpp index b5ce140203..576975fabb 100644 --- a/src/screenedge.cpp +++ b/src/screenedge.cpp @@ -1279,7 +1279,7 @@ void ScreenEdges::unreserve(ElectricBorder border, QObject *object) } } -void ScreenEdges::reserve(Window *client, ElectricBorder border) +bool ScreenEdges::reserve(Window *client, ElectricBorder border) { const auto it = std::remove_if(m_edges.begin(), m_edges.end(), [client](const auto &edge) { return edge->client() == client; @@ -1288,11 +1288,9 @@ void ScreenEdges::reserve(Window *client, ElectricBorder border) m_edges.erase(it, m_edges.end()); if (border != ElectricNone) { - createEdgeForClient(client, border); + return createEdgeForClient(client, border); } else { - if (hadBorder) { // show again - client->showOnScreenEdge(); - } + return hadBorder; } } @@ -1314,7 +1312,7 @@ void ScreenEdges::unreserveTouch(ElectricBorder border, QAction *action) } } -void ScreenEdges::createEdgeForClient(Window *client, ElectricBorder border) +bool ScreenEdges::createEdgeForClient(Window *client, ElectricBorder border) { int y = 0; int x = 0; @@ -1385,10 +1383,10 @@ void ScreenEdges::createEdgeForClient(Window *client, ElectricBorder border) Edge *edge = m_edges.back().get(); edge->setClient(client); edge->reserve(); - } else { - // we could not create an edge window, so don't allow the window to hide - client->showOnScreenEdge(); + return true; } + + return false; } void ScreenEdges::deleteEdgeForClient(Window *window) diff --git a/src/screenedge.h b/src/screenedge.h index 2a7d1e4bb2..74dee30b3d 100644 --- a/src/screenedge.h +++ b/src/screenedge.h @@ -298,7 +298,7 @@ public: * @param client The Client for which an Edge should be reserved * @param border The border which the client wants to use, only proper borders are supported (no corners) */ - void reserve(KWin::Window *client, ElectricBorder border); + bool reserve(KWin::Window *client, ElectricBorder border); /** * Mark the specified screen edge as reserved for touch gestures. This method is provided for @@ -409,7 +409,7 @@ private: void setRemainActiveOnFullscreen(bool remainActive); ElectricBorderAction actionForEdge(Edge *edge) const; ElectricBorderAction actionForTouchEdge(Edge *edge) const; - void createEdgeForClient(Window *client, ElectricBorder border); + bool createEdgeForClient(Window *client, ElectricBorder border); void deleteEdgeForClient(Window *client); bool m_desktopSwitching; bool m_desktopSwitchingMovingClients; diff --git a/src/x11window.cpp b/src/x11window.cpp index 8143b4ce4f..5c3d4fb697 100644 --- a/src/x11window.cpp +++ b/src/x11window.cpp @@ -2917,29 +2917,26 @@ void X11Window::readShowOnScreenEdge(Xcb::Property &property) if (border != ElectricNone) { disconnect(m_edgeGeometryTrackingConnection); - hideClient(); - const bool successfullyHidden = isHiddenInternal(); + auto reserveScreenEdge = [this, border]() { + if (workspace()->screenEdges()->reserve(this, border)) { + hideClient(); + } else { + showClient(); + } + }; - m_edgeGeometryTrackingConnection = connect(this, &X11Window::frameGeometryChanged, this, [this, border]() { - hideClient(); - workspace()->screenEdges()->reserve(this, border); - }); - - if (successfullyHidden) { - workspace()->screenEdges()->reserve(this, border); - } else { - workspace()->screenEdges()->reserve(this, ElectricNone); - } + reserveScreenEdge(); + m_edgeGeometryTrackingConnection = connect(this, &X11Window::frameGeometryChanged, this, reserveScreenEdge); } else if (!property.isNull() && property->type != XCB_ATOM_NONE) { // property value is incorrect, delete the property // so that the client knows that it is not hidden xcb_delete_property(kwinApp()->x11Connection(), window(), atoms->kde_screen_edge_show); } else { // restore - // TODO: add proper unreserve - - // this will call showOnScreenEdge to reset the state disconnect(m_edgeGeometryTrackingConnection); + + showClient(); + workspace()->screenEdges()->reserve(this, ElectricNone); } }