diff --git a/CMakeLists.txt b/CMakeLists.txt index 7be3482738..d293cb904b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -211,7 +211,7 @@ else() set(HAVE_WL_DISPLAY_SET_DEFAULT_MAX_BUFFER_SIZE 0) endif() -find_package(WaylandProtocols 1.34) +find_package(WaylandProtocols 1.36) set_package_properties(WaylandProtocols PROPERTIES TYPE REQUIRED PURPOSE "Collection of Wayland protocols that add functionality not available in the Wayland core protocol" diff --git a/src/scene/surfaceitem_wayland.cpp b/src/scene/surfaceitem_wayland.cpp index 5b1001b06f..4a307565c0 100644 --- a/src/scene/surfaceitem_wayland.cpp +++ b/src/scene/surfaceitem_wayland.cpp @@ -47,6 +47,7 @@ SurfaceItemWayland::SurfaceItemWayland(SurfaceInterface *surface, Item *parent) connect(surface, &SurfaceInterface::presentationModeHintChanged, this, &SurfaceItemWayland::handlePresentationModeHintChanged); connect(surface, &SurfaceInterface::bufferReleasePointChanged, this, &SurfaceItemWayland::handleReleasePointChanged); + connect(surface, &SurfaceInterface::alphaMultiplierChanged, this, &SurfaceItemWayland::handleAlphaMultiplierChanged); SubSurfaceInterface *subsurface = surface->subSurface(); if (subsurface) { @@ -66,6 +67,7 @@ SurfaceItemWayland::SurfaceItemWayland(SurfaceInterface *surface, Item *parent) setBufferSourceBox(surface->bufferSourceBox()); setBufferSize(surface->bufferSize()); setColorDescription(surface->colorDescription()); + setOpacity(surface->alphaMultiplier()); } QList SurfaceItemWayland::shape() const @@ -216,6 +218,11 @@ void SurfaceItemWayland::handleReleasePointChanged() m_bufferReleasePoint = m_surface->bufferReleasePoint(); } +void SurfaceItemWayland::handleAlphaMultiplierChanged() +{ + setOpacity(m_surface->alphaMultiplier()); +} + SurfacePixmapWayland::SurfacePixmapWayland(SurfaceItemWayland *item, QObject *parent) : SurfacePixmap(Compositor::self()->backend()->createSurfaceTextureWayland(this), parent) , m_item(item) diff --git a/src/scene/surfaceitem_wayland.h b/src/scene/surfaceitem_wayland.h index 7dfb44b427..f769284172 100644 --- a/src/scene/surfaceitem_wayland.h +++ b/src/scene/surfaceitem_wayland.h @@ -50,6 +50,7 @@ private Q_SLOTS: void handleColorDescriptionChanged(); void handlePresentationModeHintChanged(); void handleReleasePointChanged(); + void handleAlphaMultiplierChanged(); protected: std::unique_ptr createPixmap() override; diff --git a/src/wayland/CMakeLists.txt b/src/wayland/CMakeLists.txt index 015814498e..a8bdc2bc7b 100644 --- a/src/wayland/CMakeLists.txt +++ b/src/wayland/CMakeLists.txt @@ -315,10 +315,15 @@ ecm_add_qtwayland_server_protocol_kde(WaylandProtocols_xml PROTOCOL ${PLASMA_WAYLAND_PROTOCOLS_DIR}/kde-external-brightness-v1.xml BASENAME kde-external-brightness-v1 ) +ecm_add_qtwayland_server_protocol_kde(WaylandProtocols_xml + PROTOCOL ${WaylandProtocols_DATADIR}/staging/alpha-modifier/alpha-modifier-v1.xml + BASENAME alpha-modifier-v1 +) target_sources(kwin PRIVATE abstract_data_source.cpp abstract_drop_handler.cpp + alphamodifier_v1.cpp appmenu.cpp blur.cpp clientconnection.cpp @@ -403,6 +408,7 @@ target_sources(kwin PRIVATE ) install(FILES + alphamodifier_v1.h appmenu.h blur.h clientconnection.h @@ -478,12 +484,14 @@ install(FILES xwaylandshell_v1.h xx_colormanagement_v4.h + ${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-alpha-modifier-v1.h ${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-content-type-v1.h ${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-frog-color-management-v1.h ${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-kde-external-brightness-v1.h ${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-linux-drm-syncobj-v1.h ${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-presentation-time.h ${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-xx-color-management-v4.h + ${CMAKE_CURRENT_BINARY_DIR}/wayland-alpha-modifier-v1-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-content-type-v1-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-frog-color-management-v1-server-protocol.h ${CMAKE_CURRENT_BINARY_DIR}/wayland-kde-external-brightness-v1-server-protocol.h diff --git a/src/wayland/alphamodifier_v1.cpp b/src/wayland/alphamodifier_v1.cpp new file mode 100644 index 0000000000..e9e39b9845 --- /dev/null +++ b/src/wayland/alphamodifier_v1.cpp @@ -0,0 +1,75 @@ +/* + SPDX-FileCopyrightText: 2024 Xaver Hugl + + SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL +*/ +#include "alphamodifier_v1.h" + +#include "display.h" +#include "surface.h" +#include "surface_p.h" + +namespace KWin +{ + +static constexpr uint32_t s_version = 1; + +AlphaModifierManagerV1::AlphaModifierManagerV1(Display *display, QObject *parent) + : QObject(parent) + , QtWaylandServer::wp_alpha_modifier_v1(*display, s_version) +{ +} + +void AlphaModifierManagerV1::wp_alpha_modifier_v1_destroy(Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +void AlphaModifierManagerV1::wp_alpha_modifier_v1_get_surface(Resource *resource, uint32_t id, ::wl_resource *surface) +{ + SurfaceInterface *surf = SurfaceInterface::get(surface); + SurfaceInterfacePrivate *priv = SurfaceInterfacePrivate::get(surf); + if (priv->alphaModifier) { + wl_resource_post_error(surface, error_already_constructed, "wl_surface already has an alpha modifier surface"); + return; + } + new AlphaModifierSurfaceV1(resource->client(), id, resource->version(), surf); +} + +AlphaModifierSurfaceV1::AlphaModifierSurfaceV1(wl_client *client, uint32_t id, uint32_t version, SurfaceInterface *surface) + : QtWaylandServer::wp_alpha_modifier_surface_v1(client, id, version) + , m_surface(surface) +{ +} + +AlphaModifierSurfaceV1::~AlphaModifierSurfaceV1() +{ + if (m_surface) { + const auto priv = SurfaceInterfacePrivate::get(m_surface); + priv->pending->alphaMultiplier = 1; + priv->pending->alphaMultiplierIsSet = true; + } +} + +void AlphaModifierSurfaceV1::wp_alpha_modifier_surface_v1_destroy_resource(Resource *resource) +{ + delete this; +} + +void AlphaModifierSurfaceV1::wp_alpha_modifier_surface_v1_destroy(Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +void AlphaModifierSurfaceV1::wp_alpha_modifier_surface_v1_set_multiplier(Resource *resource, uint32_t factor) +{ + if (!m_surface) { + wl_resource_post_error(resource->handle, error_no_surface, "wl_surface was destroyed before a set_multiplier request"); + return; + } + const auto priv = SurfaceInterfacePrivate::get(m_surface); + priv->pending->alphaMultiplier = factor / double(std::numeric_limits::max()); + priv->pending->alphaMultiplierIsSet = true; +} + +} diff --git a/src/wayland/alphamodifier_v1.h b/src/wayland/alphamodifier_v1.h new file mode 100644 index 0000000000..1e2b8ef45f --- /dev/null +++ b/src/wayland/alphamodifier_v1.h @@ -0,0 +1,44 @@ +/* + SPDX-FileCopyrightText: 2024 Xaver Hugl + + SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL +*/ +#pragma once + +#include "kwin_export.h" +#include "wayland/qwayland-server-alpha-modifier-v1.h" + +#include +#include + +namespace KWin +{ + +class Display; +class SurfaceInterface; + +class KWIN_EXPORT AlphaModifierManagerV1 : public QObject, private QtWaylandServer::wp_alpha_modifier_v1 +{ +public: + explicit AlphaModifierManagerV1(Display *display, QObject *parent); + +private: + void wp_alpha_modifier_v1_destroy(Resource *resource) override; + void wp_alpha_modifier_v1_get_surface(Resource *resource, uint32_t id, ::wl_resource *surface) override; +}; + +class AlphaModifierSurfaceV1 : private QtWaylandServer::wp_alpha_modifier_surface_v1 +{ +public: + explicit AlphaModifierSurfaceV1(wl_client *client, uint32_t id, uint32_t version, SurfaceInterface *surface); + ~AlphaModifierSurfaceV1() override; + +private: + void wp_alpha_modifier_surface_v1_destroy_resource(Resource *resource) override; + void wp_alpha_modifier_surface_v1_destroy(Resource *resource) override; + void wp_alpha_modifier_surface_v1_set_multiplier(Resource *resource, uint32_t factor) override; + + const QPointer m_surface; +}; + +} diff --git a/src/wayland/surface.cpp b/src/wayland/surface.cpp index d4779b3a5b..8bb2077b21 100644 --- a/src/wayland/surface.cpp +++ b/src/wayland/surface.cpp @@ -589,6 +589,10 @@ void SurfaceState::mergeInto(SurfaceState *target) target->colorDescription = colorDescription; target->colorDescriptionIsSet = true; } + if (alphaMultiplierIsSet) { + target->alphaMultiplier = alphaMultiplier; + target->alphaMultiplierIsSet = true; + } target->presentationFeedback = std::move(presentationFeedback); *this = SurfaceState{}; @@ -611,6 +615,7 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next) const bool colorDescriptionChanged = next->colorDescriptionIsSet; const bool presentationModeHintChanged = next->presentationModeHintIsSet; const bool bufferReleasePointChanged = next->bufferIsSet && current->releasePoint != next->releasePoint; + const bool alphaMultiplierChanged = next->alphaMultiplierIsSet; const QSizeF oldSurfaceSize = surfaceSize; const QSize oldBufferSize = bufferSize; @@ -706,6 +711,9 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next) if (bufferReleasePointChanged) { Q_EMIT q->bufferReleasePointChanged(); } + if (alphaMultiplierChanged) { + Q_EMIT q->alphaMultiplierChanged(); + } if (bufferChanged) { if (current->buffer && (!current->damage.isEmpty() || !current->bufferDamage.isEmpty())) { @@ -1210,6 +1218,11 @@ std::shared_ptr SurfaceInterface::bufferReleasePoint() const return d->current->releasePoint; } +double SurfaceInterface::alphaMultiplier() const +{ + return d->current->alphaMultiplier; +} + } // namespace KWin #include "moc_surface.cpp" diff --git a/src/wayland/surface.h b/src/wayland/surface.h index 0b713d5bae..dad42f268d 100644 --- a/src/wayland/surface.h +++ b/src/wayland/surface.h @@ -344,6 +344,8 @@ public: void setPreferredColorDescription(const ColorDescription &descr); + double alphaMultiplier() const; + /** * Returns the current release point for the buffer on this surface. The buffer keeps the * release point referenced as long as it's referenced itself; for synchronization on the @@ -437,6 +439,7 @@ Q_SIGNALS: void colorDescriptionChanged(); void presentationModeHintChanged(); void bufferReleasePointChanged(); + void alphaMultiplierChanged(); /** * Emitted when the Surface has been committed. diff --git a/src/wayland/surface_p.h b/src/wayland/surface_p.h index 2c11f515e9..f93c0504d5 100644 --- a/src/wayland/surface_p.h +++ b/src/wayland/surface_p.h @@ -30,6 +30,7 @@ class PresentationTimeFeedback; class XXColorSurfaceV4; class XXColorFeedbackSurfaceV4; class LinuxDrmSyncObjSurfaceV1; +class AlphaModifierSurfaceV1; struct SurfaceState { @@ -60,6 +61,7 @@ struct SurfaceState bool contentTypeIsSet = false; bool presentationModeHintIsSet = false; bool colorDescriptionIsSet = false; + bool alphaMultiplierIsSet = false; qint32 bufferScale = 1; OutputTransform bufferTransform = OutputTransform::Normal; wl_list frameCallbacks; @@ -80,6 +82,7 @@ struct SurfaceState uint64_t point = 0; } acquirePoint; std::shared_ptr releasePoint; + double alphaMultiplier = 1; struct { @@ -181,6 +184,7 @@ public: XXColorSurfaceV4 *xxColorSurface = nullptr; QList xxColorFeedbacks; LinuxDrmSyncObjSurfaceV1 *syncObjV1 = nullptr; + AlphaModifierSurfaceV1 *alphaModifier = nullptr; struct { diff --git a/src/wayland_server.cpp b/src/wayland_server.cpp index b3ed841992..cf727cfc86 100644 --- a/src/wayland_server.cpp +++ b/src/wayland_server.cpp @@ -23,6 +23,7 @@ #include "utils/kernel.h" #include "utils/serviceutils.h" #include "virtualdesktops.h" +#include "wayland/alphamodifier_v1.h" #include "wayland/appmenu.h" #include "wayland/clientconnection.h" #include "wayland/compositor.h" @@ -525,7 +526,7 @@ bool WaylandServer::init() }); m_externalBrightness = new ExternalBrightnessV1(m_display, m_display); - + m_alphaModifierManager = new AlphaModifierManagerV1(m_display, m_display); return true; } diff --git a/src/wayland_server.h b/src/wayland_server.h index 7ff7185d00..874b62094c 100644 --- a/src/wayland_server.h +++ b/src/wayland_server.h @@ -63,6 +63,7 @@ class PresentationTime; class XXColorManagerV4; class LinuxDrmSyncObjV1Interface; class RenderBackend; +class AlphaModifierManagerV1; class KWIN_EXPORT WaylandServer : public QObject { @@ -291,6 +292,7 @@ private: XXColorManagerV4 *m_xxColorManager = nullptr; XdgDialogWmV1Interface *m_xdgDialogWm = nullptr; ExternalBrightnessV1 *m_externalBrightness = nullptr; + AlphaModifierManagerV1 *m_alphaModifierManager = nullptr; KWIN_SINGLETON(WaylandServer) };