diff --git a/autotests/client/CMakeLists.txt b/autotests/client/CMakeLists.txt --- a/autotests/client/CMakeLists.txt +++ b/autotests/client/CMakeLists.txt @@ -407,3 +407,15 @@ target_link_libraries( testAppmenu Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer) add_test(NAME kwayland-testAppmenu COMMAND testAppmenu) ecm_mark_as_test(testAppmenu) + +######################################################## +# Test Appmenu +######################################################## +set( testServerSideDecorationPalette_SRCS + test_server_side_decoration_palette.cpp + ) +add_executable(testServerSideDecorationPalette ${testServerSideDecorationPalette_SRCS}) +target_link_libraries( testServerSideDecorationPalette Qt5::Test Qt5::Gui KF5::WaylandClient KF5::WaylandServer) +add_test(NAME kwayland-testServerSideDecorationPalette COMMAND testServerSideDecorationPalette) +ecm_mark_as_test(testServerSideDecorationPalette) + diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -40,6 +40,7 @@ relativepointer.cpp seat.cpp server_decoration.cpp + server_decoration_palette.cpp shadow.cpp shell.cpp shm_pool.cpp @@ -159,6 +160,10 @@ PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/appmenu.xml BASENAME appmenu ) +ecm_add_wayland_client_protocol(CLIENT_LIB_SRCS + PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/server-decoration-palette.xml + BASENAME server-decoration-palette +) set(CLIENT_GENERATED_FILES ${CMAKE_CURRENT_BINARY_DIR}/wayland-fullscreen-shell-client-protocol.h @@ -174,6 +179,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/wayland-slide-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-dpms-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-server-decoration-client-protocol.h + ${CMAKE_CURRENT_BINARY_DIR}/wayland-server-decoration-palette-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-text-input-v0-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-text-input-v2-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-xdg-shell-v5-client-protocol.h @@ -245,6 +251,7 @@ relativepointer.h seat.h server_decoration.h + server_decoration_palette.h shadow.h shell.h shm_pool.h diff --git a/src/client/protocols/server-decoration-palette.xml b/src/client/protocols/server-decoration-palette.xml new file mode 100644 --- /dev/null +++ b/src/client/protocols/server-decoration-palette.xml @@ -0,0 +1,44 @@ + + + . + ]]> + +l + This interface allows a client to alter the palette of a server side decoration. + + + + + + + + + This interface allows a client to alter the palette of a server side decoration. + + + + Color scheme that should be applied to the window decoration. + Absolute file path, or name of palette in the user's config directory. + The server may choose not to follow the requested style. + + + + + + + + diff --git a/src/client/registry.h b/src/client/registry.h --- a/src/client/registry.h +++ b/src/client/registry.h @@ -50,6 +50,7 @@ struct org_kde_plasma_shell; struct org_kde_plasma_window_management; struct org_kde_kwin_server_decoration_manager; +struct org_kde_kwin_server_decoration_palette_manager; struct xdg_shell; struct zxdg_shell_v6; struct zwp_relative_pointer_manager_v1; @@ -89,6 +90,7 @@ class Shell; class ShmPool; class ServerSideDecorationManager; +class ServerSideDecorationPaletteManager; class SubCompositor; class TextInputManager; class TextInputManagerUnstableV0; @@ -167,6 +169,7 @@ XdgShellUnstableV6, ///< Refers to zxdg_shell_v6 (unstable version 6), @since 5.39 IdleInhibitManagerUnstableV1, ///< Refers to zwp_idle_inhibit_manager_v1 (unstable version 1), @since 5.41 AppMenu ///Refers to org_kde_kwin_appmenu @since 5.42 + ServerSideDecorationPalette ///Refers to org_kde_kwin_server_decoration_palette_manager @since 5.42 }; explicit Registry(QObject *parent = nullptr); virtual ~Registry(); @@ -582,10 +585,22 @@ * * Prefer using createAppMenuManager instead. * @see createAppMenuManager - * @since 5.XX + * @since 5.42 **/ org_kde_kwin_appmenu_manager *bindAppMenuManager(uint32_t name, uint32_t version) const; + /** + * Binds the org_kde_kwin_server_decoration_palette_manager with @p name and @p version. + * If the @p name does not exist or is not for the server side decoration palette manager interface, + * @c null will be returned. + * + * Prefer using createServerSideDecorationPaletteManager instead. + * @see createAppMenuManager + * @since 5.42 + **/ + org_kde_kwin_server_decoration_palette_manager *bindServerSideDecorationPaletteManager(uint32_t name, uint32_t version) const; + + /** * @name Convenient factory methods for global objects. **/ @@ -1058,6 +1073,23 @@ **/ AppMenuManager *createAppMenuManager(quint32 name, quint32 version, QObject *parent = nullptr); + /** + * Creates a ServerSideDecorationPaletteManager and sets it up to manage the interface identified by + * @p name and @p version. + * + * Note: in case @p name is invalid or isn't for the org_kde_kwin_appmenu_manager interface, + * the returned ServerSideDecorationPaletteManager will not be valid. Therefore it's recommended to call + * isValid on the created instance. + * + * @param name The name of the org_kde_kwin_server_decoration_palette_manager interface to bind + * @param version The version or the org_kde_kwin_server_decoration_palette_manager interface to use + * @param parent The parent for ServerSideDecorationPaletteManager + * + * @returns The created ServerSideDecorationPaletteManager. + * @since 5.42 + **/ + ServerSideDecorationPaletteManager *createServerSideDecorationPaletteManager(quint32 name, quint32 version, QObject *parent = nullptr); + /** * cast operator to the low-level Wayland @c wl_registry **/ @@ -1285,6 +1317,15 @@ * @since 5.42 */ void appMenuAnnounced(quint32 name, quint32 version); + + /** + * Emitted whenever a org_kde_kwin_server_decoration_palette_manager interface gets announced. + * @param name The name for the announced interface + * @param version The maximum supported version of the announced interface + * @since 5.42 + */ + void serverSideDecorationPaletteManagerAnnounced(quint32 name, quint32 version); + ///@} /** @@ -1473,6 +1514,14 @@ * @since 5.42 **/ void appMenuRemoved(quint32 name); + + /** + * Emitted whenever a org_kde_kwin_server_decoration_palette_manager gets removed. + * @param name The name of the removed interface + * @since 5.42 + **/ + void serverSideDecorationPaletteManagerRemoved(quint32 name); + ///@} /** * Generic announced signal which gets emitted whenever an interface gets diff --git a/src/client/registry.cpp b/src/client/registry.cpp --- a/src/client/registry.cpp +++ b/src/client/registry.cpp @@ -52,6 +52,7 @@ #include "wayland_pointer_p.h" #include "xdgforeign_v2.h" #include "appmenu.h" +#include "server_decoration_palette.h" // Qt #include // wayland @@ -79,6 +80,7 @@ #include #include #include +#include /***** * How to add another interface: @@ -323,6 +325,13 @@ &org_kde_kwin_appmenu_manager_interface, &Registry::appMenuAnnounced, &Registry::appMenuRemoved + }}, + {Registry::Interface::ServerSideDecorationPalette, { + 1, + QByteArrayLiteral("org_kde_kwin_server_decoration_palette_manager"), + &org_kde_kwin_server_decoration_palette_manager_interface, + &Registry::serverSideDecorationPaletteManagerAnnounced, + &Registry::serverSideDecorationPaletteManagerRemoved }} }; @@ -633,6 +642,7 @@ BIND2(SlideManager, Slide, org_kde_kwin_slide_manager) BIND2(DpmsManager, Dpms, org_kde_kwin_dpms_manager) BIND2(AppMenuManager, AppMenu, org_kde_kwin_appmenu_manager) +BIND2(ServerSideDecorationPaletteManager, ServerSideDecorationPalette, org_kde_kwin_server_decoration_palette_manager) #undef BIND #undef BIND2 @@ -683,6 +693,7 @@ CREATE(ServerSideDecorationManager) CREATE2(ShmPool, Shm) CREATE(AppMenuManager) +CREATE(ServerSideDecorationPaletteManager) #undef CREATE #undef CREATE2 diff --git a/src/client/server_decoration_palette.h b/src/client/server_decoration_palette.h new file mode 100644 --- /dev/null +++ b/src/client/server_decoration_palette.h @@ -0,0 +1,198 @@ +/**************************************************************************** +Copyright 2017 David Edmundson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +****************************************************************************/ +#ifndef KWAYLAND_CLIENT_SERVER_DECORATION_PALETTE_H +#define KWAYLAND_CLIENT_SERVER_DECORATION_PALETTE_H + +#include + +#include + +struct org_kde_kwin_server_decoration_palette_manager; +struct org_kde_kwin_server_decoration_palette; + +namespace KWayland +{ +namespace Client +{ + +class EventQueue; +class Surface; +class ServerDecorationPalette; + +/** + * @short Wrapper for the org_kde_kwin_server_decoration_palette_manager interface. + * + * This class provides a convenient wrapper for the org_kde_kwin_server_decoration_palette_manager interface. + * + * To use this class one needs to interact with the Registry. There are two + * possible ways to create the ServerDecorationPaletteManager interface: + * @code + * ServerDecorationPaletteManager *c = registry->createServerDecorationPaletteManager(name, version); + * @endcode + * + * This creates the ServerDecorationPaletteManager and sets it up directly. As an alternative this + * can also be done in a more low level way: + * @code + * ServerDecorationPaletteManager *c = new ServerDecorationPaletteManager; + * c->setup(registry->bindServerDecorationPaletteManager(name, version)); + * @endcode + * + * The ServerDecorationPaletteManager can be used as a drop-in replacement for any org_kde_kwin_server_decoration_palette_manager + * pointer as it provides matching cast operators. + * + * @see Registry + **/ +class KWAYLANDCLIENT_EXPORT ServerSideDecorationPaletteManager : public QObject +{ + Q_OBJECT +public: + /** + * Creates a new ServerDecorationPaletteManager. + * Note: after constructing the ServerDecorationPaletteManager it is not yet valid and one needs + * to call setup. In order to get a ready to use ServerDecorationPaletteManager prefer using + * Registry::createServerDecorationPaletteManager. + **/ + explicit ServerSideDecorationPaletteManager(QObject *parent = nullptr); + virtual ~ServerSideDecorationPaletteManager(); + + /** + * Setup this ServerDecorationPaletteManager to manage the @p serverDecorationPaletteManager. + * When using Registry::createServerDecorationPaletteManager there is no need to call this + * method. + **/ + void setup(org_kde_kwin_server_decoration_palette_manager *serverDecorationPaletteManager); + /** + * @returns @c true if managing a org_kde_kwin_server_decoration_palette_manager. + **/ + bool isValid() const; + /** + * Releases the org_kde_kwin_server_decoration_palette_manager interface. + * After the interface has been released the ServerDecorationPaletteManager instance is no + * longer valid and can be setup with another org_kde_kwin_server_decoration_palette_manager interface. + **/ + void release(); + /** + * Destroys the data held by this ServerDecorationPaletteManager. + * This method is supposed to be used when the connection to the Wayland + * server goes away. If the connection is not valid anymore, it's not + * possible to call release anymore as that calls into the Wayland + * connection and the call would fail. This method cleans up the data, so + * that the instance can be deleted or set up to a new org_kde_kwin_server_decoration_palette_manager interface + * once there is a new connection available. + * + * It is suggested to connect this method to ConnectionThread::connectionDied: + * @code + * connect(connection, &ConnectionThread::connectionDied, palettemanager, &ServerDecorationPaletteManager::destroy); + * @endcode + * + * @see release + **/ + void destroy(); + + /** + * Sets the @p queue to use for creating objects with this ServerDecorationPaletteManager. + **/ + void setEventQueue(EventQueue *queue); + /** + * @returns The event queue to use for creating objects with this ServerDecorationPaletteManager. + **/ + EventQueue *eventQueue(); + + ServerDecorationPalette *create(Surface *surface, QObject *parent = nullptr); + + operator org_kde_kwin_server_decoration_palette_manager*(); + operator org_kde_kwin_server_decoration_palette_manager*() const; + +Q_SIGNALS: + /** + * The corresponding global for this interface on the Registry got removed. + * + * This signal gets only emitted if the ServerDecorationPaletteManager got created by + * Registry::createServerDecorationPaletteManager + **/ + void removed(); + +private: + class Private; + QScopedPointer d; +}; + +class KWAYLANDCLIENT_EXPORT ServerDecorationPalette : public QObject +{ + Q_OBJECT +public: + virtual ~ServerDecorationPalette(); + + /** + * Setup this ServerDecorationPalette to manage the @p serversidedecorationpalette. + * When using ServerDecorationPaletteManager::create there is no need to call this + * method. + **/ + void setup(org_kde_kwin_server_decoration_palette *serversidedecorationpalette); + /** + * @returns @c true if managing a org_kde_kwin_server_decoration_palette. + **/ + bool isValid() const; + /** + * Releases the org_kde_kwin_server_decoration_palette interface. + * After the interface has been released the ServerDecorationPalette instance is no + * longer valid and can be setup with another org_kde_kwin_server_decoration_palette interface. + **/ + void release(); + /** + * Destroys the data held by this ServerDecorationPalette. + * This method is supposed to be used when the connection to the Wayland + * server goes away. If the connection is not valid anymore, it's not + * possible to call release anymore as that calls into the Wayland + * connection and the call would fail. This method cleans up the data, so + * that the instance can be deleted or set up to a new org_kde_kwin_server_decoration_palette interface + * once there is a new connection available. + * + * It is suggested to connect this method to ConnectionThread::connectionDied: + * @code + * connect(connection, &ConnectionThread::connectionDied, palette, &ServerDecorationPalette::destroy); + * @endcode + * + * @see release + **/ + void destroy(); + + /** + * Sets the palette to be used by the server side decorations. + * Absolute file path, or name of palette in the user's config directory. + * If set to empty the default palette will be used. + */ + void setPalette(const QString &palette); + + operator org_kde_kwin_server_decoration_palette*(); + operator org_kde_kwin_server_decoration_palette*() const; + +private: + friend class ServerSideDecorationPaletteManager; + explicit ServerDecorationPalette(QObject *parent = nullptr); + class Private; + QScopedPointer d; +}; + + +} +} + +#endif diff --git a/src/client/server_decoration_palette.cpp b/src/client/server_decoration_palette.cpp new file mode 100644 --- /dev/null +++ b/src/client/server_decoration_palette.cpp @@ -0,0 +1,184 @@ +/**************************************************************************** +Copyright 2017 David Edmundson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +****************************************************************************/ +#include "server_decoration_palette.h" +#include "event_queue.h" +#include "surface.h" +#include "wayland_pointer_p.h" + +#include + +#include + +namespace KWayland +{ +namespace Client +{ + +class ServerSideDecorationPaletteManager::Private +{ +public: + Private() = default; + + void setup(org_kde_kwin_server_decoration_palette_manager *arg); + + WaylandPointer serverdecomanager; + EventQueue *queue = nullptr; +}; + +ServerSideDecorationPaletteManager::ServerSideDecorationPaletteManager(QObject *parent) + : QObject(parent) + , d(new Private) +{ +} + +void ServerSideDecorationPaletteManager::Private::setup(org_kde_kwin_server_decoration_palette_manager *arg) +{ + Q_ASSERT(arg); + Q_ASSERT(!serverdecomanager); + serverdecomanager.setup(arg); +} + +ServerSideDecorationPaletteManager::~ServerSideDecorationPaletteManager() +{ + release(); +} + +void ServerSideDecorationPaletteManager::setup(org_kde_kwin_server_decoration_palette_manager *serverdecomanager) +{ + d->setup(serverdecomanager); +} + +void ServerSideDecorationPaletteManager::release() +{ + d->serverdecomanager.release(); +} + +void ServerSideDecorationPaletteManager::destroy() +{ + d->serverdecomanager.destroy(); +} + +ServerSideDecorationPaletteManager::operator org_kde_kwin_server_decoration_palette_manager*() { + return d->serverdecomanager; +} + +ServerSideDecorationPaletteManager::operator org_kde_kwin_server_decoration_palette_manager*() const { + return d->serverdecomanager; +} + +bool ServerSideDecorationPaletteManager::isValid() const +{ + return d->serverdecomanager.isValid(); +} + +void ServerSideDecorationPaletteManager::setEventQueue(EventQueue *queue) +{ + d->queue = queue; +} + +EventQueue *ServerSideDecorationPaletteManager::eventQueue() +{ + return d->queue; +} + +ServerDecorationPalette *ServerSideDecorationPaletteManager::create(Surface *surface, QObject *parent) +{ + Q_ASSERT(isValid()); + auto p = new ServerDecorationPalette(parent); + auto w = org_kde_kwin_server_decoration_palette_manager_create(d->serverdecomanager, *surface); + if (d->queue) { + d->queue->addProxy(w); + } + p->setup(w); + + return p; +} + +class ServerDecorationPalette::Private +{ +public: + Private(ServerDecorationPalette *q); + + void setup(org_kde_kwin_server_decoration_palette *arg); + + WaylandPointer decoration_palette; + +private: + ServerDecorationPalette *q; +}; + +ServerDecorationPalette::Private::Private(ServerDecorationPalette *q) + : q(q) +{ +} + +ServerDecorationPalette::ServerDecorationPalette(QObject *parent) + : QObject(parent) + , d(new Private(this)) +{ +} + +void ServerDecorationPalette::Private::setup(org_kde_kwin_server_decoration_palette *arg) +{ + Q_ASSERT(arg); + Q_ASSERT(!decoration_palette); + decoration_palette.setup(arg); +} + +ServerDecorationPalette::~ServerDecorationPalette() +{ + release(); +} + +void ServerDecorationPalette::setup(org_kde_kwin_server_decoration_palette *decoration_palette) +{ + d->setup(decoration_palette); +} + +void ServerDecorationPalette::release() +{ + d->decoration_palette.release(); +} + +void ServerDecorationPalette::destroy() +{ + d->decoration_palette.destroy(); +} + +ServerDecorationPalette::operator org_kde_kwin_server_decoration_palette*() { + return d->decoration_palette; +} + +ServerDecorationPalette::operator org_kde_kwin_server_decoration_palette*() const { + return d->decoration_palette; +} + +bool ServerDecorationPalette::isValid() const +{ + return d->decoration_palette.isValid(); +} + +void ServerDecorationPalette::setPalette(const QString &palette) +{ + Q_ASSERT(isValid()); + org_kde_kwin_server_decoration_palette_set_palette(*this, palette.toUtf8()); +} +} +} diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -40,6 +40,7 @@ blur_interface.cpp contrast_interface.cpp server_decoration_interface.cpp + server_decoration_palette_interface.cpp shell_interface.cpp surface_interface.cpp subcompositor_interface.cpp @@ -167,6 +168,12 @@ PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/appmenu.xml BASENAME appmenu ) + +ecm_add_wayland_server_protocol(SERVER_LIB_SRCS + PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/server-decoration-palette.xml + BASENAME server_decoration_palette +) + set(SERVER_GENERATED_SRCS ${CMAKE_CURRENT_BINARY_DIR}/wayland-output-management-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-output-management-server-protocol.h @@ -196,6 +203,8 @@ ${CMAKE_CURRENT_BINARY_DIR}/wayland-slide-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-server_decoration-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-server_decoration-server-protocol.h + ${CMAKE_CURRENT_BINARY_DIR}/wayland-server_decoration_palette-client-protocol.h + ${CMAKE_CURRENT_BINARY_DIR}/wayland-server_decoration_palette-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-text-client-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-text-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-text-input-unstable-v2-client-protocol.h @@ -280,6 +289,7 @@ resource.h seat_interface.h server_decoration_interface.h + server_decoration_palette_interface.h shadow_interface.h shell_interface.h slide_interface.h diff --git a/src/server/display.h b/src/server/display.h --- a/src/server/display.h +++ b/src/server/display.h @@ -84,6 +84,7 @@ class PointerConstraintsInterface; class XdgForeignInterface; class AppMenuManagerInterface; +class ServerSideDecorationPaletteManagerInterface; /** * @brief Class holding the Wayland server display loop. @@ -247,6 +248,14 @@ **/ AppMenuManagerInterface *createAppMenuManagerInterface(QObject *parent = nullptr); + /** + * Creates the ServerSideDecorationPaletteManagerInterface in interface @p version. + * + * @returns The created manager object + * @since 5.42 + **/ + ServerSideDecorationPaletteManagerInterface *createServerSideDecorationPaletteManager(QObject *parent = nullptr); + /** * Gets the ClientConnection for the given @p client. diff --git a/src/server/display.cpp b/src/server/display.cpp --- a/src/server/display.cpp +++ b/src/server/display.cpp @@ -48,6 +48,7 @@ #include "xdgforeign_interface.h" #include "xdgshell_v6_interface_p.h" #include "appmenu_interface.h" +#include "server_decoration_palette_interface.h" #include #include @@ -441,6 +442,13 @@ return b; } +ServerSideDecorationPaletteManagerInterface *Display::createServerSideDecorationPaletteManager(QObject *parent) +{ + auto b = new ServerSideDecorationPaletteManagerInterface(this, parent); + connect(this, &Display::aboutToTerminate, b, [this, b] { delete b; }); + return b; +} + void Display::createShm() { Q_ASSERT(d->display); diff --git a/src/server/server_decoration_palette_interface.h b/src/server/server_decoration_palette_interface.h new file mode 100644 --- /dev/null +++ b/src/server/server_decoration_palette_interface.h @@ -0,0 +1,106 @@ +/**************************************************************************** +Copyright 2017 David Edmundson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +****************************************************************************/ +#ifndef KWAYLAND_SERVER_DECORATION_PALETTE_H +#define KWAYLAND_SERVER_DECORATION_PALETTE_H + +#include "global.h" +#include "resource.h" + +#include + +namespace KWayland +{ +namespace Server +{ + +class Display; +class SurfaceInterface; +class ServerSideDecorationPaletteInterface; + +/** + * Allows a client to specify a preferred palette to use for server-side window decorations + * + * This global can be used for clients to bind ServerSideDecorationPaletteInterface instances + * and notifies when a new one is created + * @since 5.42 + */ +class KWAYLANDSERVER_EXPORT ServerSideDecorationPaletteManagerInterface : public Global +{ + Q_OBJECT +public: + virtual ~ServerSideDecorationPaletteManagerInterface(); + /** + * Returns any existing palette for a given surface + * This returns a null pointer if no ServerSideDecorationPaletteInterface exists. + */ + ServerSideDecorationPaletteInterface* paletteForSurface(SurfaceInterface *); + +Q_SIGNALS: + /** + * Emitted whenever a new ServerSideDecorationPaletteInterface is created. + **/ + void paletteCreated(KWayland::Server::ServerSideDecorationPaletteInterface*); + +private: + explicit ServerSideDecorationPaletteManagerInterface(Display *display, QObject *parent = nullptr); + friend class Display; + class Private; + Private *d_func() const; +}; + +/** + * Provides the palette + * This interface is attached to a wl_surface and informs the server of a requested palette + * @since 5.42 + */ +class KWAYLANDSERVER_EXPORT ServerSideDecorationPaletteInterface : public Resource +{ + Q_OBJECT +public: + virtual ~ServerSideDecorationPaletteInterface(); + + /** + * @returns the palette or an empty string if unset + */ + QString palette() const; + + /** + * @returns The SurfaceInterface this ServerSideDecorationPaletteInterface references. + **/ + SurfaceInterface *surface() const; + +Q_SIGNALS: + /** + * Emitted when the palette changes or is first received + */ + void paletteChanged(const QString &palette); + +private: + explicit ServerSideDecorationPaletteInterface(ServerSideDecorationPaletteManagerInterface *parent, SurfaceInterface *s, wl_resource *parentResource); + friend class ServerSideDecorationPaletteManagerInterface; + + class Private; + Private *d_func() const; +}; + +} +} + +#endif diff --git a/src/server/server_decoration_palette_interface.cpp b/src/server/server_decoration_palette_interface.cpp new file mode 100644 --- /dev/null +++ b/src/server/server_decoration_palette_interface.cpp @@ -0,0 +1,216 @@ +/**************************************************************************** +Copyright 2017 David Edmundson + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) version 3, or any +later version accepted by the membership of KDE e.V. (or its +successor approved by the membership of KDE e.V.), which shall +act as a proxy defined in Section 6 of version 3 of the license. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. If not, see . +****************************************************************************/ +#include "server_decoration_palette_interface.h" +#include "display.h" +#include "surface_interface.h" +#include "global_p.h" +#include "resource_p.h" +#include "logging_p.h" + +#include + +#include + +namespace KWayland +{ +namespace Server +{ +class ServerSideDecorationPaletteManagerInterface::Private : public Global::Private +{ +public: + Private(ServerSideDecorationPaletteManagerInterface *q, Display *d); + + QVector palettes; +private: + void bind(wl_client *client, uint32_t version, uint32_t id) override; + + static void unbind(wl_resource *resource); + static Private *cast(wl_resource *r) { + return reinterpret_cast(wl_resource_get_user_data(r)); + } + + static void createCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource * surface); + + ServerSideDecorationPaletteManagerInterface *q; + static const struct org_kde_kwin_server_decoration_palette_manager_interface s_interface; + static const quint32 s_version; +}; + +const quint32 ServerSideDecorationPaletteManagerInterface::Private::s_version = 1; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +const struct org_kde_kwin_server_decoration_palette_manager_interface ServerSideDecorationPaletteManagerInterface::Private::s_interface = { + createCallback +}; +#endif + +void ServerSideDecorationPaletteManagerInterface::Private::createCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource * surface) +{ + auto p = reinterpret_cast(wl_resource_get_user_data(resource)); + Q_ASSERT(p); + + SurfaceInterface *s = SurfaceInterface::get(surface); + if (!s) { + // TODO: send error? + qCWarning(KWAYLAND_SERVER) << "ServerSideDecorationPaletteInterface requested for non existing SurfaceInterface"; + return; + } + auto palette = new ServerSideDecorationPaletteInterface(p->q, s, resource); + palette->create(p->display->getConnection(client), wl_resource_get_version(resource), id); + if (!palette->resource()) { + wl_resource_post_no_memory(resource); + delete palette; + return; + } + p->palettes.append(palette); + QObject::connect(palette, &QObject::destroyed, p->q, [=]() { + p->palettes.removeOne(palette); + }); + emit p->q->paletteCreated(palette); +} + +ServerSideDecorationPaletteManagerInterface::Private::Private(ServerSideDecorationPaletteManagerInterface *q, Display *d) + : Global::Private(d, &org_kde_kwin_server_decoration_palette_manager_interface, s_version) + , q(q) +{ +} + +void ServerSideDecorationPaletteManagerInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id) +{ + auto c = display->getConnection(client); + wl_resource *resource = c->createResource(&org_kde_kwin_server_decoration_palette_manager_interface, qMin(version, s_version), id); + if (!resource) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(resource, &s_interface, this, unbind); +} + +void ServerSideDecorationPaletteManagerInterface::Private::unbind(wl_resource *resource) +{ + Q_UNUSED(resource) +} + +class ServerSideDecorationPaletteInterface::Private : public Resource::Private +{ +public: + Private(ServerSideDecorationPaletteInterface *q, ServerSideDecorationPaletteManagerInterface *c, SurfaceInterface *surface, wl_resource *parentResource); + ~Private(); + + + SurfaceInterface *surface; + QString palette; +private: + static void setPaletteCallback(wl_client *client, wl_resource *resource, const char * palette); + + ServerSideDecorationPaletteInterface *q_func() { + return reinterpret_cast(q); + } + static ServerSideDecorationPaletteInterface *get(SurfaceInterface *s); + static const struct org_kde_kwin_server_decoration_palette_interface s_interface; +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +const struct org_kde_kwin_server_decoration_palette_interface ServerSideDecorationPaletteInterface::Private::s_interface = { + setPaletteCallback, + resourceDestroyedCallback +}; +#endif + +void ServerSideDecorationPaletteInterface::Private::setPaletteCallback(wl_client *client, wl_resource *resource, const char * palette) +{ + Q_UNUSED(client); + auto p = reinterpret_cast(wl_resource_get_user_data(resource)); + Q_ASSERT(p); + + if (p->palette == QLatin1String(palette)) { + return; + } + p->palette = QString::fromUtf8(palette); + emit p->q_func()->paletteChanged(p->palette); +} + +ServerSideDecorationPaletteInterface::Private::Private(ServerSideDecorationPaletteInterface *q, ServerSideDecorationPaletteManagerInterface *c, SurfaceInterface *s, wl_resource *parentResource) + : Resource::Private(q, c, parentResource, &org_kde_kwin_server_decoration_palette_interface, &s_interface), + surface(s) +{ +} + +ServerSideDecorationPaletteInterface::Private::~Private() +{ + if (resource) { + wl_resource_destroy(resource); + resource = nullptr; + } +} + +ServerSideDecorationPaletteManagerInterface::ServerSideDecorationPaletteManagerInterface(Display *display, QObject *parent) + : Global(new Private(this, display), parent) +{ +} + +ServerSideDecorationPaletteManagerInterface::~ServerSideDecorationPaletteManagerInterface() +{ +} + +ServerSideDecorationPaletteManagerInterface::Private *ServerSideDecorationPaletteManagerInterface::d_func() const +{ + return reinterpret_cast(d.data()); +} + +ServerSideDecorationPaletteInterface* ServerSideDecorationPaletteManagerInterface::paletteForSurface(SurfaceInterface *surface) +{ + Q_D(); + for (ServerSideDecorationPaletteInterface* menu: d->palettes) { + if (menu->surface() == surface) { + return menu; + } + } + return nullptr; +} + +ServerSideDecorationPaletteInterface::ServerSideDecorationPaletteInterface(ServerSideDecorationPaletteManagerInterface *parent, SurfaceInterface *s, wl_resource *parentResource): + Resource(new Private(this, parent, s, parentResource)) +{ +} + +ServerSideDecorationPaletteInterface::Private *ServerSideDecorationPaletteInterface::d_func() const +{ + return reinterpret_cast(d.data()); +} + +ServerSideDecorationPaletteInterface::~ServerSideDecorationPaletteInterface() +{} + +QString ServerSideDecorationPaletteInterface::palette() const +{ + Q_D(); + return d->palette; +} + +SurfaceInterface* ServerSideDecorationPaletteInterface::surface() const +{ + Q_D(); + return d->surface; +} + +}//namespace +} +