Compare commits

...

8 Commits

Author SHA1 Message Date
Frank Praznik fadd6e8ef6
Merge 1119d0ea82 into 88a01fbc96 2024-09-19 15:42:07 -03:00
Ozkan Sezer 88a01fbc96 testautomation_stdlib.c: fix -Wformat warnings from mingw with %lld/%llu
i.e.:  unknown conversion type character 'l' in format
See https://github.com/libsdl-org/SDL/pull/10789#issuecomment-2354011906
2024-09-19 20:37:11 +03:00
Ryan C. Gordon b4e2777820
examples/renderer/03-lines: Fix compiler warning on Visual Studio. 2024-09-19 13:31:24 -04:00
Ryan C. Gordon 2e3e5abd7d
examples/renderer/03-lines: use a gray background. 2024-09-19 12:58:37 -04:00
Frank Praznik fd0ce75e2e tests: Fix tests when run with the --high-pixel-density flag
Scales pointer coordinates where needed to fix the following tests when run with the --high-pixel-density flag:

- testaudio
- testaudiostreamdynamicresample
- testhittesting
- testintersections
- testmanymouse
- testoverlay
- testwm
2024-09-19 12:54:13 -04:00
Ryan C. Gordon 745d5e4991
examples/renderer/03-lines: Make this less obnoxious to look at. 2024-09-19 12:52:04 -04:00
Ryan C. Gordon 1b266ec13d
examples: added renderer/03-lines 2024-09-19 12:16:12 -04:00
Frank Praznik 1119d0ea82
wayland: Add support for the key repeat event (seat v10)
The internal key repeat mechanism already disables itself if the key repeat interval is 0, and SDL tracks and handles the flagging of repeated keys itself, so just map the 'repeated' event to 'pressed'.
2024-09-13 12:46:59 -04:00
14 changed files with 345 additions and 94 deletions

View File

@ -122,6 +122,7 @@ endmacro()
add_sdl_example_executable(renderer-clear SOURCES renderer/01-clear/renderer-clear.c) add_sdl_example_executable(renderer-clear SOURCES renderer/01-clear/renderer-clear.c)
add_sdl_example_executable(renderer-primitives SOURCES renderer/02-primitives/renderer-primitives.c) add_sdl_example_executable(renderer-primitives SOURCES renderer/02-primitives/renderer-primitives.c)
add_sdl_example_executable(renderer-lines SOURCES renderer/03-lines/renderer-lines.c)
add_sdl_example_executable(audio-simple-playback SOURCES audio/01-simple-playback/simple-playback.c) add_sdl_example_executable(audio-simple-playback SOURCES audio/01-simple-playback/simple-playback.c)
add_sdl_example_executable(audio-simple-playback-callback SOURCES audio/02-simple-playback-callback/simple-playback-callback.c) add_sdl_example_executable(audio-simple-playback-callback SOURCES audio/02-simple-playback-callback/simple-playback-callback.c)
add_sdl_example_executable(audio-load-wav SOURCES audio/03-load-wav/load-wav.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.wav) add_sdl_example_executable(audio-load-wav SOURCES audio/03-load-wav/load-wav.c DATAFILES ${CMAKE_CURRENT_SOURCE_DIR}/../test/sample.wav)

View File

@ -0,0 +1,3 @@
This example creates an SDL window and renderer, and then draws a something
roughly like a Christmas tree with nothing but lines, every frame.

View File

@ -0,0 +1,93 @@
/*
* This example creates an SDL window and renderer, and then draws some lines
* to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't initialize SDL!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/lines", 640, 480, 0, &window, &renderer)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create window/renderer!", SDL_GetError(), NULL);
return SDL_APP_FAILURE;
}
SDL_srand(0); /* seed the random number generator */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
int i;
/* Lines (line segments, really) are drawn in terms of points: a set of
X and Y coordinates, one set for each end of the line.
(0, 0) is the top left of the window, and larger numbers go down
and to the right. This isn't how geometry works, but this is pretty
standard in 2D graphics. */
static const SDL_FPoint line_points[] = {
{ 100, 354 }, { 220, 230 }, { 140, 230 }, { 320, 100 }, { 500, 230 },
{ 420, 230 }, { 540, 354 }, { 400, 354 }, { 100, 354 }
};
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 100, 100, 100, 255); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* You can draw lines, one at a time, like these brown ones... */
SDL_SetRenderDrawColor(renderer, 127, 49, 32, 255);
SDL_RenderLine(renderer, 240, 450, 400, 450);
SDL_RenderLine(renderer, 240, 356, 400, 356);
SDL_RenderLine(renderer, 240, 356, 240, 450);
SDL_RenderLine(renderer, 400, 356, 400, 450);
/* You can also draw a series of connected lines in a single batch... */
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
SDL_RenderLines(renderer, line_points, SDL_arraysize(line_points));
/* here's a bunch of lines drawn out from a center point in a circle. */
/* we randomize the color of each line, so it functions as animation. */
for (i = 0; i < 360; i++) {
const float size = 30.0f;
const float x = 320.0f;
const float y = 95.0f - (size / 2.0f);
SDL_SetRenderDrawColor(renderer, SDL_rand(256), SDL_rand(256), SDL_rand(256), 255);
SDL_RenderLine(renderer, x, y, x + SDL_sinf((float) i) * size, y + SDL_cosf((float) i) * size);
}
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate)
{
/* SDL will clean up the window/renderer for us. */
}

View File

@ -1663,6 +1663,16 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
bool handled_by_ime = false; bool handled_by_ime = false;
const Uint64 timestamp_raw_ns = Wayland_GetKeyboardTimestampRaw(input, time); const Uint64 timestamp_raw_ns = Wayland_GetKeyboardTimestampRaw(input, time);
if (state == WL_KEYBOARD_KEY_STATE_REPEATED) {
// If this key shouldn't be repeated, just return.
if (input->xkb.keymap && WAYLAND_xkb_keymap_key_repeats(input->xkb.keymap, key + 8)) {
return;
}
// SDL automatically handles key tracking and repeat status, so just map 'repeated' to 'pressed'.
state = WL_KEYBOARD_KEY_STATE_PRESSED;
}
Wayland_UpdateImplicitGrabSerial(input, serial); Wayland_UpdateImplicitGrabSerial(input, serial);
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {

View File

@ -78,7 +78,9 @@
#define SDL_WL_COMPOSITOR_VERSION 4 #define SDL_WL_COMPOSITOR_VERSION 4
#endif #endif
#if SDL_WAYLAND_CHECK_VERSION(1, 22, 0) #if SDL_WAYLAND_CHECK_VERSION(1, 24, 0)
#define SDL_WL_SEAT_VERSION 10
#elif SDL_WAYLAND_CHECK_VERSION(1, 22, 0)
#define SDL_WL_SEAT_VERSION 9 #define SDL_WL_SEAT_VERSION 9
#elif SDL_WAYLAND_CHECK_VERSION(1, 21, 0) #elif SDL_WAYLAND_CHECK_VERSION(1, 21, 0)
#define SDL_WL_SEAT_VERSION 8 #define SDL_WL_SEAT_VERSION 8

View File

@ -1119,6 +1119,7 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
Thing *thing = NULL; Thing *thing = NULL;
saw_event = true; saw_event = true;
SDL_ConvertEventToRenderCoordinates(SDL_GetRenderer(SDL_GetWindowFromEvent(event)), event);
switch (event->type) { switch (event->type) {
case SDL_EVENT_MOUSE_MOTION: case SDL_EVENT_MOUSE_MOTION:

View File

@ -184,6 +184,20 @@ static const char *AudioChansToStr(const int channels)
return "?"; return "?";
} }
static void scale_mouse_coords(SDL_FPoint *p)
{
SDL_Window *window = SDL_GetMouseFocus();
if (window) {
int w, p_w;
float scale;
SDL_GetWindowSize(window, &w, NULL);
SDL_GetWindowSizeInPixels(window, &p_w, NULL);
scale = (float)p_w / (float)w;
p->x *= scale;
p->y *= scale;
}
}
static void loop(void) static void loop(void)
{ {
int i, j; int i, j;
@ -228,6 +242,7 @@ static void loop(void)
} }
if (SDL_GetMouseState(&p.x, &p.y) & SDL_BUTTON_LMASK) { if (SDL_GetMouseState(&p.x, &p.y) & SDL_BUTTON_LMASK) {
scale_mouse_coords(&p);
if (active_slider == -1) { if (active_slider == -1) {
for (i = 0; i < NUM_SLIDERS; ++i) { for (i = 0; i < NUM_SLIDERS; ++i) {
if (SDL_PointInRectFloat(&p, &sliders[i].area)) { if (SDL_PointInRectFloat(&p, &sliders[i].area)) {

View File

@ -714,6 +714,16 @@ static int SDLCALL stdlib_getsetenv(void *arg)
#endif #endif
#endif #endif
#ifndef SDL_PLATFORM_WINDOWS
#define FMT_PRILLd "%lld"
#define FMT_PRILLu "%llu"
#else
/* make sure long long is 64 bits */
SDL_COMPILE_TIME_ASSERT(longlong_size64, sizeof(long long) == 8);
#define FMT_PRILLd "%I64d"
#define FMT_PRILLu "%I64u"
#endif
/** /**
* Call to SDL_sscanf * Call to SDL_sscanf
*/ */
@ -781,7 +791,7 @@ static int SDLCALL stdlib_sscanf(void *arg)
SIZED_TEST_CASE(short, short, "%hd") SIZED_TEST_CASE(short, short, "%hd")
SIZED_TEST_CASE(long, long, "%ld") SIZED_TEST_CASE(long, long, "%ld")
SIZED_TEST_CASE(long long, long_long, "%lld") SIZED_TEST_CASE(long long, long_long, FMT_PRILLd)
size_output = 123; size_output = 123;
expected_size_output = ~((size_t)0); expected_size_output = ~((size_t)0);
@ -1301,26 +1311,26 @@ static int SDLCALL stdlib_strtox(void *arg)
} while (0) } while (0)
// infer decimal // infer decimal
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "\t 123abcxyz", 0, 123, 6); // skip leading space STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "\t 123abcxyz", 0, 123, 6); // skip leading space
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "+123abcxyz", 0, 123, 4); STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "+123abcxyz", 0, 123, 4);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "+123abcxyz", 0, 123, 4); STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "+123abcxyz", 0, 123, 4);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "-123abcxyz", 0, -123, 4); STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "-123abcxyz", 0, -123, 4);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "9999999999999999999999999999999999999999abcxyz", 0, ullong_max, 40); STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "9999999999999999999999999999999999999999abcxyz", 0, ullong_max, 40);
// infer hexadecimal // infer hexadecimal
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "0x123abcxyz", 0, 0x123abc, 8); STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "0x123abcxyz", 0, 0x123abc, 8);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "0X123ABCXYZ", 0, 0x123abc, 8); // uppercase X STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "0X123ABCXYZ", 0, 0x123abc, 8); // uppercase X
// infer octal // infer octal
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "0123abcxyz", 0, 0123, 4); STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "0123abcxyz", 0, 0123, 4);
// arbitrary bases // arbitrary bases
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "00110011", 2, 51, 8); STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "00110011", 2, 51, 8);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "-uvwxyz", 32, -991, 3); STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "-uvwxyz", 32, -991, 3);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "ZzZzZzZzZzZzZzZzZzZzZzZzZ", 36, ullong_max, 25); STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "ZzZzZzZzZzZzZzZzZzZzZzZzZ", 36, ullong_max, 25);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "-0", 10, 0, 2); STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "-0", 10, 0, 2);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", " - 1", 0, 0, 0); // invalid input STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, " - 1", 0, 0, 0); // invalid input
// We know that SDL_strtol, SDL_strtoul and SDL_strtoll share the same code path as SDL_strtoull under the hood, // We know that SDL_strtol, SDL_strtoul and SDL_strtoll share the same code path as SDL_strtoull under the hood,
// so the most interesting test cases are those close to the bounds of the integer type. // so the most interesting test cases are those close to the bounds of the integer type.
@ -1342,15 +1352,15 @@ static int SDLCALL stdlib_strtox(void *arg)
} }
if (sizeof(long long) == 8) { if (sizeof(long long) == 8) {
STRTOX_TEST_CASE(SDL_strtoll, long long, "%lld", "9223372036854775807", 10, 9223372036854775807LL, 19); STRTOX_TEST_CASE(SDL_strtoll, long long, FMT_PRILLd, "9223372036854775807", 10, 9223372036854775807LL, 19);
STRTOX_TEST_CASE(SDL_strtoll, long long, "%lld", "9223372036854775808", 10, 9223372036854775807LL, 19); STRTOX_TEST_CASE(SDL_strtoll, long long, FMT_PRILLd, "9223372036854775808", 10, 9223372036854775807LL, 19);
STRTOX_TEST_CASE(SDL_strtoll, long long, "%lld", "-9223372036854775808", 10, -9223372036854775807LL - 1, 20); STRTOX_TEST_CASE(SDL_strtoll, long long, FMT_PRILLd, "-9223372036854775808", 10, -9223372036854775807LL - 1, 20);
STRTOX_TEST_CASE(SDL_strtoll, long long, "%lld", "-9223372036854775809", 10, -9223372036854775807LL - 1, 20); STRTOX_TEST_CASE(SDL_strtoll, long long, FMT_PRILLd, "-9223372036854775809", 10, -9223372036854775807LL - 1, 20);
STRTOX_TEST_CASE(SDL_strtoll, long long, "%lld", "-9999999999999999999999999999999999999999", 10, -9223372036854775807LL - 1, 41); STRTOX_TEST_CASE(SDL_strtoll, long long, FMT_PRILLd, "-9999999999999999999999999999999999999999", 10, -9223372036854775807LL - 1, 41);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "18446744073709551615", 10, 18446744073709551615ULL, 20); STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLd, "18446744073709551615", 10, 18446744073709551615ULL, 20);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "18446744073709551616", 10, 18446744073709551615ULL, 20); STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLd, "18446744073709551616", 10, 18446744073709551615ULL, 20);
STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, "%llu", "-18446744073709551615", 10, 1, 21); STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLd, "-18446744073709551615", 10, 1, 21);
} }
#undef STRTOX_TEST_CASE #undef STRTOX_TEST_CASE

View File

@ -33,17 +33,25 @@ static SDL_HitTestResult SDLCALL
hitTest(SDL_Window *window, const SDL_Point *pt, void *data) hitTest(SDL_Window *window, const SDL_Point *pt, void *data)
{ {
int i; int i;
int w, h; int w, h, p_w;
SDL_Point adj_pt;
float scale;
SDL_GetWindowSize(window, &w, &h);
SDL_GetWindowSizeInPixels(window, &p_w, NULL);
scale = (float)p_w / (float)w;
adj_pt.x = (int)SDL_floorf(pt->x * scale);
adj_pt.y = (int)SDL_floorf(pt->y * scale);
for (i = 0; i < numareas; i++) { for (i = 0; i < numareas; i++) {
if (SDL_PointInRect(pt, &areas[i])) { if (SDL_PointInRect(&adj_pt, &areas[i])) {
SDL_Log("HIT-TEST: DRAGGABLE\n"); SDL_Log("HIT-TEST: DRAGGABLE\n");
return SDL_HITTEST_DRAGGABLE; return SDL_HITTEST_DRAGGABLE;
} }
} }
SDL_GetWindowSize(window, &w, &h);
#define REPORT_RESIZE_HIT(name) \ #define REPORT_RESIZE_HIT(name) \
{ \ { \
SDL_Log("HIT-TEST: RESIZE_" #name "\n"); \ SDL_Log("HIT-TEST: RESIZE_" #name "\n"); \

View File

@ -211,6 +211,7 @@ static void loop(void *arg)
/* Check for events */ /* Check for events */
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
SDLTest_CommonEvent(state, &event, done); SDLTest_CommonEvent(state, &event, done);
SDL_ConvertEventToRenderCoordinates(SDL_GetRenderer(SDL_GetWindowFromEvent(&event)), &event);
switch (event.type) { switch (event.type) {
case SDL_EVENT_MOUSE_BUTTON_DOWN: case SDL_EVENT_MOUSE_BUTTON_DOWN:
mouse_begin_x = event.button.x; mouse_begin_x = event.button.x;

View File

@ -184,7 +184,7 @@ static void HandleMouseAdded(SDL_MouseID instance_id)
SDL_Window *window = state->windows[0]; SDL_Window *window = state->windows[0];
int i, w = 0, h = 0; int i, w = 0, h = 0;
SDL_GetWindowSize(window, &w, &h); SDL_GetWindowSizeInPixels(window, &w, &h);
for (i = 0; i < SDL_arraysize(mice); ++i) { for (i = 0; i < SDL_arraysize(mice); ++i) {
MouseState *mouse_state = &mice[i]; MouseState *mouse_state = &mice[i];
@ -237,7 +237,7 @@ static void HandleMouseMotion(SDL_MouseMotionEvent *event)
ActivateMouse(event->which); ActivateMouse(event->which);
SDL_GetWindowSize(window, &w, &h); SDL_GetWindowSizeInPixels(window, &w, &h);
for (i = 0; i < SDL_arraysize(mice); ++i) { for (i = 0; i < SDL_arraysize(mice); ++i) {
MouseState *mouse_state = &mice[i]; MouseState *mouse_state = &mice[i];

View File

@ -255,6 +255,7 @@ static void loop(void)
/* Check for events */ /* Check for events */
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
SDLTest_CommonEvent(state, &event, &done); SDLTest_CommonEvent(state, &event, &done);
SDL_ConvertEventToRenderCoordinates(SDL_GetRenderer(SDL_GetWindowFromEvent(&event)), &event);
switch (event.type) { switch (event.type) {
case SDL_EVENT_WINDOW_RESIZED: case SDL_EVENT_WINDOW_RESIZED:

View File

@ -165,6 +165,7 @@ static void loop(void)
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
SDLTest_CommonEvent(state, &event, &done); SDLTest_CommonEvent(state, &event, &done);
SDL_ConvertEventToRenderCoordinates(SDL_GetRenderer(SDL_GetWindowFromEvent(&event)), &event);
if (event.type == SDL_EVENT_WINDOW_RESIZED) { if (event.type == SDL_EVENT_WINDOW_RESIZED) {
SDL_Window *window = SDL_GetWindowFromEvent(&event); SDL_Window *window = SDL_GetWindowFromEvent(&event);

View File

@ -46,7 +46,7 @@
compositor after the callback is fired and as such the client must not compositor after the callback is fired and as such the client must not
attempt to use it after that point. attempt to use it after that point.
The callback_data passed in the callback is the event serial. The callback_data passed in the callback is undefined and should be ignored.
</description> </description>
<arg name="callback" type="new_id" interface="wl_callback" <arg name="callback" type="new_id" interface="wl_callback"
summary="callback object for the sync request"/> summary="callback object for the sync request"/>
@ -212,7 +212,7 @@
</request> </request>
</interface> </interface>
<interface name="wl_shm_pool" version="1"> <interface name="wl_shm_pool" version="2">
<description summary="a shared memory pool"> <description summary="a shared memory pool">
The wl_shm_pool object encapsulates a piece of memory shared The wl_shm_pool object encapsulates a piece of memory shared
between the compositor and client. Through the wl_shm_pool between the compositor and client. Through the wl_shm_pool
@ -262,17 +262,17 @@
created, but using the new size. This request can only be created, but using the new size. This request can only be
used to make the pool bigger. used to make the pool bigger.
This request only changes the amount of bytes that are mmapped This request only changes the amount of bytes that are mmapped
by the server and does not touch the file corresponding to the by the server and does not touch the file corresponding to the
file descriptor passed at creation time. It is the client's file descriptor passed at creation time. It is the client's
responsibility to ensure that the file is at least as big as responsibility to ensure that the file is at least as big as
the new pool size. the new pool size.
</description> </description>
<arg name="size" type="int" summary="new size of the pool, in bytes"/> <arg name="size" type="int" summary="new size of the pool, in bytes"/>
</request> </request>
</interface> </interface>
<interface name="wl_shm" version="1"> <interface name="wl_shm" version="2">
<description summary="shared memory support"> <description summary="shared memory support">
A singleton global object that provides support for shared A singleton global object that provides support for shared
memory. memory.
@ -419,6 +419,21 @@
<entry name="xbgr16161616" value="0x38344258" summary="[63:0] x:B:G:R 16:16:16:16 little endian"/> <entry name="xbgr16161616" value="0x38344258" summary="[63:0] x:B:G:R 16:16:16:16 little endian"/>
<entry name="argb16161616" value="0x38345241" summary="[63:0] A:R:G:B 16:16:16:16 little endian"/> <entry name="argb16161616" value="0x38345241" summary="[63:0] A:R:G:B 16:16:16:16 little endian"/>
<entry name="abgr16161616" value="0x38344241" summary="[63:0] A:B:G:R 16:16:16:16 little endian"/> <entry name="abgr16161616" value="0x38344241" summary="[63:0] A:B:G:R 16:16:16:16 little endian"/>
<entry name="c1" value="0x20203143" summary="[7:0] C0:C1:C2:C3:C4:C5:C6:C7 1:1:1:1:1:1:1:1 eight pixels/byte"/>
<entry name="c2" value="0x20203243" summary="[7:0] C0:C1:C2:C3 2:2:2:2 four pixels/byte"/>
<entry name="c4" value="0x20203443" summary="[7:0] C0:C1 4:4 two pixels/byte"/>
<entry name="d1" value="0x20203144" summary="[7:0] D0:D1:D2:D3:D4:D5:D6:D7 1:1:1:1:1:1:1:1 eight pixels/byte"/>
<entry name="d2" value="0x20203244" summary="[7:0] D0:D1:D2:D3 2:2:2:2 four pixels/byte"/>
<entry name="d4" value="0x20203444" summary="[7:0] D0:D1 4:4 two pixels/byte"/>
<entry name="d8" value="0x20203844" summary="[7:0] D"/>
<entry name="r1" value="0x20203152" summary="[7:0] R0:R1:R2:R3:R4:R5:R6:R7 1:1:1:1:1:1:1:1 eight pixels/byte"/>
<entry name="r2" value="0x20203252" summary="[7:0] R0:R1:R2:R3 2:2:2:2 four pixels/byte"/>
<entry name="r4" value="0x20203452" summary="[7:0] R0:R1 4:4 two pixels/byte"/>
<entry name="r10" value="0x20303152" summary="[15:0] x:R 6:10 little endian"/>
<entry name="r12" value="0x20323152" summary="[15:0] x:R 4:12 little endian"/>
<entry name="avuy8888" value="0x59555641" summary="[31:0] A:Cr:Cb:Y 8:8:8:8 little endian"/>
<entry name="xvuy8888" value="0x59555658" summary="[31:0] X:Cr:Cb:Y 8:8:8:8 little endian"/>
<entry name="p030" value="0x30333050" summary="2x2 subsampled Cr:Cb plane 10 bits per channel packed"/>
</enum> </enum>
<request name="create_pool"> <request name="create_pool">
@ -442,6 +457,17 @@
</description> </description>
<arg name="format" type="uint" enum="format" summary="buffer pixel format"/> <arg name="format" type="uint" enum="format" summary="buffer pixel format"/>
</event> </event>
<!-- Version 2 additions -->
<request name="release" type="destructor" since="2">
<description summary="release the shm object">
Using this request a client can tell the server that it is not going to
use the shm object anymore.
Objects created via this interface remain unaffected.
</description>
</request>
</interface> </interface>
<interface name="wl_buffer" version="1"> <interface name="wl_buffer" version="1">
@ -453,9 +479,11 @@
client provides and updates the contents is defined by the buffer factory client provides and updates the contents is defined by the buffer factory
interface. interface.
If the buffer uses a format that has an alpha channel, the alpha channel Color channels are assumed to be electrical rather than optical (in other
is assumed to be premultiplied in the color channels unless otherwise words, encoded with a transfer function) unless otherwise specified. If
specified. the buffer uses a format that has an alpha channel, the alpha channel is
assumed to be premultiplied into the electrical color channel values
(after transfer function encoding) unless otherwise specified.
Note, because wl_buffer objects are created from multiple independent Note, because wl_buffer objects are created from multiple independent
factory interfaces, the wl_buffer interface is frozen at version 1. factory interfaces, the wl_buffer interface is frozen at version 1.
@ -847,6 +875,7 @@
<enum name="error"> <enum name="error">
<entry name="role" value="0" summary="given wl_surface has another role"/> <entry name="role" value="0" summary="given wl_surface has another role"/>
<entry name="used_source" value="1" summary="source has already been used"/>
</enum> </enum>
<request name="start_drag"> <request name="start_drag">
@ -868,7 +897,7 @@
The icon surface is an optional (can be NULL) surface that The icon surface is an optional (can be NULL) surface that
provides an icon to be moved around with the cursor. Initially, provides an icon to be moved around with the cursor. Initially,
the top-left corner of the icon surface is placed at the cursor the top-left corner of the icon surface is placed at the cursor
hotspot, but subsequent wl_surface.attach request can move the hotspot, but subsequent wl_surface.offset requests can move the
relative position. Attach requests must be confirmed with relative position. Attach requests must be confirmed with
wl_surface.commit as usual. The icon surface is given the role of wl_surface.commit as usual. The icon surface is given the role of
a drag-and-drop icon. If the icon surface already has another role, a drag-and-drop icon. If the icon surface already has another role,
@ -876,6 +905,10 @@
The input region is ignored for wl_surfaces with the role of a The input region is ignored for wl_surfaces with the role of a
drag-and-drop icon. drag-and-drop icon.
The given source may not be used in any further set_selection or
start_drag requests. Attempting to reuse a previously-used source
may send a used_source error.
</description> </description>
<arg name="source" type="object" interface="wl_data_source" allow-null="true" summary="data source for the eventual transfer"/> <arg name="source" type="object" interface="wl_data_source" allow-null="true" summary="data source for the eventual transfer"/>
<arg name="origin" type="object" interface="wl_surface" summary="surface where the drag originates"/> <arg name="origin" type="object" interface="wl_surface" summary="surface where the drag originates"/>
@ -889,6 +922,10 @@
to the data from the source on behalf of the client. to the data from the source on behalf of the client.
To unset the selection, set the source to NULL. To unset the selection, set the source to NULL.
The given source may not be used in any further set_selection or
start_drag requests. Attempting to reuse a previously-used source
may send a used_source error.
</description> </description>
<arg name="source" type="object" interface="wl_data_source" allow-null="true" summary="data source for the selection"/> <arg name="source" type="object" interface="wl_data_source" allow-null="true" summary="data source for the selection"/>
<arg name="serial" type="uint" summary="serial number of the event that triggered this request"/> <arg name="serial" type="uint" summary="serial number of the event that triggered this request"/>
@ -1411,7 +1448,7 @@
<entry name="invalid_size" value="2" summary="buffer size is invalid"/> <entry name="invalid_size" value="2" summary="buffer size is invalid"/>
<entry name="invalid_offset" value="3" summary="buffer offset is invalid"/> <entry name="invalid_offset" value="3" summary="buffer offset is invalid"/>
<entry name="defunct_role_object" value="4" <entry name="defunct_role_object" value="4"
summary="surface was destroyed before its role object"/> summary="surface was destroyed before its role object"/>
</enum> </enum>
<request name="destroy" type="destructor"> <request name="destroy" type="destructor">
@ -1440,9 +1477,9 @@
When the bound wl_surface version is 5 or higher, passing any When the bound wl_surface version is 5 or higher, passing any
non-zero x or y is a protocol violation, and will result in an non-zero x or y is a protocol violation, and will result in an
'invalid_offset' error being raised. The x and y arguments are ignored 'invalid_offset' error being raised. The x and y arguments are ignored
and do not change the pending state. To achieve equivalent semantics, and do not change the pending state. To achieve equivalent semantics,
use wl_surface.offset. use wl_surface.offset.
Surface contents are double-buffered state, see wl_surface.commit. Surface contents are double-buffered state, see wl_surface.commit.
@ -1477,8 +1514,9 @@
mutates the underlying buffer storage, the surface contents become mutates the underlying buffer storage, the surface contents become
undefined immediately. undefined immediately.
If wl_surface.attach is sent with a NULL wl_buffer, the If wl_surface.attach is sent with a NULL wl_buffer, or the pending
following wl_surface.commit will remove the surface content. wl_buffer has been destroyed, the following wl_surface.commit will
remove the surface content.
</description> </description>
<arg name="buffer" type="object" interface="wl_buffer" allow-null="true" <arg name="buffer" type="object" interface="wl_buffer" allow-null="true"
summary="buffer of surface contents"/> summary="buffer of surface contents"/>
@ -1618,16 +1656,18 @@
<description summary="commit pending surface state"> <description summary="commit pending surface state">
Surface state (input, opaque, and damage regions, attached buffers, Surface state (input, opaque, and damage regions, attached buffers,
etc.) is double-buffered. Protocol requests modify the pending state, etc.) is double-buffered. Protocol requests modify the pending state,
as opposed to the current state in use by the compositor. A commit as opposed to the active state in use by the compositor.
request atomically applies all pending state, replacing the current
state. After commit, the new pending state is as documented for each
related request.
On commit, a pending wl_buffer is applied first, and all other state A commit request atomically creates a content update from the pending
second. This means that all coordinates in double-buffered state are state, even if the pending state has not been touched. The content
relative to the new wl_buffer coming into use, except for update is placed in a queue until it becomes active. After commit, the
wl_surface.attach itself. If there is no pending wl_buffer, the new pending state is as documented for each related request.
coordinates are relative to the current surface contents.
When the content update is applied, the wl_buffer is applied before all
other state. This means that all coordinates in double-buffered state
are relative to the newly attached wl_buffers, except for
wl_surface.attach itself. If there is no newly attached wl_buffer, the
coordinates are relative to the previous content update.
All requests that need a commit to become effective are documented All requests that need a commit to become effective are documented
to affect double-buffered state. to affect double-buffered state.
@ -1666,10 +1706,12 @@
<request name="set_buffer_transform" since="2"> <request name="set_buffer_transform" since="2">
<description summary="sets the buffer transformation"> <description summary="sets the buffer transformation">
This request sets an optional transformation on how the compositor This request sets the transformation that the client has already applied
interprets the contents of the buffer attached to the surface. The to the content of the buffer. The accepted values for the transform
accepted values for the transform parameter are the values for parameter are the values for wl_output.transform.
wl_output.transform.
The compositor applies the inverse of this transformation whenever it
uses the buffer contents.
Buffer transform is double-buffered state, see wl_surface.commit. Buffer transform is double-buffered state, see wl_surface.commit.
@ -1725,11 +1767,11 @@
a buffer that is larger (by a factor of scale in each dimension) a buffer that is larger (by a factor of scale in each dimension)
than the desired surface size. than the desired surface size.
If scale is not positive the invalid_scale protocol error is If scale is not greater than 0 the invalid_scale protocol error is
raised. raised.
</description> </description>
<arg name="scale" type="int" <arg name="scale" type="int"
summary="positive scale for interpreting buffer contents"/> summary="scale for interpreting buffer contents"/>
</request> </request>
<!-- Version 4 additions --> <!-- Version 4 additions -->
@ -1802,10 +1844,15 @@
This event indicates the preferred buffer scale for this surface. It is This event indicates the preferred buffer scale for this surface. It is
sent whenever the compositor's preference changes. sent whenever the compositor's preference changes.
Before receiving this event the preferred buffer scale for this surface
is 1.
It is intended that scaling aware clients use this event to scale their It is intended that scaling aware clients use this event to scale their
content and use wl_surface.set_buffer_scale to indicate the scale they content and use wl_surface.set_buffer_scale to indicate the scale they
have rendered with. This allows clients to supply a higher detail have rendered with. This allows clients to supply a higher detail
buffer. buffer.
The compositor shall emit a scale value greater than 0.
</description> </description>
<arg name="factor" type="int" summary="preferred scaling factor"/> <arg name="factor" type="int" summary="preferred scaling factor"/>
</event> </event>
@ -1815,16 +1862,19 @@
This event indicates the preferred buffer transform for this surface. This event indicates the preferred buffer transform for this surface.
It is sent whenever the compositor's preference changes. It is sent whenever the compositor's preference changes.
It is intended that transform aware clients use this event to apply the Before receiving this event the preferred buffer transform for this
transform to their content and use wl_surface.set_buffer_transform to surface is normal.
indicate the transform they have rendered with.
Applying this transformation to the surface buffer contents and using
wl_surface.set_buffer_transform might allow the compositor to use the
surface buffer more efficiently.
</description> </description>
<arg name="transform" type="uint" enum="wl_output.transform" <arg name="transform" type="uint" enum="wl_output.transform"
summary="preferred transform"/> summary="preferred transform"/>
</event> </event>
</interface> </interface>
<interface name="wl_seat" version="9"> <interface name="wl_seat" version="10">
<description summary="group of input devices"> <description summary="group of input devices">
A seat is a group of keyboards, pointer and touch devices. This A seat is a group of keyboards, pointer and touch devices. This
object is published as a global during start up, or when such a object is published as a global during start up, or when such a
@ -1957,7 +2007,7 @@
</interface> </interface>
<interface name="wl_pointer" version="9"> <interface name="wl_pointer" version="10">
<description summary="pointer input device"> <description summary="pointer input device">
The wl_pointer interface represents one or more input devices, The wl_pointer interface represents one or more input devices,
such as mice, which control the pointer location and pointer_focus such as mice, which control the pointer location and pointer_focus
@ -1992,9 +2042,9 @@
where (x, y) are the coordinates of the pointer location, in where (x, y) are the coordinates of the pointer location, in
surface-local coordinates. surface-local coordinates.
On surface.attach requests to the pointer surface, hotspot_x On wl_surface.offset requests to the pointer surface, hotspot_x
and hotspot_y are decremented by the x and y parameters and hotspot_y are decremented by the x and y parameters
passed to the request. Attach must be confirmed by passed to the request. The offset must be applied by
wl_surface.commit as usual. wl_surface.commit as usual.
The hotspot can also be updated by passing the currently set The hotspot can also be updated by passing the currently set
@ -2248,7 +2298,7 @@
<arg name="axis" type="uint" enum="axis" summary="the axis stopped with this event"/> <arg name="axis" type="uint" enum="axis" summary="the axis stopped with this event"/>
</event> </event>
<event name="axis_discrete" since="5"> <event name="axis_discrete" since="5" deprecated-since="8">
<description summary="axis click event"> <description summary="axis click event">
Discrete step information for scroll and other axes. Discrete step information for scroll and other axes.
@ -2370,10 +2420,20 @@
</event> </event>
</interface> </interface>
<interface name="wl_keyboard" version="9"> <interface name="wl_keyboard" version="10">
<description summary="keyboard input device"> <description summary="keyboard input device">
The wl_keyboard interface represents one or more keyboards The wl_keyboard interface represents one or more keyboards
associated with a seat. associated with a seat.
Each wl_keyboard has the following logical state:
- an active surface (possibly null),
- the keys currently logically down,
- the active modifiers,
- the active group.
By default, the active surface is null, the keys currently logically down
are empty, the active modifiers and the active group are 0.
</description> </description>
<enum name="keymap_format"> <enum name="keymap_format">
@ -2408,10 +2468,15 @@
The compositor must send the wl_keyboard.modifiers event after this The compositor must send the wl_keyboard.modifiers event after this
event. event.
In the wl_keyboard logical state, this event sets the active surface to
the surface argument and the keys currently logically down to the keys
in the keys argument. The compositor must not send this event if the
wl_keyboard already had an active surface immediately before this event.
</description> </description>
<arg name="serial" type="uint" summary="serial number of the enter event"/> <arg name="serial" type="uint" summary="serial number of the enter event"/>
<arg name="surface" type="object" interface="wl_surface" summary="surface gaining keyboard focus"/> <arg name="surface" type="object" interface="wl_surface" summary="surface gaining keyboard focus"/>
<arg name="keys" type="array" summary="the currently pressed keys"/> <arg name="keys" type="array" summary="the keys currently logically down"/>
</event> </event>
<event name="leave"> <event name="leave">
@ -2422,8 +2487,10 @@
The leave notification is sent before the enter notification The leave notification is sent before the enter notification
for the new focus. for the new focus.
After this event client must assume that all keys, including modifiers, In the wl_keyboard logical state, this event resets all values to their
are lifted and also it must stop key repeating if there's some going on. defaults. The compositor must not send this event if the active surface
of the wl_keyboard was not equal to the surface argument immediately
before this event.
</description> </description>
<arg name="serial" type="uint" summary="serial number of the leave event"/> <arg name="serial" type="uint" summary="serial number of the leave event"/>
<arg name="surface" type="object" interface="wl_surface" summary="surface that lost keyboard focus"/> <arg name="surface" type="object" interface="wl_surface" summary="surface that lost keyboard focus"/>
@ -2432,9 +2499,18 @@
<enum name="key_state"> <enum name="key_state">
<description summary="physical key state"> <description summary="physical key state">
Describes the physical state of a key that produced the key event. Describes the physical state of a key that produced the key event.
Since version 10, the key can be in a "repeated" pseudo-state which
means the same as "pressed", but is used to signal repetition in the
key event.
The key may only enter the repeated state after entering the pressed
state and before entering the released state. This event may be
generated multiple times while the key is down.
</description> </description>
<entry name="released" value="0" summary="key is not pressed"/> <entry name="released" value="0" summary="key is not pressed"/>
<entry name="pressed" value="1" summary="key is pressed"/> <entry name="pressed" value="1" summary="key is pressed"/>
<entry name="repeated" value="2" summary="key was repeated" since="10"/>
</enum> </enum>
<event name="key"> <event name="key">
@ -2448,6 +2524,20 @@
If this event produces a change in modifiers, then the resulting If this event produces a change in modifiers, then the resulting
wl_keyboard.modifiers event must be sent after this event. wl_keyboard.modifiers event must be sent after this event.
In the wl_keyboard logical state, this event adds the key to the keys
currently logically down (if the state argument is pressed) or removes
the key from the keys currently logically down (if the state argument is
released). The compositor must not send this event if the wl_keyboard
did not have an active surface immediately before this event. The
compositor must not send this event if state is pressed (resp. released)
and the key was already logically down (resp. was not logically down)
immediately before this event.
Since version 10, compositors may send key events with the "repeated"
key state when a wl_keyboard.repeat_info event with a rate argument of
0 has been received. This allows the compositor to take over the
responsibility of key repetition.
</description> </description>
<arg name="serial" type="uint" summary="serial number of the key event"/> <arg name="serial" type="uint" summary="serial number of the key event"/>
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/> <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
@ -2459,6 +2549,17 @@
<description summary="modifier and group state"> <description summary="modifier and group state">
Notifies clients that the modifier and/or group state has Notifies clients that the modifier and/or group state has
changed, and it should update its local state. changed, and it should update its local state.
The compositor may send this event without a surface of the client
having keyboard focus, for example to tie modifier information to
pointer focus instead. If a modifier event with pressed modifiers is sent
without a prior enter event, the client can assume the modifier state is
valid until it receives the next wl_keyboard.modifiers event. In order to
reset the modifier state again, the compositor can send a
wl_keyboard.modifiers event with no pressed modifiers.
In the wl_keyboard logical state, this event updates the modifiers and
group.
</description> </description>
<arg name="serial" type="uint" summary="serial number of the modifiers event"/> <arg name="serial" type="uint" summary="serial number of the modifiers event"/>
<arg name="mods_depressed" type="uint" summary="depressed modifiers"/> <arg name="mods_depressed" type="uint" summary="depressed modifiers"/>
@ -2497,7 +2598,7 @@
</event> </event>
</interface> </interface>
<interface name="wl_touch" version="9"> <interface name="wl_touch" version="10">
<description summary="touchscreen input device"> <description summary="touchscreen input device">
The wl_touch interface represents a touchscreen The wl_touch interface represents a touchscreen
associated with a seat. associated with a seat.
@ -2566,6 +2667,8 @@
currently active on this client's surface. The client is currently active on this client's surface. The client is
responsible for finalizing the touch points, future touch points on responsible for finalizing the touch points, future touch points on
this surface may reuse the touch point ID. this surface may reuse the touch point ID.
No frame event is required after the cancel event.
</description> </description>
</event> </event>
@ -2665,10 +2768,9 @@
</enum> </enum>
<enum name="transform"> <enum name="transform">
<description summary="transform from framebuffer to output"> <description summary="transformation applied to buffer contents">
This describes the transform that a compositor will apply to a This describes transformations that clients and compositors apply to
surface to compensate for the rotation or mirroring of an buffer contents.
output device.
The flipped values correspond to an initial flip around a The flipped values correspond to an initial flip around a
vertical axis followed by rotation. vertical axis followed by rotation.
@ -2700,6 +2802,10 @@
The geometry event will be followed by a done event (starting from The geometry event will be followed by a done event (starting from
version 2). version 2).
Clients should use wl_surface.preferred_buffer_transform instead of the
transform advertised by this event to find the preferred buffer
transform to use for a surface.
Note: wl_output only advertises partial information about the output Note: wl_output only advertises partial information about the output
position and identification. Some compositors, for instance those not position and identification. Some compositors, for instance those not
implementing a desktop-style output layout or those exposing virtual implementing a desktop-style output layout or those exposing virtual
@ -2722,7 +2828,7 @@
<arg name="model" type="string" <arg name="model" type="string"
summary="textual description of the model"/> summary="textual description of the model"/>
<arg name="transform" type="int" enum="transform" <arg name="transform" type="int" enum="transform"
summary="transform that maps framebuffer to output"/> summary="additional transformation applied to buffer contents during presentation"/>
</event> </event>
<enum name="mode" bitfield="true"> <enum name="mode" bitfield="true">
@ -2795,8 +2901,9 @@
This event contains scaling geometry information This event contains scaling geometry information
that is not in the geometry event. It may be sent after that is not in the geometry event. It may be sent after
binding the output object or if the output scale changes binding the output object or if the output scale changes
later. If it is not sent, the client should assume a later. The compositor will emit a non-zero, positive
scale of 1. value for scale. If it is not sent, the client should
assume a scale of 1.
A scale larger than 1 means that the compositor will A scale larger than 1 means that the compositor will
automatically scale surface buffers by this amount automatically scale surface buffers by this amount
@ -2804,12 +2911,9 @@
displays where applications rendering at the native displays where applications rendering at the native
resolution would be too small to be legible. resolution would be too small to be legible.
It is intended that scaling aware clients track the Clients should use wl_surface.preferred_buffer_scale
current output of a surface, and if it is on a scaled instead of this event to find the preferred buffer
output it should use wl_surface.set_buffer_scale with scale to use for a surface.
the scale of the output. That way the compositor can
avoid scaling the surface, and the client can supply
a higher detail image.
The scale event will be followed by a done event. The scale event will be followed by a done event.
</description> </description>
@ -3035,6 +3139,11 @@
If the parent wl_surface object is destroyed, the sub-surface is If the parent wl_surface object is destroyed, the sub-surface is
unmapped. unmapped.
A sub-surface never has the keyboard focus of any seat.
The wl_surface.offset request is ignored: clients must use set_position
instead to move the sub-surface.
</description> </description>
<request name="destroy" type="destructor"> <request name="destroy" type="destructor">
@ -3060,9 +3169,7 @@
surface area. Negative values are allowed. surface area. Negative values are allowed.
The scheduled coordinates will take effect whenever the state of the The scheduled coordinates will take effect whenever the state of the
parent surface is applied. When this happens depends on whether the parent surface is applied.
parent surface is in synchronized mode or not. See
wl_subsurface.set_sync and wl_subsurface.set_desync for details.
If more than one set_position request is invoked by the client before If more than one set_position request is invoked by the client before
the commit of the parent surface, the position of a new request always the commit of the parent surface, the position of a new request always
@ -3085,9 +3192,7 @@
The z-order is double-buffered. Requests are handled in order and The z-order is double-buffered. Requests are handled in order and
applied immediately to a pending state. The final pending state is applied immediately to a pending state. The final pending state is
copied to the active state the next time the state of the parent copied to the active state the next time the state of the parent
surface is applied. When this happens depends on whether the parent surface is applied.
surface is in synchronized mode or not. See wl_subsurface.set_sync and
wl_subsurface.set_desync for details.
A new sub-surface is initially added as the top-most in the stack A new sub-surface is initially added as the top-most in the stack
of its siblings and parent. of its siblings and parent.