wayland: Implement xdg-shell v5

In v5, the xdg_toplevel.wm_capabilities event had been introduced which
specifies a list of actions allowed by the compositors. Mainly useful to
client-side decorated apps.
This commit is contained in:
Vlad Zahorodnii 2023-07-20 12:47:14 +03:00
parent 950458b428
commit 5fae9a944e
4 changed files with 73 additions and 1 deletions

View file

@ -16,7 +16,7 @@
namespace KWaylandServer
{
static const int s_version = 4;
static const int s_version = 5;
XdgShellInterfacePrivate::XdgShellInterfacePrivate(XdgShellInterface *shell)
: q(shell)
@ -595,6 +595,32 @@ void XdgToplevelInterface::sendConfigureBounds(const QSize &size)
}
}
void XdgToplevelInterface::sendWmCapabilities(Capabilities capabilities)
{
if (d->resource()->version() < XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) {
return;
}
// Note that the capabilities listed in the event must be an array of uint32_t.
uint32_t capabilitiesData[4] = {0};
int i = 0;
if (capabilities & Capability::WindowMenu) {
capabilitiesData[i++] = QtWaylandServer::xdg_toplevel::wm_capabilities_window_menu;
}
if (capabilities & Capability::Maximize) {
capabilitiesData[i++] = QtWaylandServer::xdg_toplevel::wm_capabilities_maximize;
}
if (capabilities & Capability::FullScreen) {
capabilitiesData[i++] = QtWaylandServer::xdg_toplevel::wm_capabilities_fullscreen;
}
if (capabilities & Capability::Minimize) {
capabilitiesData[i++] = QtWaylandServer::xdg_toplevel::wm_capabilities_minimize;
}
d->send_wm_capabilities(QByteArray::fromRawData(reinterpret_cast<char *>(capabilitiesData), sizeof(uint32_t) * i));
}
XdgToplevelInterface *XdgToplevelInterface::get(::wl_resource *resource)
{
if (auto toplevelPrivate = resource_cast<XdgToplevelInterfacePrivate *>(resource)) {

View file

@ -224,6 +224,14 @@ public:
};
Q_ENUM(ResizeAnchor)
enum class Capability {
WindowMenu = 0x1,
Maximize = 0x2,
FullScreen = 0x4,
Minimize = 0x8,
};
Q_DECLARE_FLAGS(Capabilities, Capability)
/**
* Constructs an XdgToplevelInterface for the given xdg-surface \a surface.
*/
@ -297,6 +305,11 @@ public:
*/
void sendConfigureBounds(const QSize &size);
/**
* Sends an event to the client specifying allowed actions by the compositor.
*/
void sendWmCapabilities(Capabilities capabilities);
/**
* Returns the XdgToplevelInterface for the specified wayland resource object \a resource.
*/
@ -585,5 +598,6 @@ private:
} // namespace KWaylandServer
Q_DECLARE_OPERATORS_FOR_FLAGS(KWaylandServer::XdgToplevelInterface::States)
Q_DECLARE_OPERATORS_FOR_FLAGS(KWaylandServer::XdgToplevelInterface::Capabilities)
Q_DECLARE_METATYPE(KWaylandServer::XdgToplevelInterface::State)
Q_DECLARE_METATYPE(KWaylandServer::XdgToplevelInterface::States)

View file

@ -643,6 +643,12 @@ bool XdgToplevelWindow::supportsWindowRules() const
return true;
}
void XdgToplevelWindow::applyWindowRules()
{
WaylandWindow::applyWindowRules();
updateCapabilities();
}
void XdgToplevelWindow::closeWindow()
{
if (isCloseable()) {
@ -1120,11 +1126,13 @@ void XdgToplevelWindow::handlePongReceived(quint32 serial)
void XdgToplevelWindow::handleMaximumSizeChanged()
{
updateCapabilities();
Q_EMIT maximizeableChanged(isMaximizable());
}
void XdgToplevelWindow::handleMinimumSizeChanged()
{
updateCapabilities();
Q_EMIT maximizeableChanged(isMaximizable());
}
@ -1207,6 +1215,7 @@ void XdgToplevelWindow::initialize()
configureDecoration();
scheduleConfigure();
updateColorScheme();
updateCapabilities();
setupWindowManagementInterface();
m_isInitialized = true;
@ -1234,6 +1243,26 @@ void XdgToplevelWindow::updateFullScreenMode(bool set)
Q_EMIT fullScreenChanged();
}
void XdgToplevelWindow::updateCapabilities()
{
KWaylandServer::XdgToplevelInterface::Capabilities caps = KWaylandServer::XdgToplevelInterface::Capability::WindowMenu;
if (isMaximizable()) {
caps.setFlag(KWaylandServer::XdgToplevelInterface::Capability::Maximize);
}
if (isFullScreenable()) {
caps.setFlag(KWaylandServer::XdgToplevelInterface::Capability::FullScreen);
}
if (isMinimizable()) {
caps.setFlag(KWaylandServer::XdgToplevelInterface::Capability::Minimize);
}
if (m_capabilities != caps) {
m_capabilities = caps;
m_shellSurface->sendWmCapabilities(caps);
}
}
QString XdgToplevelWindow::preferredColorScheme() const
{
if (m_paletteInterface) {

View file

@ -150,6 +150,7 @@ public:
void invalidateDecoration() override;
QString preferredColorScheme() const override;
bool supportsWindowRules() const override;
void applyWindowRules() override;
bool takeFocus() override;
bool wantsInput() const override;
bool dockWantsInput() const override;
@ -209,6 +210,7 @@ private:
void configureXdgDecoration(DecorationMode decorationMode);
void configureServerDecoration(DecorationMode decorationMode);
void clearDecoration();
void updateCapabilities();
QPointer<KWaylandServer::AppMenuInterface> m_appMenuInterface;
QPointer<KWaylandServer::ServerSideDecorationPaletteInterface> m_paletteInterface;
@ -218,6 +220,7 @@ private:
KWaylandServer::XdgToplevelInterface::States m_nextStates;
KWaylandServer::XdgToplevelInterface::States m_acknowledgedStates;
KWaylandServer::XdgToplevelInterface::States m_initialStates;
KWaylandServer::XdgToplevelInterface::Capabilities m_capabilities;
QMap<quint32, PingReason> m_pings;
MaximizeMode m_maximizeMode = MaximizeRestore;
MaximizeMode m_requestedMaximizeMode = MaximizeRestore;