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.
This commit is contained in:
Vlad Zahorodnii 2023-05-25 10:57:36 +03:00
parent 687415076f
commit 71e8fad1f6
4 changed files with 26 additions and 28 deletions

View file

@ -322,8 +322,11 @@ void LayerShellV1Window::installAutoHideScreenEdgeV1(KWaylandServer::AutoHideScr
void LayerShellV1Window::reserveScreenEdge() void LayerShellV1Window::reserveScreenEdge()
{ {
hideClient(); if (workspace()->screenEdges()->reserve(this, m_screenEdge->border())) {
workspace()->screenEdges()->reserve(this, m_screenEdge->border()); hideClient();
} else {
showClient();
}
} }
void LayerShellV1Window::unreserveScreenEdge() void LayerShellV1Window::unreserveScreenEdge()

View file

@ -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) { const auto it = std::remove_if(m_edges.begin(), m_edges.end(), [client](const auto &edge) {
return edge->client() == client; return edge->client() == client;
@ -1288,11 +1288,9 @@ void ScreenEdges::reserve(Window *client, ElectricBorder border)
m_edges.erase(it, m_edges.end()); m_edges.erase(it, m_edges.end());
if (border != ElectricNone) { if (border != ElectricNone) {
createEdgeForClient(client, border); return createEdgeForClient(client, border);
} else { } else {
if (hadBorder) { // show again return hadBorder;
client->showOnScreenEdge();
}
} }
} }
@ -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 y = 0;
int x = 0; int x = 0;
@ -1385,10 +1383,10 @@ void ScreenEdges::createEdgeForClient(Window *client, ElectricBorder border)
Edge *edge = m_edges.back().get(); Edge *edge = m_edges.back().get();
edge->setClient(client); edge->setClient(client);
edge->reserve(); edge->reserve();
} else { return true;
// we could not create an edge window, so don't allow the window to hide
client->showOnScreenEdge();
} }
return false;
} }
void ScreenEdges::deleteEdgeForClient(Window *window) void ScreenEdges::deleteEdgeForClient(Window *window)

View file

@ -298,7 +298,7 @@ public:
* @param client The Client for which an Edge should be reserved * @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) * @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 * Mark the specified screen edge as reserved for touch gestures. This method is provided for
@ -409,7 +409,7 @@ private:
void setRemainActiveOnFullscreen(bool remainActive); void setRemainActiveOnFullscreen(bool remainActive);
ElectricBorderAction actionForEdge(Edge *edge) const; ElectricBorderAction actionForEdge(Edge *edge) const;
ElectricBorderAction actionForTouchEdge(Edge *edge) const; ElectricBorderAction actionForTouchEdge(Edge *edge) const;
void createEdgeForClient(Window *client, ElectricBorder border); bool createEdgeForClient(Window *client, ElectricBorder border);
void deleteEdgeForClient(Window *client); void deleteEdgeForClient(Window *client);
bool m_desktopSwitching; bool m_desktopSwitching;
bool m_desktopSwitchingMovingClients; bool m_desktopSwitchingMovingClients;

View file

@ -2917,29 +2917,26 @@ void X11Window::readShowOnScreenEdge(Xcb::Property &property)
if (border != ElectricNone) { if (border != ElectricNone) {
disconnect(m_edgeGeometryTrackingConnection); disconnect(m_edgeGeometryTrackingConnection);
hideClient(); auto reserveScreenEdge = [this, border]() {
const bool successfullyHidden = isHiddenInternal(); if (workspace()->screenEdges()->reserve(this, border)) {
hideClient();
} else {
showClient();
}
};
m_edgeGeometryTrackingConnection = connect(this, &X11Window::frameGeometryChanged, this, [this, border]() { reserveScreenEdge();
hideClient(); m_edgeGeometryTrackingConnection = connect(this, &X11Window::frameGeometryChanged, this, reserveScreenEdge);
workspace()->screenEdges()->reserve(this, border);
});
if (successfullyHidden) {
workspace()->screenEdges()->reserve(this, border);
} else {
workspace()->screenEdges()->reserve(this, ElectricNone);
}
} else if (!property.isNull() && property->type != XCB_ATOM_NONE) { } else if (!property.isNull() && property->type != XCB_ATOM_NONE) {
// property value is incorrect, delete the property // property value is incorrect, delete the property
// so that the client knows that it is not hidden // so that the client knows that it is not hidden
xcb_delete_property(kwinApp()->x11Connection(), window(), atoms->kde_screen_edge_show); xcb_delete_property(kwinApp()->x11Connection(), window(), atoms->kde_screen_edge_show);
} else { } else {
// restore // restore
// TODO: add proper unreserve
// this will call showOnScreenEdge to reset the state
disconnect(m_edgeGeometryTrackingConnection); disconnect(m_edgeGeometryTrackingConnection);
showClient();
workspace()->screenEdges()->reserve(this, ElectricNone); workspace()->screenEdges()->reserve(this, ElectricNone);
} }
} }