mirror of
https://github.com/libsdl-org/SDL.git
synced 2024-11-26 21:06:24 +08:00
wayland: Implement SetWindowOpacity via the alpha modifier protocol
The wp_alpha_modifier_v1 protocol allows for a global blending factor to be specified for an entire surface. Use this to add support for SDL_SetWindowOpacity().
This commit is contained in:
parent
606903c02f
commit
716dc0e1bf
@ -43,6 +43,7 @@
|
||||
|
||||
#include <wayland-util.h>
|
||||
|
||||
#include "alpha-modifier-v1-client-protocol.h"
|
||||
#include "cursor-shape-v1-client-protocol.h"
|
||||
#include "fractional-scale-v1-client-protocol.h"
|
||||
#include "idle-inhibit-unstable-v1-client-protocol.h"
|
||||
@ -487,6 +488,7 @@ static SDL_VideoDevice *Wayland_CreateDevice(void)
|
||||
device->SetWindowMinimumSize = Wayland_SetWindowMinimumSize;
|
||||
device->SetWindowMaximumSize = Wayland_SetWindowMaximumSize;
|
||||
device->SetWindowModalFor = Wayland_SetWindowModalFor;
|
||||
device->SetWindowOpacity = Wayland_SetWindowOpacity;
|
||||
device->SetWindowTitle = Wayland_SetWindowTitle;
|
||||
device->GetWindowSizeInPixels = Wayland_GetWindowSizeInPixels;
|
||||
device->GetDisplayForWindow = Wayland_GetDisplayForWindow;
|
||||
@ -1107,6 +1109,8 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint
|
||||
d->zxdg_exporter_v2 = wl_registry_bind(d->registry, id, &zxdg_exporter_v2_interface, 1);
|
||||
} else if (SDL_strcmp(interface, "xdg_wm_dialog_v1") == 0) {
|
||||
d->xdg_wm_dialog_v1 = wl_registry_bind(d->registry, id, &xdg_wm_dialog_v1_interface, 1);
|
||||
} else if (SDL_strcmp(interface, "wp_alpha_modifier_v1") == 0) {
|
||||
d->wp_alpha_modifier_v1 = wl_registry_bind(d->registry, id, &wp_alpha_modifier_v1_interface, 1);
|
||||
} else if (SDL_strcmp(interface, "kde_output_order_v1") == 0) {
|
||||
d->kde_output_order = wl_registry_bind(d->registry, id, &kde_output_order_v1_interface, 1);
|
||||
kde_output_order_v1_add_listener(d->kde_output_order, &kde_output_order_listener, d);
|
||||
@ -1369,6 +1373,11 @@ static void Wayland_VideoCleanup(SDL_VideoDevice *_this)
|
||||
data->xdg_wm_dialog_v1 = NULL;
|
||||
}
|
||||
|
||||
if (data->wp_alpha_modifier_v1) {
|
||||
wp_alpha_modifier_v1_destroy(data->wp_alpha_modifier_v1);
|
||||
data->wp_alpha_modifier_v1 = NULL;
|
||||
}
|
||||
|
||||
if (data->kde_output_order) {
|
||||
Wayland_FlushOutputOrder(data);
|
||||
kde_output_order_v1_destroy(data->kde_output_order);
|
||||
|
@ -81,6 +81,7 @@ struct SDL_VideoData
|
||||
struct zwp_input_timestamps_manager_v1 *input_timestamps_manager;
|
||||
struct zxdg_exporter_v2 *zxdg_exporter_v2;
|
||||
struct xdg_wm_dialog_v1 *xdg_wm_dialog_v1;
|
||||
struct wp_alpha_modifier_v1 *wp_alpha_modifier_v1;
|
||||
struct kde_output_order_v1 *kde_output_order;
|
||||
|
||||
struct xkb_context *xkb_context;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "SDL_waylandvideo.h"
|
||||
#include "../../SDL_hints_c.h"
|
||||
|
||||
#include "alpha-modifier-v1-client-protocol.h"
|
||||
#include "xdg-shell-client-protocol.h"
|
||||
#include "xdg-decoration-unstable-v1-client-protocol.h"
|
||||
#include "idle-inhibit-unstable-v1-client-protocol.h"
|
||||
@ -279,10 +280,24 @@ static void RepositionPopup(SDL_Window *window, SDL_bool use_current_position)
|
||||
}
|
||||
}
|
||||
|
||||
static void SetSurfaceOpaqueRegion(SDL_WindowData *wind, SDL_bool is_opaque)
|
||||
{
|
||||
SDL_VideoData *viddata = wind->waylandData;
|
||||
|
||||
if (is_opaque) {
|
||||
struct wl_region *region = wl_compositor_create_region(viddata->compositor);
|
||||
wl_region_add(region, 0, 0,
|
||||
wind->current.logical_width, wind->current.logical_height);
|
||||
wl_surface_set_opaque_region(wind->surface, region);
|
||||
wl_region_destroy(region);
|
||||
} else {
|
||||
wl_surface_set_opaque_region(wind->surface, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void ConfigureWindowGeometry(SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
SDL_VideoData *viddata = data->waylandData;
|
||||
const int old_pixel_width = data->current.pixel_width;
|
||||
const int old_pixel_height = data->current.pixel_height;
|
||||
int window_width, window_height;
|
||||
@ -391,20 +406,12 @@ static void ConfigureWindowGeometry(SDL_Window *window)
|
||||
* need to be recalculated if the output size has changed.
|
||||
*/
|
||||
if (window_size_changed) {
|
||||
struct wl_region *region;
|
||||
|
||||
/* libdecor does this internally on frame commits, so it's only needed for xdg surfaces. */
|
||||
if (data->shell_surface_type != WAYLAND_SURFACE_LIBDECOR && data->shell_surface.xdg.surface) {
|
||||
xdg_surface_set_window_geometry(data->shell_surface.xdg.surface, 0, 0, data->current.logical_width, data->current.logical_height);
|
||||
}
|
||||
|
||||
if (!(window->flags & SDL_WINDOW_TRANSPARENT)) {
|
||||
region = wl_compositor_create_region(viddata->compositor);
|
||||
wl_region_add(region, 0, 0,
|
||||
data->current.logical_width, data->current.logical_height);
|
||||
wl_surface_set_opaque_region(data->surface, region);
|
||||
wl_region_destroy(region);
|
||||
}
|
||||
SetSurfaceOpaqueRegion(data, !(window->flags & SDL_WINDOW_TRANSPARENT) && window->opacity == 1.0f);
|
||||
|
||||
/* Ensure that child popup windows are still in bounds. */
|
||||
for (SDL_Window *child = window->first_child; child; child = child->next_sibling) {
|
||||
@ -2302,6 +2309,11 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert
|
||||
}
|
||||
}
|
||||
|
||||
if (!custom_surface_role && c->wp_alpha_modifier_v1) {
|
||||
data->wp_alpha_modifier_surface_v1 = wp_alpha_modifier_v1_get_surface(c->wp_alpha_modifier_v1, data->surface);
|
||||
wp_alpha_modifier_surface_v1_set_multiplier(data->wp_alpha_modifier_surface_v1, SDL_MAX_UINT32);
|
||||
}
|
||||
|
||||
/* Must be called before EGL configuration to set the drawable backbuffer size. */
|
||||
ConfigureWindowGeometry(window);
|
||||
|
||||
@ -2494,6 +2506,20 @@ SDL_DisplayID Wayland_GetDisplayForWindow(SDL_VideoDevice *_this, SDL_Window *wi
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Wayland_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float opacity)
|
||||
{
|
||||
SDL_WindowData *wind = window->driverdata;
|
||||
|
||||
if (wind->wp_alpha_modifier_surface_v1) {
|
||||
SetSurfaceOpaqueRegion(wind, !(window->flags & SDL_WINDOW_TRANSPARENT) && opacity == 1.0f);
|
||||
wp_alpha_modifier_surface_v1_set_multiplier(wind->wp_alpha_modifier_surface_v1, (Uint32)((double)SDL_MAX_UINT32 * (double)opacity));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return SDL_SetError("wayland: set window opacity failed; compositor lacks support for the required wp_alpha_modifier_v1 protocol");
|
||||
}
|
||||
|
||||
void Wayland_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *wind = window->driverdata;
|
||||
@ -2614,6 +2640,10 @@ void Wayland_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
wp_fractional_scale_v1_destroy(wind->fractional_scale);
|
||||
}
|
||||
|
||||
if (wind->wp_alpha_modifier_surface_v1) {
|
||||
wp_alpha_modifier_surface_v1_destroy(wind->wp_alpha_modifier_surface_v1);
|
||||
}
|
||||
|
||||
SDL_free(wind->outputs);
|
||||
SDL_free(wind->app_id);
|
||||
|
||||
|
@ -97,6 +97,7 @@ struct SDL_WindowData
|
||||
struct wp_fractional_scale_v1 *fractional_scale;
|
||||
struct zxdg_exported_v2 *exported;
|
||||
struct xdg_dialog_v1 *xdg_dialog_v1;
|
||||
struct wp_alpha_modifier_surface_v1 *wp_alpha_modifier_surface_v1;
|
||||
|
||||
SDL_AtomicInt swap_interval_ready;
|
||||
|
||||
@ -193,6 +194,7 @@ extern void Wayland_SetWindowMaximumSize(SDL_VideoDevice *_this, SDL_Window *win
|
||||
extern void Wayland_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, int *w, int *h);
|
||||
extern SDL_DisplayID Wayland_GetDisplayForWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int Wayland_SetWindowModalFor(SDL_VideoDevice *_this, SDL_Window *modal_window, SDL_Window *parent_window);
|
||||
extern int Wayland_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float opacity);
|
||||
extern void Wayland_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void Wayland_ShowWindowSystemMenu(SDL_Window *window, int x, int y);
|
||||
extern void Wayland_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
|
103
wayland-protocols/alpha-modifier-v1.xml
Normal file
103
wayland-protocols/alpha-modifier-v1.xml
Normal file
@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="alpha_modifier_v1">
|
||||
<copyright>
|
||||
Copyright © 2024 Xaver Hugl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="wp_alpha_modifier_v1" version="1">
|
||||
<description summary="surface alpha modifier manager">
|
||||
This interface allows a client to set a factor for the alpha values on a
|
||||
surface, which can be used to offload such operations to the compositor,
|
||||
which can in turn for example offload them to KMS.
|
||||
|
||||
Warning! The protocol described in this file is currently in the testing
|
||||
phase. Backward compatible changes may be added together with the
|
||||
corresponding interface version bump. Backward incompatible changes can
|
||||
only be done by creating a new major version of the extension.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the alpha modifier manager object">
|
||||
Destroy the alpha modifier manager. This doesn't destroy objects
|
||||
created with the manager.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="already_constructed" value="0"
|
||||
summary="wl_surface already has a alpha modifier object"/>
|
||||
</enum>
|
||||
|
||||
<request name="get_surface">
|
||||
<description summary="create a new toplevel decoration object">
|
||||
Create a new alpha modifier surface object associated with the
|
||||
given wl_surface. If there is already such an object associated with
|
||||
the wl_surface, the already_constructed error will be raised.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="wp_alpha_modifier_surface_v1"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="wp_alpha_modifier_surface_v1" version="1">
|
||||
<description summary="alpha modifier object for a surface">
|
||||
This interface allows the client to set a factor for the alpha values on
|
||||
a surface, which can be used to offload such operations to the compositor.
|
||||
The default factor is UINT32_MAX.
|
||||
|
||||
This object has to be destroyed before the associated wl_surface. Once the
|
||||
wl_surface is destroyed, all request on this object will raise the
|
||||
no_surface error.
|
||||
</description>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="no_surface" value="0" summary="wl_surface was destroyed"/>
|
||||
</enum>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the alpha modifier object">
|
||||
This destroys the object, and is equivalent to set_multiplier with
|
||||
a value of UINT32_MAX, with the same double-buffered semantics as
|
||||
set_multiplier.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="set_multiplier">
|
||||
<description summary="specify the alpha multiplier">
|
||||
Sets the alpha multiplier for the surface. The alpha multiplier is
|
||||
double-buffered state, see wl_surface.commit for details.
|
||||
|
||||
This factor is applied in the compositor's blending space, as an
|
||||
additional step after the processing of per-pixel alpha values for the
|
||||
wl_surface. The exact meaning of the factor is thus undefined, unless
|
||||
the blending space is specified in a different extension.
|
||||
|
||||
This multiplier is applied even if the buffer attached to the
|
||||
wl_surface doesn't have an alpha channel; in that case an alpha value
|
||||
of one is used instead.
|
||||
|
||||
Zero means completely transparent, UINT32_MAX means completely opaque.
|
||||
</description>
|
||||
<arg name="factor" type="uint"/>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
Loading…
Reference in New Issue
Block a user