update sdl Merge commit '644725478f4de0f074a6834e8423ac36dce3974f'

This commit is contained in:
2023-09-23 18:53:11 +02:00
172 changed files with 7495 additions and 4062 deletions

View File

@ -29,6 +29,7 @@
#define TEXT_MIME "text/plain;charset=utf-8"
#define FILE_MIME "text/uri-list"
#define FILE_PORTAL_MIME "application/vnd.portal.filetransfer"
typedef struct
{

View File

@ -34,34 +34,30 @@ typedef struct
const char *libname;
} waylanddynlib;
#ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL
#define SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL NULL
#endif
#ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR
#define SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR NULL
#endif
#ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON
#define SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON NULL
#endif
#ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR
#define SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR NULL
#endif
static waylanddynlib waylandlibs[] = {
{ NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC },
#ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL
{ NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL },
#endif
#ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR
{ NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR },
#endif
#ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON
{ NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON },
{ NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR }
#endif
#ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR
{ NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR },
#endif
{ NULL, NULL }
};
static void *WAYLAND_GetSym(const char *fnname, int *pHasModule, SDL_bool required)
{
int i;
void *fn = NULL;
for (i = 0; i < SDL_TABLESIZE(waylandlibs); i++) {
if (waylandlibs[i].lib != NULL) {
fn = SDL_LoadFunction(waylandlibs[i].lib, fnname);
waylanddynlib *dynlib;
for (dynlib = waylandlibs; dynlib->libname; dynlib++) {
if (dynlib->lib != NULL) {
fn = SDL_LoadFunction(dynlib->lib, fnname);
if (fn != NULL) {
break;
}
@ -69,10 +65,11 @@ static void *WAYLAND_GetSym(const char *fnname, int *pHasModule, SDL_bool requir
}
#if DEBUG_DYNAMIC_WAYLAND
if (fn != NULL)
SDL_Log("WAYLAND: Found '%s' in %s (%p)\n", fnname, waylandlibs[i].libname, fn);
else
if (fn != NULL) {
SDL_Log("WAYLAND: Found '%s' in %s (%p)\n", fnname, dynlib->libname, fn);
} else {
SDL_Log("WAYLAND: Symbol '%s' NOT FOUND!\n", fnname);
}
#endif
if (fn == NULL && required) {

View File

@ -823,7 +823,7 @@ static void pointer_handle_axis(void *data, struct wl_pointer *pointer,
{
struct SDL_WaylandInput *input = data;
if (wl_seat_get_version(input->seat) >= 5) {
if (wl_seat_get_version(input->seat) >= WL_POINTER_FRAME_SINCE_VERSION) {
input->pointer_curr_axis_info.timestamp_ns = Wayland_GetPointerTimestamp(input, time);
pointer_handle_axis_common(input, AXIS_EVENT_CONTINUOUS, axis, value);
} else {
@ -1848,28 +1848,40 @@ static void data_device_handle_enter(void *data, struct wl_data_device *wl_data_
data_device->drag_offer = wl_data_offer_get_user_data(id);
/* TODO: SDL Support more mime types */
has_mime = Wayland_data_offer_has_mime(
data_device->drag_offer, FILE_MIME);
/* If drag_mime is NULL this will decline the offer */
wl_data_offer_accept(id, serial,
(has_mime == SDL_TRUE) ? FILE_MIME : NULL);
#ifdef SDL_USE_LIBDBUS
if (Wayland_data_offer_has_mime(data_device->drag_offer, FILE_PORTAL_MIME)) {
has_mime = SDL_TRUE;
wl_data_offer_accept(id, serial, FILE_PORTAL_MIME);
}
#endif
if (Wayland_data_offer_has_mime(data_device->drag_offer, FILE_MIME)) {
has_mime = SDL_TRUE;
wl_data_offer_accept(id, serial, FILE_MIME);
}
/* SDL only supports "copy" style drag and drop */
if (has_mime == SDL_TRUE) {
if (has_mime) {
dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
} else {
/* drag_mime is NULL this will decline the offer */
wl_data_offer_accept(id, serial, NULL);
}
if (wl_data_offer_get_version(data_device->drag_offer->offer) >= 3) {
if (wl_data_offer_get_version(data_device->drag_offer->offer) >=
WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION) {
wl_data_offer_set_actions(data_device->drag_offer->offer,
dnd_action, dnd_action);
}
/* find the current window */
if (surface && SDL_WAYLAND_own_surface(surface)) {
SDL_WindowData *window = (SDL_WindowData *)wl_surface_get_user_data(surface);
if (window) {
data_device->dnd_window = window->sdlwindow;
}
if (surface) {
if (SDL_WAYLAND_own_surface(surface)) {
SDL_WindowData *window = (SDL_WindowData *)wl_surface_get_user_data(surface);
if (window) {
data_device->dnd_window = window->sdlwindow;
}
} else {
data_device->dnd_window = NULL;
}
}
}
}
@ -1877,11 +1889,10 @@ static void data_device_handle_enter(void *data, struct wl_data_device *wl_data_
static void data_device_handle_leave(void *data, struct wl_data_device *wl_data_device)
{
SDL_WaylandDataDevice *data_device = data;
SDL_WaylandDataOffer *offer = NULL;
if (data_device->selection_offer != NULL) {
data_device->selection_offer = NULL;
Wayland_data_offer_destroy(offer);
if (data_device->drag_offer != NULL) {
Wayland_data_offer_destroy(data_device->drag_offer);
data_device->drag_offer = NULL;
}
}
@ -1890,27 +1901,15 @@ static void data_device_handle_motion(void *data, struct wl_data_device *wl_data
{
SDL_WaylandDataDevice *data_device = data;
if (data_device->drag_offer != NULL) {
/* TODO: SDL Support more mime types */
size_t length;
void *buffer = Wayland_data_offer_receive(data_device->drag_offer,
FILE_MIME, &length);
if (buffer) {
char *saveptr = NULL;
char *token = SDL_strtok_r((char *)buffer, "\r\n", &saveptr);
while (token != NULL) {
char *fn = Wayland_URIToLocal(token);
if (fn) {
double dx;
double dy;
dx = wl_fixed_to_double(x);
dy = wl_fixed_to_double(y);
SDL_SendDropPosition(data_device->dnd_window, fn, (float)dx, (float)dy);
}
token = SDL_strtok_r(NULL, "\r\n", &saveptr);
}
SDL_free(buffer);
}
if (data_device->drag_offer != NULL && data_device->dnd_window) {
const float dx = (float)wl_fixed_to_double(x);
const float dy = (float)wl_fixed_to_double(y);
/* XXX: Send the filename here if the event system ever starts passing it though.
* Any future implementation should cache the filenames, as otherwise this could
* hammer the DBus interface hundreds or even thousands of times per second.
*/
SDL_SendDropPosition(data_device->dnd_window, NULL, dx, dy);
}
}
@ -2039,25 +2038,66 @@ static void data_device_handle_drop(void *data, struct wl_data_device *wl_data_d
{
SDL_WaylandDataDevice *data_device = data;
if (data_device->drag_offer != NULL) {
if (data_device->drag_offer != NULL && data_device->dnd_window) {
/* TODO: SDL Support more mime types */
size_t length;
void *buffer = Wayland_data_offer_receive(data_device->drag_offer,
FILE_MIME, &length);
if (buffer) {
char *saveptr = NULL;
char *token = SDL_strtok_r((char *)buffer, "\r\n", &saveptr);
while (token != NULL) {
char *fn = Wayland_URIToLocal(token);
if (fn) {
SDL_SendDropFile(data_device->dnd_window, fn);
SDL_bool drop_handled = SDL_FALSE;
#ifdef SDL_USE_LIBDBUS
if (Wayland_data_offer_has_mime(
data_device->drag_offer, FILE_PORTAL_MIME)) {
void *buffer = Wayland_data_offer_receive(data_device->drag_offer,
FILE_PORTAL_MIME, &length);
if (buffer) {
SDL_DBusContext *dbus = SDL_DBus_GetContext();
if (dbus) {
int path_count = 0;
char **paths = SDL_DBus_DocumentsPortalRetrieveFiles(buffer, &path_count);
/* If dropped files contain a directory the list is empty */
if (paths && path_count > 0) {
for (int i = 0; i < path_count; i++) {
SDL_SendDropFile(data_device->dnd_window, paths[i]);
}
dbus->free_string_array(paths);
SDL_SendDropComplete(data_device->dnd_window);
drop_handled = SDL_TRUE;
}
}
token = SDL_strtok_r(NULL, "\r\n", &saveptr);
SDL_free(buffer);
}
SDL_SendDropComplete(data_device->dnd_window);
SDL_free(buffer);
}
#endif
/* If XDG document portal fails fallback.
* When running a flatpak sandbox this will most likely be a list of
* non paths that are not visible to the application
*/
if (!drop_handled && Wayland_data_offer_has_mime(
data_device->drag_offer, FILE_MIME)) {
void *buffer = Wayland_data_offer_receive(data_device->drag_offer,
FILE_MIME, &length);
if (buffer) {
char *saveptr = NULL;
char *token = SDL_strtok_r((char *)buffer, "\r\n", &saveptr);
while (token != NULL) {
char *fn = Wayland_URIToLocal(token);
if (fn) {
SDL_SendDropFile(data_device->dnd_window, fn);
}
token = SDL_strtok_r(NULL, "\r\n", &saveptr);
}
SDL_SendDropComplete(data_device->dnd_window);
SDL_free(buffer);
drop_handled = SDL_TRUE;
}
}
if (drop_handled && wl_data_offer_get_version(data_device->drag_offer->offer) >=
WL_DATA_OFFER_FINISH_SINCE_VERSION) {
wl_data_offer_finish(data_device->drag_offer->offer);
}
}
Wayland_data_offer_destroy(data_device->drag_offer);
data_device->drag_offer = NULL;
}
static void data_device_handle_selection(void *data, struct wl_data_device *wl_data_device,

View File

@ -916,7 +916,7 @@ static int Wayland_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *di
/* When an emulated, exclusive fullscreen window has focus, treat the mode dimensions as the display bounds. */
if (display->fullscreen_window &&
display->fullscreen_window->fullscreen_exclusive &&
display->fullscreen_window == SDL_GetFocusWindow() &&
display->fullscreen_window->driverdata->active &&
display->fullscreen_window->current_fullscreen_mode.w != 0 &&
display->fullscreen_window->current_fullscreen_mode.h != 0) {
rect->w = display->fullscreen_window->current_fullscreen_mode.w;

View File

@ -28,9 +28,12 @@
#if defined(SDL_VIDEO_VULKAN) && defined(SDL_VIDEO_DRIVER_WAYLAND)
#include "../SDL_vulkan_internal.h"
#include "SDL_waylandvideo.h"
#include "SDL_waylandwindow.h"
#include "../SDL_vulkan_internal.h"
#include "SDL_waylandvulkan.h"
#include <SDL3/SDL_syswm.h>

View File

@ -29,7 +29,7 @@
#ifndef SDL_waylandvulkan_h_
#define SDL_waylandvulkan_h_
#include "../SDL_vulkan_internal.h"
#include <SDL3/SDL_vulkan.h>
#include "../SDL_sysvideo.h"
#if defined(SDL_VIDEO_VULKAN) && defined(SDL_VIDEO_DRIVER_WAYLAND)

View File

@ -639,7 +639,7 @@ static void handle_configure_xdg_toplevel(void *data,
SDL_bool fullscreen = SDL_FALSE;
SDL_bool maximized = SDL_FALSE;
SDL_bool floating = SDL_TRUE;
SDL_bool focused = SDL_FALSE;
SDL_bool active = SDL_FALSE;
SDL_bool suspended = SDL_FALSE;
wl_array_for_each (state, states) {
switch (*state) {
@ -652,7 +652,7 @@ static void handle_configure_xdg_toplevel(void *data,
floating = SDL_FALSE;
break;
case XDG_TOPLEVEL_STATE_ACTIVATED:
focused = SDL_TRUE;
active = SDL_TRUE;
break;
case XDG_TOPLEVEL_STATE_TILED_LEFT:
case XDG_TOPLEVEL_STATE_TILED_RIGHT:
@ -715,7 +715,7 @@ static void handle_configure_xdg_toplevel(void *data,
* dependent, but in general, we can assume that the flag should remain set until
* the next focused configure event occurs.
*/
if (focused || !(window->flags & SDL_WINDOW_MINIMIZED)) {
if (active || !(window->flags & SDL_WINDOW_MINIMIZED)) {
SDL_SendWindowEvent(window,
maximized ? SDL_EVENT_WINDOW_MAXIMIZED : SDL_EVENT_WINDOW_RESTORED,
0, 0);
@ -745,15 +745,11 @@ static void handle_configure_xdg_toplevel(void *data,
}
}
/* Similar to maximized/restore events above, send focus events too! */
SDL_SendWindowEvent(window,
focused ? SDL_EVENT_WINDOW_FOCUS_GAINED : SDL_EVENT_WINDOW_FOCUS_LOST,
0, 0);
wind->requested_window_width = width;
wind->requested_window_height = height;
wind->floating = floating;
wind->suspended = suspended;
wind->active = active;
if (wind->surface_status == WAYLAND_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
wind->surface_status = WAYLAND_SURFACE_STATUS_WAITING_FOR_FRAME;
}
@ -855,11 +851,10 @@ static void handle_configure_zxdg_decoration(void *data,
WAYLAND_wl_display_roundtrip(driverdata->waylandData->display);
Wayland_HideWindow(device, window);
SDL_zero(driverdata->shell_surface);
driverdata->shell_surface_type = WAYLAND_SURFACE_LIBDECOR;
if (!window->is_hiding && !(window->flags & SDL_WINDOW_HIDDEN)) {
Wayland_ShowWindow(device, window);
}
Wayland_ShowWindow(device, window);
}
}
@ -921,7 +916,7 @@ static void decoration_frame_configure(struct libdecor_frame *frame,
int width, height;
SDL_bool prev_fullscreen = wind->is_fullscreen;
SDL_bool focused = SDL_FALSE;
SDL_bool active = SDL_FALSE;
SDL_bool fullscreen = SDL_FALSE;
SDL_bool maximized = SDL_FALSE;
SDL_bool tiled = SDL_FALSE;
@ -935,7 +930,7 @@ static void decoration_frame_configure(struct libdecor_frame *frame,
if (libdecor_configuration_get_window_state(configuration, &window_state)) {
fullscreen = (window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN) != 0;
maximized = (window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED) != 0;
focused = (window_state & LIBDECOR_WINDOW_STATE_ACTIVE) != 0;
active = (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;
@ -954,18 +949,13 @@ static void decoration_frame_configure(struct libdecor_frame *frame,
* dependent, but in general, we can assume that the flag should remain set until
* the next focused configure event occurs.
*/
if (focused || !(window->flags & SDL_WINDOW_MINIMIZED)) {
if (active || !(window->flags & SDL_WINDOW_MINIMIZED)) {
SDL_SendWindowEvent(window,
maximized ? SDL_EVENT_WINDOW_MAXIMIZED : SDL_EVENT_WINDOW_RESTORED,
0, 0);
}
}
/* Similar to maximized/restore events above, send focus events too! */
SDL_SendWindowEvent(window,
focused ? SDL_EVENT_WINDOW_FOCUS_GAINED : SDL_EVENT_WINDOW_FOCUS_LOST,
0, 0);
/* For fullscreen or fixed-size windows we know our size.
* Always assume the configure is wrong.
*/
@ -1055,6 +1045,7 @@ static void decoration_frame_configure(struct libdecor_frame *frame,
/* Store the new state. */
wind->floating = floating;
wind->suspended = suspended;
wind->active = active;
/* Calculate the new window geometry */
wind->requested_window_width = width;
@ -1529,12 +1520,6 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
/* Restore state that was set prior to this call */
Wayland_SetWindowTitle(_this, window);
if (window->flags & SDL_WINDOW_MAXIMIZED) {
Wayland_MaximizeWindow(_this, window);
}
if (window->flags & SDL_WINDOW_MINIMIZED) {
Wayland_MinimizeWindow(_this, window);
}
/* We have to wait until the surface gets a "configure" event, or use of
* this surface will fail. This is a new rule for xdg_shell.
@ -1940,11 +1925,6 @@ void Wayland_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window)
return;
}
/* Set this flag now even if we never actually maximized, eventually
* ShowWindow will take care of it along with the other window state.
*/
window->flags &= ~SDL_WINDOW_MAXIMIZED;
#ifdef HAVE_LIBDECOR_H
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (wind->shell_surface.libdecor.frame == NULL) {
@ -2025,11 +2005,6 @@ void Wayland_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
return;
}
/* Set this flag now even if we don't actually maximize yet, eventually
* ShowWindow will take care of it along with the other window state.
*/
window->flags |= SDL_WINDOW_MAXIMIZED;
#ifdef HAVE_LIBDECOR_H
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (wind->shell_surface.libdecor.frame == NULL) {
@ -2057,6 +2032,8 @@ void Wayland_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
SDL_VideoData *viddata = _this->driverdata;
SDL_WindowData *wind = window->driverdata;
/* Maximized and minimized flags are mutually exclusive */
window->flags &= ~SDL_WINDOW_MAXIMIZED;
window->flags |= SDL_WINDOW_MINIMIZED;
#ifdef HAVE_LIBDECOR_H

View File

@ -123,6 +123,7 @@ struct SDL_WindowData
SDL_DisplayID last_displayID;
SDL_bool floating;
SDL_bool suspended;
SDL_bool active;
SDL_bool is_fullscreen;
SDL_bool in_fullscreen_transition;
SDL_bool fullscreen_was_positioned;