Implement plasma-surface open-under-cursor

The surface is positioned at the current cursor location but kept in
bounds to keep it fully visible when the cursor is near the screen border.
This commit is contained in:
David Redondo 2022-03-07 14:21:07 +01:00
parent 0130b53126
commit d548f4bce4
3 changed files with 46 additions and 1 deletions

View file

@ -46,6 +46,7 @@ public:
bool m_skipTaskbar = false;
bool m_skipSwitcher = false;
bool m_panelTakesFocus = false;
bool m_openUnderCursorRequested = false;
private:
void org_kde_plasma_surface_destroy_resource(Resource *resource) override;
@ -59,6 +60,7 @@ private:
void org_kde_plasma_surface_panel_auto_hide_show(Resource *resource) override;
void org_kde_plasma_surface_set_panel_takes_focus(Resource *resource, uint32_t takes_focus) override;
void org_kde_plasma_surface_set_skip_switcher(Resource *resource, uint32_t skip) override;
void org_kde_plasma_surface_open_under_cursor(Resource *resource) override;
};
PlasmaShellInterface::PlasmaShellInterface(Display *display, QObject *parent)
@ -148,6 +150,15 @@ void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_set_position(Res
Q_EMIT q->positionChanged();
}
void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_open_under_cursor(Resource *resource)
{
if (surface && surface->buffer()) {
wl_resource_post_error(resource->handle, -1, "open_under_cursor: surface has a buffer");
}
m_openUnderCursorRequested = true;
Q_EMIT q->openUnderCursorRequested();
}
void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_set_role(Resource *resource, uint32_t role)
{
Q_UNUSED(resource)
@ -272,6 +283,11 @@ bool PlasmaShellSurfaceInterface::isPositionSet() const
return d->m_positionSet;
}
bool PlasmaShellSurfaceInterface::wantsOpenUnderCursor() const
{
return d->m_openUnderCursorRequested;
}
PlasmaShellSurfaceInterface::PanelBehavior PlasmaShellSurfaceInterface::panelBehavior() const
{
return d->m_panelBehavior;

View file

@ -74,6 +74,11 @@ public:
*/
bool isPositionSet() const;
/**
* @returns Whether the surface has requested to be opened under the cursor.
*/
bool wantsOpenUnderCursor() const;
/**
* Describes possible roles this PlasmaShellSurfaceInterface can have.
* The role can be used by the server to e.g. change the stacking order accordingly.
@ -159,6 +164,12 @@ Q_SIGNALS:
* A change of global position has been requested.
*/
void positionChanged();
/**
* The surface has requested to be initially shown under the cursor. Can only occur
* before any buffer has been attached.
*/
void openUnderCursorRequested();
/**
* A change of the role has been requested.
*/

View file

@ -438,6 +438,17 @@ void XdgSurfaceWindow::installPlasmaShellSurface(PlasmaShellSurfaceInterface *sh
auto updatePosition = [this, shellSurface] {
move(shellSurface->position());
};
auto moveUnderCursor = [this, shellSurface] {
// Wait for the first commit
auto connection = new QMetaObject::Connection;
*connection = connect(this, &Window::windowShown, [this, connection] () {
disconnect(*connection);
if (input()->hasPointer()) {
move(input()->globalPointer().toPoint());
keepInArea(workspace()->clientArea(PlacementArea, this));
}
});
};
auto updateRole = [this, shellSurface] {
NET::WindowType type = NET::Unknown;
switch (shellSurface->role()) {
@ -486,6 +497,7 @@ void XdgSurfaceWindow::installPlasmaShellSurface(PlasmaShellSurfaceInterface *sh
workspace()->updateClientArea();
};
connect(shellSurface, &PlasmaShellSurfaceInterface::positionChanged, this, updatePosition);
connect(shellSurface, &PlasmaShellSurfaceInterface::openUnderCursorRequested, this, moveUnderCursor);
connect(shellSurface, &PlasmaShellSurfaceInterface::roleChanged, this, updateRole);
connect(shellSurface, &PlasmaShellSurfaceInterface::panelBehaviorChanged, this, [this] {
updateShowOnScreenEdge();
@ -511,6 +523,9 @@ void XdgSurfaceWindow::installPlasmaShellSurface(PlasmaShellSurfaceInterface *sh
if (shellSurface->isPositionSet()) {
updatePosition();
}
if (shellSurface->wantsOpenUnderCursor()) {
moveUnderCursor();
}
updateRole();
updateShowOnScreenEdge();
connect(this, &XdgSurfaceWindow::frameGeometryChanged,
@ -707,7 +722,10 @@ bool XdgToplevelWindow::isMinimizable() const
bool XdgToplevelWindow::isPlaceable() const
{
return !m_plasmaShellSurface || !m_plasmaShellSurface->isPositionSet();
if (m_plasmaShellSurface) {
return !m_plasmaShellSurface->isPositionSet() && !m_plasmaShellSurface->wantsOpenUnderCursor();
}
return true;
}
bool XdgToplevelWindow::isTransient() const