mirror of
https://github.com/libsdl-org/SDL.git
synced 2024-11-23 02:43:30 +08:00
Add and event and flag to report when a window has been occluded
Adds the SDL_EVENT_WINDOW_OCCLUDED events and the window flag SDL_WINDOW_OCCLUDED to report when the window occlusion state has changed, so that the application can take appropriate measures, as it may wish to suspend drawing, throttle, or otherwise behave in a more energy efficient manner when the window is not visible. When the window is no longer occluded, the SDL_EVENT_WINDOW_EXPOSED event is sent and the occlusion flag is cleared. This is handled on macOS via the window occlusion state event (available as of 10.9), and via the xdg-shell protocol on Wayland (version 6, wayland-protocols 1.32, passed through in libdecor 0.1.2).
This commit is contained in:
parent
7aec9ad4a6
commit
44536b7537
@ -571,16 +571,10 @@ macro(CheckWayland)
|
||||
list(APPEND SDL_EXTRA_LIBS ${PKG_LIBDECOR_LIBRARIES})
|
||||
endif()
|
||||
|
||||
cmake_push_check_state()
|
||||
list(APPEND CMAKE_REQUIRED_FLAGS ${PKG_LIBDECOR_CFLAGS})
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES ${PKG_LIBDECOR_INCLUDE_DIRS})
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES ${PKG_LIBDECOR_LINK_LIBRARIES})
|
||||
check_symbol_exists(libdecor_frame_get_max_content_size "libdecor.h" HAVE_LIBDECOR_FRAME_GET_MAX_CONTENT_SIZE)
|
||||
check_symbol_exists(libdecor_frame_get_min_content_size "libdecor.h" HAVE_LIBDECOR_FRAME_GET_MIN_CONTENT_SIZE)
|
||||
if(HAVE_LIBDECOR_FRAME_GET_MAX_CONTENT_SIZE AND HAVE_LIBDECOR_FRAME_GET_MIN_CONTENT_SIZE)
|
||||
set(SDL_HAVE_LIBDECOR_GET_MIN_MAX 1)
|
||||
endif()
|
||||
cmake_pop_check_state()
|
||||
# Version 0.1.2 or higher is needed for suspended window state and statically linked min/max getters.
|
||||
if (PKG_LIBDECOR_VERSION VERSION_GREATER_EQUAL "0.1.2")
|
||||
set(SDL_HAVE_LIBDECOR_VER_0_1_2 1)
|
||||
endif ()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -121,6 +121,7 @@ typedef enum
|
||||
SDL_EVENT_WINDOW_ICCPROF_CHANGED, /**< The ICC profile of the window's display has changed */
|
||||
SDL_EVENT_WINDOW_DISPLAY_CHANGED, /**< Window has been moved to display data1 */
|
||||
SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED, /**< Window display scale has been changed */
|
||||
SDL_EVENT_WINDOW_OCCLUDED, /**< The window has been occluded */
|
||||
SDL_EVENT_WINDOW_DESTROYED, /**< The window with the associated ID is being or has been destroyed. If this message is being handled
|
||||
in an event watcher, the window handle is still valid and can still be used to retrieve any userdata
|
||||
associated with the window. Otherwise, the handle has already been destroyed and all resources
|
||||
|
@ -130,6 +130,7 @@ typedef enum
|
||||
{
|
||||
SDL_WINDOW_FULLSCREEN = 0x00000001, /**< window is in fullscreen mode */
|
||||
SDL_WINDOW_OPENGL = 0x00000002, /**< window usable with OpenGL context */
|
||||
SDL_WINDOW_OCCLUDED = 0x00000004, /**< window is occluded */
|
||||
SDL_WINDOW_HIDDEN = 0x00000008, /**< window is not visible */
|
||||
SDL_WINDOW_BORDERLESS = 0x00000010, /**< no window decoration */
|
||||
SDL_WINDOW_RESIZABLE = 0x00000020, /**< window can be resized */
|
||||
|
@ -557,7 +557,7 @@
|
||||
#cmakedefine SDL_VIDEO_VITA_PVR @SDL_VIDEO_VITA_PVR@
|
||||
#cmakedefine SDL_VIDEO_VITA_PVR_OGL @SDL_VIDEO_VITA_PVR_OGL@
|
||||
|
||||
#cmakedefine SDL_HAVE_LIBDECOR_GET_MIN_MAX @SDL_HAVE_LIBDECOR_GET_MIN_MAX@
|
||||
#cmakedefine SDL_HAVE_LIBDECOR_VER_0_1_2 @SDL_HAVE_LIBDECOR_VER_0_1_2@
|
||||
|
||||
#if !defined(HAVE_STDINT_H) && !defined(_STDINT_H_)
|
||||
/* Most everything except Visual Studio 2008 and earlier has stdint.h now */
|
||||
|
@ -253,6 +253,7 @@ static void SDL_LogEvent(const SDL_Event *event)
|
||||
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_ICCPROF_CHANGED);
|
||||
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_DISPLAY_CHANGED);
|
||||
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED);
|
||||
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_OCCLUDED);
|
||||
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_DESTROYED);
|
||||
#undef SDL_WINDOWEVENT_CASE
|
||||
|
||||
|
@ -62,6 +62,9 @@ int SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent,
|
||||
}
|
||||
window->flags |= SDL_WINDOW_HIDDEN;
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_EXPOSED:
|
||||
window->flags &= ~SDL_WINDOW_OCCLUDED;
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_MOVED:
|
||||
window->undefined_x = SDL_FALSE;
|
||||
window->undefined_y = SDL_FALSE;
|
||||
@ -144,6 +147,12 @@ int SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent,
|
||||
}
|
||||
window->last_displayID = (SDL_DisplayID)data1;
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_OCCLUDED:
|
||||
if (window->flags & SDL_WINDOW_OCCLUDED) {
|
||||
return 0;
|
||||
}
|
||||
window->flags |= SDL_WINDOW_OCCLUDED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -162,7 +171,8 @@ int SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent,
|
||||
if (windowevent == SDL_EVENT_WINDOW_MOVED ||
|
||||
windowevent == SDL_EVENT_WINDOW_RESIZED ||
|
||||
windowevent == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED ||
|
||||
windowevent == SDL_EVENT_WINDOW_EXPOSED) {
|
||||
windowevent == SDL_EVENT_WINDOW_EXPOSED ||
|
||||
windowevent == SDL_EVENT_WINDOW_OCCLUDED) {
|
||||
SDL_FilterEvents(RemoveSupercededWindowEvents, &event);
|
||||
}
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
|
@ -562,6 +562,14 @@ static void Cocoa_SetKeyboardFocus(SDL_Window *window)
|
||||
SDL_SetKeyboardFocus(window);
|
||||
}
|
||||
|
||||
static void Cocoa_SendExposedEventIfVisible(SDL_Window *window)
|
||||
{
|
||||
NSWindow *nswindow = ((__bridge SDL_CocoaWindowData*)window->driverdata).nswindow;
|
||||
if ([nswindow occlusionState] & NSWindowOcclusionStateVisible) {
|
||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@implementation Cocoa_WindowListener
|
||||
|
||||
- (void)listen:(SDL_CocoaWindowData *)data
|
||||
@ -600,6 +608,7 @@ static void Cocoa_SetKeyboardFocus(SDL_Window *window)
|
||||
[center addObserver:self selector:@selector(windowDidExitFullScreen:) name:NSWindowDidExitFullScreenNotification object:window];
|
||||
[center addObserver:self selector:@selector(windowDidFailToEnterFullScreen:) name:@"NSWindowDidFailToEnterFullScreenNotification" object:window];
|
||||
[center addObserver:self selector:@selector(windowDidFailToExitFullScreen:) name:@"NSWindowDidFailToExitFullScreenNotification" object:window];
|
||||
[center addObserver:self selector:@selector(windowDidChangeOcclusionState:) name:NSWindowDidChangeOcclusionStateNotification object:window];
|
||||
} else {
|
||||
[window setDelegate:self];
|
||||
}
|
||||
@ -733,6 +742,7 @@ static void Cocoa_SetKeyboardFocus(SDL_Window *window)
|
||||
[center removeObserver:self name:NSWindowDidExitFullScreenNotification object:window];
|
||||
[center removeObserver:self name:@"NSWindowDidFailToEnterFullScreenNotification" object:window];
|
||||
[center removeObserver:self name:@"NSWindowDidFailToExitFullScreenNotification" object:window];
|
||||
[center removeObserver:self name:NSWindowDidChangeOcclusionStateNotification object:window];
|
||||
} else {
|
||||
[window setDelegate:nil];
|
||||
}
|
||||
@ -825,7 +835,16 @@ static void Cocoa_SetKeyboardFocus(SDL_Window *window)
|
||||
|
||||
- (void)windowDidExpose:(NSNotification *)aNotification
|
||||
{
|
||||
SDL_SendWindowEvent(_data.window, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
|
||||
Cocoa_SendExposedEventIfVisible(_data.window);
|
||||
}
|
||||
|
||||
- (void)windowDidChangeOcclusionState:(NSNotification *)aNotification
|
||||
{
|
||||
if ([_data.nswindow occlusionState] & NSWindowOcclusionStateVisible) {
|
||||
SDL_SendWindowEvent(_data.window, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
|
||||
} else {
|
||||
SDL_SendWindowEvent(_data.window, SDL_EVENT_WINDOW_OCCLUDED, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)windowWillMove:(NSNotification *)aNotification
|
||||
@ -1669,7 +1688,7 @@ static int Cocoa_SendMouseButtonClicks(SDL_Mouse *mouse, NSEvent *theEvent, SDL_
|
||||
self.layer.backgroundColor = CGColorGetConstantColor(color);
|
||||
}
|
||||
|
||||
SDL_SendWindowEvent(_sdlWindow, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
|
||||
Cocoa_SendExposedEventIfVisible(_sdlWindow);
|
||||
}
|
||||
|
||||
- (BOOL)wantsUpdateLayer
|
||||
@ -1687,7 +1706,7 @@ static int Cocoa_SendMouseButtonClicks(SDL_Mouse *mouse, NSEvent *theEvent, SDL_
|
||||
CFStringRef color = transparent ? kCGColorClear : kCGColorBlack;
|
||||
self.layer.backgroundColor = CGColorGetConstantColor(color);
|
||||
ScheduleContextUpdates((__bridge SDL_CocoaWindowData *)_sdlWindow->driverdata);
|
||||
SDL_SendWindowEvent(_sdlWindow, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
|
||||
Cocoa_SendExposedEventIfVisible(_sdlWindow);
|
||||
}
|
||||
|
||||
- (void)rightMouseDown:(NSEvent *)theEvent
|
||||
|
@ -218,7 +218,7 @@ SDL_WAYLAND_SYM(bool, libdecor_configuration_get_window_state, (struct libdecor_
|
||||
enum libdecor_window_state *))
|
||||
SDL_WAYLAND_SYM(int, libdecor_dispatch, (struct libdecor *, int))
|
||||
|
||||
#if defined(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR) || defined(SDL_HAVE_LIBDECOR_GET_MIN_MAX)
|
||||
#if defined(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR) || defined(SDL_HAVE_LIBDECOR_VER_0_1_2)
|
||||
/* Only found in libdecor 0.1.1 or higher, so failure to load them is not fatal. */
|
||||
SDL_WAYLAND_SYM_OPT(void, libdecor_frame_get_min_content_size, (struct libdecor_frame *,\
|
||||
int *,\
|
||||
|
@ -752,7 +752,7 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint
|
||||
} else if (SDL_strcmp(interface, "wl_seat") == 0) {
|
||||
Wayland_display_add_input(d, id, version);
|
||||
} else if (SDL_strcmp(interface, "xdg_wm_base") == 0) {
|
||||
d->shell.xdg = wl_registry_bind(d->registry, id, &xdg_wm_base_interface, SDL_min(version, 3));
|
||||
d->shell.xdg = wl_registry_bind(d->registry, id, &xdg_wm_base_interface, SDL_min(version, 6));
|
||||
xdg_wm_base_add_listener(d->shell.xdg, &shell_listener_xdg, NULL);
|
||||
} else if (SDL_strcmp(interface, "wl_shm") == 0) {
|
||||
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
|
||||
|
@ -376,6 +376,23 @@ static void ConfigureWindowGeometry(SDL_Window *window)
|
||||
/* Unconditionally send the window and drawable size, the video core will deduplicate when required. */
|
||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, window_width, window_height);
|
||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED, data->drawable_width, data->drawable_height);
|
||||
|
||||
/* Send an exposure event if the window is in the shown state and the size has changed,
|
||||
* even if the window is occluded, as the client needs to commit a new frame for the
|
||||
* changes to take effect.
|
||||
*
|
||||
* The occlusion state is immediately set again afterward, if necessary.
|
||||
*/
|
||||
if (data->surface_status == WAYLAND_SURFACE_STATUS_SHOWN) {
|
||||
if ((drawable_size_changed || window_size_changed) ||
|
||||
(!data->suspended && (window->flags & SDL_WINDOW_OCCLUDED))) {
|
||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
|
||||
}
|
||||
|
||||
if (data->suspended) {
|
||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_OCCLUDED, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void EnsurePopupPositionIsValid(SDL_Window *window)
|
||||
@ -535,14 +552,13 @@ static const struct wl_callback_listener surface_frame_listener;
|
||||
|
||||
static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time)
|
||||
{
|
||||
SDL_Window *w;
|
||||
SDL_WindowData *wind = (SDL_WindowData *)data;
|
||||
|
||||
/*
|
||||
* wl_surface.damage_buffer is the preferred method of setting the damage region
|
||||
* on compositor version 4 and above.
|
||||
*/
|
||||
if (wl_compositor_get_version(wind->waylandData->compositor) >= 4) {
|
||||
if (wl_compositor_get_version(wind->waylandData->compositor) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION) {
|
||||
wl_surface_damage_buffer(wind->surface, 0, 0,
|
||||
wind->drawable_width, wind->drawable_height);
|
||||
} else {
|
||||
@ -554,11 +570,18 @@ static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time
|
||||
wind->surface_status = WAYLAND_SURFACE_STATUS_SHOWN;
|
||||
|
||||
/* If any child windows are waiting on this window to be shown, show them now */
|
||||
for (w = wind->sdlwindow->first_child; w != NULL; w = w->next_sibling) {
|
||||
for (SDL_Window *w = wind->sdlwindow->first_child; w != NULL; w = w->next_sibling) {
|
||||
if (w->driverdata->surface_status == WAYLAND_SURFACE_STATUS_SHOW_PENDING) {
|
||||
Wayland_ShowWindow(SDL_GetVideoDevice(), w);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the window was initially set to the suspended state, send the occluded event now,
|
||||
* as we don't want to mark the window as occluded until at least one frame has been submitted.
|
||||
*/
|
||||
if (wind->suspended) {
|
||||
SDL_SendWindowEvent(wind->sdlwindow, SDL_EVENT_WINDOW_OCCLUDED, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
wl_callback_destroy(cb);
|
||||
@ -616,6 +639,7 @@ static void handle_configure_xdg_toplevel(void *data,
|
||||
SDL_bool maximized = SDL_FALSE;
|
||||
SDL_bool floating = SDL_TRUE;
|
||||
SDL_bool focused = SDL_FALSE;
|
||||
SDL_bool suspended = SDL_FALSE;
|
||||
wl_array_for_each (state, states) {
|
||||
switch (*state) {
|
||||
case XDG_TOPLEVEL_STATE_FULLSCREEN:
|
||||
@ -635,6 +659,8 @@ static void handle_configure_xdg_toplevel(void *data,
|
||||
case XDG_TOPLEVEL_STATE_TILED_BOTTOM:
|
||||
floating = SDL_FALSE;
|
||||
break;
|
||||
case XDG_TOPLEVEL_STATE_SUSPENDED:
|
||||
suspended = SDL_TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -721,6 +747,7 @@ static void handle_configure_xdg_toplevel(void *data,
|
||||
wind->requested_window_width = width;
|
||||
wind->requested_window_height = height;
|
||||
wind->floating = floating;
|
||||
wind->suspended = suspended;
|
||||
if (wind->surface_status == WAYLAND_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
|
||||
wind->surface_status = WAYLAND_SURFACE_STATUS_WAITING_FOR_FRAME;
|
||||
}
|
||||
@ -732,9 +759,25 @@ static void handle_close_xdg_toplevel(void *data, struct xdg_toplevel *xdg_tople
|
||||
SDL_SendWindowEvent(window->sdlwindow, SDL_EVENT_WINDOW_CLOSE_REQUESTED, 0, 0);
|
||||
}
|
||||
|
||||
static void handle_xdg_configure_toplevel_bounds(void *data,
|
||||
struct xdg_toplevel *xdg_toplevel,
|
||||
int32_t width, int32_t height)
|
||||
{
|
||||
/* NOP */
|
||||
}
|
||||
|
||||
void handle_xdg_toplevel_wm_capabilities(void *data,
|
||||
struct xdg_toplevel *xdg_toplevel,
|
||||
struct wl_array *capabilities)
|
||||
{
|
||||
/* NOP */
|
||||
}
|
||||
|
||||
static const struct xdg_toplevel_listener toplevel_listener_xdg = {
|
||||
handle_configure_xdg_toplevel,
|
||||
handle_close_xdg_toplevel
|
||||
handle_close_xdg_toplevel,
|
||||
handle_xdg_configure_toplevel_bounds, /* Version 4 */
|
||||
handle_xdg_toplevel_wm_capabilities /* Version 5 */
|
||||
};
|
||||
|
||||
static void handle_configure_xdg_popup(void *data,
|
||||
@ -824,11 +867,11 @@ static const struct zxdg_toplevel_decoration_v1_listener decoration_listener = {
|
||||
* minimum content size limit. The internal limits must always be overridden
|
||||
* to ensure that very small windows don't cause errors or crashes.
|
||||
*
|
||||
* On versions of libdecor that expose the function to get the minimum content
|
||||
* On libdecor >= 0.1.2, which exposes the function to get the minimum content
|
||||
* size limit, this function is a no-op.
|
||||
*
|
||||
* Can be removed if the minimum required version of libdecor is raised
|
||||
* to a version that guarantees the availability of this function.
|
||||
* Can be removed if the minimum required version of libdecor is raised to
|
||||
* 0.1.2 or higher.
|
||||
*/
|
||||
static void OverrideLibdecorLimits(SDL_Window *window)
|
||||
{
|
||||
@ -836,7 +879,7 @@ static void OverrideLibdecorLimits(SDL_Window *window)
|
||||
if (libdecor_frame_get_min_content_size == NULL) {
|
||||
libdecor_frame_set_min_content_size(window->driverdata->shell_surface.libdecor.frame, window->min_w, window->min_h);
|
||||
}
|
||||
#elif !defined(SDL_HAVE_LIBDECOR_GET_MIN_MAX)
|
||||
#elif !defined(SDL_HAVE_LIBDECOR_VER_0_1_2)
|
||||
libdecor_frame_set_min_content_size(window->driverdata->shell_surface.libdecor.frame, window->min_w, window->min_h);
|
||||
#endif
|
||||
}
|
||||
@ -847,7 +890,7 @@ static void OverrideLibdecorLimits(SDL_Window *window)
|
||||
* function is a no-op.
|
||||
*
|
||||
* Can be replaced with a direct call if the minimum required version of libdecor is raised
|
||||
* to a version that guarantees the availability of this function.
|
||||
* to 0.1.2 or higher.
|
||||
*/
|
||||
static void LibdecorGetMinContentSize(struct libdecor_frame *frame, int *min_w, int *min_h)
|
||||
{
|
||||
@ -855,7 +898,7 @@ static void LibdecorGetMinContentSize(struct libdecor_frame *frame, int *min_w,
|
||||
if (libdecor_frame_get_min_content_size != NULL) {
|
||||
libdecor_frame_get_min_content_size(frame, min_w, min_h);
|
||||
}
|
||||
#elif defined(SDL_HAVE_LIBDECOR_GET_MIN_MAX)
|
||||
#elif defined(SDL_HAVE_LIBDECOR_VER_0_1_2)
|
||||
libdecor_frame_get_min_content_size(frame, min_w, min_h);
|
||||
#endif
|
||||
}
|
||||
@ -876,6 +919,7 @@ static void decoration_frame_configure(struct libdecor_frame *frame,
|
||||
SDL_bool fullscreen = SDL_FALSE;
|
||||
SDL_bool maximized = SDL_FALSE;
|
||||
SDL_bool tiled = SDL_FALSE;
|
||||
SDL_bool suspended = SDL_FALSE;
|
||||
SDL_bool floating;
|
||||
|
||||
static const enum libdecor_window_state tiled_states = (LIBDECOR_WINDOW_STATE_TILED_LEFT | LIBDECOR_WINDOW_STATE_TILED_RIGHT |
|
||||
@ -887,6 +931,9 @@ static void decoration_frame_configure(struct libdecor_frame *frame,
|
||||
maximized = (window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED) != 0;
|
||||
focused = (window_state & LIBDECOR_WINDOW_STATE_ACTIVE) != 0;
|
||||
tiled = (window_state & tiled_states) != 0;
|
||||
#ifdef SDL_HAVE_LIBDECOR_VER_0_1_2
|
||||
suspended = (window_state & LIBDECOR_WINDOW_STATE_SUSPENDED) != 0;
|
||||
#endif
|
||||
}
|
||||
floating = !(fullscreen || maximized || tiled);
|
||||
|
||||
@ -999,8 +1046,9 @@ static void decoration_frame_configure(struct libdecor_frame *frame,
|
||||
wind->floating_height = height;
|
||||
}
|
||||
|
||||
/* Store the new floating state. */
|
||||
/* Store the new state. */
|
||||
wind->floating = floating;
|
||||
wind->suspended = suspended;
|
||||
|
||||
/* Calculate the new window geometry */
|
||||
wind->requested_window_width = width;
|
||||
@ -1039,9 +1087,13 @@ static void decoration_frame_close(struct libdecor_frame *frame, void *user_data
|
||||
|
||||
static void decoration_frame_commit(struct libdecor_frame *frame, void *user_data)
|
||||
{
|
||||
SDL_WindowData *wind = user_data;
|
||||
|
||||
SDL_SendWindowEvent(wind->sdlwindow, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
|
||||
/* libdecor decoration subsurfaces are synchronous, so the client needs to
|
||||
* commit a frame to trigger an update of the decoration surfaces.
|
||||
*/
|
||||
SDL_WindowData *wind = (SDL_WindowData *)user_data;
|
||||
if (!wind->suspended && wind->surface_status == WAYLAND_SURFACE_STATUS_SHOWN) {
|
||||
SDL_SendWindowEvent(wind->sdlwindow, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static struct libdecor_frame_interface libdecor_frame_interface = {
|
||||
@ -1565,6 +1617,11 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
* HideWindow was called immediately before ShowWindow.
|
||||
*/
|
||||
WAYLAND_wl_display_roundtrip(c->display);
|
||||
|
||||
/* Send an exposure event to signal that the client should draw. */
|
||||
if (data->surface_status == WAYLAND_SURFACE_STATUS_WAITING_FOR_FRAME) {
|
||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void Wayland_ReleasePopup(SDL_VideoDevice *_this, SDL_Window *popup)
|
||||
|
@ -122,6 +122,7 @@ struct SDL_WindowData
|
||||
int system_min_required_height;
|
||||
SDL_DisplayID last_displayID;
|
||||
SDL_bool floating;
|
||||
SDL_bool suspended;
|
||||
SDL_bool is_fullscreen;
|
||||
SDL_bool in_fullscreen_transition;
|
||||
SDL_bool fullscreen_was_positioned;
|
||||
|
@ -29,7 +29,7 @@
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="xdg_wm_base" version="3">
|
||||
<interface name="xdg_wm_base" version="6">
|
||||
<description summary="create desktop-style surfaces">
|
||||
The xdg_wm_base interface is exposed as a global object enabling clients
|
||||
to turn their wl_surfaces into windows in a desktop environment. It
|
||||
@ -50,6 +50,8 @@
|
||||
summary="the client provided an invalid surface state"/>
|
||||
<entry name="invalid_positioner" value="5"
|
||||
summary="the client provided an invalid positioner"/>
|
||||
<entry name="unresponsive" value="6"
|
||||
summary="the client didn’t respond to a ping event in time"/>
|
||||
</enum>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
@ -58,7 +60,7 @@
|
||||
|
||||
Destroying a bound xdg_wm_base object while there are surfaces
|
||||
still alive created by this xdg_wm_base object instance is illegal
|
||||
and will result in a protocol error.
|
||||
and will result in a defunct_surfaces error.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
@ -75,7 +77,9 @@
|
||||
<description summary="create a shell surface from a surface">
|
||||
This creates an xdg_surface for the given surface. While xdg_surface
|
||||
itself is not a role, the corresponding surface may only be assigned
|
||||
a role extending xdg_surface, such as xdg_toplevel or xdg_popup.
|
||||
a role extending xdg_surface, such as xdg_toplevel or xdg_popup. It is
|
||||
illegal to create an xdg_surface for a wl_surface which already has an
|
||||
assigned role and this will result in a role error.
|
||||
|
||||
This creates an xdg_surface for the given surface. An xdg_surface is
|
||||
used as basis to define a role to a given surface, such as xdg_toplevel
|
||||
@ -92,7 +96,8 @@
|
||||
<request name="pong">
|
||||
<description summary="respond to a ping event">
|
||||
A client must respond to a ping event with a pong request or
|
||||
the client may be deemed unresponsive. See xdg_wm_base.ping.
|
||||
the client may be deemed unresponsive. See xdg_wm_base.ping
|
||||
and xdg_wm_base.error.unresponsive.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial of the ping event"/>
|
||||
</request>
|
||||
@ -106,7 +111,9 @@
|
||||
Compositors can use this to determine if the client is still
|
||||
alive. It's unspecified what will happen if the client doesn't
|
||||
respond to the ping request, or in what timeframe. Clients should
|
||||
try to respond in a reasonable amount of time.
|
||||
try to respond in a reasonable amount of time. The “unresponsive”
|
||||
error is provided for compositors that wish to disconnect unresponsive
|
||||
clients.
|
||||
|
||||
A compositor is free to ping in any way it wants, but a client must
|
||||
always respond to any xdg_wm_base object it created.
|
||||
@ -115,7 +122,7 @@
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="xdg_positioner" version="3">
|
||||
<interface name="xdg_positioner" version="6">
|
||||
<description summary="child surface positioner">
|
||||
The xdg_positioner provides a collection of rules for the placement of a
|
||||
child surface relative to a parent surface. Rules can be defined to ensure
|
||||
@ -135,7 +142,7 @@
|
||||
For an xdg_positioner object to be considered complete, it must have a
|
||||
non-zero size set by set_size, and a non-zero anchor rectangle set by
|
||||
set_anchor_rect. Passing an incomplete xdg_positioner object when
|
||||
positioning a surface raises an error.
|
||||
positioning a surface raises an invalid_positioner error.
|
||||
</description>
|
||||
|
||||
<enum name="error">
|
||||
@ -223,7 +230,8 @@
|
||||
specified (e.g. 'bottom_right' or 'top_left'), then the child surface
|
||||
will be placed towards the specified gravity; otherwise, the child
|
||||
surface will be centered over the anchor point on any axis that had no
|
||||
gravity specified.
|
||||
gravity specified. If the gravity is not in the ‘gravity’ enum, an
|
||||
invalid_input error is raised.
|
||||
</description>
|
||||
<arg name="gravity" type="uint" enum="gravity"
|
||||
summary="gravity direction"/>
|
||||
@ -389,7 +397,7 @@
|
||||
|
||||
<request name="set_parent_configure" since="3">
|
||||
<description summary="set parent configure this is a response to">
|
||||
Set the serial of a xdg_surface.configure event this positioner will be
|
||||
Set the serial of an xdg_surface.configure event this positioner will be
|
||||
used in response to. The compositor may use this information together
|
||||
with set_parent_size to determine what future state the popup should be
|
||||
constrained using.
|
||||
@ -399,7 +407,7 @@
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="xdg_surface" version="3">
|
||||
<interface name="xdg_surface" version="6">
|
||||
<description summary="desktop user interface surface base interface">
|
||||
An interface that may be implemented by a wl_surface, for
|
||||
implementations that provide a desktop-style user interface.
|
||||
@ -426,6 +434,13 @@
|
||||
manipulate a buffer prior to the first xdg_surface.configure call must
|
||||
also be treated as errors.
|
||||
|
||||
After creating a role-specific object and setting it up, the client must
|
||||
perform an initial commit without any buffer attached. The compositor
|
||||
will reply with initial wl_surface state such as
|
||||
wl_surface.preferred_buffer_scale followed by an xdg_surface.configure
|
||||
event. The client must acknowledge it and is then allowed to attach a
|
||||
buffer to map the surface.
|
||||
|
||||
Mapping an xdg_surface-based role surface is defined as making it
|
||||
possible for the surface to be shown by the compositor. Note that
|
||||
a mapped surface is not guaranteed to be visible once it is mapped.
|
||||
@ -439,19 +454,30 @@
|
||||
|
||||
A newly-unmapped surface is considered to have met condition (1) out
|
||||
of the 3 required conditions for mapping a surface if its role surface
|
||||
has not been destroyed.
|
||||
has not been destroyed, i.e. the client must perform the initial commit
|
||||
again before attaching a buffer.
|
||||
</description>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="not_constructed" value="1"/>
|
||||
<entry name="already_constructed" value="2"/>
|
||||
<entry name="unconfigured_buffer" value="3"/>
|
||||
<entry name="not_constructed" value="1"
|
||||
summary="Surface was not fully constructed"/>
|
||||
<entry name="already_constructed" value="2"
|
||||
summary="Surface was already constructed"/>
|
||||
<entry name="unconfigured_buffer" value="3"
|
||||
summary="Attaching a buffer to an unconfigured surface"/>
|
||||
<entry name="invalid_serial" value="4"
|
||||
summary="Invalid serial number when acking a configure event"/>
|
||||
<entry name="invalid_size" value="5"
|
||||
summary="Width or height was zero or negative"/>
|
||||
<entry name="defunct_role_object" value="6"
|
||||
summary="Surface was destroyed before its role object"/>
|
||||
</enum>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the xdg_surface">
|
||||
Destroy the xdg_surface object. An xdg_surface must only be destroyed
|
||||
after its role object has been destroyed.
|
||||
after its role object has been destroyed, otherwise
|
||||
a defunct_role_object error is raised.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
@ -506,13 +532,22 @@
|
||||
commit. This unset is meant for extremely simple clients.
|
||||
|
||||
The arguments are given in the surface-local coordinate space of
|
||||
the wl_surface associated with this xdg_surface.
|
||||
the wl_surface associated with this xdg_surface, and may extend outside
|
||||
of the wl_surface itself to mark parts of the subsurface tree as part of
|
||||
the window geometry.
|
||||
|
||||
The width and height must be greater than zero. Setting an invalid size
|
||||
will raise an error. When applied, the effective window geometry will be
|
||||
the set window geometry clamped to the bounding rectangle of the
|
||||
combined geometry of the surface of the xdg_surface and the associated
|
||||
When applied, the effective window geometry will be the set window
|
||||
geometry clamped to the bounding rectangle of the combined
|
||||
geometry of the surface of the xdg_surface and the associated
|
||||
subsurfaces.
|
||||
|
||||
The effective geometry will not be recalculated unless a new call to
|
||||
set_window_geometry is done and the new pending surface state is
|
||||
subsequently applied.
|
||||
|
||||
The width and height of the effective window geometry must be
|
||||
greater than zero. Setting an invalid size will raise an
|
||||
invalid_size error.
|
||||
</description>
|
||||
<arg name="x" type="int"/>
|
||||
<arg name="y" type="int"/>
|
||||
@ -533,6 +568,8 @@
|
||||
|
||||
If the client receives multiple configure events before it
|
||||
can respond to one, it only has to ack the last configure event.
|
||||
Acking a configure event that was never sent raises an invalid_serial
|
||||
error.
|
||||
|
||||
A client is not required to commit immediately after sending
|
||||
an ack_configure request - it may even ack_configure several times
|
||||
@ -541,6 +578,17 @@
|
||||
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.
|
||||
|
||||
Sending an ack_configure request consumes the serial number sent with
|
||||
the request, as well as serial numbers sent by all configure events
|
||||
sent on this xdg_surface prior to the configure event referenced by
|
||||
the committed serial.
|
||||
|
||||
It is an error to issue multiple ack_configure requests referencing a
|
||||
serial from the same configure event, or to issue an ack_configure
|
||||
request referencing a serial from a configure event issued before the
|
||||
event identified by the last ack_configure request for the same
|
||||
xdg_surface. Doing so will raise an invalid_serial error.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="the serial from the configure event"/>
|
||||
</request>
|
||||
@ -569,7 +617,7 @@
|
||||
|
||||
</interface>
|
||||
|
||||
<interface name="xdg_toplevel" version="3">
|
||||
<interface name="xdg_toplevel" version="6">
|
||||
<description summary="toplevel surface">
|
||||
This interface defines an xdg_surface role which allows a surface to,
|
||||
among other things, set window-like properties such as maximize,
|
||||
@ -581,7 +629,11 @@
|
||||
by the compositor until it is explicitly mapped again.
|
||||
All active operations (e.g., move, resize) are canceled and all
|
||||
attributes (e.g. title, state, stacking, ...) are discarded for
|
||||
an xdg_toplevel surface when it is unmapped.
|
||||
an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to
|
||||
the state it had right after xdg_surface.get_toplevel. The client
|
||||
can re-map the toplevel by perfoming a commit without any buffer
|
||||
attached, waiting for a configure event and handling it as usual (see
|
||||
xdg_surface description).
|
||||
|
||||
Attaching a null buffer to a toplevel unmaps the surface.
|
||||
</description>
|
||||
@ -593,24 +645,37 @@
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="invalid_resize_edge" value="0" summary="provided value is
|
||||
not a valid variant of the resize_edge enum"/>
|
||||
<entry name="invalid_parent" value="1"
|
||||
summary="invalid parent toplevel"/>
|
||||
<entry name="invalid_size" value="2"
|
||||
summary="client provided an invalid min or max size"/>
|
||||
</enum>
|
||||
|
||||
<request name="set_parent">
|
||||
<description summary="set the parent of this surface">
|
||||
Set the "parent" of this surface. This surface should be stacked
|
||||
above the parent surface and all other ancestor surfaces.
|
||||
|
||||
Parent windows should be set on dialogs, toolboxes, or other
|
||||
Parent surfaces should be set on dialogs, toolboxes, or other
|
||||
"auxiliary" surfaces, so that the parent is raised when the dialog
|
||||
is raised.
|
||||
|
||||
Setting a null parent for a child window removes any parent-child
|
||||
relationship for the child. Setting a null parent for a window which
|
||||
currently has no parent is a no-op.
|
||||
Setting a null parent for a child surface unsets its parent. Setting
|
||||
a null parent for a surface which currently has no parent is a no-op.
|
||||
|
||||
If the parent is unmapped then its children are managed as
|
||||
though the parent of the now-unmapped parent has become the
|
||||
parent of this surface. If no parent exists for the now-unmapped
|
||||
parent then the children are managed as though they have no
|
||||
parent surface.
|
||||
Only mapped surfaces can have child surfaces. Setting a parent which
|
||||
is not mapped is equivalent to setting a null parent. If a surface
|
||||
becomes unmapped, its children's parent is set to the parent of
|
||||
the now-unmapped surface. If the now-unmapped surface has no parent,
|
||||
its children's parent is unset. If the now-unmapped surface becomes
|
||||
mapped again, its parent-child relationship is not restored.
|
||||
|
||||
The parent toplevel must not be one of the child toplevel's
|
||||
descendants, and the parent must be different from the child toplevel,
|
||||
otherwise the invalid_parent protocol error is raised.
|
||||
</description>
|
||||
<arg name="parent" type="object" interface="xdg_toplevel" allow-null="true"/>
|
||||
</request>
|
||||
@ -652,7 +717,7 @@
|
||||
application identifiers and how they relate to well-known D-Bus
|
||||
names and .desktop files.
|
||||
|
||||
[0] http://standards.freedesktop.org/desktop-entry-spec/
|
||||
[0] https://standards.freedesktop.org/desktop-entry-spec/
|
||||
</description>
|
||||
<arg name="app_id" type="string"/>
|
||||
</request>
|
||||
@ -666,7 +731,8 @@
|
||||
This request asks the compositor to pop up such a window menu at
|
||||
the given position, relative to the local surface coordinates of
|
||||
the parent surface. There are no guarantees as to what menu items
|
||||
the window menu contains.
|
||||
the window menu contains, or even if a window menu will be drawn
|
||||
at all.
|
||||
|
||||
This request must be used in response to some sort of user action
|
||||
like a button press, key press, or touch down event.
|
||||
@ -742,12 +808,13 @@
|
||||
guarantee that the device focus will return when the resize is
|
||||
completed.
|
||||
|
||||
The edges parameter specifies how the surface should be resized,
|
||||
and is one of the values of the resize_edge enum. The compositor
|
||||
may use this information to update the surface position for
|
||||
example when dragging the top left corner. The compositor may also
|
||||
use this information to adapt its behavior, e.g. choose an
|
||||
appropriate cursor image.
|
||||
The edges parameter specifies how the surface should be resized, and
|
||||
is one of the values of the resize_edge enum. Values not matching
|
||||
a variant of the enum will cause the invalid_resize_edge protocol error.
|
||||
The compositor may use this information to update the surface position
|
||||
for example when dragging the top left corner. The compositor may also
|
||||
use this information to adapt its behavior, e.g. choose an appropriate
|
||||
cursor image.
|
||||
</description>
|
||||
<arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
|
||||
<arg name="serial" type="uint" summary="the serial of the user event"/>
|
||||
@ -767,7 +834,8 @@
|
||||
<entry name="maximized" value="1" summary="the surface is maximized">
|
||||
<description summary="the surface is maximized">
|
||||
The surface is maximized. The window geometry specified in the configure
|
||||
event must be obeyed by the client.
|
||||
event must be obeyed by the client, or the xdg_wm_base.invalid_surface_state
|
||||
error is raised.
|
||||
|
||||
The client should draw without shadow or other
|
||||
decoration outside of the window geometry.
|
||||
@ -798,29 +866,36 @@
|
||||
</description>
|
||||
</entry>
|
||||
<entry name="tiled_left" value="5" since="2">
|
||||
<description summary="the surface is tiled">
|
||||
<description summary="the surface’s left edge is tiled">
|
||||
The window is currently in a tiled layout and the left edge is
|
||||
considered to be adjacent to another part of the tiling grid.
|
||||
</description>
|
||||
</entry>
|
||||
<entry name="tiled_right" value="6" since="2">
|
||||
<description summary="the surface is tiled">
|
||||
<description summary="the surface’s right edge is tiled">
|
||||
The window is currently in a tiled layout and the right edge is
|
||||
considered to be adjacent to another part of the tiling grid.
|
||||
</description>
|
||||
</entry>
|
||||
<entry name="tiled_top" value="7" since="2">
|
||||
<description summary="the surface is tiled">
|
||||
<description summary="the surface’s top edge is tiled">
|
||||
The window is currently in a tiled layout and the top edge is
|
||||
considered to be adjacent to another part of the tiling grid.
|
||||
</description>
|
||||
</entry>
|
||||
<entry name="tiled_bottom" value="8" since="2">
|
||||
<description summary="the surface is tiled">
|
||||
<description summary="the surface’s bottom edge is tiled">
|
||||
The window is currently in a tiled layout and the bottom edge is
|
||||
considered to be adjacent to another part of the tiling grid.
|
||||
</description>
|
||||
</entry>
|
||||
<entry name="suspended" value="9" since="6">
|
||||
<description summary="surface repaint is suspended">
|
||||
The surface is currently not ordinarily being repainted; for
|
||||
example because its content is occluded by another window, or its
|
||||
outputs are switched off due to screen locking.
|
||||
</description>
|
||||
</entry>
|
||||
</enum>
|
||||
|
||||
<request name="set_max_size">
|
||||
@ -854,11 +929,11 @@
|
||||
request.
|
||||
|
||||
Requesting a maximum size to be smaller than the minimum size of
|
||||
a surface is illegal and will result in a protocol error.
|
||||
a surface is illegal and will result in an invalid_size error.
|
||||
|
||||
The width and height must be greater than or equal to zero. Using
|
||||
strictly negative values for width and height will result in a
|
||||
protocol error.
|
||||
strictly negative values for width or height will result in a
|
||||
invalid_size error.
|
||||
</description>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
@ -895,11 +970,11 @@
|
||||
request.
|
||||
|
||||
Requesting a minimum size to be larger than the maximum size of
|
||||
a surface is illegal and will result in a protocol error.
|
||||
a surface is illegal and will result in an invalid_size error.
|
||||
|
||||
The width and height must be greater than or equal to zero. Using
|
||||
strictly negative values for width and height will result in a
|
||||
protocol error.
|
||||
invalid_size error.
|
||||
</description>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
@ -1058,9 +1133,68 @@
|
||||
a dialog to ask the user to save their data, etc.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<!-- Version 4 additions -->
|
||||
|
||||
<event name="configure_bounds" since="4">
|
||||
<description summary="recommended window geometry bounds">
|
||||
The configure_bounds event may be sent prior to a xdg_toplevel.configure
|
||||
event to communicate the bounds a window geometry size is recommended
|
||||
to constrain to.
|
||||
|
||||
The passed width and height are in surface coordinate space. If width
|
||||
and height are 0, it means bounds is unknown and equivalent to as if no
|
||||
configure_bounds event was ever sent for this surface.
|
||||
|
||||
The bounds can for example correspond to the size of a monitor excluding
|
||||
any panels or other shell components, so that a surface isn't created in
|
||||
a way that it cannot fit.
|
||||
|
||||
The bounds may change at any point, and in such a case, a new
|
||||
xdg_toplevel.configure_bounds will be sent, followed by
|
||||
xdg_toplevel.configure and xdg_surface.configure.
|
||||
</description>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
</event>
|
||||
|
||||
<!-- Version 5 additions -->
|
||||
|
||||
<enum name="wm_capabilities" since="5">
|
||||
<entry name="window_menu" value="1" summary="show_window_menu is available"/>
|
||||
<entry name="maximize" value="2" summary="set_maximized and unset_maximized are available"/>
|
||||
<entry name="fullscreen" value="3" summary="set_fullscreen and unset_fullscreen are available"/>
|
||||
<entry name="minimize" value="4" summary="set_minimized is available"/>
|
||||
</enum>
|
||||
|
||||
<event name="wm_capabilities" since="5">
|
||||
<description summary="compositor capabilities">
|
||||
This event advertises the capabilities supported by the compositor. If
|
||||
a capability isn't supported, clients should hide or disable the UI
|
||||
elements that expose this functionality. For instance, if the
|
||||
compositor doesn't advertise support for minimized toplevels, a button
|
||||
triggering the set_minimized request should not be displayed.
|
||||
|
||||
The compositor will ignore requests it doesn't support. For instance,
|
||||
a compositor which doesn't advertise support for minimized will ignore
|
||||
set_minimized requests.
|
||||
|
||||
Compositors must send this event once before the first
|
||||
xdg_surface.configure event. When the capabilities change, compositors
|
||||
must send this event again and then send an xdg_surface.configure
|
||||
event.
|
||||
|
||||
The configured state should not be applied immediately. See
|
||||
xdg_surface.configure for details.
|
||||
|
||||
The capabilities are sent as an array of 32-bit unsigned integers in
|
||||
native endianness.
|
||||
</description>
|
||||
<arg name="capabilities" type="array" summary="array of 32-bit capabilities"/>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="xdg_popup" version="3">
|
||||
<interface name="xdg_popup" version="6">
|
||||
<description summary="short-lived, popup surfaces for menus">
|
||||
A popup surface is a short-lived, temporary surface. It can be used to
|
||||
implement for example menus, popovers, tooltips and other similar user
|
||||
@ -1098,8 +1232,8 @@
|
||||
This destroys the popup. Explicitly destroying the xdg_popup
|
||||
object will also dismiss the popup, and unmap the surface.
|
||||
|
||||
If this xdg_popup is not the "topmost" popup, a protocol error
|
||||
will be sent.
|
||||
If this xdg_popup is not the "topmost" popup, the
|
||||
xdg_wm_base.not_the_topmost_popup protocol error will be sent.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
@ -1131,10 +1265,6 @@
|
||||
nested grabbing popup as well. When a compositor dismisses popups, it
|
||||
will follow the same dismissing order as required from the client.
|
||||
|
||||
The parent of a grabbing popup must either be another xdg_popup with an
|
||||
active explicit grab, or an xdg_popup or xdg_toplevel, if there are no
|
||||
explicit grabs already taken.
|
||||
|
||||
If the topmost grabbing popup is destroyed, the grab will be returned to
|
||||
the parent of the popup, if that parent previously had an explicit grab.
|
||||
|
||||
@ -1204,12 +1334,12 @@
|
||||
|
||||
If the popup is repositioned in response to a configure event for its
|
||||
parent, the client should send an xdg_positioner.set_parent_configure
|
||||
and possibly a xdg_positioner.set_parent_size request to allow the
|
||||
and possibly an xdg_positioner.set_parent_size request to allow the
|
||||
compositor to properly constrain the popup.
|
||||
|
||||
If the popup is repositioned together with a parent that is being
|
||||
resized, but not in response to a configure event, the client should
|
||||
send a xdg_positioner.set_parent_size request.
|
||||
send an xdg_positioner.set_parent_size request.
|
||||
</description>
|
||||
<arg name="positioner" type="object" interface="xdg_positioner"/>
|
||||
<arg name="token" type="uint" summary="reposition request token"/>
|
||||
|
Loading…
Reference in New Issue
Block a user