2020-08-02 22:22:19 +00:00
|
|
|
/*
|
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
2015-03-04 08:21:10 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
|
|
|
|
SPDX-FileCopyrightText: 2018 David Edmundson <davidedmundson@kde.org>
|
|
|
|
SPDX-FileCopyrightText: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
2015-03-04 08:21:10 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
2019-09-15 09:44:33 +00:00
|
|
|
|
|
|
|
#pragma once
|
2015-03-04 08:21:10 +00:00
|
|
|
|
2020-02-17 18:39:17 +00:00
|
|
|
#include "waylandclient.h"
|
2019-09-15 09:41:21 +00:00
|
|
|
|
2020-04-29 15:18:41 +00:00
|
|
|
#include <KWaylandServer/xdgshell_interface.h>
|
2015-03-04 08:21:10 +00:00
|
|
|
|
2020-02-17 18:39:17 +00:00
|
|
|
#include <QQueue>
|
|
|
|
#include <QTimer>
|
|
|
|
|
2020-04-29 15:18:41 +00:00
|
|
|
namespace KWaylandServer
|
2015-03-04 08:21:10 +00:00
|
|
|
{
|
2017-12-22 14:22:24 +00:00
|
|
|
class AppMenuInterface;
|
2015-06-09 17:10:56 +00:00
|
|
|
class PlasmaShellSurfaceInterface;
|
2020-02-17 18:39:17 +00:00
|
|
|
class ServerSideDecorationInterface;
|
|
|
|
class ServerSideDecorationPaletteInterface;
|
|
|
|
class XdgToplevelDecorationV1Interface;
|
2015-03-04 08:21:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace KWin
|
|
|
|
{
|
2020-11-23 18:24:37 +00:00
|
|
|
class AbstractOutput;
|
2015-03-04 08:21:10 +00:00
|
|
|
|
2020-02-17 18:39:17 +00:00
|
|
|
class XdgSurfaceConfigure
|
|
|
|
{
|
|
|
|
public:
|
2021-05-12 14:14:31 +00:00
|
|
|
virtual ~XdgSurfaceConfigure() {}
|
|
|
|
|
Rework async geometry updates
Window management features were written with synchronous geometry
updates in mind. Currently, this poses a big problem on Wayland because
geometry updates are done in asynchronous fashion there.
At the moment, geometry is updated in a so called pseudo-asynchronous
fashion, meaning that the frame geometry will be reset to the old value
once geometry updates are unblocked. The main drawback of this approach
is that it is too error prone, the data flow is hard to comprehend, etc.
It is worth noting that there is already a machinery to perform async
geometry which is used during interactive move/resize operations.
This change extends the move/resize geometry usage beyond interactive
move/resize to make asynchronous geometry updates less error prone and
easier to comprehend.
With the proposed solution, all geometry updates must be done on the
move/resize geometry first. After that, the new geometry is passed on to
the Client-specific implementation of moveResizeInternal().
To be more specific, the frameGeometry() returns the current frame
geometry, it is primarily useful only to the scene. If you want to move
or resize a window, you need to use moveResizeGeometry() because it
corresponds to the last requested frame geometry.
It is worth noting that the moveResizeGeometry() returns the desired
bounding geometry. The client may commit the xdg_toplevel surface with a
slightly smaller window geometry, for example to enforce a specific
aspect ratio. The client is not allowed to resize beyond the size as
indicated in moveResizeGeometry().
The data flow is very simple: moveResize() updates the move/resize
geometry and calls the client-specific implementation of the
moveResizeInternal() method. Based on whether a configure event is
needed, moveResizeInternal() will update the frameGeometry() either
immediately or after the client commits a new buffer.
Unfortunately, both the compositor and xdg-shell clients try to update
the window geometry. It means that it's possible to have conflicts
between the two. With this change, the compositor's move resize geometry
will be synced only if there are no pending configure events, meaning
that the user doesn't try to resize the window.
2021-04-30 18:26:09 +00:00
|
|
|
enum ConfigureFlag {
|
|
|
|
ConfigurePosition = 0x1,
|
2021-05-13 07:18:10 +00:00
|
|
|
};
|
Rework async geometry updates
Window management features were written with synchronous geometry
updates in mind. Currently, this poses a big problem on Wayland because
geometry updates are done in asynchronous fashion there.
At the moment, geometry is updated in a so called pseudo-asynchronous
fashion, meaning that the frame geometry will be reset to the old value
once geometry updates are unblocked. The main drawback of this approach
is that it is too error prone, the data flow is hard to comprehend, etc.
It is worth noting that there is already a machinery to perform async
geometry which is used during interactive move/resize operations.
This change extends the move/resize geometry usage beyond interactive
move/resize to make asynchronous geometry updates less error prone and
easier to comprehend.
With the proposed solution, all geometry updates must be done on the
move/resize geometry first. After that, the new geometry is passed on to
the Client-specific implementation of moveResizeInternal().
To be more specific, the frameGeometry() returns the current frame
geometry, it is primarily useful only to the scene. If you want to move
or resize a window, you need to use moveResizeGeometry() because it
corresponds to the last requested frame geometry.
It is worth noting that the moveResizeGeometry() returns the desired
bounding geometry. The client may commit the xdg_toplevel surface with a
slightly smaller window geometry, for example to enforce a specific
aspect ratio. The client is not allowed to resize beyond the size as
indicated in moveResizeGeometry().
The data flow is very simple: moveResize() updates the move/resize
geometry and calls the client-specific implementation of the
moveResizeInternal() method. Based on whether a configure event is
needed, moveResizeInternal() will update the frameGeometry() either
immediately or after the client commits a new buffer.
Unfortunately, both the compositor and xdg-shell clients try to update
the window geometry. It means that it's possible to have conflicts
between the two. With this change, the compositor's move resize geometry
will be synced only if there are no pending configure events, meaning
that the user doesn't try to resize the window.
2021-04-30 18:26:09 +00:00
|
|
|
Q_DECLARE_FLAGS(ConfigureFlags, ConfigureFlag)
|
2021-05-13 07:18:10 +00:00
|
|
|
|
2020-02-17 18:39:17 +00:00
|
|
|
QPoint position;
|
|
|
|
qreal serial;
|
Rework async geometry updates
Window management features were written with synchronous geometry
updates in mind. Currently, this poses a big problem on Wayland because
geometry updates are done in asynchronous fashion there.
At the moment, geometry is updated in a so called pseudo-asynchronous
fashion, meaning that the frame geometry will be reset to the old value
once geometry updates are unblocked. The main drawback of this approach
is that it is too error prone, the data flow is hard to comprehend, etc.
It is worth noting that there is already a machinery to perform async
geometry which is used during interactive move/resize operations.
This change extends the move/resize geometry usage beyond interactive
move/resize to make asynchronous geometry updates less error prone and
easier to comprehend.
With the proposed solution, all geometry updates must be done on the
move/resize geometry first. After that, the new geometry is passed on to
the Client-specific implementation of moveResizeInternal().
To be more specific, the frameGeometry() returns the current frame
geometry, it is primarily useful only to the scene. If you want to move
or resize a window, you need to use moveResizeGeometry() because it
corresponds to the last requested frame geometry.
It is worth noting that the moveResizeGeometry() returns the desired
bounding geometry. The client may commit the xdg_toplevel surface with a
slightly smaller window geometry, for example to enforce a specific
aspect ratio. The client is not allowed to resize beyond the size as
indicated in moveResizeGeometry().
The data flow is very simple: moveResize() updates the move/resize
geometry and calls the client-specific implementation of the
moveResizeInternal() method. Based on whether a configure event is
needed, moveResizeInternal() will update the frameGeometry() either
immediately or after the client commits a new buffer.
Unfortunately, both the compositor and xdg-shell clients try to update
the window geometry. It means that it's possible to have conflicts
between the two. With this change, the compositor's move resize geometry
will be synced only if there are no pending configure events, meaning
that the user doesn't try to resize the window.
2021-04-30 18:26:09 +00:00
|
|
|
ConfigureFlags flags;
|
XdgV6 - Kwin side
Summary:
Adds XDGV6 support for the kwin side.
Popup placement support is limited to the stuff v5 had,
a simple offset, rather than the awesome new positioner.
But Qt doesn't make use of it yet either.
Also ideally we should do all the positioning before sending the first
configure, but again Qt doesn't actually do anything with that anyway.
Also integrate pinging clients
Test Plan: gtk3-demo works nicely.
Reviewers: #plasma, graesslin, mart
Reviewed By: #plasma, graesslin
Subscribers: mart, graesslin, kwin, plasma-devel, #kwin
Tags: #plasma
Differential Revision: https://phabricator.kde.org/D6591
2017-09-25 15:37:59 +00:00
|
|
|
};
|
2019-01-28 00:28:48 +00:00
|
|
|
|
2020-02-17 18:39:17 +00:00
|
|
|
class XdgSurfaceClient : public WaylandClient
|
2015-03-04 08:21:10 +00:00
|
|
|
{
|
|
|
|
Q_OBJECT
|
2019-09-15 09:41:21 +00:00
|
|
|
|
2015-03-04 08:21:10 +00:00
|
|
|
public:
|
2020-02-17 18:39:17 +00:00
|
|
|
explicit XdgSurfaceClient(KWaylandServer::XdgSurfaceInterface *shellSurface);
|
|
|
|
~XdgSurfaceClient() override;
|
2015-03-04 08:21:10 +00:00
|
|
|
|
2020-08-18 12:51:20 +00:00
|
|
|
QRect frameRectToBufferRect(const QRect &rect) const override;
|
2020-01-16 20:15:24 +00:00
|
|
|
QRect inputGeometry() const override;
|
2020-02-17 18:39:17 +00:00
|
|
|
QMatrix4x4 inputTransformation() const override;
|
|
|
|
void destroyClient() override;
|
|
|
|
|
2020-08-04 01:15:59 +00:00
|
|
|
virtual void installPlasmaShellSurface(KWaylandServer::PlasmaShellSurfaceInterface *shellSurface) = 0;
|
|
|
|
|
2020-02-17 18:39:17 +00:00
|
|
|
protected:
|
Rework async geometry updates
Window management features were written with synchronous geometry
updates in mind. Currently, this poses a big problem on Wayland because
geometry updates are done in asynchronous fashion there.
At the moment, geometry is updated in a so called pseudo-asynchronous
fashion, meaning that the frame geometry will be reset to the old value
once geometry updates are unblocked. The main drawback of this approach
is that it is too error prone, the data flow is hard to comprehend, etc.
It is worth noting that there is already a machinery to perform async
geometry which is used during interactive move/resize operations.
This change extends the move/resize geometry usage beyond interactive
move/resize to make asynchronous geometry updates less error prone and
easier to comprehend.
With the proposed solution, all geometry updates must be done on the
move/resize geometry first. After that, the new geometry is passed on to
the Client-specific implementation of moveResizeInternal().
To be more specific, the frameGeometry() returns the current frame
geometry, it is primarily useful only to the scene. If you want to move
or resize a window, you need to use moveResizeGeometry() because it
corresponds to the last requested frame geometry.
It is worth noting that the moveResizeGeometry() returns the desired
bounding geometry. The client may commit the xdg_toplevel surface with a
slightly smaller window geometry, for example to enforce a specific
aspect ratio. The client is not allowed to resize beyond the size as
indicated in moveResizeGeometry().
The data flow is very simple: moveResize() updates the move/resize
geometry and calls the client-specific implementation of the
moveResizeInternal() method. Based on whether a configure event is
needed, moveResizeInternal() will update the frameGeometry() either
immediately or after the client commits a new buffer.
Unfortunately, both the compositor and xdg-shell clients try to update
the window geometry. It means that it's possible to have conflicts
between the two. With this change, the compositor's move resize geometry
will be synced only if there are no pending configure events, meaning
that the user doesn't try to resize the window.
2021-04-30 18:26:09 +00:00
|
|
|
void moveResizeInternal(const QRect &rect, MoveResizeMode mode) override;
|
2020-02-17 18:39:17 +00:00
|
|
|
|
|
|
|
virtual XdgSurfaceConfigure *sendRoleConfigure() const = 0;
|
|
|
|
virtual void handleRoleCommit();
|
2020-10-26 13:56:01 +00:00
|
|
|
|
2020-02-17 18:39:17 +00:00
|
|
|
XdgSurfaceConfigure *lastAcknowledgedConfigure() const;
|
Rework async geometry updates
Window management features were written with synchronous geometry
updates in mind. Currently, this poses a big problem on Wayland because
geometry updates are done in asynchronous fashion there.
At the moment, geometry is updated in a so called pseudo-asynchronous
fashion, meaning that the frame geometry will be reset to the old value
once geometry updates are unblocked. The main drawback of this approach
is that it is too error prone, the data flow is hard to comprehend, etc.
It is worth noting that there is already a machinery to perform async
geometry which is used during interactive move/resize operations.
This change extends the move/resize geometry usage beyond interactive
move/resize to make asynchronous geometry updates less error prone and
easier to comprehend.
With the proposed solution, all geometry updates must be done on the
move/resize geometry first. After that, the new geometry is passed on to
the Client-specific implementation of moveResizeInternal().
To be more specific, the frameGeometry() returns the current frame
geometry, it is primarily useful only to the scene. If you want to move
or resize a window, you need to use moveResizeGeometry() because it
corresponds to the last requested frame geometry.
It is worth noting that the moveResizeGeometry() returns the desired
bounding geometry. The client may commit the xdg_toplevel surface with a
slightly smaller window geometry, for example to enforce a specific
aspect ratio. The client is not allowed to resize beyond the size as
indicated in moveResizeGeometry().
The data flow is very simple: moveResize() updates the move/resize
geometry and calls the client-specific implementation of the
moveResizeInternal() method. Based on whether a configure event is
needed, moveResizeInternal() will update the frameGeometry() either
immediately or after the client commits a new buffer.
Unfortunately, both the compositor and xdg-shell clients try to update
the window geometry. It means that it's possible to have conflicts
between the two. With this change, the compositor's move resize geometry
will be synced only if there are no pending configure events, meaning
that the user doesn't try to resize the window.
2021-04-30 18:26:09 +00:00
|
|
|
void scheduleConfigure();
|
2020-02-17 18:39:17 +00:00
|
|
|
void sendConfigure();
|
|
|
|
|
2020-08-04 01:15:59 +00:00
|
|
|
QPointer<KWaylandServer::PlasmaShellSurfaceInterface> m_plasmaShellSurface;
|
|
|
|
|
2020-02-17 18:39:17 +00:00
|
|
|
private:
|
|
|
|
void handleConfigureAcknowledged(quint32 serial);
|
|
|
|
void handleCommit();
|
|
|
|
void handleNextWindowGeometry();
|
|
|
|
bool haveNextWindowGeometry() const;
|
|
|
|
void setHaveNextWindowGeometry();
|
|
|
|
void resetHaveNextWindowGeometry();
|
|
|
|
QRect adjustMoveResizeGeometry(const QRect &rect) const;
|
|
|
|
void updateGeometryRestoreHack();
|
Rework async geometry updates
Window management features were written with synchronous geometry
updates in mind. Currently, this poses a big problem on Wayland because
geometry updates are done in asynchronous fashion there.
At the moment, geometry is updated in a so called pseudo-asynchronous
fashion, meaning that the frame geometry will be reset to the old value
once geometry updates are unblocked. The main drawback of this approach
is that it is too error prone, the data flow is hard to comprehend, etc.
It is worth noting that there is already a machinery to perform async
geometry which is used during interactive move/resize operations.
This change extends the move/resize geometry usage beyond interactive
move/resize to make asynchronous geometry updates less error prone and
easier to comprehend.
With the proposed solution, all geometry updates must be done on the
move/resize geometry first. After that, the new geometry is passed on to
the Client-specific implementation of moveResizeInternal().
To be more specific, the frameGeometry() returns the current frame
geometry, it is primarily useful only to the scene. If you want to move
or resize a window, you need to use moveResizeGeometry() because it
corresponds to the last requested frame geometry.
It is worth noting that the moveResizeGeometry() returns the desired
bounding geometry. The client may commit the xdg_toplevel surface with a
slightly smaller window geometry, for example to enforce a specific
aspect ratio. The client is not allowed to resize beyond the size as
indicated in moveResizeGeometry().
The data flow is very simple: moveResize() updates the move/resize
geometry and calls the client-specific implementation of the
moveResizeInternal() method. Based on whether a configure event is
needed, moveResizeInternal() will update the frameGeometry() either
immediately or after the client commits a new buffer.
Unfortunately, both the compositor and xdg-shell clients try to update
the window geometry. It means that it's possible to have conflicts
between the two. With this change, the compositor's move resize geometry
will be synced only if there are no pending configure events, meaning
that the user doesn't try to resize the window.
2021-04-30 18:26:09 +00:00
|
|
|
void maybeUpdateMoveResizeGeometry(const QRect &rect);
|
2020-02-17 18:39:17 +00:00
|
|
|
|
|
|
|
KWaylandServer::XdgSurfaceInterface *m_shellSurface;
|
|
|
|
QTimer *m_configureTimer;
|
Rework async geometry updates
Window management features were written with synchronous geometry
updates in mind. Currently, this poses a big problem on Wayland because
geometry updates are done in asynchronous fashion there.
At the moment, geometry is updated in a so called pseudo-asynchronous
fashion, meaning that the frame geometry will be reset to the old value
once geometry updates are unblocked. The main drawback of this approach
is that it is too error prone, the data flow is hard to comprehend, etc.
It is worth noting that there is already a machinery to perform async
geometry which is used during interactive move/resize operations.
This change extends the move/resize geometry usage beyond interactive
move/resize to make asynchronous geometry updates less error prone and
easier to comprehend.
With the proposed solution, all geometry updates must be done on the
move/resize geometry first. After that, the new geometry is passed on to
the Client-specific implementation of moveResizeInternal().
To be more specific, the frameGeometry() returns the current frame
geometry, it is primarily useful only to the scene. If you want to move
or resize a window, you need to use moveResizeGeometry() because it
corresponds to the last requested frame geometry.
It is worth noting that the moveResizeGeometry() returns the desired
bounding geometry. The client may commit the xdg_toplevel surface with a
slightly smaller window geometry, for example to enforce a specific
aspect ratio. The client is not allowed to resize beyond the size as
indicated in moveResizeGeometry().
The data flow is very simple: moveResize() updates the move/resize
geometry and calls the client-specific implementation of the
moveResizeInternal() method. Based on whether a configure event is
needed, moveResizeInternal() will update the frameGeometry() either
immediately or after the client commits a new buffer.
Unfortunately, both the compositor and xdg-shell clients try to update
the window geometry. It means that it's possible to have conflicts
between the two. With this change, the compositor's move resize geometry
will be synced only if there are no pending configure events, meaning
that the user doesn't try to resize the window.
2021-04-30 18:26:09 +00:00
|
|
|
XdgSurfaceConfigure::ConfigureFlags m_configureFlags;
|
2020-02-17 18:39:17 +00:00
|
|
|
QQueue<XdgSurfaceConfigure *> m_configureEvents;
|
|
|
|
QScopedPointer<XdgSurfaceConfigure> m_lastAcknowledgedConfigure;
|
|
|
|
QRect m_windowGeometry;
|
|
|
|
bool m_haveNextWindowGeometry = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
class XdgToplevelConfigure final : public XdgSurfaceConfigure
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
KWaylandServer::XdgToplevelInterface::States states;
|
|
|
|
};
|
|
|
|
|
|
|
|
class XdgToplevelClient final : public XdgSurfaceClient
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
2021-03-14 17:06:22 +00:00
|
|
|
enum class PingReason {
|
|
|
|
CloseWindow,
|
|
|
|
FocusWindow,
|
|
|
|
};
|
2020-02-17 18:39:17 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
explicit XdgToplevelClient(KWaylandServer::XdgToplevelInterface *shellSurface);
|
|
|
|
~XdgToplevelClient() override;
|
2020-05-07 14:29:41 +00:00
|
|
|
|
|
|
|
KWaylandServer::XdgToplevelInterface *shellSurface() const;
|
2020-02-17 18:39:17 +00:00
|
|
|
|
|
|
|
NET::WindowType windowType(bool direct = false, int supported_types = 0) const override;
|
|
|
|
MaximizeMode maximizeMode() const override;
|
|
|
|
MaximizeMode requestedMaximizeMode() const override;
|
2020-02-12 10:43:30 +00:00
|
|
|
QSize minSize() const override;
|
|
|
|
QSize maxSize() const override;
|
2020-02-17 18:39:17 +00:00
|
|
|
bool isFullScreen() const override;
|
2021-05-01 15:07:11 +00:00
|
|
|
bool isRequestedFullScreen() const override;
|
2020-02-17 18:39:17 +00:00
|
|
|
bool isMovableAcrossScreens() const override;
|
|
|
|
bool isMovable() const override;
|
|
|
|
bool isResizable() const override;
|
2015-03-16 08:14:04 +00:00
|
|
|
bool isCloseable() const override;
|
2019-01-09 14:20:19 +00:00
|
|
|
bool isFullScreenable() const override;
|
2015-03-16 08:14:04 +00:00
|
|
|
bool isMaximizable() const override;
|
|
|
|
bool isMinimizable() const override;
|
2020-11-19 15:31:42 +00:00
|
|
|
bool isPlaceable() const override;
|
2020-02-17 18:39:17 +00:00
|
|
|
bool isTransient() const override;
|
|
|
|
bool userCanSetFullScreen() const override;
|
|
|
|
bool userCanSetNoBorder() const override;
|
2015-03-16 08:14:04 +00:00
|
|
|
bool noBorder() const override;
|
|
|
|
void setNoBorder(bool set) override;
|
2015-12-17 14:47:36 +00:00
|
|
|
void updateDecoration(bool check_workspace_pos, bool force = false) override;
|
2020-08-19 09:21:00 +00:00
|
|
|
QString preferredColorScheme() const override;
|
2020-02-17 18:39:17 +00:00
|
|
|
bool supportsWindowRules() const override;
|
2020-07-22 11:00:11 +00:00
|
|
|
bool takeFocus() override;
|
2015-03-16 08:14:04 +00:00
|
|
|
bool wantsInput() const override;
|
2016-10-12 13:09:52 +00:00
|
|
|
bool dockWantsInput() const override;
|
2020-08-17 13:14:20 +00:00
|
|
|
StrutRect strutRect(StrutArea area) const override;
|
2015-06-19 22:14:49 +00:00
|
|
|
bool hasStrut() const override;
|
2016-09-15 19:03:40 +00:00
|
|
|
void showOnScreenEdge() override;
|
2020-02-17 18:39:17 +00:00
|
|
|
void setFullScreen(bool set, bool user) override;
|
|
|
|
void closeWindow() override;
|
[effects] Make Scale and Glide effects Wayland-friendly
Summary:
The Scale effect and the Glide effect have to animate only ordinary
windows(i.e. the ones that are considered to be apps).
On X11, in order to distinguish ordinary windows from combo box popups,
popup menus, and other popups, those effects check whether given window
is managed.
On Wayland, there is no concept of managed/unmanaged windows.
XDG Shell protocol defines 2 surface roles:
* xdg_toplevel;
* and, xdg_popup.
The former can be used to implement typical windows, the ones that can
be minimized, maximized, etc.
The latter can be used to implement tooltips, popup menus, etc. Thus,
that's a good criteria to filter popup windows.
CCBUG: 398100
Reviewers: #kwin, graesslin, davidedmundson
Reviewed By: #kwin, graesslin, davidedmundson
Subscribers: davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D15117
2018-10-08 18:08:13 +00:00
|
|
|
|
2020-02-17 18:39:17 +00:00
|
|
|
void installAppMenu(KWaylandServer::AppMenuInterface *appMenu);
|
|
|
|
void installServerDecoration(KWaylandServer::ServerSideDecorationInterface *decoration);
|
2020-04-29 15:18:41 +00:00
|
|
|
void installPalette(KWaylandServer::ServerSideDecorationPaletteInterface *palette);
|
2020-08-04 01:15:59 +00:00
|
|
|
void installPlasmaShellSurface(KWaylandServer::PlasmaShellSurfaceInterface *shellSurface) override;
|
2020-02-17 18:39:17 +00:00
|
|
|
void installXdgDecoration(KWaylandServer::XdgToplevelDecorationV1Interface *decoration);
|
2018-12-23 07:56:15 +00:00
|
|
|
|
2015-03-04 08:21:10 +00:00
|
|
|
protected:
|
2020-02-17 18:39:17 +00:00
|
|
|
XdgSurfaceConfigure *sendRoleConfigure() const override;
|
|
|
|
void handleRoleCommit() override;
|
|
|
|
void doMinimize() override;
|
2021-04-30 18:06:58 +00:00
|
|
|
void doInteractiveResizeSync() override;
|
2020-02-17 18:39:17 +00:00
|
|
|
void doSetActive() override;
|
|
|
|
void doSetFullScreen();
|
|
|
|
void doSetMaximized();
|
2021-04-30 18:06:58 +00:00
|
|
|
bool doStartInteractiveMoveResize() override;
|
|
|
|
void doFinishInteractiveMoveResize() override;
|
2015-12-07 15:18:30 +00:00
|
|
|
bool acceptsFocus() const override;
|
2020-02-17 18:39:17 +00:00
|
|
|
void changeMaximize(bool horizontal, bool vertical, bool adjust) override;
|
|
|
|
Layer layerForDock() const override;
|
2020-08-23 11:23:23 +00:00
|
|
|
void doSetQuickTileMode() override;
|
2015-03-04 08:21:10 +00:00
|
|
|
|
2020-02-17 18:39:17 +00:00
|
|
|
private:
|
|
|
|
void handleWindowTitleChanged();
|
|
|
|
void handleWindowClassChanged();
|
|
|
|
void handleWindowMenuRequested(KWaylandServer::SeatInterface *seat,
|
|
|
|
const QPoint &surfacePos, quint32 serial);
|
2020-04-29 15:18:41 +00:00
|
|
|
void handleMoveRequested(KWaylandServer::SeatInterface *seat, quint32 serial);
|
2020-02-17 18:39:17 +00:00
|
|
|
void handleResizeRequested(KWaylandServer::SeatInterface *seat, Qt::Edges, quint32 serial);
|
|
|
|
void handleStatesAcknowledged(const KWaylandServer::XdgToplevelInterface::States &states);
|
|
|
|
void handleMaximizeRequested();
|
|
|
|
void handleUnmaximizeRequested();
|
|
|
|
void handleFullscreenRequested(KWaylandServer::OutputInterface *output);
|
|
|
|
void handleUnfullscreenRequested();
|
2019-09-15 10:54:53 +00:00
|
|
|
void handleMinimizeRequested();
|
2020-02-17 18:39:17 +00:00
|
|
|
void handleTransientForChanged();
|
|
|
|
void handleForeignTransientForChanged(KWaylandServer::SurfaceInterface *child);
|
2019-09-15 10:54:53 +00:00
|
|
|
void handlePingTimeout(quint32 serial);
|
2020-02-17 18:39:17 +00:00
|
|
|
void handlePingDelayed(quint32 serial);
|
2019-09-15 10:54:53 +00:00
|
|
|
void handlePongReceived(quint32 serial);
|
2021-07-07 11:50:02 +00:00
|
|
|
void handleMaximumSizeChanged();
|
|
|
|
void handleMinimumSizeChanged();
|
2020-02-17 18:39:17 +00:00
|
|
|
void initialize();
|
[wayland] Asyncronously update maximise flags
Summary:
A window maximising is an async operation. We work out what size we want
the client to be, then request the client to update. The window isn't
really maximised until we get that new buffer with the new size.
This patch splits the requested, pending and current state, updating as
appropriate.
Things are a bit complex with things like borders. Technically we
shouldn't update them till we get a response, but we also need to have
the correct geometry of the full size window in our request. For now
they behave as before, updating when we request the change.
X code is untouched.
This hopefully fixes maximise animations on wayland as now we update the
geometry before emitting maximisedChanged.
Test Plan:
Maximised a window with the button and double clicking title bar.
I get only the following events on maximise/restore:
19:51:39.156 KWin::EffectsHandlerImpl::slotGeometryShapeChanged geometry
shape changed QRect(47,24 640x509) QRect(0,0 716x573)
19:51:39.157 KWin::EffectsHandlerImpl::slotClientMaximized slot client
maximised true true
19:51:40.522 KWin::EffectsHandlerImpl::slotGeometryShapeChanged geometry
shape changed QRect(0,0 716x573) QRect(47,24 640x509)
19:51:40.522 KWin::EffectsHandlerImpl::slotClientMaximized slot client
maximised false false
BUG: 382698
Reviewers: #kwin, romangg
Reviewed By: #kwin, romangg
Subscribers: romangg, zzag, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D15150
2018-10-05 14:36:02 +00:00
|
|
|
void updateMaximizeMode(MaximizeMode maximizeMode);
|
2020-02-17 18:39:17 +00:00
|
|
|
void updateFullScreenMode(bool set);
|
|
|
|
void updateShowOnScreenEdge();
|
2020-08-07 19:01:42 +00:00
|
|
|
void updateClientArea();
|
2020-02-17 18:39:17 +00:00
|
|
|
void setupPlasmaShellIntegration();
|
|
|
|
void sendPing(PingReason reason);
|
2020-06-26 09:14:38 +00:00
|
|
|
MaximizeMode initialMaximizeMode() const;
|
|
|
|
bool initialFullScreenMode() const;
|
[wayland] Asyncronously update maximise flags
Summary:
A window maximising is an async operation. We work out what size we want
the client to be, then request the client to update. The window isn't
really maximised until we get that new buffer with the new size.
This patch splits the requested, pending and current state, updating as
appropriate.
Things are a bit complex with things like borders. Technically we
shouldn't update them till we get a response, but we also need to have
the correct geometry of the full size window in our request. For now
they behave as before, updating when we request the change.
X code is untouched.
This hopefully fixes maximise animations on wayland as now we update the
geometry before emitting maximisedChanged.
Test Plan:
Maximised a window with the button and double clicking title bar.
I get only the following events on maximise/restore:
19:51:39.156 KWin::EffectsHandlerImpl::slotGeometryShapeChanged geometry
shape changed QRect(47,24 640x509) QRect(0,0 716x573)
19:51:39.157 KWin::EffectsHandlerImpl::slotClientMaximized slot client
maximised true true
19:51:40.522 KWin::EffectsHandlerImpl::slotGeometryShapeChanged geometry
shape changed QRect(0,0 716x573) QRect(47,24 640x509)
19:51:40.522 KWin::EffectsHandlerImpl::slotClientMaximized slot client
maximised false false
BUG: 382698
Reviewers: #kwin, romangg
Reviewed By: #kwin, romangg
Subscribers: romangg, zzag, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D15150
2018-10-05 14:36:02 +00:00
|
|
|
|
2020-04-29 15:18:41 +00:00
|
|
|
QPointer<KWaylandServer::AppMenuInterface> m_appMenuInterface;
|
|
|
|
QPointer<KWaylandServer::ServerSideDecorationPaletteInterface> m_paletteInterface;
|
2020-02-17 18:39:17 +00:00
|
|
|
QPointer<KWaylandServer::ServerSideDecorationInterface> m_serverDecoration;
|
|
|
|
QPointer<KWaylandServer::XdgToplevelDecorationV1Interface> m_xdgDecoration;
|
|
|
|
KWaylandServer::XdgToplevelInterface *m_shellSurface;
|
|
|
|
KWaylandServer::XdgToplevelInterface::States m_requestedStates;
|
|
|
|
KWaylandServer::XdgToplevelInterface::States m_acknowledgedStates;
|
2020-06-26 09:14:38 +00:00
|
|
|
KWaylandServer::XdgToplevelInterface::States m_initialStates;
|
2020-02-17 18:39:17 +00:00
|
|
|
QMap<quint32, PingReason> m_pings;
|
|
|
|
NET::WindowType m_windowType = NET::Normal;
|
|
|
|
MaximizeMode m_maximizeMode = MaximizeRestore;
|
|
|
|
MaximizeMode m_requestedMaximizeMode = MaximizeRestore;
|
|
|
|
bool m_isFullScreen = false;
|
2021-05-01 15:07:11 +00:00
|
|
|
bool m_isRequestedFullScreen = false;
|
2020-06-26 09:14:38 +00:00
|
|
|
bool m_isInitialized = false;
|
2015-12-17 14:47:36 +00:00
|
|
|
bool m_userNoBorder = false;
|
2020-02-17 18:39:17 +00:00
|
|
|
bool m_isTransient = false;
|
2020-11-23 18:24:37 +00:00
|
|
|
QPointer<AbstractOutput> m_fullScreenRequestedOutput;
|
2020-02-17 18:39:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class XdgPopupClient final : public XdgSurfaceClient
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit XdgPopupClient(KWaylandServer::XdgPopupInterface *shellSurface);
|
|
|
|
~XdgPopupClient() override;
|
|
|
|
|
|
|
|
NET::WindowType windowType(bool direct = false, int supported_types = 0) const override;
|
|
|
|
bool hasPopupGrab() const override;
|
|
|
|
void popupDone() override;
|
|
|
|
bool isPopupWindow() const override;
|
|
|
|
bool isTransient() const override;
|
|
|
|
bool isResizable() const override;
|
|
|
|
bool isMovable() const override;
|
|
|
|
bool isMovableAcrossScreens() const override;
|
|
|
|
bool hasTransientPlacementHint() const override;
|
|
|
|
QRect transientPlacement(const QRect &bounds) const override;
|
|
|
|
bool isCloseable() const override;
|
|
|
|
void closeWindow() override;
|
|
|
|
bool wantsInput() const override;
|
2020-07-22 11:00:11 +00:00
|
|
|
bool takeFocus() override;
|
2020-08-04 01:15:59 +00:00
|
|
|
void installPlasmaShellSurface(KWaylandServer::PlasmaShellSurfaceInterface *shellSurface) override;
|
2016-08-19 10:33:59 +00:00
|
|
|
|
2020-02-17 18:39:17 +00:00
|
|
|
protected:
|
|
|
|
bool acceptsFocus() const override;
|
|
|
|
XdgSurfaceConfigure *sendRoleConfigure() const override;
|
2019-09-10 07:40:36 +00:00
|
|
|
|
2020-02-17 18:39:17 +00:00
|
|
|
private:
|
|
|
|
void handleGrabRequested(KWaylandServer::SeatInterface *seat, quint32 serial);
|
2021-01-06 01:08:25 +00:00
|
|
|
void handleRepositionRequested(quint32 token);
|
2020-02-17 18:39:17 +00:00
|
|
|
void initialize();
|
2021-01-06 01:08:25 +00:00
|
|
|
void relayout();
|
2021-02-01 07:59:02 +00:00
|
|
|
void updateReactive();
|
2020-02-17 18:39:17 +00:00
|
|
|
|
|
|
|
KWaylandServer::XdgPopupInterface *m_shellSurface;
|
|
|
|
bool m_haveExplicitGrab = false;
|
2015-03-04 08:21:10 +00:00
|
|
|
};
|
|
|
|
|
2020-02-17 18:39:17 +00:00
|
|
|
} // namespace KWin
|
2021-05-13 07:18:10 +00:00
|
|
|
|
Rework async geometry updates
Window management features were written with synchronous geometry
updates in mind. Currently, this poses a big problem on Wayland because
geometry updates are done in asynchronous fashion there.
At the moment, geometry is updated in a so called pseudo-asynchronous
fashion, meaning that the frame geometry will be reset to the old value
once geometry updates are unblocked. The main drawback of this approach
is that it is too error prone, the data flow is hard to comprehend, etc.
It is worth noting that there is already a machinery to perform async
geometry which is used during interactive move/resize operations.
This change extends the move/resize geometry usage beyond interactive
move/resize to make asynchronous geometry updates less error prone and
easier to comprehend.
With the proposed solution, all geometry updates must be done on the
move/resize geometry first. After that, the new geometry is passed on to
the Client-specific implementation of moveResizeInternal().
To be more specific, the frameGeometry() returns the current frame
geometry, it is primarily useful only to the scene. If you want to move
or resize a window, you need to use moveResizeGeometry() because it
corresponds to the last requested frame geometry.
It is worth noting that the moveResizeGeometry() returns the desired
bounding geometry. The client may commit the xdg_toplevel surface with a
slightly smaller window geometry, for example to enforce a specific
aspect ratio. The client is not allowed to resize beyond the size as
indicated in moveResizeGeometry().
The data flow is very simple: moveResize() updates the move/resize
geometry and calls the client-specific implementation of the
moveResizeInternal() method. Based on whether a configure event is
needed, moveResizeInternal() will update the frameGeometry() either
immediately or after the client commits a new buffer.
Unfortunately, both the compositor and xdg-shell clients try to update
the window geometry. It means that it's possible to have conflicts
between the two. With this change, the compositor's move resize geometry
will be synced only if there are no pending configure events, meaning
that the user doesn't try to resize the window.
2021-04-30 18:26:09 +00:00
|
|
|
Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::XdgSurfaceConfigure::ConfigureFlags)
|