diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 14a28430c983e..94374ea72c9c1 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -632,37 +632,75 @@ pointer_handle_axis_common_v1(struct SDL_WaylandInput *input, } static void -pointer_handle_axis_common(struct SDL_WaylandInput *input, SDL_bool discrete, +pointer_handle_axis_common(struct SDL_WaylandInput *input, enum SDL_WaylandAxisEvent type, uint32_t axis, wl_fixed_t value) { enum wl_pointer_axis a = axis; if (input->pointer_focus) { switch (a) { - case WL_POINTER_AXIS_VERTICAL_SCROLL: - if (discrete) { - /* this is a discrete axis event so we process it and flag - * to ignore future continuous axis events in this frame */ - input->pointer_curr_axis_info.is_y_discrete = SDL_TRUE; - } else if(input->pointer_curr_axis_info.is_y_discrete) { - /* this is a continuous axis event and we have already - * processed a discrete axis event before so we ignore it */ - break; + case WL_POINTER_AXIS_VERTICAL_SCROLL: + switch (type) { + case AXIS_EVENT_VALUE120: + /* + * High resolution scroll event. The spec doesn't state that axis_value120 + * events are limited to one per frame, so the values are accumulated. + */ + if (input->pointer_curr_axis_info.y_axis_type != AXIS_EVENT_VALUE120) { + input->pointer_curr_axis_info.y_axis_type = AXIS_EVENT_VALUE120; + input->pointer_curr_axis_info.y = 0.0f; } - input->pointer_curr_axis_info.y = 0 - (float)wl_fixed_to_double(value); + input->pointer_curr_axis_info.y += 0 - (float)wl_fixed_to_double(value); break; - case WL_POINTER_AXIS_HORIZONTAL_SCROLL: - if (discrete) { - /* this is a discrete axis event so we process it and flag - * to ignore future continuous axis events in this frame */ - input->pointer_curr_axis_info.is_x_discrete = SDL_TRUE; - } else if(input->pointer_curr_axis_info.is_x_discrete) { - /* this is a continuous axis event and we have already - * processed a discrete axis event before so we ignore it */ - break; + case AXIS_EVENT_DISCRETE: + /* + * This is a discrete axis event, so we process it and set the + * flag to ignore future continuous axis events in this frame. + */ + if (input->pointer_curr_axis_info.y_axis_type != AXIS_EVENT_DISCRETE) { + input->pointer_curr_axis_info.y_axis_type = AXIS_EVENT_DISCRETE; + input->pointer_curr_axis_info.y = 0 - (float)wl_fixed_to_double(value); + } + break; + case AXIS_EVENT_CONTINUOUS: + /* Only process continuous events if no discrete events have been received. */ + if (input->pointer_curr_axis_info.y_axis_type == AXIS_EVENT_CONTINUOUS) { + input->pointer_curr_axis_info.y = 0 - (float)wl_fixed_to_double(value); + } + break; + } + break; + case WL_POINTER_AXIS_HORIZONTAL_SCROLL: + switch (type) { + case AXIS_EVENT_VALUE120: + /* + * High resolution scroll event. The spec doesn't state that axis_value120 + * events are limited to one per frame, so the values are accumulated. + */ + if (input->pointer_curr_axis_info.x_axis_type != AXIS_EVENT_VALUE120) { + input->pointer_curr_axis_info.x_axis_type = AXIS_EVENT_VALUE120; + input->pointer_curr_axis_info.x = 0.0f; + } + input->pointer_curr_axis_info.x += (float)wl_fixed_to_double(value); + break; + case AXIS_EVENT_DISCRETE: + /* + * This is a discrete axis event, so we process it and set the + * flag to ignore future continuous axis events in this frame. + */ + if (input->pointer_curr_axis_info.x_axis_type != AXIS_EVENT_DISCRETE) { + input->pointer_curr_axis_info.x_axis_type = AXIS_EVENT_DISCRETE; + input->pointer_curr_axis_info.x = (float)wl_fixed_to_double(value); } - input->pointer_curr_axis_info.x = (float)wl_fixed_to_double(value); break; + case AXIS_EVENT_CONTINUOUS: + /* Only process continuous events if no discrete events have been received. */ + if (input->pointer_curr_axis_info.x_axis_type == AXIS_EVENT_CONTINUOUS) { + input->pointer_curr_axis_info.x = (float)wl_fixed_to_double(value); + } + break; + } + break; } } } @@ -674,7 +712,7 @@ pointer_handle_axis(void *data, struct wl_pointer *pointer, struct SDL_WaylandInput *input = data; if(wl_seat_get_version(input->seat) >= 5) - pointer_handle_axis_common(input, SDL_FALSE, axis, value); + pointer_handle_axis_common(input, AXIS_EVENT_CONTINUOUS, axis, value); else pointer_handle_axis_common_v1(input, time, axis, value); } @@ -686,15 +724,29 @@ pointer_handle_frame(void *data, struct wl_pointer *pointer) SDL_WindowData *window = input->pointer_focus; float x, y; - if (input->pointer_curr_axis_info.is_x_discrete) - x = input->pointer_curr_axis_info.x; - else + switch(input->pointer_curr_axis_info.x_axis_type) { + case AXIS_EVENT_CONTINUOUS: x = input->pointer_curr_axis_info.x / WAYLAND_WHEEL_AXIS_UNIT; + break; + case AXIS_EVENT_DISCRETE: + x = input->pointer_curr_axis_info.x; + break; + case AXIS_EVENT_VALUE120: + x = input->pointer_curr_axis_info.x / 120.0f; + break; + } - if (input->pointer_curr_axis_info.is_y_discrete) - y = input->pointer_curr_axis_info.y; - else + switch(input->pointer_curr_axis_info.y_axis_type) { + case AXIS_EVENT_CONTINUOUS: y = input->pointer_curr_axis_info.y / WAYLAND_WHEEL_AXIS_UNIT; + break; + case AXIS_EVENT_DISCRETE: + y = input->pointer_curr_axis_info.y; + break; + case AXIS_EVENT_VALUE120: + y = input->pointer_curr_axis_info.y / 120.0f; + break; + } /* clear pointer_curr_axis_info for next frame */ SDL_memset(&input->pointer_curr_axis_info, 0, sizeof input->pointer_curr_axis_info); @@ -725,9 +777,17 @@ pointer_handle_axis_discrete(void *data, struct wl_pointer *pointer, { struct SDL_WaylandInput *input = data; - pointer_handle_axis_common(input, SDL_TRUE, axis, wl_fixed_from_int(discrete)); + pointer_handle_axis_common(input, AXIS_EVENT_DISCRETE, axis, wl_fixed_from_int(discrete)); } +static void +pointer_handle_axis_value120(void *data, struct wl_pointer *pointer, + uint32_t axis, int32_t value120) +{ + struct SDL_WaylandInput *input = data; + + pointer_handle_axis_common(input, AXIS_EVENT_VALUE120, axis, wl_fixed_from_int(value120)); +} static const struct wl_pointer_listener pointer_listener = { pointer_handle_enter, @@ -739,6 +799,7 @@ static const struct wl_pointer_listener pointer_listener = { pointer_handle_axis_source, // Version 5 pointer_handle_axis_stop, // Version 5 pointer_handle_axis_discrete, // Version 5 + pointer_handle_axis_value120 // Version 8 }; static void diff --git a/src/video/wayland/SDL_waylandevents_c.h b/src/video/wayland/SDL_waylandevents_c.h index 9bcb2c9b155f7..491c3852660ee 100644 --- a/src/video/wayland/SDL_waylandevents_c.h +++ b/src/video/wayland/SDL_waylandevents_c.h @@ -29,6 +29,13 @@ #include "SDL_waylanddatamanager.h" #include "SDL_waylandkeyboard.h" +enum SDL_WaylandAxisEvent +{ + AXIS_EVENT_CONTINUOUS = 0, + AXIS_EVENT_DISCRETE, + AXIS_EVENT_VALUE120 +}; + struct SDL_WaylandTabletSeat; struct SDL_WaylandTabletObjectListNode { @@ -113,10 +120,10 @@ struct SDL_WaylandInput { /* information about axis events on current frame */ struct { - SDL_bool is_x_discrete; + enum SDL_WaylandAxisEvent x_axis_type; float x; - SDL_bool is_y_discrete; + enum SDL_WaylandAxisEvent y_axis_type; float y; } pointer_curr_axis_info; diff --git a/wayland-protocols/wayland.xml b/wayland-protocols/wayland.xml index 471daf668e388..10781cf167949 100644 --- a/wayland-protocols/wayland.xml +++ b/wayland-protocols/wayland.xml @@ -179,7 +179,7 @@ the related request is done. - + Notify the client when the related request is done. @@ -187,7 +187,7 @@ - + A compositor. This object is a singleton global. The compositor is in charge of combining the contents of multiple @@ -258,6 +258,12 @@ for the pool from the file descriptor passed when the pool was created, but using the new size. This request can only be used to make the pool bigger. + + This request only changes the amount of bytes that are mmapped + by the server and does not touch the file corresponding to the + file descriptor passed at creation time. It is the client's + responsibility to ensure that the file is at least as big as + the new pool size. @@ -271,8 +277,8 @@ Clients can create wl_shm_pool objects using the create_pool request. - At connection setup time, the wl_shm object emits one or more - format events to inform clients about the valid pixel formats + On binding the wl_shm object one or more format events + are emitted to inform clients about the valid pixel formats that can be used for buffers. @@ -296,6 +302,9 @@ The drm format codes match the macros defined in drm_fourcc.h, except argb8888 and xrgb8888. The formats actually supported by the compositor will be reported by the format event. + + For all wl_shm formats and unless specified in another protocol + extension, pre-multiplied alpha is used for pixel values. @@ -403,6 +412,10 @@ + + + + @@ -431,10 +444,15 @@ A buffer provides the content for a wl_surface. Buffers are - created through factory interfaces such as wl_drm, wl_shm or - similar. It has a width and a height and can be attached to a - wl_surface, but the mechanism by which a client provides and - updates the contents is defined by the buffer factory interface. + created through factory interfaces such as wl_shm, wp_linux_buffer_params + (from the linux-dmabuf protocol extension) or similar. It has a width and + a height and can be attached to a wl_surface, but the mechanism by which a + client provides and updates the contents is defined by the buffer factory + interface. + + If the buffer uses a format that has an alpha channel, the alpha channel + is assumed to be premultiplied in the color channels unless otherwise + specified. @@ -878,7 +896,7 @@ which will subsequently be used in either the data_device.enter event (for drag-and-drop) or the data_device.selection event (for selections). Immediately - following the data_device_data_offer event, the new data_offer + following the data_device.data_offer event, the new data_offer object will send out data_offer.offer events to describe the mime types it offers. @@ -948,9 +966,10 @@ immediately before receiving keyboard focus and when a new selection is set while the client has keyboard focus. The data_offer is valid until a new data_offer or NULL is received - or until the client loses keyboard focus. The client must - destroy the previous selection data_offer, if any, upon receiving - this event. + or until the client loses keyboard focus. Switching surface with + keyboard focus within the same client doesn't mean a new selection + will be sent. The client must destroy the previous selection + data_offer, if any, upon receiving this event. @@ -1038,7 +1057,8 @@ a basic surface. Note! This protocol is deprecated and not intended for production use. - For desktop-style user interfaces, use xdg_shell. + For desktop-style user interfaces, use xdg_shell. Compositors and clients + should not implement this interface. @@ -1332,7 +1352,7 @@ - + A surface is a rectangular area that may be displayed on zero or more outputs, and shown any number of times at the compositor's @@ -1384,6 +1404,7 @@ + @@ -1406,7 +1427,14 @@ buffer's upper left corner, relative to the current buffer's upper left corner, in surface-local coordinates. In other words, the x and y, combined with the new surface size define in which - directions the surface's size changes. + directions the surface's size changes. Setting anything other than 0 + as x and y arguments is discouraged, and should instead be replaced + with using the separate wl_surface.offset request. + + 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 + 'invalid_offset' error being raised. To achieve equivalent semantics, + use wl_surface.offset. Surface contents are double-buffered state, see wl_surface.commit. @@ -1434,9 +1462,12 @@ from the same backing storage or use wp_linux_buffer_release. Destroying the wl_buffer after wl_buffer.release does not change - the surface contents. However, if the client destroys the - wl_buffer before receiving the wl_buffer.release event, the surface - contents become undefined immediately. + the surface contents. Destroying the wl_buffer before wl_buffer.release + is allowed as long as the underlying buffer storage isn't re-used (this + can happen e.g. on client process termination). However, if the client + destroys the wl_buffer before receiving the wl_buffer.release event and + mutates the underlying buffer storage, the surface contents become + undefined immediately. If wl_surface.attach is sent with a NULL wl_buffer, the following wl_surface.commit will remove the surface content. @@ -1734,9 +1765,30 @@ + + + + + + The x and y arguments specify the location of the new pending + buffer's upper left corner, relative to the current buffer's upper + left corner, in surface-local coordinates. In other words, the + x and y, combined with the new surface size define in which + directions the surface's size changes. + + Surface location offset is double-buffered state, see + wl_surface.commit. + + This request is semantically equivalent to and the replaces the x and y + arguments in the wl_surface.attach request in wl_surface versions prior + to 5. See wl_surface.attach for details. + + + + - + 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 @@ -1838,9 +1890,22 @@ - In a multiseat configuration this can be used by the client to help - identify which physical devices the seat represents. Based on - the seat configuration used by the compositor. + In a multi-seat configuration the seat name can be used by clients to + help identify which physical devices the seat represents. + + The seat name is a UTF-8 string with no convention defined for its + contents. Each name is unique among all wl_seat globals. The name is + only guaranteed to be unique for the current compositor instance. + + The same seat names are used for all clients. Thus, the name can be + shared across processes to refer to a specific wl_seat global. + + The name event is sent after binding to the seat global. This event is + only sent once per seat object, and the name does not change over the + lifetime of the wl_seat global. + + Compositors may re-use the same seat name if the wl_seat global is + destroyed and re-created later. @@ -1856,7 +1921,7 @@ - + The wl_pointer interface represents one or more input devices, such as mice, which control the pointer location and pointer_focus @@ -1905,6 +1970,10 @@ wl_surface is no longer used as the cursor. When the use as a cursor ends, the current and pending input regions become undefined, and the wl_surface is unmapped. + + The serial parameter must match the latest wl_pointer.enter + serial number sent to the client. Otherwise the request will be + ignored. + + + + Discrete high-resolution scroll information. + + This event carries high-resolution wheel scroll information, + with each multiple of 120 representing one logical scroll step + (a wheel detent). For example, an axis_value120 of 30 is one quarter of + a logical scroll step in the positive direction, a value120 of + -240 are two logical scroll steps in the negative direction within the + same hardware event. + Clients that rely on discrete scrolling should accumulate the + value120 to multiples of 120 before processing the event. + + The value120 must not be zero. + + This event replaces the wl_pointer.axis_discrete event in clients + supporting wl_pointer version 8 or later. + + Where a wl_pointer.axis_source event occurs in the same + wl_pointer.frame, the axis source applies to this event. + + The order of wl_pointer.axis_value120 and wl_pointer.axis_source is + not guaranteed. + + + + - + The wl_keyboard interface represents one or more keyboards associated with a seat. @@ -2193,13 +2294,14 @@ + summary="libxkbcommon compatible, null-terminated string; to determine the xkb keycode, clients must add 8 to the key event keycode"/> This event provides a file descriptor to the client which can be - memory-mapped to provide a keyboard mapping description. + memory-mapped in read-only mode to provide a keyboard mapping + description. From version 7 onwards, the fd must be mapped with MAP_PRIVATE by the recipient, as MAP_SHARED may fail. @@ -2305,7 +2407,7 @@ - + The wl_touch interface represents a touchscreen associated with a seat. @@ -2449,7 +2551,7 @@ - + An output describes part of the compositor geometry. The compositor works in the 'compositor coordinate system' and an @@ -2505,12 +2607,15 @@ The physical size can be set to zero if it doesn't make sense for this output (e.g. for projectors or virtual outputs). + The geometry event will be followed by a done event (starting from + version 2). + Note: wl_output only advertises partial information about the output position and identification. Some compositors, for instance those not implementing a desktop-style output layout or those exposing virtual outputs, might fake this information. Instead of using x and y, clients should use xdg_output.logical_position. Instead of using make and model, - clients should use xdg_output.name and xdg_output.description. + clients should use name and description. @@ -2566,6 +2671,9 @@ The vertical refresh rate can be set to zero if it doesn't make sense for this output (e.g. for virtual outputs). + The mode event will be followed by a done event (starting from + version 2). + Clients should not use the refresh rate to schedule frames. Instead, they should use the wl_surface.frame event or the presentation-time protocol. @@ -2612,6 +2720,8 @@ 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. @@ -2624,6 +2734,62 @@ use the output object anymore. + + + + + + Many compositors will assign user-friendly names to their outputs, show + them to the user, allow the user to refer to an output, etc. The client + may wish to know this name as well to offer the user similar behaviors. + + The name is a UTF-8 string with no convention defined for its contents. + Each name is unique among all wl_output globals. The name is only + guaranteed to be unique for the compositor instance. + + The same output name is used for all clients for a given wl_output + global. Thus, the name can be shared across processes to refer to a + specific wl_output global. + + The name is not guaranteed to be persistent across sessions, thus cannot + be used to reliably identify an output in e.g. configuration files. + + Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc. However, do + not assume that the name is a reflection of an underlying DRM connector, + X11 connection, etc. + + The name event is sent after binding the output object. This event is + only sent once per output object, and the name does not change over the + lifetime of the wl_output global. + + Compositors may re-use the same output name if the wl_output global is + destroyed and re-created later. Compositors should avoid re-using the + same name if possible. + + The name event will be followed by a done event. + + + + + + + Many compositors can produce human-readable descriptions of their + outputs. The client may wish to know this description as well, e.g. for + output selection purposes. + + The description is a UTF-8 string with no convention defined for its + contents. The description is not guaranteed to be unique among all + wl_output globals. Examples might include 'Foocorp 11" Display' or + 'Virtual X11 output via :1'. + + The description event is sent after binding the output object and + whenever the description changes. The description is optional, and may + not be sent at all. + + The description event will be followed by a done event. + + +