Merge 8c2090a92c
into eea4711110
This commit is contained in:
commit
9f66ee34dc
|
@ -1722,6 +1722,39 @@ extern "C" {
|
|||
*/
|
||||
#define SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP "SDL_VIDEO_WAYLAND_EMULATE_MOUSE_WARP"
|
||||
|
||||
/**
|
||||
* \brief Create Wayland layer-shell windows.
|
||||
*
|
||||
* If this hint is set, the Wayland video backend will create and allow
|
||||
* operation on layer-shell windows. These windows have different semenatics
|
||||
* and behavior compared to default (XDG) Wayland windows. The value of this
|
||||
* hint indicates the layer that subsequently created layer-shell windows use.
|
||||
*
|
||||
* The value of this hint is a layer enumeration as a string. i.e.
|
||||
* layer = "background"|"bottom"|"top"|"overlay"
|
||||
* e.g. "top"
|
||||
*
|
||||
* This hint defaults to not specifying a Wayland layer-shell layer (i.e. ""),
|
||||
* in which case the SDL Wayland video backend remains using XDG windows only.
|
||||
*/
|
||||
#define SDL_HINT_VIDEO_WAYLAND_SHELL_LAYER "SDL_HINT_VIDEO_WAYLAND_SHELL_LAYER"
|
||||
|
||||
/**
|
||||
* \brief Set a Wayland layer-shell window exclusive zone.
|
||||
*
|
||||
* This hint is used to specify an exclusive zone for an anchored Wayland
|
||||
* layer-shell window. Addtionally, this hint can also be used to indicate how
|
||||
* an unachored Wayland layer-shell window would like to be ordered with
|
||||
* respect to other exclusive-zoned windows (0 to try not to occlude other
|
||||
* windows, -1 for no ordering changes).
|
||||
*
|
||||
* This hints value is a signed 32-bit integer (-2147483648,2147483647)
|
||||
* converted to a string (e.g. "-1").
|
||||
*
|
||||
* This hints default value is "0".
|
||||
*/
|
||||
#define SDL_HINT_VIDEO_WAYLAND_SHELL_EXCL "SDL_HINT_VIDEO_WAYLAND_SHELL_EXCL"
|
||||
|
||||
/**
|
||||
* \brief A variable that is the address of another SDL_Window* (as a hex string formatted with "%p").
|
||||
*
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "tablet-unstable-v2-client-protocol.h"
|
||||
#include "primary-selection-unstable-v1-client-protocol.h"
|
||||
#include "input-timestamps-unstable-v1-client-protocol.h"
|
||||
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
#include <libdecor.h>
|
||||
|
@ -2970,6 +2971,18 @@ int Wayland_input_grab_keyboard(SDL_Window *window, struct SDL_WaylandInput *inp
|
|||
SDL_WindowData *w = window->driverdata;
|
||||
SDL_VideoData *d = input->display;
|
||||
|
||||
/* Layer-shell windows have exclusive grab baked in */
|
||||
if (w->shell_surface_type == WAYLAND_SURFACE_LAYER) {
|
||||
if (w->shell_surface.layer.surface != NULL) {
|
||||
w->shell_surface.layer.kbi = WAYLAND_LAYER_KBI_EXCLUSIVE;
|
||||
zwlr_layer_surface_v1_set_keyboard_interactivity(w->shell_surface.layer.surface,
|
||||
w->shell_surface.layer.kbi);
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!d->key_inhibitor_manager) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -2990,6 +3003,22 @@ int Wayland_input_ungrab_keyboard(SDL_Window *window)
|
|||
{
|
||||
SDL_WindowData *w = window->driverdata;
|
||||
|
||||
/* Layer-shell windows have exclusive grab baked in */
|
||||
if (w->shell_surface_type == WAYLAND_SURFACE_LAYER) {
|
||||
if (w->shell_surface.layer.surface != NULL) {
|
||||
if (zwlr_layer_surface_v1_get_version(w->shell_surface.layer.surface) >= 4) {
|
||||
w->shell_surface.layer.kbi = WAYLAND_LAYER_KBI_ON_DEMAND;
|
||||
} else {
|
||||
w->shell_surface.layer.kbi = WAYLAND_LAYER_KBI_NONE;
|
||||
}
|
||||
zwlr_layer_surface_v1_set_keyboard_interactivity(w->shell_surface.layer.surface,
|
||||
w->shell_surface.layer.kbi);
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (w->key_inhibitor) {
|
||||
zwp_keyboard_shortcuts_inhibitor_v1_destroy(w->key_inhibitor);
|
||||
w->key_inhibitor = NULL;
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "primary-selection-unstable-v1-client-protocol.h"
|
||||
#include "fractional-scale-v1-client-protocol.h"
|
||||
#include "input-timestamps-unstable-v1-client-protocol.h"
|
||||
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
#include <libdecor.h>
|
||||
|
@ -241,6 +242,7 @@ static SDL_VideoDevice *Wayland_CreateDevice(void)
|
|||
device->SetWindowSize = Wayland_SetWindowSize;
|
||||
device->SetWindowMinimumSize = Wayland_SetWindowMinimumSize;
|
||||
device->SetWindowMaximumSize = Wayland_SetWindowMaximumSize;
|
||||
device->SetWindowPosition = Wayland_SetWindowPosition;
|
||||
device->SetWindowModalFor = Wayland_SetWindowModalFor;
|
||||
device->SetWindowTitle = Wayland_SetWindowTitle;
|
||||
device->GetWindowSizeInPixels = Wayland_GetWindowSizeInPixels;
|
||||
|
@ -851,6 +853,8 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint
|
|||
&qt_windowmanager_interface, 1);
|
||||
qt_windowmanager_add_listener(d->windowmanager, &windowmanager_listener, d);
|
||||
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
|
||||
} else if (SDL_strcmp(interface, "zwlr_layer_shell_v1") == 0) {
|
||||
d->shell.layer = wl_registry_bind(d->registry, id, &zwlr_layer_shell_v1_interface, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1089,6 +1093,11 @@ static void Wayland_VideoCleanup(_THIS)
|
|||
data->input_timestamps_manager = NULL;
|
||||
}
|
||||
|
||||
if (data->shell.layer) {
|
||||
zwlr_layer_shell_v1_destroy(data->shell.layer);
|
||||
data->shell.layer = NULL;
|
||||
}
|
||||
|
||||
if (data->compositor) {
|
||||
wl_compositor_destroy(data->compositor);
|
||||
data->compositor = NULL;
|
||||
|
|
|
@ -64,6 +64,7 @@ struct SDL_VideoData
|
|||
#ifdef HAVE_LIBDECOR_H
|
||||
struct libdecor *libdecor;
|
||||
#endif
|
||||
struct zwlr_layer_shell_v1 *layer;
|
||||
} shell;
|
||||
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
|
||||
struct zwp_pointer_constraints_v1 *pointer_constraints;
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "xdg-activation-v1-client-protocol.h"
|
||||
#include "viewporter-client-protocol.h"
|
||||
#include "fractional-scale-v1-client-protocol.h"
|
||||
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
#include <libdecor.h>
|
||||
|
@ -220,9 +221,13 @@ static void ConfigureWindowGeometry(SDL_Window *window)
|
|||
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 &&
|
||||
viddata->shell.xdg && data->shell_surface.xdg.surface != NULL) {
|
||||
if (((data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) ||
|
||||
(data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP)) &&
|
||||
(data->shell_surface.xdg.surface != NULL)) {
|
||||
xdg_surface_set_window_geometry(data->shell_surface.xdg.surface, 0, 0, data->wl_window_width, data->wl_window_height);
|
||||
} else if ((data->shell_surface_type == WAYLAND_SURFACE_LAYER) &&
|
||||
(data->shell_surface.layer.surface != NULL)) {
|
||||
zwlr_layer_surface_v1_set_size(data->shell_surface.layer.surface, data->wl_window_width, data->wl_window_height);
|
||||
}
|
||||
|
||||
if (!viddata->egl_transparency_enabled) {
|
||||
|
@ -243,6 +248,49 @@ static void ConfigureWindowGeometry(SDL_Window *window)
|
|||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED, data->drawable_width, data->drawable_height);
|
||||
}
|
||||
|
||||
static void ConfigureWindowLayerPosition(SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
|
||||
/* Set layer-shell surface anchors and margins */
|
||||
data->shell_surface.layer.anchor = WAYLAND_LAYER_ANCHOR_NONE;
|
||||
data->shell_surface.layer.margin.top = 0;
|
||||
data->shell_surface.layer.margin.bottom = 0;
|
||||
data->shell_surface.layer.margin.left = 0;
|
||||
data->shell_surface.layer.margin.right = 0;
|
||||
if (window->x == SDL_WINDOWPOS_UNDEFINED) {
|
||||
;/* continue */
|
||||
} else if (window->x > 0) {
|
||||
data->shell_surface.layer.anchor |= WAYLAND_LAYER_ANCHOR_LEFT;
|
||||
data->shell_surface.layer.margin.left = (window->x - 1);
|
||||
} else if (window->x < 0) {
|
||||
data->shell_surface.layer.anchor |= WAYLAND_LAYER_ANCHOR_RIGHT;
|
||||
data->shell_surface.layer.margin.right = SDL_abs(window->x + 1);
|
||||
} else { /* 0 */
|
||||
data->shell_surface.layer.anchor |= (WAYLAND_LAYER_ANCHOR_LEFT | WAYLAND_LAYER_ANCHOR_RIGHT);
|
||||
}
|
||||
|
||||
if (window->y == SDL_WINDOWPOS_UNDEFINED) {
|
||||
;/* continue */
|
||||
} else if (window->y > 0) {
|
||||
data->shell_surface.layer.anchor |= WAYLAND_LAYER_ANCHOR_TOP;
|
||||
data->shell_surface.layer.margin.top = (window->y - 1);
|
||||
} else if (window->y < 0) {
|
||||
data->shell_surface.layer.anchor |= WAYLAND_LAYER_ANCHOR_BOTTOM;
|
||||
data->shell_surface.layer.margin.bottom = SDL_abs(window->y + 1);
|
||||
} else { /* 0 */
|
||||
data->shell_surface.layer.anchor |= (WAYLAND_LAYER_ANCHOR_TOP | WAYLAND_LAYER_ANCHOR_BOTTOM);
|
||||
}
|
||||
|
||||
zwlr_layer_surface_v1_set_anchor(data->shell_surface.layer.surface,
|
||||
data->shell_surface.layer.anchor);
|
||||
zwlr_layer_surface_v1_set_margin(data->shell_surface.layer.surface,
|
||||
data->shell_surface.layer.margin.top,
|
||||
data->shell_surface.layer.margin.right,
|
||||
data->shell_surface.layer.margin.bottom,
|
||||
data->shell_surface.layer.margin.left);
|
||||
}
|
||||
|
||||
static void CommitLibdecorFrame(SDL_Window *window)
|
||||
{
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
|
@ -263,7 +311,8 @@ static void SetMinMaxDimensions(SDL_Window *window, SDL_bool commit)
|
|||
int min_width, min_height, max_width, max_height;
|
||||
|
||||
/* Pop-ups don't get to change size */
|
||||
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) {
|
||||
if ((wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) ||
|
||||
(wind->shell_surface_type == WAYLAND_SURFACE_LAYER)) {
|
||||
/* ... but we still want to commit, particularly for ShowWindow */
|
||||
if (commit) {
|
||||
wl_surface_commit(wind->surface);
|
||||
|
@ -405,6 +454,29 @@ static void UpdateWindowFullscreen(SDL_Window *window, SDL_bool fullscreen)
|
|||
}
|
||||
}
|
||||
|
||||
static int SetLayerShellSurface(SDL_WindowData *wind, const char *hint)
|
||||
{
|
||||
if (SDL_strcasecmp(hint, "background") == 0) {
|
||||
wind->shell_surface.layer.layer = WAYLAND_LAYER_BACKGROUND;
|
||||
} else if (SDL_strcasecmp(hint, "bottom") == 0) {
|
||||
wind->shell_surface.layer.layer = WAYLAND_LAYER_BOTTOM;
|
||||
} else if (SDL_strcasecmp(hint, "top") == 0) {
|
||||
wind->shell_surface.layer.layer = WAYLAND_LAYER_TOP;
|
||||
} else if (SDL_strcasecmp(hint, "overlay") == 0) {
|
||||
wind->shell_surface.layer.layer = WAYLAND_LAYER_OVERLAY;
|
||||
} else {
|
||||
return SDL_SetError("Wayland layer-shell hint expects layer enumeration");
|
||||
}
|
||||
|
||||
hint = SDL_GetHint(SDL_HINT_VIDEO_WAYLAND_SHELL_EXCL);
|
||||
if (hint) {
|
||||
wind->shell_surface.layer.excl_zone = SDL_atoi(hint);
|
||||
}
|
||||
|
||||
wind->shell_surface.layer.kbi = WAYLAND_LAYER_KBI_ON_DEMAND;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener surface_damage_frame_listener;
|
||||
|
||||
static void surface_damage_frame_done(void *data, struct wl_callback *cb, uint32_t time)
|
||||
|
@ -667,6 +739,56 @@ static const struct zxdg_toplevel_decoration_v1_listener decoration_listener = {
|
|||
handle_configure_zxdg_decoration
|
||||
};
|
||||
|
||||
static void handle_configure_layer_shell_surface(void *data,
|
||||
struct zwlr_layer_surface_v1 *zwlr_layer_surface_v1,
|
||||
uint32_t serial,
|
||||
uint32_t width,
|
||||
uint32_t height)
|
||||
{
|
||||
SDL_WindowData *wind = (SDL_WindowData *)data;
|
||||
SDL_Window *window = wind->sdlwindow;
|
||||
|
||||
/* Toss up a focus event, even though layer may not be focused */
|
||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_FOCUS_GAINED, 0, 0);
|
||||
|
||||
/* When not maximized, shrink to fixed size */
|
||||
if (!(window->flags & SDL_WINDOW_MAXIMIZED)) {
|
||||
/* Respect min/max window size contraints */
|
||||
if (window->max_w > 0) {
|
||||
width = SDL_min(width, window->max_w);
|
||||
}
|
||||
width = SDL_max(width, window->min_w);
|
||||
width = SDL_min(width, window->windowed.w);
|
||||
|
||||
if (window->max_h > 0) {
|
||||
height = SDL_min(height, window->max_h);
|
||||
}
|
||||
height = SDL_max(height, window->min_h);
|
||||
height = SDL_min(height, window->windowed.h);
|
||||
}
|
||||
|
||||
wind->floating = TRUE;
|
||||
wind->floating_width = width;
|
||||
wind->floating_height = height;
|
||||
wind->requested_window_width = width;
|
||||
wind->requested_window_height = height;
|
||||
|
||||
ConfigureWindowGeometry(window);
|
||||
zwlr_layer_surface_v1_ack_configure(zwlr_layer_surface_v1, serial);
|
||||
wind->shell_surface.layer.initial_configure_seen = SDL_TRUE;
|
||||
}
|
||||
|
||||
static void handle_closed_layer_shell_surface(void *data, struct zwlr_layer_surface_v1 *zwlr_layer_surface_v1)
|
||||
{
|
||||
SDL_WindowData *window = (SDL_WindowData *)data;
|
||||
SDL_SendWindowEvent(window->sdlwindow, SDL_EVENT_WINDOW_CLOSE_REQUESTED, 0, 0);
|
||||
}
|
||||
|
||||
static const struct zwlr_layer_surface_v1_listener shell_surface_listener_layer = {
|
||||
handle_configure_layer_shell_surface,
|
||||
handle_closed_layer_shell_surface,
|
||||
};
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
/*
|
||||
* XXX: Hack for older versions of libdecor that lack the function to query the
|
||||
|
@ -1028,7 +1150,6 @@ static const struct wl_surface_listener surface_listener = {
|
|||
|
||||
int Wayland_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *info)
|
||||
{
|
||||
SDL_VideoData *viddata = _this->driverdata;
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
|
||||
info->subsystem = SDL_SYSWM_WAYLAND;
|
||||
|
@ -1044,7 +1165,9 @@ int Wayland_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *info)
|
|||
}
|
||||
} else
|
||||
#endif
|
||||
if (viddata->shell.xdg && data->shell_surface.xdg.surface != NULL) {
|
||||
if (((data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) ||
|
||||
(data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP)) &&
|
||||
(data->shell_surface.xdg.surface != NULL)) {
|
||||
SDL_bool popup = (data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) ? SDL_TRUE : SDL_FALSE;
|
||||
info->info.wl.xdg_surface = data->shell_surface.xdg.surface;
|
||||
info->info.wl.xdg_toplevel = popup ? NULL : data->shell_surface.xdg.roleobj.toplevel;
|
||||
|
@ -1068,8 +1191,11 @@ int Wayland_SetWindowModalFor(_THIS, SDL_Window *modal_window, SDL_Window *paren
|
|||
SDL_WindowData *modal_data = modal_window->driverdata;
|
||||
SDL_WindowData *parent_data = parent_window->driverdata;
|
||||
|
||||
if (modal_data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP || parent_data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) {
|
||||
return SDL_SetError("Modal/Parent was a popup, not a toplevel");
|
||||
if ((modal_data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) ||
|
||||
(parent_data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) ||
|
||||
(modal_data->shell_surface_type == WAYLAND_SURFACE_LAYER) ||
|
||||
(parent_data->shell_surface_type == WAYLAND_SURFACE_LAYER)) {
|
||||
return SDL_SetError("Modal/Parent not a toplevel");
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
|
@ -1144,7 +1270,8 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
|
|||
}
|
||||
} else
|
||||
#endif
|
||||
if (c->shell.xdg) {
|
||||
if ((data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) ||
|
||||
(data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP)) {
|
||||
data->shell_surface.xdg.surface = xdg_wm_base_get_xdg_surface(c->shell.xdg, data->surface);
|
||||
xdg_surface_set_user_data(data->shell_surface.xdg.surface, data);
|
||||
xdg_surface_add_listener(data->shell_surface.xdg.surface, &shell_surface_listener_xdg, data);
|
||||
|
@ -1174,6 +1301,12 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
|
|||
data->shell_surface.xdg.roleobj.popup.positioner);
|
||||
xdg_popup_add_listener(data->shell_surface.xdg.roleobj.popup.popup, &popup_listener_xdg, data);
|
||||
|
||||
/* Properly parent pop-up if parent is a layer-shell surface */
|
||||
if (focuseddata->shell_surface_type == WAYLAND_SURFACE_LAYER) {
|
||||
zwlr_layer_surface_v1_get_popup(focuseddata->shell_surface.layer.surface,
|
||||
data->shell_surface.xdg.roleobj.popup.popup);
|
||||
}
|
||||
|
||||
/* For tooltips, track mouse motion so it follows the cursor */
|
||||
if (window->flags & SDL_WINDOW_TOOLTIP) {
|
||||
if (xdg_popup_get_version(data->shell_surface.xdg.roleobj.popup.popup) >= 3) {
|
||||
|
@ -1185,6 +1318,17 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
|
|||
xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, c->classname);
|
||||
xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data);
|
||||
}
|
||||
} else if (data->shell_surface_type == WAYLAND_SURFACE_LAYER) {
|
||||
data->shell_surface.layer.surface = zwlr_layer_shell_v1_get_layer_surface(c->shell.layer,
|
||||
data->surface,
|
||||
NULL,
|
||||
data->shell_surface.layer.layer,
|
||||
window->title ? window->title : "");
|
||||
zwlr_layer_surface_v1_set_user_data(data->shell_surface.layer.surface, data);
|
||||
zwlr_layer_surface_v1_add_listener(data->shell_surface.layer.surface, &shell_surface_listener_layer, data);
|
||||
|
||||
/* Restore anchor/margin position */
|
||||
ConfigureWindowLayerPosition(window);
|
||||
}
|
||||
|
||||
/* Restore state that was set prior to this call */
|
||||
|
@ -1209,7 +1353,8 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
|
|||
}
|
||||
} else
|
||||
#endif
|
||||
if (c->shell.xdg) {
|
||||
if ((data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) ||
|
||||
(data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP)) {
|
||||
/* Unlike libdecor we need to call this explicitly to prevent a deadlock.
|
||||
* libdecor will call this as part of their configure event!
|
||||
* -flibit
|
||||
|
@ -1232,6 +1377,38 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
|
|||
|
||||
/* Set the geometry */
|
||||
xdg_surface_set_window_geometry(data->shell_surface.xdg.surface, 0, 0, data->wl_window_width, data->wl_window_height);
|
||||
} else if (data->shell_surface_type == WAYLAND_SURFACE_LAYER) {
|
||||
/* Restore size */
|
||||
if (!(window->flags & SDL_WINDOW_MAXIMIZED)) {
|
||||
/* Strangely layer-shell surface initial values conflict with each
|
||||
* other (namely, size=0 and anchor=0 is invalid), so if not
|
||||
* maximized set an initial size here to keep from having a protocol
|
||||
* error.
|
||||
*/
|
||||
zwlr_layer_surface_v1_set_size(data->shell_surface.layer.surface, data->wl_window_width, data->wl_window_height);
|
||||
}
|
||||
|
||||
/* Restore exclusive zone */
|
||||
if (data->shell_surface.layer.excl_zone) {
|
||||
zwlr_layer_surface_v1_set_exclusive_zone(data->shell_surface.layer.surface, data->shell_surface.layer.excl_zone);
|
||||
}
|
||||
|
||||
/* Restore keyboard-interactivity */
|
||||
if (zwlr_layer_surface_v1_get_version(data->shell_surface.layer.surface) < 4) {
|
||||
data->shell_surface.layer.kbi = WAYLAND_LAYER_KBI_NONE;
|
||||
}
|
||||
if (data->shell_surface.layer.kbi != WAYLAND_LAYER_KBI_NONE) {
|
||||
zwlr_layer_surface_v1_set_keyboard_interactivity(data->shell_surface.layer.surface, data->shell_surface.layer.kbi);
|
||||
}
|
||||
|
||||
/* Same as XDG windows, wait for first 'configure' event */
|
||||
wl_surface_commit(data->surface);
|
||||
if (data->shell_surface.layer.surface) {
|
||||
while (!data->shell_surface.layer.initial_configure_seen) {
|
||||
WAYLAND_wl_display_flush(c->display);
|
||||
WAYLAND_wl_display_dispatch(c->display);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Nothing to see here, just commit. */
|
||||
wl_surface_commit(data->surface);
|
||||
|
@ -1270,7 +1447,8 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
|
|||
}
|
||||
|
||||
/* We're finally done putting the window together, raise if possible */
|
||||
if (c->activation_manager) {
|
||||
if ((c->activation_manager) &&
|
||||
(data->shell_surface_type != WAYLAND_SURFACE_LAYER)) {
|
||||
/* Note that we don't check for empty strings, as that is still
|
||||
* considered a valid activation token!
|
||||
*/
|
||||
|
@ -1349,7 +1527,8 @@ void Wayland_HideWindow(_THIS, SDL_Window *window)
|
|||
}
|
||||
} else
|
||||
#endif
|
||||
if (data->shell.xdg) {
|
||||
if ((wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) ||
|
||||
(wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP)) {
|
||||
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) {
|
||||
Wayland_ReleasePopup(_this, window);
|
||||
} else if (wind->shell_surface.xdg.roleobj.toplevel) {
|
||||
|
@ -1360,6 +1539,11 @@ void Wayland_HideWindow(_THIS, SDL_Window *window)
|
|||
xdg_surface_destroy(wind->shell_surface.xdg.surface);
|
||||
wind->shell_surface.xdg.surface = NULL;
|
||||
}
|
||||
} else if (wind->shell_surface_type == WAYLAND_SURFACE_LAYER) {
|
||||
if (wind->shell_surface.layer.surface) {
|
||||
zwlr_layer_surface_v1_destroy(wind->shell_surface.layer.surface);
|
||||
}
|
||||
wind->shell_surface.layer.surface = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1411,6 +1595,11 @@ static void Wayland_activate_window(SDL_VideoData *data, SDL_WindowData *wind,
|
|||
struct wl_surface *surface,
|
||||
uint32_t serial, struct wl_seat *seat)
|
||||
{
|
||||
/* Layer-shell windows are 'always' active */
|
||||
if (wind->shell_surface_type == WAYLAND_SURFACE_LAYER) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->activation_manager) {
|
||||
if (wind->activation_token != NULL) {
|
||||
/* We're about to overwrite this with a new request */
|
||||
|
@ -1580,8 +1769,10 @@ void Wayland_SetWindowFullscreen(_THIS, SDL_Window *window,
|
|||
SDL_WindowData *wind = window->driverdata;
|
||||
struct wl_output *output = display->driverdata->output;
|
||||
|
||||
/* Called from within a configure event or the window is a popup, drop it. */
|
||||
if (wind->in_fullscreen_transition || wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) {
|
||||
/* Called from within a configure event or the window is a layer or popup, drop it. */
|
||||
if (wind->in_fullscreen_transition ||
|
||||
(wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) ||
|
||||
(wind->shell_surface_type == WAYLAND_SURFACE_LAYER)) {
|
||||
if (!fullscreen) {
|
||||
/* Clear the display ID so it will be set next time. */
|
||||
wind->fullscreen_display = 0;
|
||||
|
@ -1638,13 +1829,22 @@ void Wayland_RestoreWindow(_THIS, SDL_Window *window)
|
|||
libdecor_frame_unset_maximized(wind->shell_surface.libdecor.frame);
|
||||
} else
|
||||
#endif
|
||||
/* Note that xdg-shell does NOT provide a way to unset minimize! */
|
||||
if (viddata->shell.xdg) {
|
||||
if (wind->shell_surface.xdg.roleobj.toplevel == NULL) {
|
||||
return; /* Can't do anything yet, wait for ShowWindow */
|
||||
}
|
||||
xdg_toplevel_unset_maximized(wind->shell_surface.xdg.roleobj.toplevel);
|
||||
/* Note that xdg-shell does NOT provide a way to unset minimize! */
|
||||
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) {
|
||||
if (wind->shell_surface.xdg.roleobj.toplevel == NULL) {
|
||||
return; /* Can't do anything yet, wait for ShowWindow */
|
||||
}
|
||||
xdg_toplevel_unset_maximized(wind->shell_surface.xdg.roleobj.toplevel);
|
||||
} else if (wind->shell_surface_type == WAYLAND_SURFACE_LAYER) {
|
||||
if (wind->shell_surface.layer.surface == NULL) {
|
||||
return; /* Can't do anything yet, wait for ShowWindow */
|
||||
}
|
||||
|
||||
/* Note anchors that may have been added to maximize are not removed */
|
||||
zwlr_layer_surface_v1_set_size(wind->shell_surface.layer.surface,
|
||||
window->w,
|
||||
window->h);
|
||||
}
|
||||
|
||||
WAYLAND_wl_display_roundtrip(viddata->display);
|
||||
}
|
||||
|
@ -1654,7 +1854,8 @@ void Wayland_SetWindowBordered(_THIS, SDL_Window *window, SDL_bool bordered)
|
|||
SDL_WindowData *wind = window->driverdata;
|
||||
const SDL_VideoData *viddata = (const SDL_VideoData *)_this->driverdata;
|
||||
|
||||
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) {
|
||||
if ((wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) ||
|
||||
(wind->shell_surface_type == WAYLAND_SURFACE_LAYER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1696,12 +1897,15 @@ void Wayland_MaximizeWindow(_THIS, SDL_Window *window)
|
|||
{
|
||||
SDL_VideoData *viddata = _this->driverdata;
|
||||
SDL_WindowData *wind = window->driverdata;
|
||||
unsigned int layer_width;
|
||||
unsigned int layer_height;
|
||||
|
||||
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
|
||||
if ((!(window->flags & SDL_WINDOW_RESIZABLE)) &&
|
||||
(wind->shell_surface_type != WAYLAND_SURFACE_LAYER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1718,11 +1922,54 @@ void Wayland_MaximizeWindow(_THIS, SDL_Window *window)
|
|||
libdecor_frame_set_maximized(wind->shell_surface.libdecor.frame);
|
||||
} else
|
||||
#endif
|
||||
if (viddata->shell.xdg) {
|
||||
if ((wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) &&
|
||||
(viddata->shell.xdg)) {
|
||||
if (wind->shell_surface.xdg.roleobj.toplevel == NULL) {
|
||||
return; /* Can't do anything yet, wait for ShowWindow */
|
||||
}
|
||||
xdg_toplevel_set_maximized(wind->shell_surface.xdg.roleobj.toplevel);
|
||||
} else if (wind->shell_surface_type == WAYLAND_SURFACE_LAYER) {
|
||||
if (wind->shell_surface.layer.surface == NULL) {
|
||||
return; /* Can't do anything yet, wait for ShowWindow */
|
||||
}
|
||||
|
||||
/* At least two opposing edges must be anchored to maximize */
|
||||
if (wind->shell_surface.layer.anchor & (WAYLAND_LAYER_ANCHOR_TOP | WAYLAND_LAYER_ANCHOR_BOTTOM)) {
|
||||
if (!((wind->shell_surface.layer.anchor & WAYLAND_LAYER_ANCHOR_LEFT) &&
|
||||
(wind->shell_surface.layer.anchor & WAYLAND_LAYER_ANCHOR_RIGHT))) {
|
||||
wind->shell_surface.layer.anchor |= WAYLAND_LAYER_ANCHOR_TOP |
|
||||
WAYLAND_LAYER_ANCHOR_BOTTOM;
|
||||
}
|
||||
} else if (wind->shell_surface.layer.anchor & (WAYLAND_LAYER_ANCHOR_LEFT | WAYLAND_LAYER_ANCHOR_RIGHT)) {
|
||||
if (!((wind->shell_surface.layer.anchor & WAYLAND_LAYER_ANCHOR_TOP) &&
|
||||
(wind->shell_surface.layer.anchor & WAYLAND_LAYER_ANCHOR_BOTTOM))) {
|
||||
wind->shell_surface.layer.anchor |= WAYLAND_LAYER_ANCHOR_LEFT |
|
||||
WAYLAND_LAYER_ANCHOR_RIGHT;
|
||||
}
|
||||
} else {
|
||||
wind->shell_surface.layer.anchor = WAYLAND_LAYER_ANCHOR_TOP |
|
||||
WAYLAND_LAYER_ANCHOR_BOTTOM |
|
||||
WAYLAND_LAYER_ANCHOR_LEFT |
|
||||
WAYLAND_LAYER_ANCHOR_RIGHT;
|
||||
}
|
||||
|
||||
zwlr_layer_surface_v1_set_anchor(wind->shell_surface.layer.surface,
|
||||
wind->shell_surface.layer.anchor);
|
||||
|
||||
/* Maximize to anchored edges (set size to '0' according to spec) */
|
||||
if ((wind->shell_surface.layer.anchor & WAYLAND_LAYER_ANCHOR_LEFT) &&
|
||||
(wind->shell_surface.layer.anchor & WAYLAND_LAYER_ANCHOR_RIGHT)) {
|
||||
layer_width = 0;
|
||||
} else {
|
||||
layer_width = window->w;
|
||||
}
|
||||
if ((wind->shell_surface.layer.anchor & WAYLAND_LAYER_ANCHOR_TOP) &&
|
||||
(wind->shell_surface.layer.anchor & WAYLAND_LAYER_ANCHOR_BOTTOM)) {
|
||||
layer_height = 0;
|
||||
} else {
|
||||
layer_height = window->h;
|
||||
}
|
||||
zwlr_layer_surface_v1_set_size(wind->shell_surface.layer.surface, layer_width, layer_height);
|
||||
}
|
||||
|
||||
WAYLAND_wl_display_roundtrip(viddata->display);
|
||||
|
@ -1733,7 +1980,8 @@ void Wayland_MinimizeWindow(_THIS, SDL_Window *window)
|
|||
SDL_VideoData *viddata = _this->driverdata;
|
||||
SDL_WindowData *wind = window->driverdata;
|
||||
|
||||
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) {
|
||||
if ((wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) ||
|
||||
(wind->shell_surface_type == WAYLAND_SURFACE_LAYER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1800,6 +2048,7 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
|
|||
{
|
||||
SDL_WindowData *data;
|
||||
SDL_VideoData *c;
|
||||
const char *hint;
|
||||
|
||||
data = SDL_calloc(1, sizeof *data);
|
||||
if (data == NULL) {
|
||||
|
@ -1808,6 +2057,8 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
|
|||
|
||||
c = _this->driverdata;
|
||||
window->driverdata = data;
|
||||
window->x = SDL_WINDOWPOS_UNDEFINED;
|
||||
window->y = SDL_WINDOWPOS_UNDEFINED;
|
||||
|
||||
if (!(window->flags & SDL_WINDOW_VULKAN)) {
|
||||
if (!(window->flags & SDL_WINDOW_OPENGL)) {
|
||||
|
@ -1816,13 +2067,6 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
|
|||
}
|
||||
}
|
||||
|
||||
if (window->x == SDL_WINDOWPOS_UNDEFINED) {
|
||||
window->x = 0;
|
||||
}
|
||||
if (window->y == SDL_WINDOWPOS_UNDEFINED) {
|
||||
window->y = 0;
|
||||
}
|
||||
|
||||
data->waylandData = c;
|
||||
data->sdlwindow = window;
|
||||
|
||||
|
@ -1917,6 +2161,14 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
|
|||
/* We may need to create an idle inhibitor for this new window */
|
||||
Wayland_SuspendScreenSaver(_this);
|
||||
|
||||
hint = SDL_GetHint(SDL_HINT_VIDEO_WAYLAND_SHELL_LAYER);
|
||||
if ((c->shell.layer) &&
|
||||
(hint) &&
|
||||
(hint[0] != '\0')) {
|
||||
data->shell_surface_type = WAYLAND_SURFACE_LAYER;
|
||||
return SetLayerShellSurface(data, hint);
|
||||
}
|
||||
|
||||
#define IS_POPUP(window) \
|
||||
(window->flags & (SDL_WINDOW_TOOLTIP | SDL_WINDOW_POPUP_MENU))
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
|
@ -1977,13 +2229,32 @@ void Wayland_GetWindowSizeInPixels(_THIS, SDL_Window *window, int *w, int *h)
|
|||
}
|
||||
}
|
||||
|
||||
void Wayland_SetWindowPosition(_THIS, SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *wind = window->driverdata;
|
||||
SDL_VideoData *viddata = _this->driverdata;
|
||||
|
||||
if (wind->shell_surface_type == WAYLAND_SURFACE_LAYER) {
|
||||
if (wind->shell_surface.layer.surface == NULL) {
|
||||
return; /* Can't do anything yet, wait for ShowWindow */
|
||||
}
|
||||
|
||||
ConfigureWindowLayerPosition(window);
|
||||
wl_surface_commit(wind->surface);
|
||||
WAYLAND_wl_display_flush(viddata->display);
|
||||
} else {
|
||||
SDL_Unsupported();
|
||||
}
|
||||
}
|
||||
|
||||
void Wayland_SetWindowTitle(_THIS, SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *wind = window->driverdata;
|
||||
SDL_VideoData *viddata = _this->driverdata;
|
||||
const char *title = window->title ? window->title : "";
|
||||
|
||||
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) {
|
||||
if ((wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) ||
|
||||
(wind->shell_surface_type == WAYLAND_SURFACE_LAYER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,13 +68,48 @@ struct SDL_WindowData
|
|||
} roleobj;
|
||||
SDL_bool initial_configure_seen;
|
||||
} xdg;
|
||||
struct
|
||||
{
|
||||
struct zwlr_layer_surface_v1 *surface;
|
||||
int excl_zone;
|
||||
struct
|
||||
{
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
int left;
|
||||
} margin;
|
||||
enum
|
||||
{
|
||||
WAYLAND_LAYER_ANCHOR_NONE = 0,
|
||||
WAYLAND_LAYER_ANCHOR_TOP = 1U,
|
||||
WAYLAND_LAYER_ANCHOR_BOTTOM = 2U,
|
||||
WAYLAND_LAYER_ANCHOR_LEFT = 4U,
|
||||
WAYLAND_LAYER_ANCHOR_RIGHT = 8U
|
||||
} anchor;
|
||||
enum
|
||||
{
|
||||
WAYLAND_LAYER_BACKGROUND = 0,
|
||||
WAYLAND_LAYER_BOTTOM,
|
||||
WAYLAND_LAYER_TOP,
|
||||
WAYLAND_LAYER_OVERLAY
|
||||
} layer;
|
||||
enum
|
||||
{
|
||||
WAYLAND_LAYER_KBI_NONE = 0,
|
||||
WAYLAND_LAYER_KBI_EXCLUSIVE,
|
||||
WAYLAND_LAYER_KBI_ON_DEMAND
|
||||
} kbi;
|
||||
SDL_bool initial_configure_seen;
|
||||
} layer;
|
||||
} shell_surface;
|
||||
enum
|
||||
{
|
||||
WAYLAND_SURFACE_UNKNOWN = 0,
|
||||
WAYLAND_SURFACE_XDG_TOPLEVEL,
|
||||
WAYLAND_SURFACE_XDG_POPUP,
|
||||
WAYLAND_SURFACE_LIBDECOR
|
||||
WAYLAND_SURFACE_LIBDECOR,
|
||||
WAYLAND_SURFACE_LAYER
|
||||
} shell_surface_type;
|
||||
|
||||
struct wl_egl_window *egl_window;
|
||||
|
@ -133,6 +168,7 @@ extern void Wayland_SetWindowBordered(_THIS, SDL_Window *window, SDL_bool border
|
|||
extern void Wayland_SetWindowResizable(_THIS, SDL_Window *window, SDL_bool resizable);
|
||||
extern int Wayland_CreateWindow(_THIS, SDL_Window *window);
|
||||
extern void Wayland_SetWindowSize(_THIS, SDL_Window *window);
|
||||
extern void Wayland_SetWindowPosition(_THIS, SDL_Window *window);
|
||||
extern void Wayland_SetWindowMinimumSize(_THIS, SDL_Window *window);
|
||||
extern void Wayland_SetWindowMaximumSize(_THIS, SDL_Window *window);
|
||||
extern void Wayland_GetWindowSizeInPixels(_THIS, SDL_Window *window, int *w, int *h);
|
||||
|
|
390
wayland-protocols/wlr-layer-shell-unstable-v1.xml
Normal file
390
wayland-protocols/wlr-layer-shell-unstable-v1.xml
Normal file
|
@ -0,0 +1,390 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="wlr_layer_shell_unstable_v1">
|
||||
<copyright>
|
||||
Copyright © 2017 Drew DeVault
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that copyright notice and this permission
|
||||
notice appear in supporting documentation, and that the name of
|
||||
the copyright holders not be used in advertising or publicity
|
||||
pertaining to distribution of the software without specific,
|
||||
written prior permission. The copyright holders make no
|
||||
representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied
|
||||
warranty.
|
||||
|
||||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="zwlr_layer_shell_v1" version="4">
|
||||
<description summary="create surfaces that are layers of the desktop">
|
||||
Clients can use this interface to assign the surface_layer role to
|
||||
wl_surfaces. Such surfaces are assigned to a "layer" of the output and
|
||||
rendered with a defined z-depth respective to each other. They may also be
|
||||
anchored to the edges and corners of a screen and specify input handling
|
||||
semantics. This interface should be suitable for the implementation of
|
||||
many desktop shell components, and a broad number of other applications
|
||||
that interact with the desktop.
|
||||
</description>
|
||||
|
||||
<request name="get_layer_surface">
|
||||
<description summary="create a layer_surface from a surface">
|
||||
Create a layer surface for an existing surface. This assigns the role of
|
||||
layer_surface, or raises a protocol error if another role is already
|
||||
assigned.
|
||||
|
||||
Creating a layer surface from a wl_surface which has a buffer attached
|
||||
or committed is a client error, and any attempts by a client to attach
|
||||
or manipulate a buffer prior to the first layer_surface.configure call
|
||||
must also be treated as errors.
|
||||
|
||||
After creating a layer_surface object and setting it up, the client
|
||||
must perform an initial commit without any buffer attached.
|
||||
The compositor will reply with a layer_surface.configure event.
|
||||
The client must acknowledge it and is then allowed to attach a buffer
|
||||
to map the surface.
|
||||
|
||||
You may pass NULL for output to allow the compositor to decide which
|
||||
output to use. Generally this will be the one that the user most
|
||||
recently interacted with.
|
||||
|
||||
Clients can specify a namespace that defines the purpose of the layer
|
||||
surface.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwlr_layer_surface_v1"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
|
||||
<arg name="layer" type="uint" enum="layer" summary="layer to add this surface to"/>
|
||||
<arg name="namespace" type="string" summary="namespace for the layer surface"/>
|
||||
</request>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="role" value="0" summary="wl_surface has another role"/>
|
||||
<entry name="invalid_layer" value="1" summary="layer value is invalid"/>
|
||||
<entry name="already_constructed" value="2" summary="wl_surface has a buffer attached or committed"/>
|
||||
</enum>
|
||||
|
||||
<enum name="layer">
|
||||
<description summary="available layers for surfaces">
|
||||
These values indicate which layers a surface can be rendered in. They
|
||||
are ordered by z depth, bottom-most first. Traditional shell surfaces
|
||||
will typically be rendered between the bottom and top layers.
|
||||
Fullscreen shell surfaces are typically rendered at the top layer.
|
||||
Multiple surfaces can share a single layer, and ordering within a
|
||||
single layer is undefined.
|
||||
</description>
|
||||
|
||||
<entry name="background" value="0"/>
|
||||
<entry name="bottom" value="1"/>
|
||||
<entry name="top" value="2"/>
|
||||
<entry name="overlay" value="3"/>
|
||||
</enum>
|
||||
|
||||
<!-- Version 3 additions -->
|
||||
|
||||
<request name="destroy" type="destructor" since="3">
|
||||
<description summary="destroy the layer_shell object">
|
||||
This request indicates that the client will not use the layer_shell
|
||||
object any more. Objects that have been created through this instance
|
||||
are not affected.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="zwlr_layer_surface_v1" version="4">
|
||||
<description summary="layer metadata interface">
|
||||
An interface that may be implemented by a wl_surface, for surfaces that
|
||||
are designed to be rendered as a layer of a stacked desktop-like
|
||||
environment.
|
||||
|
||||
Layer surface state (layer, size, anchor, exclusive zone,
|
||||
margin, interactivity) is double-buffered, and will be applied at the
|
||||
time wl_surface.commit of the corresponding wl_surface is called.
|
||||
|
||||
Attaching a null buffer to a layer surface unmaps it.
|
||||
|
||||
Unmapping a layer_surface means that the surface cannot be shown by the
|
||||
compositor until it is explicitly mapped again. The layer_surface
|
||||
returns to the state it had right after layer_shell.get_layer_surface.
|
||||
The client can re-map the surface by performing a commit without any
|
||||
buffer attached, waiting for a configure event and handling it as usual.
|
||||
</description>
|
||||
|
||||
<request name="set_size">
|
||||
<description summary="sets the size of the surface">
|
||||
Sets the size of the surface in surface-local coordinates. The
|
||||
compositor will display the surface centered with respect to its
|
||||
anchors.
|
||||
|
||||
If you pass 0 for either value, the compositor will assign it and
|
||||
inform you of the assignment in the configure event. You must set your
|
||||
anchor to opposite edges in the dimensions you omit; not doing so is a
|
||||
protocol error. Both values are 0 by default.
|
||||
|
||||
Size is double-buffered, see wl_surface.commit.
|
||||
</description>
|
||||
<arg name="width" type="uint"/>
|
||||
<arg name="height" type="uint"/>
|
||||
</request>
|
||||
|
||||
<request name="set_anchor">
|
||||
<description summary="configures the anchor point of the surface">
|
||||
Requests that the compositor anchor the surface to the specified edges
|
||||
and corners. If two orthogonal edges are specified (e.g. 'top' and
|
||||
'left'), then the anchor point will be the intersection of the edges
|
||||
(e.g. the top left corner of the output); otherwise the anchor point
|
||||
will be centered on that edge, or in the center if none is specified.
|
||||
|
||||
Anchor is double-buffered, see wl_surface.commit.
|
||||
</description>
|
||||
<arg name="anchor" type="uint" enum="anchor"/>
|
||||
</request>
|
||||
|
||||
<request name="set_exclusive_zone">
|
||||
<description summary="configures the exclusive geometry of this surface">
|
||||
Requests that the compositor avoids occluding an area with other
|
||||
surfaces. The compositor's use of this information is
|
||||
implementation-dependent - do not assume that this region will not
|
||||
actually be occluded.
|
||||
|
||||
A positive value is only meaningful if the surface is anchored to one
|
||||
edge or an edge and both perpendicular edges. If the surface is not
|
||||
anchored, anchored to only two perpendicular edges (a corner), anchored
|
||||
to only two parallel edges or anchored to all edges, a positive value
|
||||
will be treated the same as zero.
|
||||
|
||||
A positive zone is the distance from the edge in surface-local
|
||||
coordinates to consider exclusive.
|
||||
|
||||
Surfaces that do not wish to have an exclusive zone may instead specify
|
||||
how they should interact with surfaces that do. If set to zero, the
|
||||
surface indicates that it would like to be moved to avoid occluding
|
||||
surfaces with a positive exclusive zone. If set to -1, the surface
|
||||
indicates that it would not like to be moved to accommodate for other
|
||||
surfaces, and the compositor should extend it all the way to the edges
|
||||
it is anchored to.
|
||||
|
||||
For example, a panel might set its exclusive zone to 10, so that
|
||||
maximized shell surfaces are not shown on top of it. A notification
|
||||
might set its exclusive zone to 0, so that it is moved to avoid
|
||||
occluding the panel, but shell surfaces are shown underneath it. A
|
||||
wallpaper or lock screen might set their exclusive zone to -1, so that
|
||||
they stretch below or over the panel.
|
||||
|
||||
The default value is 0.
|
||||
|
||||
Exclusive zone is double-buffered, see wl_surface.commit.
|
||||
</description>
|
||||
<arg name="zone" type="int"/>
|
||||
</request>
|
||||
|
||||
<request name="set_margin">
|
||||
<description summary="sets a margin from the anchor point">
|
||||
Requests that the surface be placed some distance away from the anchor
|
||||
point on the output, in surface-local coordinates. Setting this value
|
||||
for edges you are not anchored to has no effect.
|
||||
|
||||
The exclusive zone includes the margin.
|
||||
|
||||
Margin is double-buffered, see wl_surface.commit.
|
||||
</description>
|
||||
<arg name="top" type="int"/>
|
||||
<arg name="right" type="int"/>
|
||||
<arg name="bottom" type="int"/>
|
||||
<arg name="left" type="int"/>
|
||||
</request>
|
||||
|
||||
<enum name="keyboard_interactivity">
|
||||
<description summary="types of keyboard interaction possible for a layer shell surface">
|
||||
Types of keyboard interaction possible for layer shell surfaces. The
|
||||
rationale for this is twofold: (1) some applications are not interested
|
||||
in keyboard events and not allowing them to be focused can improve the
|
||||
desktop experience; (2) some applications will want to take exclusive
|
||||
keyboard focus.
|
||||
</description>
|
||||
|
||||
<entry name="none" value="0">
|
||||
<description summary="no keyboard focus is possible">
|
||||
This value indicates that this surface is not interested in keyboard
|
||||
events and the compositor should never assign it the keyboard focus.
|
||||
|
||||
This is the default value, set for newly created layer shell surfaces.
|
||||
|
||||
This is useful for e.g. desktop widgets that display information or
|
||||
only have interaction with non-keyboard input devices.
|
||||
</description>
|
||||
</entry>
|
||||
<entry name="exclusive" value="1">
|
||||
<description summary="request exclusive keyboard focus">
|
||||
Request exclusive keyboard focus if this surface is above the shell surface layer.
|
||||
|
||||
For the top and overlay layers, the seat will always give
|
||||
exclusive keyboard focus to the top-most layer which has keyboard
|
||||
interactivity set to exclusive. If this layer contains multiple
|
||||
surfaces with keyboard interactivity set to exclusive, the compositor
|
||||
determines the one receiving keyboard events in an implementation-
|
||||
defined manner. In this case, no guarantee is made when this surface
|
||||
will receive keyboard focus (if ever).
|
||||
|
||||
For the bottom and background layers, the compositor is allowed to use
|
||||
normal focus semantics.
|
||||
|
||||
This setting is mainly intended for applications that need to ensure
|
||||
they receive all keyboard events, such as a lock screen or a password
|
||||
prompt.
|
||||
</description>
|
||||
</entry>
|
||||
<entry name="on_demand" value="2" since="4">
|
||||
<description summary="request regular keyboard focus semantics">
|
||||
This requests the compositor to allow this surface to be focused and
|
||||
unfocused by the user in an implementation-defined manner. The user
|
||||
should be able to unfocus this surface even regardless of the layer
|
||||
it is on.
|
||||
|
||||
Typically, the compositor will want to use its normal mechanism to
|
||||
manage keyboard focus between layer shell surfaces with this setting
|
||||
and regular toplevels on the desktop layer (e.g. click to focus).
|
||||
Nevertheless, it is possible for a compositor to require a special
|
||||
interaction to focus or unfocus layer shell surfaces (e.g. requiring
|
||||
a click even if focus follows the mouse normally, or providing a
|
||||
keybinding to switch focus between layers).
|
||||
|
||||
This setting is mainly intended for desktop shell components (e.g.
|
||||
panels) that allow keyboard interaction. Using this option can allow
|
||||
implementing a desktop shell that can be fully usable without the
|
||||
mouse.
|
||||
</description>
|
||||
</entry>
|
||||
</enum>
|
||||
|
||||
<request name="set_keyboard_interactivity">
|
||||
<description summary="requests keyboard events">
|
||||
Set how keyboard events are delivered to this surface. By default,
|
||||
layer shell surfaces do not receive keyboard events; this request can
|
||||
be used to change this.
|
||||
|
||||
This setting is inherited by child surfaces set by the get_popup
|
||||
request.
|
||||
|
||||
Layer surfaces receive pointer, touch, and tablet events normally. If
|
||||
you do not want to receive them, set the input region on your surface
|
||||
to an empty region.
|
||||
|
||||
Keyboard interactivity is double-buffered, see wl_surface.commit.
|
||||
</description>
|
||||
<arg name="keyboard_interactivity" type="uint" enum="keyboard_interactivity"/>
|
||||
</request>
|
||||
|
||||
<request name="get_popup">
|
||||
<description summary="assign this layer_surface as an xdg_popup parent">
|
||||
This assigns an xdg_popup's parent to this layer_surface. This popup
|
||||
should have been created via xdg_surface::get_popup with the parent set
|
||||
to NULL, and this request must be invoked before committing the popup's
|
||||
initial state.
|
||||
|
||||
See the documentation of xdg_popup for more details about what an
|
||||
xdg_popup is and how it is used.
|
||||
</description>
|
||||
<arg name="popup" type="object" interface="xdg_popup"/>
|
||||
</request>
|
||||
|
||||
<request name="ack_configure">
|
||||
<description summary="ack a configure event">
|
||||
When a configure event is received, if a client commits the
|
||||
surface in response to the configure event, then the client
|
||||
must make an ack_configure request sometime before the commit
|
||||
request, passing along the serial of the configure event.
|
||||
|
||||
If the client receives multiple configure events before it
|
||||
can respond to one, it only has to ack the last configure event.
|
||||
|
||||
A client is not required to commit immediately after sending
|
||||
an ack_configure request - it may even ack_configure several times
|
||||
before its next surface commit.
|
||||
|
||||
A client may send multiple ack_configure requests before committing, but
|
||||
only the last request sent before a commit indicates which configure
|
||||
event the client really is responding to.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="the serial from the configure event"/>
|
||||
</request>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the layer_surface">
|
||||
This request destroys the layer surface.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="configure">
|
||||
<description summary="suggest a surface change">
|
||||
The configure event asks the client to resize its surface.
|
||||
|
||||
Clients should arrange their surface for the new states, and then send
|
||||
an ack_configure request with the serial sent in this configure event at
|
||||
some point before committing the new surface.
|
||||
|
||||
The client is free to dismiss all but the last configure event it
|
||||
received.
|
||||
|
||||
The width and height arguments specify the size of the window in
|
||||
surface-local coordinates.
|
||||
|
||||
The size is a hint, in the sense that the client is free to ignore it if
|
||||
it doesn't resize, pick a smaller size (to satisfy aspect ratio or
|
||||
resize in steps of NxM pixels). If the client picks a smaller size and
|
||||
is anchored to two opposite anchors (e.g. 'top' and 'bottom'), the
|
||||
surface will be centered on this axis.
|
||||
|
||||
If the width or height arguments are zero, it means the client should
|
||||
decide its own window dimension.
|
||||
</description>
|
||||
<arg name="serial" type="uint"/>
|
||||
<arg name="width" type="uint"/>
|
||||
<arg name="height" type="uint"/>
|
||||
</event>
|
||||
|
||||
<event name="closed">
|
||||
<description summary="surface should be closed">
|
||||
The closed event is sent by the compositor when the surface will no
|
||||
longer be shown. The output may have been destroyed or the user may
|
||||
have asked for it to be removed. Further changes to the surface will be
|
||||
ignored. The client should destroy the resource after receiving this
|
||||
event, and create a new surface if they so choose.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="invalid_surface_state" value="0" summary="provided surface state is invalid"/>
|
||||
<entry name="invalid_size" value="1" summary="size is invalid"/>
|
||||
<entry name="invalid_anchor" value="2" summary="anchor bitfield is invalid"/>
|
||||
<entry name="invalid_keyboard_interactivity" value="3" summary="keyboard interactivity is invalid"/>
|
||||
</enum>
|
||||
|
||||
<enum name="anchor" bitfield="true">
|
||||
<entry name="top" value="1" summary="the top edge of the anchor rectangle"/>
|
||||
<entry name="bottom" value="2" summary="the bottom edge of the anchor rectangle"/>
|
||||
<entry name="left" value="4" summary="the left edge of the anchor rectangle"/>
|
||||
<entry name="right" value="8" summary="the right edge of the anchor rectangle"/>
|
||||
</enum>
|
||||
|
||||
<!-- Version 2 additions -->
|
||||
|
||||
<request name="set_layer" since="2">
|
||||
<description summary="change the layer of the surface">
|
||||
Change the layer that the surface is rendered on.
|
||||
|
||||
Layer is double-buffered, see wl_surface.commit.
|
||||
</description>
|
||||
<arg name="layer" type="uint" enum="zwlr_layer_shell_v1.layer" summary="layer to move this surface to"/>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
Loading…
Reference in a new issue