Merge commit '852f2a6343518919e5ca8d3c1bbcab9f493e3cd8'
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -99,11 +99,9 @@ static int SetSelectionData(SDL_VideoDevice *_this, Atom selection, SDL_Clipboar
|
||||
static void *CloneDataBuffer(const void *buffer, size_t *len)
|
||||
{
|
||||
void *clone = NULL;
|
||||
if (*len > 0 && buffer != NULL) {
|
||||
if (*len > 0 && buffer) {
|
||||
clone = SDL_malloc((*len)+sizeof(Uint32));
|
||||
if (clone == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
} else {
|
||||
if (clone) {
|
||||
SDL_memcpy(clone, buffer, *len);
|
||||
SDL_memset((Uint8 *)clone + *len, 0, sizeof(Uint32));
|
||||
}
|
||||
@ -228,7 +226,7 @@ SDL_bool X11_HasClipboardData(SDL_VideoDevice *_this, const char *mime_type)
|
||||
size_t length;
|
||||
void *data;
|
||||
data = X11_GetClipboardData(_this, mime_type, &length);
|
||||
if (data != NULL) {
|
||||
if (data) {
|
||||
SDL_free(data);
|
||||
}
|
||||
return length > 0;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
14
external/sdl/SDL/src/video/x11/SDL_x11dyn.c
vendored
14
external/sdl/SDL/src/video/x11/SDL_x11dyn.c
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -72,22 +72,22 @@ static void *X11_GetSym(const char *fnname, int *pHasModule)
|
||||
int i;
|
||||
void *fn = NULL;
|
||||
for (i = 0; i < SDL_TABLESIZE(x11libs); i++) {
|
||||
if (x11libs[i].lib != NULL) {
|
||||
if (x11libs[i].lib) {
|
||||
fn = SDL_LoadFunction(x11libs[i].lib, fnname);
|
||||
if (fn != NULL) {
|
||||
if (fn) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG_DYNAMIC_X11
|
||||
if (fn != NULL)
|
||||
if (fn)
|
||||
printf("X11: Found '%s' in %s (%p)\n", fnname, x11libs[i].libname, fn);
|
||||
else
|
||||
printf("X11: Symbol '%s' NOT FOUND!\n", fnname);
|
||||
#endif
|
||||
|
||||
if (fn == NULL) {
|
||||
if (!fn) {
|
||||
*pHasModule = 0; /* kill this module. */
|
||||
}
|
||||
|
||||
@ -133,7 +133,7 @@ void SDL_X11_UnloadSymbols(void)
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC
|
||||
for (i = 0; i < SDL_TABLESIZE(x11libs); i++) {
|
||||
if (x11libs[i].lib != NULL) {
|
||||
if (x11libs[i].lib) {
|
||||
SDL_UnloadObject(x11libs[i].lib);
|
||||
x11libs[i].lib = NULL;
|
||||
}
|
||||
@ -154,7 +154,7 @@ int SDL_X11_LoadSymbols(void)
|
||||
int i;
|
||||
int *thismod = NULL;
|
||||
for (i = 0; i < SDL_TABLESIZE(x11libs); i++) {
|
||||
if (x11libs[i].libname != NULL) {
|
||||
if (x11libs[i].libname) {
|
||||
x11libs[i].lib = SDL_LoadObject(x11libs[i].libname);
|
||||
}
|
||||
}
|
||||
|
2
external/sdl/SDL/src/video/x11/SDL_x11dyn.h
vendored
2
external/sdl/SDL/src/video/x11/SDL_x11dyn.h
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
471
external/sdl/SDL/src/video/x11/SDL_x11events.c
vendored
471
external/sdl/SDL/src/video/x11/SDL_x11events.c
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -39,8 +39,7 @@
|
||||
#include "../../events/SDL_touch_c.h"
|
||||
#include "../../core/linux/SDL_system_theme.h"
|
||||
#include "../../SDL_utils_c.h"
|
||||
|
||||
#include <SDL3/SDL_syswm.h>
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@ -102,7 +101,7 @@ static void X11_ReadProperty(SDL_x11Prop *p, Display *disp, Window w, Atom prop)
|
||||
int bytes_fetch = 0;
|
||||
|
||||
do {
|
||||
if (ret != NULL) {
|
||||
if (ret) {
|
||||
X11_XFree(ret);
|
||||
}
|
||||
X11_XGetWindowProperty(disp, w, prop, 0, bytes_fetch, False, AnyPropertyType, &type, &fmt, &count, &bytes_left, &ret);
|
||||
@ -181,14 +180,14 @@ static SDL_bool X11_KeyRepeat(Display *display, XEvent *event)
|
||||
return d.found;
|
||||
}
|
||||
|
||||
static SDL_bool X11_IsWheelEvent(Display *display, XEvent *event, int *xticks, int *yticks)
|
||||
static SDL_bool X11_IsWheelEvent(Display *display, int button, int *xticks, int *yticks)
|
||||
{
|
||||
/* according to the xlib docs, no specific mouse wheel events exist.
|
||||
However, the defacto standard is that the vertical wheel is X buttons
|
||||
4 (up) and 5 (down) and a horizontal wheel is 6 (left) and 7 (right). */
|
||||
|
||||
/* Xlib defines "Button1" through 5, so we just use literals here. */
|
||||
switch (event->xbutton.button) {
|
||||
switch (button) {
|
||||
case 4:
|
||||
*yticks = 1;
|
||||
return SDL_TRUE;
|
||||
@ -224,7 +223,7 @@ static int X11_URIDecode(char *buf, int len)
|
||||
{
|
||||
int ri, wi, di;
|
||||
char decode = '\0';
|
||||
if (buf == NULL || len < 0) {
|
||||
if (!buf || len < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
@ -300,7 +299,7 @@ static char *X11_URIToLocal(char *uri)
|
||||
/* got a hostname? */
|
||||
if (!local && uri[0] == '/' && uri[2] != '/') {
|
||||
char *hostname_end = SDL_strchr(uri + 1, '/');
|
||||
if (hostname_end != NULL) {
|
||||
if (hostname_end) {
|
||||
char hostname[257];
|
||||
if (gethostname(hostname, 255) == 0) {
|
||||
hostname[256] = '\0';
|
||||
@ -324,27 +323,27 @@ static char *X11_URIToLocal(char *uri)
|
||||
return file;
|
||||
}
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
|
||||
static void X11_HandleGenericEvent(SDL_VideoData *videodata, XEvent *xev)
|
||||
/* An X11 event hook */
|
||||
static SDL_X11EventHook g_X11EventHook = NULL;
|
||||
static void *g_X11EventHookData = NULL;
|
||||
|
||||
void SDL_SetX11EventHook(SDL_X11EventHook callback, void *userdata)
|
||||
{
|
||||
g_X11EventHook = callback;
|
||||
g_X11EventHookData = userdata;
|
||||
}
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
|
||||
static void X11_HandleGenericEvent(SDL_VideoDevice *_this, XEvent *xev)
|
||||
{
|
||||
SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
|
||||
|
||||
/* event is a union, so cookie == &event, but this is type safe. */
|
||||
XGenericEventCookie *cookie = &xev->xcookie;
|
||||
if (X11_XGetEventData(videodata->display, cookie)) {
|
||||
X11_HandleXinput2Event(videodata, cookie);
|
||||
|
||||
/* Send a SDL_EVENT_SYSWM if the application wants them.
|
||||
* Since event data is only available until XFreeEventData is called,
|
||||
* the *only* way for an application to access it is to register an event filter/watcher
|
||||
* and do all the processing on the SDL_EVENT_SYSWM inside the callback. */
|
||||
if (SDL_EventEnabled(SDL_EVENT_SYSWM)) {
|
||||
SDL_SysWMmsg wmmsg;
|
||||
|
||||
wmmsg.version = SDL_SYSWM_CURRENT_VERSION;
|
||||
wmmsg.subsystem = SDL_SYSWM_X11;
|
||||
wmmsg.msg.x11.event = *xev;
|
||||
SDL_SendSysWMEvent(&wmmsg);
|
||||
if (!g_X11EventHook || g_X11EventHook(g_X11EventHookData, xev)) {
|
||||
X11_HandleXinput2Event(_this, cookie);
|
||||
}
|
||||
|
||||
X11_XFreeEventData(videodata->display, cookie);
|
||||
}
|
||||
}
|
||||
@ -561,13 +560,26 @@ static void InitiateWindowResize(SDL_VideoDevice *_this, const SDL_WindowData *d
|
||||
X11_XSync(display, 0);
|
||||
}
|
||||
|
||||
static SDL_bool ProcessHitTest(SDL_VideoDevice *_this, const SDL_WindowData *data, const XEvent *xev)
|
||||
SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y, SDL_bool force_new_result)
|
||||
{
|
||||
SDL_Window *window = data->window;
|
||||
if (!window->hit_test) return SDL_FALSE;
|
||||
const SDL_Point point = { x, y };
|
||||
SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
|
||||
if (!force_new_result && rc == data->hit_test_result) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
X11_SetHitTestCursor(rc);
|
||||
data->hit_test_result = rc;
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
SDL_bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, const SDL_WindowData *data, const float x, const float y)
|
||||
{
|
||||
SDL_Window *window = data->window;
|
||||
|
||||
if (window->hit_test) {
|
||||
const SDL_Point point = { xev->xbutton.x, xev->xbutton.y };
|
||||
const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
|
||||
const SDL_Point point = { x, y };
|
||||
static const int directions[] = {
|
||||
_NET_WM_MOVERESIZE_SIZE_TOPLEFT, _NET_WM_MOVERESIZE_SIZE_TOP,
|
||||
_NET_WM_MOVERESIZE_SIZE_TOPRIGHT, _NET_WM_MOVERESIZE_SIZE_RIGHT,
|
||||
@ -575,7 +587,7 @@ static SDL_bool ProcessHitTest(SDL_VideoDevice *_this, const SDL_WindowData *dat
|
||||
_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT, _NET_WM_MOVERESIZE_SIZE_LEFT
|
||||
};
|
||||
|
||||
switch (rc) {
|
||||
switch (data->hit_test_result) {
|
||||
case SDL_HITTEST_DRAGGABLE:
|
||||
InitiateWindowMove(_this, data, &point);
|
||||
return SDL_TRUE;
|
||||
@ -588,7 +600,7 @@ static SDL_bool ProcessHitTest(SDL_VideoDevice *_this, const SDL_WindowData *dat
|
||||
case SDL_HITTEST_RESIZE_BOTTOM:
|
||||
case SDL_HITTEST_RESIZE_BOTTOMLEFT:
|
||||
case SDL_HITTEST_RESIZE_LEFT:
|
||||
InitiateWindowResize(_this, data, &point, directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
|
||||
InitiateWindowResize(_this, data, &point, directions[data->hit_test_result - SDL_HITTEST_RESIZE_TOPLEFT]);
|
||||
return SDL_TRUE;
|
||||
|
||||
default:
|
||||
@ -689,7 +701,7 @@ static void X11_HandleClipboardEvent(SDL_VideoDevice *_this, const XEvent *xeven
|
||||
/* FIXME: We don't support the X11 INCR protocol for large clipboards. Do we want that? - Yes, yes we do. */
|
||||
/* This is a safe cast, XChangeProperty() doesn't take a const value, but it doesn't modify the data */
|
||||
seln_data = (unsigned char *)clipboard->callback(clipboard->userdata, mime_type, &seln_length);
|
||||
if (seln_data != NULL) {
|
||||
if (seln_data) {
|
||||
X11_XChangeProperty(display, req->requestor, req->property,
|
||||
req->target, 8, PropModeReplace,
|
||||
seln_data, seln_length);
|
||||
@ -765,21 +777,21 @@ static Bool isReparentNotify(Display *display, XEvent *ev, XPointer arg)
|
||||
|
||||
static SDL_bool IsHighLatin1(const char *string, int length)
|
||||
{
|
||||
while (length-- > 0) {
|
||||
Uint8 ch = (Uint8)*string;
|
||||
if (ch >= 0x80) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
++string;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
while (length-- > 0) {
|
||||
Uint8 ch = (Uint8)*string;
|
||||
if (ch >= 0x80) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
++string;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
static int XLookupStringAsUTF8(XKeyEvent *event_struct, char *buffer_return, int bytes_buffer, KeySym *keysym_return, XComposeStatus *status_in_out)
|
||||
{
|
||||
int result = X11_XLookupString(event_struct, buffer_return, bytes_buffer, keysym_return, status_in_out);
|
||||
if (IsHighLatin1(buffer_return, result)) {
|
||||
char *utf8_text = SDL_iconv_string("UTF-8", "ISO-8859-1", buffer_return, result);
|
||||
char *utf8_text = SDL_iconv_string("UTF-8", "ISO-8859-1", buffer_return, result + 1);
|
||||
if (utf8_text) {
|
||||
SDL_strlcpy(buffer_return, utf8_text, bytes_buffer);
|
||||
SDL_free(utf8_text);
|
||||
@ -791,6 +803,78 @@ static int XLookupStringAsUTF8(XKeyEvent *event_struct, char *buffer_return, int
|
||||
return result;
|
||||
}
|
||||
|
||||
SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window)
|
||||
{
|
||||
const SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
|
||||
int i;
|
||||
|
||||
if (videodata && videodata->windowlist) {
|
||||
for (i = 0; i < videodata->numwindows; ++i) {
|
||||
if ((videodata->windowlist[i] != NULL) &&
|
||||
(videodata->windowlist[i]->xwindow == window)) {
|
||||
return videodata->windowlist[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, int button, const float x, const float y, const unsigned long time)
|
||||
{
|
||||
SDL_Window *window = windowdata->window;
|
||||
const SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
|
||||
Display *display = videodata->display;
|
||||
int xticks = 0, yticks = 0;
|
||||
#ifdef DEBUG_XEVENTS
|
||||
printf("window %p: ButtonPress (X11 button = %d)\n", window, button);
|
||||
#endif
|
||||
if (X11_IsWheelEvent(display, button, &xticks, &yticks)) {
|
||||
SDL_SendMouseWheel(0, window, 0, (float)-xticks, (float)yticks, SDL_MOUSEWHEEL_NORMAL);
|
||||
} else {
|
||||
SDL_bool ignore_click = SDL_FALSE;
|
||||
if (button == Button1) {
|
||||
if (X11_TriggerHitTestAction(_this, windowdata, x, y)) {
|
||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0);
|
||||
return; /* don't pass this event on to app. */
|
||||
}
|
||||
} else if (button > 7) {
|
||||
/* X button values 4-7 are used for scrolling, so X1 is 8, X2 is 9, ...
|
||||
=> subtract (8-SDL_BUTTON_X1) to get value SDL expects */
|
||||
button -= (8 - SDL_BUTTON_X1);
|
||||
}
|
||||
if (windowdata->last_focus_event_time) {
|
||||
const int X11_FOCUS_CLICK_TIMEOUT = 10;
|
||||
if (SDL_GetTicks() < (windowdata->last_focus_event_time + X11_FOCUS_CLICK_TIMEOUT)) {
|
||||
ignore_click = !SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, SDL_FALSE);
|
||||
}
|
||||
windowdata->last_focus_event_time = 0;
|
||||
}
|
||||
if (!ignore_click) {
|
||||
SDL_SendMouseButton(0, window, 0, SDL_PRESSED, button);
|
||||
}
|
||||
}
|
||||
X11_UpdateUserTime(windowdata, time);
|
||||
}
|
||||
|
||||
void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata, int button)
|
||||
{
|
||||
SDL_Window *window = windowdata->window;
|
||||
const SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
|
||||
Display *display = videodata->display;
|
||||
/* The X server sends a Release event for each Press for wheels. Ignore them. */
|
||||
int xticks = 0, yticks = 0;
|
||||
#ifdef DEBUG_XEVENTS
|
||||
printf("window %p: ButtonRelease (X11 button = %d)\n", data, xevent->xbutton.button);
|
||||
#endif
|
||||
if (!X11_IsWheelEvent(display, button, &xticks, &yticks)) {
|
||||
if (button > 7) {
|
||||
/* see explanation at case ButtonPress */
|
||||
button -= (8 - SDL_BUTTON_X1);
|
||||
}
|
||||
SDL_SendMouseButton(0, window, 0, SDL_RELEASED, button);
|
||||
}
|
||||
}
|
||||
|
||||
void X11_GetBorderValues(SDL_WindowData *data)
|
||||
{
|
||||
SDL_VideoData *videodata = data->videodata;
|
||||
@ -800,18 +884,24 @@ void X11_GetBorderValues(SDL_WindowData *data)
|
||||
int format;
|
||||
unsigned long nitems, bytes_after;
|
||||
unsigned char *property;
|
||||
if (X11_XGetWindowProperty(display, data->xwindow, videodata->_NET_FRAME_EXTENTS, 0, 16, 0, XA_CARDINAL, &type, &format, &nitems, &bytes_after, &property) == Success) {
|
||||
if (type != None && nitems == 4) {
|
||||
data->border_left = (int)((long *)property)[0];
|
||||
data->border_right = (int)((long *)property)[1];
|
||||
data->border_top = (int)((long *)property)[2];
|
||||
data->border_bottom = (int)((long *)property)[3];
|
||||
}
|
||||
X11_XFree(property);
|
||||
|
||||
/* Some compositors will send extents even when the border hint is turned off. Ignore them in this case. */
|
||||
if (!(data->window->flags & SDL_WINDOW_BORDERLESS)) {
|
||||
if (X11_XGetWindowProperty(display, data->xwindow, videodata->_NET_FRAME_EXTENTS, 0, 16, 0, XA_CARDINAL, &type, &format, &nitems, &bytes_after, &property) == Success) {
|
||||
if (type != None && nitems == 4) {
|
||||
data->border_left = (int)((long *)property)[0];
|
||||
data->border_right = (int)((long *)property)[1];
|
||||
data->border_top = (int)((long *)property)[2];
|
||||
data->border_bottom = (int)((long *)property)[3];
|
||||
}
|
||||
X11_XFree(property);
|
||||
|
||||
#ifdef DEBUG_XEVENTS
|
||||
printf("New _NET_FRAME_EXTENTS: left=%d right=%d, top=%d, bottom=%d\n", data->border_left, data->border_right, data->border_top, data->border_bottom);
|
||||
printf("New _NET_FRAME_EXTENTS: left=%d right=%d, top=%d, bottom=%d\n", data->border_left, data->border_right, data->border_top, data->border_bottom);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
data->border_left = data->border_top = data->border_right = data->border_bottom = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -865,27 +955,24 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
|
||||
if (xevent->type == GenericEvent) {
|
||||
X11_HandleGenericEvent(videodata, xevent);
|
||||
X11_HandleGenericEvent(_this, xevent);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Calling the event hook for generic events happens in X11_HandleGenericEvent(), where the event data is available */
|
||||
if (g_X11EventHook) {
|
||||
if (!g_X11EventHook(g_X11EventHookData, xevent)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XRANDR
|
||||
if (videodata->xrandr_event_base && (xevent->type == (videodata->xrandr_event_base + RRNotify))) {
|
||||
X11_HandleXRandREvent(_this, xevent);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Send a SDL_EVENT_SYSWM if the application wants them */
|
||||
if (SDL_EventEnabled(SDL_EVENT_SYSWM)) {
|
||||
SDL_SysWMmsg wmmsg;
|
||||
|
||||
wmmsg.version = SDL_SYSWM_CURRENT_VERSION;
|
||||
wmmsg.subsystem = SDL_SYSWM_X11;
|
||||
wmmsg.msg.x11.event = *xevent;
|
||||
SDL_SendSysWMEvent(&wmmsg);
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("type = %d display = %d window = %d\n",
|
||||
xevent->type, xevent->xany.display, xevent->xany.window);
|
||||
@ -893,19 +980,19 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XFIXES
|
||||
if (SDL_X11_HAVE_XFIXES &&
|
||||
xevent->type == X11_GetXFixesSelectionNotifyEvent()) {
|
||||
XFixesSelectionNotifyEvent *ev = (XFixesSelectionNotifyEvent *) xevent;
|
||||
xevent->type == X11_GetXFixesSelectionNotifyEvent()) {
|
||||
XFixesSelectionNotifyEvent *ev = (XFixesSelectionNotifyEvent *)xevent;
|
||||
|
||||
/* !!! FIXME: cache atoms */
|
||||
Atom XA_CLIPBOARD = X11_XInternAtom(display, "CLIPBOARD", 0);
|
||||
|
||||
#ifdef DEBUG_XEVENTS
|
||||
printf("window CLIPBOARD: XFixesSelectionNotify (selection = %s)\n",
|
||||
X11_XGetAtomName(display, ev->selection));
|
||||
X11_XGetAtomName(display, ev->selection));
|
||||
#endif
|
||||
|
||||
if (ev->selection == XA_PRIMARY ||
|
||||
(XA_CLIPBOARD != None && ev->selection == XA_CLIPBOARD)) {
|
||||
(XA_CLIPBOARD != None && ev->selection == XA_CLIPBOARD)) {
|
||||
SDL_SendClipboardUpdate();
|
||||
return;
|
||||
}
|
||||
@ -918,17 +1005,9 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
return;
|
||||
}
|
||||
|
||||
data = NULL;
|
||||
if (videodata && videodata->windowlist) {
|
||||
for (i = 0; i < videodata->numwindows; ++i) {
|
||||
if ((videodata->windowlist[i] != NULL) &&
|
||||
(videodata->windowlist[i]->xwindow == xevent->xany.window)) {
|
||||
data = videodata->windowlist[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data == NULL) {
|
||||
data = X11_FindWindow(_this, xevent->xany.window);
|
||||
|
||||
if (!data) {
|
||||
/* The window for KeymapNotify, etc events is 0 */
|
||||
if (xevent->type == KeymapNotify) {
|
||||
#ifdef DEBUG_XEVENTS
|
||||
@ -1019,6 +1098,8 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
|
||||
/* We ungrab in LeaveNotify, so we may need to grab again here */
|
||||
SDL_UpdateWindowGrab(data->window);
|
||||
|
||||
X11_ProcessHitTest(_this, data, mouse->last_x, mouse->last_y, SDL_TRUE);
|
||||
} break;
|
||||
/* Losing mouse coverage? */
|
||||
case LeaveNotify:
|
||||
@ -1234,8 +1315,9 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
xevent->xconfigure.x, xevent->xconfigure.y,
|
||||
xevent->xconfigure.width, xevent->xconfigure.height);
|
||||
#endif
|
||||
/* Real configure notify events are relative to the parent, synthetic events are absolute. */
|
||||
if (!xevent->xconfigure.send_event) {
|
||||
/* Real configure notify events are relative to the parent, synthetic events are absolute. */
|
||||
if (!xevent->xconfigure.send_event)
|
||||
{
|
||||
unsigned int NumChildren;
|
||||
Window ChildReturn, Root, Parent;
|
||||
Window *Children;
|
||||
@ -1250,33 +1332,39 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
|
||||
if (xevent->xconfigure.x != data->last_xconfigure.x ||
|
||||
xevent->xconfigure.y != data->last_xconfigure.y) {
|
||||
SDL_Window *w;
|
||||
int x = xevent->xconfigure.x;
|
||||
int y = xevent->xconfigure.y;
|
||||
if (!data->disable_size_position_events) {
|
||||
SDL_Window *w;
|
||||
int x = xevent->xconfigure.x;
|
||||
int y = xevent->xconfigure.y;
|
||||
|
||||
SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y);
|
||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED,
|
||||
x, y);
|
||||
data->pending_operation &= ~X11_PENDING_OP_MOVE;
|
||||
SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y);
|
||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, x, y);
|
||||
|
||||
#ifdef SDL_USE_IME
|
||||
if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) {
|
||||
/* Update IME candidate list position */
|
||||
SDL_IME_UpdateTextRect(NULL);
|
||||
}
|
||||
if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) {
|
||||
/* Update IME candidate list position */
|
||||
SDL_IME_UpdateTextRect(NULL);
|
||||
}
|
||||
#endif
|
||||
for (w = data->window->first_child; w != NULL; w = w->next_sibling) {
|
||||
/* Don't update hidden child windows, their relative position doesn't change */
|
||||
if (!(w->flags & SDL_WINDOW_HIDDEN)) {
|
||||
X11_UpdateWindowPosition(w);
|
||||
for (w = data->window->first_child; w; w = w->next_sibling) {
|
||||
/* Don't update hidden child windows, their relative position doesn't change */
|
||||
if (!(w->flags & SDL_WINDOW_HIDDEN)) {
|
||||
X11_UpdateWindowPosition(w, SDL_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (xevent->xconfigure.width != data->last_xconfigure.width ||
|
||||
xevent->xconfigure.height != data->last_xconfigure.height) {
|
||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED,
|
||||
xevent->xconfigure.width,
|
||||
xevent->xconfigure.height);
|
||||
if (!data->disable_size_position_events) {
|
||||
data->pending_operation &= ~X11_PENDING_OP_RESIZE;
|
||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED,
|
||||
xevent->xconfigure.width,
|
||||
xevent->xconfigure.height);
|
||||
}
|
||||
}
|
||||
|
||||
data->last_xconfigure = xevent->xconfigure;
|
||||
} break;
|
||||
|
||||
@ -1325,9 +1413,9 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
root_y = xevent->xclient.data.l[2] & 0xffff;
|
||||
/* Translate from root to current window position */
|
||||
X11_XTranslateCoordinates(display, DefaultRootWindow(display), data->xwindow,
|
||||
root_x, root_y, &window_x, &window_y, &ChildReturn);
|
||||
root_x, root_y, &window_x, &window_y, &ChildReturn);
|
||||
|
||||
SDL_SendDropPosition(data->window, NULL, (float)window_x, (float)window_y); /* FIXME, can we get the filename ? */
|
||||
SDL_SendDropPosition(data->window, (float)window_x, (float)window_y);
|
||||
}
|
||||
|
||||
/* reply with status */
|
||||
@ -1409,6 +1497,12 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
|
||||
} break;
|
||||
|
||||
/* Use XInput2 instead of the xevents API if possible, for:
|
||||
- MotionNotify
|
||||
- ButtonPress
|
||||
- ButtonRelease
|
||||
XInput2 has more precise information, e.g., to distinguish different input devices. */
|
||||
#ifndef SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||
case MotionNotify:
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
@ -1417,61 +1511,22 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
printf("window %p: X11 motion: %d,%d\n", data, xevent->xmotion.x, xevent->xmotion.y);
|
||||
#endif
|
||||
|
||||
X11_ProcessHitTest(_this, data, (float)xevent->xmotion.x, (float)xevent->xmotion.y, SDL_FALSE);
|
||||
SDL_SendMouseMotion(0, data->window, 0, 0, (float)xevent->xmotion.x, (float)xevent->xmotion.y);
|
||||
}
|
||||
} break;
|
||||
|
||||
case ButtonPress:
|
||||
{
|
||||
int xticks = 0, yticks = 0;
|
||||
#ifdef DEBUG_XEVENTS
|
||||
printf("window %p: ButtonPress (X11 button = %d)\n", data, xevent->xbutton.button);
|
||||
#endif
|
||||
if (X11_IsWheelEvent(display, xevent, &xticks, &yticks)) {
|
||||
SDL_SendMouseWheel(0, data->window, 0, (float)-xticks, (float)yticks, SDL_MOUSEWHEEL_NORMAL);
|
||||
} else {
|
||||
SDL_bool ignore_click = SDL_FALSE;
|
||||
int button = xevent->xbutton.button;
|
||||
if (button == Button1) {
|
||||
if (ProcessHitTest(_this, data, xevent)) {
|
||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0);
|
||||
break; /* don't pass this event on to app. */
|
||||
}
|
||||
} else if (button > 7) {
|
||||
/* X button values 4-7 are used for scrolling, so X1 is 8, X2 is 9, ...
|
||||
=> subtract (8-SDL_BUTTON_X1) to get value SDL expects */
|
||||
button -= (8 - SDL_BUTTON_X1);
|
||||
}
|
||||
if (data->last_focus_event_time) {
|
||||
const int X11_FOCUS_CLICK_TIMEOUT = 10;
|
||||
if (SDL_GetTicks() < (data->last_focus_event_time + X11_FOCUS_CLICK_TIMEOUT)) {
|
||||
ignore_click = !SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, SDL_FALSE);
|
||||
}
|
||||
data->last_focus_event_time = 0;
|
||||
}
|
||||
if (!ignore_click) {
|
||||
SDL_SendMouseButton(0, data->window, 0, SDL_PRESSED, button);
|
||||
}
|
||||
}
|
||||
X11_UpdateUserTime(data, xevent->xbutton.time);
|
||||
X11_HandleButtonPress(_this, data, xevent->xbutton.button,
|
||||
xevent->xbutton.x, xevent->xbutton.y, xevent->xbutton.time);
|
||||
} break;
|
||||
|
||||
case ButtonRelease:
|
||||
{
|
||||
int button = xevent->xbutton.button;
|
||||
/* The X server sends a Release event for each Press for wheels. Ignore them. */
|
||||
int xticks = 0, yticks = 0;
|
||||
#ifdef DEBUG_XEVENTS
|
||||
printf("window %p: ButtonRelease (X11 button = %d)\n", data, xevent->xbutton.button);
|
||||
#endif
|
||||
if (!X11_IsWheelEvent(display, xevent, &xticks, &yticks)) {
|
||||
if (button > 7) {
|
||||
/* see explanation at case ButtonPress */
|
||||
button -= (8 - SDL_BUTTON_X1);
|
||||
}
|
||||
SDL_SendMouseButton(0, data->window, 0, SDL_RELEASED, button);
|
||||
}
|
||||
X11_HandleButtonRelease(_this, data, xevent->xbutton.button);
|
||||
} break;
|
||||
#endif /* !SDL_VIDEO_DRIVER_X11_XINPUT2 */
|
||||
|
||||
case PropertyNotify:
|
||||
{
|
||||
@ -1579,17 +1634,92 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
}
|
||||
}
|
||||
|
||||
if ((changed & SDL_WINDOW_MAXIMIZED) && ((flags & SDL_WINDOW_MAXIMIZED) && !(flags & SDL_WINDOW_MINIMIZED))) {
|
||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MAXIMIZED, 0, 0);
|
||||
}
|
||||
if ((changed & SDL_WINDOW_MINIMIZED) && (flags & SDL_WINDOW_MINIMIZED)) {
|
||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0);
|
||||
}
|
||||
if (((changed & SDL_WINDOW_MAXIMIZED) || (changed & SDL_WINDOW_MINIMIZED)) &&
|
||||
(!(flags & SDL_WINDOW_MAXIMIZED) && !(flags & SDL_WINDOW_MINIMIZED))) {
|
||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESTORED, 0, 0);
|
||||
}
|
||||
if (!SDL_WINDOW_IS_POPUP(data->window)) {
|
||||
if (changed & SDL_WINDOW_FULLSCREEN) {
|
||||
data->pending_operation &= ~X11_PENDING_OP_FULLSCREEN;
|
||||
|
||||
if (flags & SDL_WINDOW_FULLSCREEN) {
|
||||
if (!(flags & SDL_WINDOW_MINIMIZED)) {
|
||||
const SDL_bool commit = data->requested_fullscreen_mode.displayID == 0 ||
|
||||
SDL_memcmp(&data->window->current_fullscreen_mode, &data->requested_fullscreen_mode, sizeof(SDL_DisplayMode)) != 0;
|
||||
|
||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_ENTER_FULLSCREEN, 0, 0);
|
||||
if (commit) {
|
||||
/* This was initiated by the compositor, or the mode was changed between the request and the window
|
||||
* becoming fullscreen. Switch to the application requested mode if necessary.
|
||||
*/
|
||||
SDL_copyp(&data->window->current_fullscreen_mode, &data->window->requested_fullscreen_mode);
|
||||
SDL_UpdateFullscreenMode(data->window, SDL_TRUE, SDL_TRUE);
|
||||
} else {
|
||||
SDL_UpdateFullscreenMode(data->window, SDL_TRUE, SDL_FALSE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_LEAVE_FULLSCREEN, 0, 0);
|
||||
SDL_UpdateFullscreenMode(data->window, SDL_FALSE, SDL_FALSE);
|
||||
|
||||
/* Need to restore or update any limits changed while the window was fullscreen. */
|
||||
X11_SetWindowMinMax(data->window, !!(flags & SDL_WINDOW_MAXIMIZED));
|
||||
}
|
||||
|
||||
if ((flags & SDL_WINDOW_FULLSCREEN) &&
|
||||
(data->border_top || data->border_left || data->border_bottom || data->border_right)) {
|
||||
/* If the window is entering fullscreen and the borders are
|
||||
* non-zero sized, turn off size events until the borders are
|
||||
* shut off to avoid bogus window sizes and positions, and
|
||||
* note that the old borders were non-zero for restoration.
|
||||
*/
|
||||
data->disable_size_position_events = SDL_TRUE;
|
||||
data->previous_borders_nonzero = SDL_TRUE;
|
||||
} else if (!(flags & SDL_WINDOW_FULLSCREEN) &&
|
||||
data->previous_borders_nonzero &&
|
||||
(!data->border_top && !data->border_left && !data->border_bottom && !data->border_right)) {
|
||||
/* If the window is leaving fullscreen and the current borders
|
||||
* are zero sized, but weren't when entering fullscreen, turn
|
||||
* off size events until the borders come back to avoid bogus
|
||||
* window sizes and positions.
|
||||
*/
|
||||
data->disable_size_position_events = SDL_TRUE;
|
||||
data->previous_borders_nonzero = SDL_FALSE;
|
||||
} else {
|
||||
data->disable_size_position_events = SDL_FALSE;
|
||||
data->previous_borders_nonzero = SDL_FALSE;
|
||||
|
||||
if (!(data->window->flags & SDL_WINDOW_FULLSCREEN) && data->toggle_borders) {
|
||||
data->toggle_borders = SDL_FALSE;
|
||||
X11_SetWindowBordered(_this, data->window, !(data->window->flags & SDL_WINDOW_BORDERLESS));
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((changed & SDL_WINDOW_MAXIMIZED) && ((flags & SDL_WINDOW_MAXIMIZED) && !(flags & SDL_WINDOW_MINIMIZED))) {
|
||||
data->pending_operation &= ~X11_PENDING_OP_MAXIMIZE;
|
||||
if ((changed & SDL_WINDOW_MINIMIZED)) {
|
||||
data->pending_operation &= ~X11_PENDING_OP_RESTORE;
|
||||
/* If coming out of minimized, send a restore event before sending maximized. */
|
||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESTORED, 0, 0);
|
||||
}
|
||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MAXIMIZED, 0, 0);
|
||||
}
|
||||
if ((changed & SDL_WINDOW_MINIMIZED) && (flags & SDL_WINDOW_MINIMIZED)) {
|
||||
data->pending_operation &= ~X11_PENDING_OP_MINIMIZE;
|
||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0);
|
||||
}
|
||||
if (!(flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) {
|
||||
data->pending_operation &= ~X11_PENDING_OP_RESTORE;
|
||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESTORED, 0, 0);
|
||||
|
||||
/* Restore the last known floating state if leaving maximized mode */
|
||||
if (!(flags & SDL_WINDOW_FULLSCREEN)) {
|
||||
data->pending_operation |= X11_PENDING_OP_MOVE | X11_PENDING_OP_RESIZE;
|
||||
data->expected.x = data->window->floating.x - data->border_left;
|
||||
data->expected.y = data->window->floating.y - data->border_top;
|
||||
data->expected.w = data->window->floating.w;
|
||||
data->expected.h = data->window->floating.h;
|
||||
X11_XMoveWindow(display, data->xwindow, data->window->floating.x - data->border_left, data->window->floating.y - data->border_top);
|
||||
X11_XResizeWindow(display, data->xwindow, data->window->floating.w, data->window->floating.h);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (changed & SDL_WINDOW_OCCLUDED) {
|
||||
SDL_SendWindowEvent(data->window, (flags & SDL_WINDOW_OCCLUDED) ? SDL_EVENT_WINDOW_OCCLUDED : SDL_EVENT_WINDOW_EXPOSED, 0, 0);
|
||||
}
|
||||
@ -1602,7 +1732,30 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
right approach, but it seems to work. */
|
||||
X11_UpdateKeymap(_this, SDL_TRUE);
|
||||
} else if (xevent->xproperty.atom == videodata->_NET_FRAME_EXTENTS) {
|
||||
/* Re-enable size events if they were turned off waiting for the borders to come back
|
||||
* when leaving fullscreen.
|
||||
*/
|
||||
data->disable_size_position_events = SDL_FALSE;
|
||||
X11_GetBorderValues(data);
|
||||
if (data->border_top != 0 || data->border_left != 0 || data->border_right != 0 || data->border_bottom != 0) {
|
||||
/* Adjust if the window size/position changed to accommodate the borders. */
|
||||
if (data->window->flags & SDL_WINDOW_MAXIMIZED) {
|
||||
data->pending_operation |= X11_PENDING_OP_RESIZE;
|
||||
data->expected.w = data->window->windowed.w;
|
||||
data->expected.h = data->window->windowed.h;
|
||||
X11_XResizeWindow(display, data->xwindow, data->window->windowed.w, data->window->windowed.h);
|
||||
} else {
|
||||
data->pending_operation |= X11_PENDING_OP_RESIZE | X11_PENDING_OP_MOVE;
|
||||
data->expected.w = data->window->floating.w;
|
||||
data->expected.h = data->window->floating.h;
|
||||
X11_XMoveWindow(display, data->xwindow, data->window->floating.x - data->border_left, data->window->floating.y - data->border_top);
|
||||
X11_XResizeWindow(display, data->xwindow, data->window->floating.w, data->window->floating.h);
|
||||
}
|
||||
}
|
||||
if (!(data->window->flags & SDL_WINDOW_FULLSCREEN) && data->toggle_borders) {
|
||||
data->toggle_borders = SDL_FALSE;
|
||||
X11_SetWindowBordered(_this, data->window, !(data->window->flags & SDL_WINDOW_BORDERLESS));
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -1623,13 +1776,13 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
char *name = X11_XGetAtomName(display, target);
|
||||
if (name) {
|
||||
char *token = SDL_strtok_r((char *)p.data, "\r\n", &saveptr);
|
||||
while (token != NULL) {
|
||||
while (token) {
|
||||
if (SDL_strcmp("text/plain", name) == 0) {
|
||||
SDL_SendDropText(data->window, token);
|
||||
} else if (SDL_strcmp("text/uri-list", name) == 0) {
|
||||
char *fn = X11_URIToLocal(token);
|
||||
if (fn) {
|
||||
SDL_SendDropFile(data->window, fn);
|
||||
SDL_SendDropFile(data->window, NULL, fn);
|
||||
}
|
||||
}
|
||||
token = SDL_strtok_r(NULL, "\r\n", &saveptr);
|
||||
@ -1782,6 +1935,22 @@ void X11_PumpEvents(SDL_VideoDevice *_this)
|
||||
XEvent xevent;
|
||||
int i;
|
||||
|
||||
/* Check if a display had the mode changed and is waiting for a window to asynchronously become
|
||||
* fullscreen. If there is no fullscreen window past the elapsed timeout, revert the mode switch.
|
||||
*/
|
||||
for (i = 0; i < _this->num_displays; ++i) {
|
||||
if (_this->displays[i]->driverdata->mode_switch_deadline_ns &&
|
||||
SDL_GetTicksNS() >= _this->displays[i]->driverdata->mode_switch_deadline_ns) {
|
||||
if (_this->displays[i]->fullscreen_window) {
|
||||
_this->displays[i]->driverdata->mode_switch_deadline_ns = 0;
|
||||
} else {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO,
|
||||
"Time out elapsed after mode switch on display %" SDL_PRIu32 " with no window becoming fullscreen; reverting", _this->displays[i]->id);
|
||||
SDL_SetDisplayModeForDisplay(_this->displays[i], NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data->last_mode_change_deadline) {
|
||||
if (SDL_GetTicks() >= data->last_mode_change_deadline) {
|
||||
data->last_mode_change_deadline = 0; /* assume we're done. */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -29,5 +29,10 @@ extern void X11_SendWakeupEvent(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int X11_SuspendScreenSaver(SDL_VideoDevice *_this);
|
||||
extern void X11_ReconcileKeyboardState(SDL_VideoDevice *_this);
|
||||
extern void X11_GetBorderValues(SDL_WindowData *data);
|
||||
extern void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *wdata, int button, const float x, const float y, const unsigned long time);
|
||||
extern void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *wdata, int button);
|
||||
extern SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window);
|
||||
extern SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y, SDL_bool force_new_result);
|
||||
extern SDL_bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, const SDL_WindowData *data, const float x, const float y);
|
||||
|
||||
#endif /* SDL_x11events_h_ */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -127,8 +127,8 @@ int X11_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, Uint
|
||||
#endif /* not NO_SHARED_MEMORY */
|
||||
|
||||
*pixels = SDL_malloc((size_t)h * (*pitch));
|
||||
if (*pixels == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!*pixels) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->ximage = X11_XCreateImage(display, data->visual,
|
||||
@ -226,7 +226,7 @@ void X11_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
Display *display;
|
||||
|
||||
if (data == NULL) {
|
||||
if (!data) {
|
||||
/* The window wasn't fully initialized */
|
||||
return;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -190,15 +190,15 @@ static int X11_MessageBoxInit(SDL_MessageBoxDataX11 *data, const SDL_MessageBoxD
|
||||
int num_missing = 0;
|
||||
data->font_set = X11_XCreateFontSet(data->display, g_MessageBoxFont,
|
||||
&missing, &num_missing, NULL);
|
||||
if (missing != NULL) {
|
||||
if (missing) {
|
||||
X11_XFreeStringList(missing);
|
||||
}
|
||||
if (data->font_set == NULL) {
|
||||
if (!data->font_set) {
|
||||
return SDL_SetError("Couldn't load font %s", g_MessageBoxFont);
|
||||
}
|
||||
} else {
|
||||
data->font_struct = X11_XLoadQueryFont(data->display, g_MessageBoxFontLatin1);
|
||||
if (data->font_struct == NULL) {
|
||||
if (!data->font_struct) {
|
||||
return SDL_SetError("Couldn't load font %s", g_MessageBoxFontLatin1);
|
||||
}
|
||||
}
|
||||
@ -239,13 +239,13 @@ static int X11_MessageBoxInitPositions(SDL_MessageBoxDataX11 *data)
|
||||
const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
|
||||
|
||||
/* Go over text and break linefeeds into separate lines. */
|
||||
if (messageboxdata != NULL && messageboxdata->message[0]) {
|
||||
if (messageboxdata && messageboxdata->message[0]) {
|
||||
const char *text = messageboxdata->message;
|
||||
const int linecount = CountLinesOfText(text);
|
||||
TextLineData *plinedata = (TextLineData *)SDL_malloc(sizeof(TextLineData) * linecount);
|
||||
|
||||
if (plinedata == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!plinedata) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->linedata = plinedata;
|
||||
@ -272,7 +272,7 @@ static int X11_MessageBoxInitPositions(SDL_MessageBoxDataX11 *data)
|
||||
text += length + 1;
|
||||
|
||||
/* Break if there are no more linefeeds. */
|
||||
if (lf == NULL) {
|
||||
if (!lf) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -361,12 +361,12 @@ static int X11_MessageBoxInitPositions(SDL_MessageBoxDataX11 *data)
|
||||
/* Free SDL_MessageBoxData data. */
|
||||
static void X11_MessageBoxShutdown(SDL_MessageBoxDataX11 *data)
|
||||
{
|
||||
if (data->font_set != NULL) {
|
||||
if (data->font_set) {
|
||||
X11_XFreeFontSet(data->display, data->font_set);
|
||||
data->font_set = NULL;
|
||||
}
|
||||
|
||||
if (data->font_struct != NULL) {
|
||||
if (data->font_struct) {
|
||||
X11_XFreeFont(data->display, data->font_struct);
|
||||
data->font_struct = NULL;
|
||||
}
|
||||
@ -760,10 +760,10 @@ static int X11_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int
|
||||
|
||||
#if SDL_SET_LOCALE
|
||||
origlocale = setlocale(LC_ALL, NULL);
|
||||
if (origlocale != NULL) {
|
||||
if (origlocale) {
|
||||
origlocale = SDL_strdup(origlocale);
|
||||
if (origlocale == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!origlocale) {
|
||||
return -1;
|
||||
}
|
||||
(void)setlocale(LC_ALL, "");
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
51
external/sdl/SDL/src/video/x11/SDL_x11modes.c
vendored
51
external/sdl/SDL/src/video/x11/SDL_x11modes.c
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -27,6 +27,11 @@
|
||||
|
||||
/* #define X11MODES_DEBUG */
|
||||
|
||||
/* Timeout and revert mode switches if the timespan has elapsed without the window becoming fullscreen.
|
||||
* 5 seconds seems good from testing.
|
||||
*/
|
||||
#define MODE_SWITCH_TIMEOUT_NS SDL_NS_PER_SECOND * 5
|
||||
|
||||
/* I'm becoming more and more convinced that the application should never
|
||||
* use XRandR, and it's the window manager's responsibility to track and
|
||||
* manage display modes for fullscreen windows. Right now XRandR is completely
|
||||
@ -536,7 +541,7 @@ static int X11_AddXRandRDisplay(SDL_VideoDevice *_this, Display *dpy, int screen
|
||||
}
|
||||
|
||||
output_info = X11_XRRGetOutputInfo(dpy, res, outputid);
|
||||
if (output_info == NULL || !output_info->crtc || output_info->connection == RR_Disconnected) {
|
||||
if (!output_info || !output_info->crtc || output_info->connection == RR_Disconnected) {
|
||||
X11_XRRFreeOutputInfo(output_info);
|
||||
return 0; /* ignore this one. */
|
||||
}
|
||||
@ -548,7 +553,7 @@ static int X11_AddXRandRDisplay(SDL_VideoDevice *_this, Display *dpy, int screen
|
||||
X11_XRRFreeOutputInfo(output_info);
|
||||
|
||||
crtc = X11_XRRGetCrtcInfo(dpy, res, output_crtc);
|
||||
if (crtc == NULL) {
|
||||
if (!crtc) {
|
||||
return 0; /* oh well, ignore it. */
|
||||
}
|
||||
|
||||
@ -564,14 +569,14 @@ static int X11_AddXRandRDisplay(SDL_VideoDevice *_this, Display *dpy, int screen
|
||||
X11_XRRFreeCrtcInfo(crtc);
|
||||
|
||||
displaydata = (SDL_DisplayData *)SDL_calloc(1, sizeof(*displaydata));
|
||||
if (displaydata == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!displaydata) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
modedata = (SDL_DisplayModeData *)SDL_calloc(1, sizeof(SDL_DisplayModeData));
|
||||
if (modedata == NULL) {
|
||||
if (!modedata) {
|
||||
SDL_free(displaydata);
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
modedata->xrandr_mode = modeID;
|
||||
@ -626,11 +631,11 @@ static void X11_HandleXRandROutputChange(SDL_VideoDevice *_this, const XRROutput
|
||||
}
|
||||
|
||||
if (ev->connection == RR_Disconnected) { /* output is going away */
|
||||
if (display != NULL) {
|
||||
if (display) {
|
||||
SDL_DelVideoDisplay(display->id, SDL_TRUE);
|
||||
}
|
||||
} else if (ev->connection == RR_Connected) { /* output is coming online */
|
||||
if (display != NULL) {
|
||||
if (display) {
|
||||
/* !!! FIXME: update rotation or current mode of existing display? */
|
||||
} else {
|
||||
Display *dpy = ev->display;
|
||||
@ -638,7 +643,7 @@ static void X11_HandleXRandROutputChange(SDL_VideoDevice *_this, const XRROutput
|
||||
XVisualInfo vinfo;
|
||||
if (get_visualinfo(dpy, screen, &vinfo) == 0) {
|
||||
XRRScreenResources *res = X11_XRRGetScreenResourcesCurrent(dpy, RootWindow(dpy, screen));
|
||||
if (res == NULL || res->noutput == 0) {
|
||||
if (!res || res->noutput == 0) {
|
||||
if (res) {
|
||||
X11_XRRFreeScreenResources(res);
|
||||
}
|
||||
@ -694,13 +699,13 @@ static int X11_InitModes_XRandR(SDL_VideoDevice *_this)
|
||||
}
|
||||
|
||||
res = X11_XRRGetScreenResourcesCurrent(dpy, RootWindow(dpy, screen));
|
||||
if (res == NULL || res->noutput == 0) {
|
||||
if (!res || res->noutput == 0) {
|
||||
if (res) {
|
||||
X11_XRRFreeScreenResources(res);
|
||||
}
|
||||
|
||||
res = X11_XRRGetScreenResources(dpy, RootWindow(dpy, screen));
|
||||
if (res == NULL) {
|
||||
if (!res) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -767,14 +772,14 @@ static int X11_InitModes_StdXlib(SDL_VideoDevice *_this)
|
||||
mode.format = pixelformat;
|
||||
|
||||
displaydata = (SDL_DisplayData *)SDL_calloc(1, sizeof(*displaydata));
|
||||
if (displaydata == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
if (!displaydata) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
modedata = (SDL_DisplayModeData *)SDL_calloc(1, sizeof(SDL_DisplayModeData));
|
||||
if (modedata == NULL) {
|
||||
if (!modedata) {
|
||||
SDL_free(displaydata);
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
mode.driverdata = modedata;
|
||||
|
||||
@ -861,7 +866,7 @@ int X11_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *sdl_display)
|
||||
if (output_info && output_info->connection != RR_Disconnected) {
|
||||
for (i = 0; i < output_info->nmode; ++i) {
|
||||
modedata = (SDL_DisplayModeData *)SDL_calloc(1, sizeof(SDL_DisplayModeData));
|
||||
if (modedata == NULL) {
|
||||
if (!modedata) {
|
||||
continue;
|
||||
}
|
||||
mode.driverdata = modedata;
|
||||
@ -903,6 +908,12 @@ int X11_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *sdl_display, SD
|
||||
|
||||
viddata->last_mode_change_deadline = SDL_GetTicks() + (PENDING_FOCUS_TIME * 2);
|
||||
|
||||
if (mode != &sdl_display->desktop_mode) {
|
||||
data->mode_switch_deadline_ns = SDL_GetTicksNS() + MODE_SWITCH_TIMEOUT_NS;
|
||||
} else {
|
||||
data->mode_switch_deadline_ns = 0;
|
||||
}
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XRANDR
|
||||
if (data->use_xrandr) {
|
||||
Display *display = viddata->display;
|
||||
@ -914,18 +925,18 @@ int X11_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *sdl_display, SD
|
||||
Status status;
|
||||
|
||||
res = X11_XRRGetScreenResources(display, RootWindow(display, data->screen));
|
||||
if (res == NULL) {
|
||||
if (!res) {
|
||||
return SDL_SetError("Couldn't get XRandR screen resources");
|
||||
}
|
||||
|
||||
output_info = X11_XRRGetOutputInfo(display, res, data->xrandr_output);
|
||||
if (output_info == NULL || output_info->connection == RR_Disconnected) {
|
||||
if (!output_info || output_info->connection == RR_Disconnected) {
|
||||
X11_XRRFreeScreenResources(res);
|
||||
return SDL_SetError("Couldn't get XRandR output info");
|
||||
}
|
||||
|
||||
crtc = X11_XRRGetCrtcInfo(display, res, output_info->crtc);
|
||||
if (crtc == NULL) {
|
||||
if (!crtc) {
|
||||
X11_XRRFreeOutputInfo(output_info);
|
||||
X11_XRRFreeScreenResources(res);
|
||||
return SDL_SetError("Couldn't get XRandR crtc info");
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -32,6 +32,8 @@ struct SDL_DisplayData
|
||||
int x;
|
||||
int y;
|
||||
|
||||
Uint64 mode_switch_deadline_ns;
|
||||
|
||||
SDL_bool use_xrandr;
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XRANDR
|
||||
|
113
external/sdl/SDL/src/video/x11/SDL_x11mouse.c
vendored
113
external/sdl/SDL/src/video/x11/SDL_x11mouse.c
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -31,6 +31,8 @@
|
||||
/* FIXME: Find a better place to put this... */
|
||||
static Cursor x11_empty_cursor = None;
|
||||
|
||||
static SDL_Cursor *sys_cursors[SDL_HITTEST_RESIZE_LEFT + 1];
|
||||
|
||||
static Display *GetDisplay(void)
|
||||
{
|
||||
return SDL_GetVideoDevice()->driverdata->display;
|
||||
@ -67,14 +69,10 @@ static void X11_DestroyEmptyCursor(void)
|
||||
|
||||
static SDL_Cursor *X11_CreateDefaultCursor(void)
|
||||
{
|
||||
SDL_Cursor *cursor;
|
||||
|
||||
cursor = SDL_calloc(1, sizeof(*cursor));
|
||||
SDL_Cursor *cursor = SDL_calloc(1, sizeof(*cursor));
|
||||
if (cursor) {
|
||||
/* None is used to indicate the default cursor */
|
||||
cursor->driverdata = (void *)(uintptr_t)None;
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
return cursor;
|
||||
@ -88,7 +86,7 @@ static Cursor X11_CreateXCursorCursor(SDL_Surface *surface, int hot_x, int hot_y
|
||||
XcursorImage *image;
|
||||
|
||||
image = X11_XcursorImageCreate(surface->w, surface->h);
|
||||
if (image == NULL) {
|
||||
if (!image) {
|
||||
SDL_OutOfMemory();
|
||||
return None;
|
||||
}
|
||||
@ -121,15 +119,13 @@ static Cursor X11_CreatePixmapCursor(SDL_Surface *surface, int hot_x, int hot_y)
|
||||
size_t width_bytes = ((surface->w + 7) & ~((size_t)7)) / 8;
|
||||
|
||||
data_bits = SDL_calloc(1, surface->h * width_bytes);
|
||||
if (data_bits == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
if (!data_bits) {
|
||||
return None;
|
||||
}
|
||||
|
||||
mask_bits = SDL_calloc(1, surface->h * width_bytes);
|
||||
if (mask_bits == NULL) {
|
||||
if (!mask_bits) {
|
||||
SDL_free(data_bits);
|
||||
SDL_OutOfMemory();
|
||||
return None;
|
||||
}
|
||||
|
||||
@ -198,9 +194,7 @@ static Cursor X11_CreatePixmapCursor(SDL_Surface *surface, int hot_x, int hot_y)
|
||||
|
||||
static SDL_Cursor *X11_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
|
||||
{
|
||||
SDL_Cursor *cursor;
|
||||
|
||||
cursor = SDL_calloc(1, sizeof(*cursor));
|
||||
SDL_Cursor *cursor = SDL_calloc(1, sizeof(*cursor));
|
||||
if (cursor) {
|
||||
Cursor x11_cursor = None;
|
||||
|
||||
@ -213,8 +207,6 @@ static SDL_Cursor *X11_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
|
||||
x11_cursor = X11_CreatePixmapCursor(surface, hot_x, hot_y);
|
||||
}
|
||||
cursor->driverdata = (void *)(uintptr_t)x11_cursor;
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
return cursor;
|
||||
@ -267,6 +259,30 @@ static SDL_Cursor *X11_CreateSystemCursor(SDL_SystemCursor id)
|
||||
case SDL_SYSTEM_CURSOR_HAND:
|
||||
shape = XC_hand2;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT:
|
||||
shape = XC_top_left_corner;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WINDOW_TOP:
|
||||
shape = XC_top_side;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT:
|
||||
shape = XC_top_right_corner;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WINDOW_RIGHT:
|
||||
shape = XC_right_side;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT:
|
||||
shape = XC_bottom_right_corner;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WINDOW_BOTTOM:
|
||||
shape = XC_bottom_side;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT:
|
||||
shape = XC_bottom_left_corner;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WINDOW_LEFT:
|
||||
shape = XC_left_side;
|
||||
break;
|
||||
}
|
||||
|
||||
cursor = SDL_calloc(1, sizeof(*cursor));
|
||||
@ -276,8 +292,6 @@ static SDL_Cursor *X11_CreateSystemCursor(SDL_SystemCursor id)
|
||||
x11_cursor = X11_XCreateFontCursor(GetDisplay(), shape);
|
||||
|
||||
cursor->driverdata = (void *)(uintptr_t)x11_cursor;
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
return cursor;
|
||||
@ -330,13 +344,16 @@ static void X11_WarpMouseInternal(Window xwindow, float x, float y)
|
||||
Display *display = videodata->display;
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||
int deviceid = 0;
|
||||
/* It seems XIWarpPointer() doesn't work correctly on multi-head setups:
|
||||
* https://developer.blender.org/rB165caafb99c6846e53d11c4e966990aaffc06cea
|
||||
*/
|
||||
if (ScreenCount(display) == 1) {
|
||||
X11_XIGetClientPointer(display, None, &deviceid);
|
||||
if (X11_Xinput2IsInitialized()) {
|
||||
/* It seems XIWarpPointer() doesn't work correctly on multi-head setups:
|
||||
* https://developer.blender.org/rB165caafb99c6846e53d11c4e966990aaffc06cea
|
||||
*/
|
||||
if (ScreenCount(display) == 1) {
|
||||
X11_XIGetClientPointer(display, None, &deviceid);
|
||||
}
|
||||
}
|
||||
if (deviceid != 0) {
|
||||
SDL_assert(SDL_X11_HAVE_XINPUT2);
|
||||
X11_XIWarpPointer(display, deviceid, None, xwindow, 0.0, 0.0, 0, 0, x, y);
|
||||
} else
|
||||
#endif
|
||||
@ -370,12 +387,7 @@ static int X11_WarpMouseGlobal(float x, float y)
|
||||
|
||||
static int X11_SetRelativeMouseMode(SDL_bool enabled)
|
||||
{
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||
if (X11_Xinput2IsInitialized()) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return SDL_Unsupported();
|
||||
return X11_Xinput2IsInitialized() ? 0 : SDL_Unsupported();
|
||||
}
|
||||
|
||||
static int X11_CaptureMouse(SDL_Window *window)
|
||||
@ -413,12 +425,9 @@ static Uint32 X11_GetGlobalMouseState(float *x, float *y)
|
||||
|
||||
/* !!! FIXME: should we XSync() here first? */
|
||||
|
||||
#ifndef SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||
videodata->global_mouse_changed = SDL_TRUE;
|
||||
#else
|
||||
if (!SDL_X11_HAVE_XINPUT2)
|
||||
if (!X11_Xinput2IsInitialized()) {
|
||||
videodata->global_mouse_changed = SDL_TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* check if we have this cached since XInput last saw the mouse move. */
|
||||
/* !!! FIXME: can we just calculate this from XInput's events? */
|
||||
@ -427,7 +436,7 @@ static Uint32 X11_GetGlobalMouseState(float *x, float *y)
|
||||
if (displays) {
|
||||
for (i = 0; displays[i]; ++i) {
|
||||
SDL_DisplayData *data = SDL_GetDisplayDriverData(displays[i]);
|
||||
if (data != NULL) {
|
||||
if (data) {
|
||||
Window root, child;
|
||||
int rootx, rooty, winx, winy;
|
||||
unsigned int mask;
|
||||
@ -477,6 +486,23 @@ void X11_InitMouse(SDL_VideoDevice *_this)
|
||||
mouse->CaptureMouse = X11_CaptureMouse;
|
||||
mouse->GetGlobalMouseState = X11_GetGlobalMouseState;
|
||||
|
||||
SDL_HitTestResult r = SDL_HITTEST_NORMAL;
|
||||
while (r <= SDL_HITTEST_RESIZE_LEFT) {
|
||||
switch (r) {
|
||||
case SDL_HITTEST_NORMAL: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); break;
|
||||
case SDL_HITTEST_DRAGGABLE: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); break;
|
||||
case SDL_HITTEST_RESIZE_TOPLEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT); break;
|
||||
case SDL_HITTEST_RESIZE_TOP: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_TOP); break;
|
||||
case SDL_HITTEST_RESIZE_TOPRIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT); break;
|
||||
case SDL_HITTEST_RESIZE_RIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_RIGHT); break;
|
||||
case SDL_HITTEST_RESIZE_BOTTOMRIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT); break;
|
||||
case SDL_HITTEST_RESIZE_BOTTOM: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_BOTTOM); break;
|
||||
case SDL_HITTEST_RESIZE_BOTTOMLEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT); break;
|
||||
case SDL_HITTEST_RESIZE_LEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_WINDOW_LEFT); break;
|
||||
}
|
||||
r++;
|
||||
}
|
||||
|
||||
SDL_SetDefaultCursor(X11_CreateDefaultCursor());
|
||||
}
|
||||
|
||||
@ -485,8 +511,14 @@ void X11_QuitMouse(SDL_VideoDevice *_this)
|
||||
SDL_VideoData *data = _this->driverdata;
|
||||
SDL_XInput2DeviceInfo *i;
|
||||
SDL_XInput2DeviceInfo *next;
|
||||
int j;
|
||||
|
||||
for (i = data->mouse_device_info; i != NULL; i = next) {
|
||||
for (j = 0; j < SDL_arraysize(sys_cursors); j++) {
|
||||
X11_FreeCursor(sys_cursors[j]);
|
||||
sys_cursors[j] = NULL;
|
||||
}
|
||||
|
||||
for (i = data->mouse_device_info; i; i = next) {
|
||||
next = i->next;
|
||||
SDL_free(i);
|
||||
}
|
||||
@ -495,4 +527,13 @@ void X11_QuitMouse(SDL_VideoDevice *_this)
|
||||
X11_DestroyEmptyCursor();
|
||||
}
|
||||
|
||||
void X11_SetHitTestCursor(SDL_HitTestResult rc)
|
||||
{
|
||||
if (rc == SDL_HITTEST_NORMAL || rc == SDL_HITTEST_DRAGGABLE) {
|
||||
SDL_SetCursor(NULL);
|
||||
} else {
|
||||
X11_ShowCursor(sys_cursors[rc]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_X11 */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -35,5 +35,6 @@ typedef struct SDL_XInput2DeviceInfo
|
||||
|
||||
extern void X11_InitMouse(SDL_VideoDevice *_this);
|
||||
extern void X11_QuitMouse(SDL_VideoDevice *_this);
|
||||
extern void X11_SetHitTestCursor(SDL_HitTestResult rc);
|
||||
|
||||
#endif /* SDL_x11mouse_h_ */
|
||||
|
72
external/sdl/SDL/src/video/x11/SDL_x11opengl.c
vendored
72
external/sdl/SDL/src/video/x11/SDL_x11opengl.c
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 2021 NVIDIA Corporation
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
@ -193,7 +193,7 @@ int X11_GL_LoadLibrary(SDL_VideoDevice *_this, const char *path)
|
||||
sizeof(struct
|
||||
SDL_GLDriverData));
|
||||
if (!_this->gl_data) {
|
||||
return SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Load function pointers */
|
||||
@ -237,6 +237,8 @@ int X11_GL_LoadLibrary(SDL_VideoDevice *_this, const char *path)
|
||||
return SDL_SetError("GLX is not supported");
|
||||
}
|
||||
|
||||
_this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_UNTESTED;
|
||||
|
||||
/* Initialize extensions */
|
||||
/* See lengthy comment about the inc/dec in
|
||||
../windows/SDL_windowsopengl.c. */
|
||||
@ -902,7 +904,6 @@ int X11_GL_SetSwapInterval(SDL_VideoDevice *_this, int interval)
|
||||
X11_GL_GetSwapInterval(_this, ¤tInterval);
|
||||
_this->gl_data->glXSwapIntervalEXT(display, drawable, currentInterval);
|
||||
_this->gl_data->glXSwapIntervalEXT(display, drawable, interval);
|
||||
|
||||
status = 0;
|
||||
swapinterval = interval;
|
||||
} else if (_this->gl_data->glXSwapIntervalMESA) {
|
||||
@ -925,6 +926,53 @@ int X11_GL_SetSwapInterval(SDL_VideoDevice *_this, int interval)
|
||||
return status;
|
||||
}
|
||||
|
||||
static SDL_GLSwapIntervalTearBehavior CheckSwapIntervalTearBehavior(SDL_VideoDevice *_this, Window drawable, unsigned int current_val, unsigned int current_allow_late)
|
||||
{
|
||||
/* Mesa and Nvidia interpret GLX_EXT_swap_control_tear differently, as of this writing, so
|
||||
figure out which behavior we have.
|
||||
Technical details: https://github.com/libsdl-org/SDL/issues/8004#issuecomment-1819603282 */
|
||||
if (_this->gl_data->swap_interval_tear_behavior == SDL_SWAPINTERVALTEAR_UNTESTED) {
|
||||
if (!_this->gl_data->HAS_GLX_EXT_swap_control_tear) {
|
||||
_this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_UNKNOWN;
|
||||
} else {
|
||||
Display *display = _this->driverdata->display;
|
||||
unsigned int allow_late_swap_tearing = 22;
|
||||
int original_val = (int) current_val;
|
||||
|
||||
/*
|
||||
* This is a workaround for a bug in NVIDIA drivers. Bug has been reported
|
||||
* and will be fixed in a future release (probably 319.xx).
|
||||
*
|
||||
* There's a bug where glXSetSwapIntervalEXT ignores updates because
|
||||
* it has the wrong value cached. To work around it, we just run a no-op
|
||||
* update to the current value.
|
||||
*/
|
||||
_this->gl_data->glXSwapIntervalEXT(display, drawable, current_val);
|
||||
|
||||
/* set it to no swap interval and see how it affects GLX_LATE_SWAPS_TEAR_EXT... */
|
||||
_this->gl_data->glXSwapIntervalEXT(display, drawable, 0);
|
||||
_this->gl_data->glXQueryDrawable(display, drawable, GLX_LATE_SWAPS_TEAR_EXT, &allow_late_swap_tearing);
|
||||
|
||||
if (allow_late_swap_tearing == 0) { /* GLX_LATE_SWAPS_TEAR_EXT says whether late swapping is currently in use */
|
||||
_this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_NVIDIA;
|
||||
if (current_allow_late) {
|
||||
original_val = -original_val;
|
||||
}
|
||||
} else if (allow_late_swap_tearing == 1) { /* GLX_LATE_SWAPS_TEAR_EXT says whether the Drawable can use late swapping at all */
|
||||
_this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_MESA;
|
||||
} else { /* unexpected outcome! */
|
||||
_this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_UNKNOWN;
|
||||
}
|
||||
|
||||
/* set us back to what it was originally... */
|
||||
_this->gl_data->glXSwapIntervalEXT(display, drawable, original_val);
|
||||
}
|
||||
}
|
||||
|
||||
return _this->gl_data->swap_interval_tear_behavior;
|
||||
}
|
||||
|
||||
|
||||
int X11_GL_GetSwapInterval(SDL_VideoDevice *_this, int *interval)
|
||||
{
|
||||
if (_this->gl_data->glXSwapIntervalEXT) {
|
||||
@ -935,6 +983,7 @@ int X11_GL_GetSwapInterval(SDL_VideoDevice *_this, int *interval)
|
||||
unsigned int val = 0;
|
||||
|
||||
if (_this->gl_data->HAS_GLX_EXT_swap_control_tear) {
|
||||
allow_late_swap_tearing = 22; /* set this to nonsense. */
|
||||
_this->gl_data->glXQueryDrawable(display, drawable,
|
||||
GLX_LATE_SWAPS_TEAR_EXT,
|
||||
&allow_late_swap_tearing);
|
||||
@ -943,12 +992,21 @@ int X11_GL_GetSwapInterval(SDL_VideoDevice *_this, int *interval)
|
||||
_this->gl_data->glXQueryDrawable(display, drawable,
|
||||
GLX_SWAP_INTERVAL_EXT, &val);
|
||||
|
||||
if ((allow_late_swap_tearing) && (val > 0)) {
|
||||
*interval = -((int)val);
|
||||
return 0;
|
||||
*interval = (int)val;
|
||||
|
||||
switch (CheckSwapIntervalTearBehavior(_this, drawable, val, allow_late_swap_tearing)) {
|
||||
case SDL_SWAPINTERVALTEAR_MESA:
|
||||
*interval = (int)val; /* unsigned int cast to signed that generates negative value if necessary. */
|
||||
break;
|
||||
|
||||
case SDL_SWAPINTERVALTEAR_NVIDIA:
|
||||
default:
|
||||
if ((allow_late_swap_tearing) && (val > 0)) {
|
||||
*interval = -((int)val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
*interval = (int)val;
|
||||
return 0;
|
||||
} else if (_this->gl_data->glXGetSwapIntervalMESA) {
|
||||
int val = _this->gl_data->glXGetSwapIntervalMESA();
|
||||
|
12
external/sdl/SDL/src/video/x11/SDL_x11opengl.h
vendored
12
external/sdl/SDL/src/video/x11/SDL_x11opengl.h
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -29,6 +29,14 @@
|
||||
|
||||
typedef void (*__GLXextFuncPtr)(void);
|
||||
|
||||
typedef enum SDL_GLSwapIntervalTearBehavior
|
||||
{
|
||||
SDL_SWAPINTERVALTEAR_UNTESTED,
|
||||
SDL_SWAPINTERVALTEAR_UNKNOWN,
|
||||
SDL_SWAPINTERVALTEAR_MESA,
|
||||
SDL_SWAPINTERVALTEAR_NVIDIA
|
||||
} SDL_GLSwapIntervalTearBehavior;
|
||||
|
||||
struct SDL_GLDriverData
|
||||
{
|
||||
int errorBase, eventBase;
|
||||
@ -50,6 +58,8 @@ struct SDL_GLDriverData
|
||||
int minor;
|
||||
} es_profile_max_supported_version;
|
||||
|
||||
SDL_GLSwapIntervalTearBehavior swap_interval_tear_behavior;
|
||||
|
||||
Bool (*glXQueryExtension)(Display *, int *, int *);
|
||||
__GLXextFuncPtr (*glXGetProcAddress)(const GLubyte *);
|
||||
XVisualInfo *(*glXChooseVisual)(Display *, int, int *);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
696
external/sdl/SDL/src/video/x11/SDL_x11pen.c
vendored
Normal file
696
external/sdl/SDL/src/video/x11/SDL_x11pen.c
vendored
Normal file
@ -0,0 +1,696 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||
|
||||
#include "../../events/SDL_pen_c.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "SDL_x11pen.h"
|
||||
#include "SDL_x11video.h"
|
||||
#include "SDL_x11xinput2.h"
|
||||
|
||||
#define PEN_ERASER_ID_MAXLEN 256 /* Max # characters of device name to scan */
|
||||
#define PEN_ERASER_NAME_TAG "eraser" /* String constant to identify erasers */
|
||||
|
||||
#define DEBUG_PEN (SDL_PEN_DEBUG_NOID | SDL_PEN_DEBUG_NONWACOM | SDL_PEN_DEBUG_UNKNOWN_WACOM | SDL_PEN_DEBUG_NOSERIAL_WACOM)
|
||||
|
||||
#define SDL_PEN_AXIS_VALUATOR_MISSING -1
|
||||
|
||||
/* X11-specific information attached to each pen */
|
||||
typedef struct xinput2_pen
|
||||
{
|
||||
float axis_min[SDL_PEN_NUM_AXES];
|
||||
float axis_max[SDL_PEN_NUM_AXES];
|
||||
float slider_bias; /* shift value to add to PEN_AXIS_SLIDER (before normalisation) */
|
||||
float rotation_bias; /* rotation to add to PEN_AXIS_ROTATION (after normalisation) */
|
||||
Sint8 valuator_for_axis[SDL_PEN_NUM_AXES]; /* SDL_PEN_AXIS_VALUATOR_MISSING if not supported */
|
||||
} xinput2_pen;
|
||||
|
||||
/* X11 atoms */
|
||||
static struct
|
||||
{
|
||||
int initialized; /* initialised to 0 */
|
||||
Atom device_product_id;
|
||||
Atom abs_pressure;
|
||||
Atom abs_tilt_x;
|
||||
Atom abs_tilt_y;
|
||||
Atom wacom_serial_ids;
|
||||
Atom wacom_tool_type;
|
||||
} pen_atoms;
|
||||
|
||||
/*
|
||||
* Mapping from X11 device IDs to pen IDs
|
||||
*
|
||||
* In X11, the same device ID may represent any number of pens. We
|
||||
* thus cannot directly use device IDs as pen IDs.
|
||||
*/
|
||||
static struct
|
||||
{
|
||||
int num_pens_known; /* Number of currently known pens (based on their GUID); used to give pen ID to new pens */
|
||||
int num_entries; /* Number of X11 device IDs that correspond to pens */
|
||||
|
||||
struct pen_device_id_mapping
|
||||
{
|
||||
Uint32 deviceid;
|
||||
Uint32 pen_id;
|
||||
} * entries; /* Current pen to device ID mappings */
|
||||
} pen_map;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SDL_PEN_VENDOR_UNKNOWN = 0,
|
||||
SDL_PEN_VENDOR_WACOM
|
||||
} sdl_pen_vendor;
|
||||
|
||||
/* Information to identify pens during discovery */
|
||||
typedef struct
|
||||
{
|
||||
sdl_pen_vendor vendor;
|
||||
SDL_GUID guid;
|
||||
SDL_PenSubtype heuristic_type; /* Distinguish pen+eraser devices with shared bus ID */
|
||||
Uint32 devicetype_id, serial; /* used by PEN_VENDOR_WACOM */
|
||||
Uint32 deviceid;
|
||||
} pen_identity;
|
||||
|
||||
int X11_PenIDFromDeviceID(int deviceid)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < pen_map.num_entries; ++i) {
|
||||
if (pen_map.entries[i].deviceid == deviceid) {
|
||||
return pen_map.entries[i].pen_id;
|
||||
}
|
||||
}
|
||||
return SDL_PEN_INVALID;
|
||||
}
|
||||
|
||||
static void pen_atoms_ensure_initialized(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
|
||||
|
||||
if (pen_atoms.initialized) {
|
||||
return;
|
||||
}
|
||||
/* Create atoms if they don't exist yet to pre-empt hotplugging updates */
|
||||
pen_atoms.device_product_id = X11_XInternAtom(data->display, "Device Product ID", False);
|
||||
pen_atoms.wacom_serial_ids = X11_XInternAtom(data->display, "Wacom Serial IDs", False);
|
||||
pen_atoms.wacom_tool_type = X11_XInternAtom(data->display, "Wacom Tool Type", False);
|
||||
pen_atoms.abs_pressure = X11_XInternAtom(data->display, "Abs Pressure", False);
|
||||
pen_atoms.abs_tilt_x = X11_XInternAtom(data->display, "Abs Tilt X", False);
|
||||
pen_atoms.abs_tilt_y = X11_XInternAtom(data->display, "Abs Tilt Y", False);
|
||||
|
||||
pen_atoms.initialized = 1;
|
||||
}
|
||||
|
||||
/* Read out an integer property and store into a preallocated Sint32 array, extending 8 and 16 bit values suitably.
|
||||
Returns number of Sint32s written (<= max_words), or 0 on error. */
|
||||
static size_t xinput2_pen_get_int_property(SDL_VideoDevice *_this, int deviceid, Atom property, Sint32 *dest, size_t max_words)
|
||||
{
|
||||
const SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
|
||||
Atom type_return;
|
||||
int format_return;
|
||||
unsigned long num_items_return;
|
||||
unsigned long bytes_after_return;
|
||||
unsigned char *output;
|
||||
|
||||
if (property == None) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Success != X11_XIGetProperty(data->display, deviceid,
|
||||
property,
|
||||
0, max_words, False,
|
||||
XA_INTEGER, &type_return, &format_return,
|
||||
&num_items_return, &bytes_after_return,
|
||||
&output) ||
|
||||
num_items_return == 0 || output == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (type_return == XA_INTEGER) {
|
||||
int k;
|
||||
const int to_copy = SDL_min(max_words, num_items_return);
|
||||
|
||||
if (format_return == 8) {
|
||||
Sint8 *numdata = (Sint8 *)output;
|
||||
for (k = 0; k < to_copy; ++k) {
|
||||
dest[k] = numdata[k];
|
||||
}
|
||||
} else if (format_return == 16) {
|
||||
Sint16 *numdata = (Sint16 *)output;
|
||||
for (k = 0; k < to_copy; ++k) {
|
||||
dest[k] = numdata[k];
|
||||
}
|
||||
} else {
|
||||
SDL_memcpy(dest, output, sizeof(Sint32) * to_copy);
|
||||
}
|
||||
X11_XFree(output);
|
||||
return to_copy;
|
||||
}
|
||||
return 0; /* type mismatch */
|
||||
}
|
||||
|
||||
/* 32 bit vendor + device ID from evdev */
|
||||
static Uint32 xinput2_pen_evdevid(SDL_VideoDevice *_this, int deviceid)
|
||||
{
|
||||
#if !(SDL_PEN_DEBUG_NOID)
|
||||
Sint32 ids[2];
|
||||
|
||||
pen_atoms_ensure_initialized(_this);
|
||||
|
||||
if (2 != xinput2_pen_get_int_property(_this, deviceid, pen_atoms.device_product_id, ids, 2)) {
|
||||
return 0;
|
||||
}
|
||||
return ((ids[0] << 16) | (ids[1] & 0xffff));
|
||||
#else /* Testing: pretend that we have no ID (not sure if this can happen IRL) */
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Gets reasonably-unique GUID for the device */
|
||||
static void xinput2_pen_update_generic_guid(SDL_VideoDevice *_this, pen_identity *pident, int deviceid)
|
||||
{
|
||||
Uint32 evdevid = xinput2_pen_evdevid(_this, deviceid); /* also initialises pen_atoms */
|
||||
|
||||
if (!evdevid) {
|
||||
/* Fallback: if no evdevid is available; try to at least distinguish devices within the
|
||||
current session. This is a poor GUID and our last resort. */
|
||||
evdevid = deviceid;
|
||||
}
|
||||
SDL_PenUpdateGUIDForGeneric(&pident->guid, 0, evdevid);
|
||||
}
|
||||
|
||||
/* Identify Wacom devices (if SDL_TRUE is returned) and extract their device type and serial IDs */
|
||||
static SDL_bool xinput2_wacom_deviceid(SDL_VideoDevice *_this, int deviceid, Uint32 *wacom_devicetype_id, Uint32 *wacom_serial)
|
||||
{
|
||||
#if !(SDL_PEN_DEBUG_NONWACOM) /* Can be disabled for testing */
|
||||
Sint32 serial_id_buf[3];
|
||||
int result;
|
||||
|
||||
pen_atoms_ensure_initialized(_this);
|
||||
|
||||
if ((result = xinput2_pen_get_int_property(_this, deviceid, pen_atoms.wacom_serial_ids, serial_id_buf, 3)) == 3) {
|
||||
*wacom_devicetype_id = serial_id_buf[2];
|
||||
*wacom_serial = serial_id_buf[1];
|
||||
#if SDL_PEN_DEBUG_NOSERIAL_WACOM /* Disabled for testing? */
|
||||
*wacom_serial = 0;
|
||||
#endif
|
||||
return SDL_TRUE;
|
||||
}
|
||||
#endif
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Heuristically determines if device is an eraser */
|
||||
static SDL_bool xinput2_pen_is_eraser(SDL_VideoDevice *_this, int deviceid, char *devicename)
|
||||
{
|
||||
SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
|
||||
char dev_name[PEN_ERASER_ID_MAXLEN];
|
||||
int k;
|
||||
|
||||
pen_atoms_ensure_initialized(_this);
|
||||
|
||||
if (pen_atoms.wacom_tool_type != None) {
|
||||
Atom type_return;
|
||||
int format_return;
|
||||
unsigned long num_items_return;
|
||||
unsigned long bytes_after_return;
|
||||
unsigned char *tooltype_name_info = NULL;
|
||||
|
||||
/* Try Wacom-specific method */
|
||||
if (Success == X11_XIGetProperty(data->display, deviceid,
|
||||
pen_atoms.wacom_tool_type,
|
||||
0, 32, False,
|
||||
AnyPropertyType, &type_return, &format_return,
|
||||
&num_items_return, &bytes_after_return,
|
||||
&tooltype_name_info) &&
|
||||
tooltype_name_info != NULL && num_items_return > 0) {
|
||||
|
||||
SDL_bool result = SDL_FALSE;
|
||||
char *tooltype_name = NULL;
|
||||
|
||||
if (type_return == XA_ATOM) {
|
||||
/* Atom instead of string? Un-intern */
|
||||
Atom atom = *((Atom *)tooltype_name_info);
|
||||
if (atom != None) {
|
||||
tooltype_name = X11_XGetAtomName(data->display, atom);
|
||||
}
|
||||
} else if (type_return == XA_STRING && format_return == 8) {
|
||||
tooltype_name = (char *)tooltype_name_info;
|
||||
}
|
||||
|
||||
if (tooltype_name) {
|
||||
if (0 == SDL_strcasecmp(tooltype_name, PEN_ERASER_NAME_TAG)) {
|
||||
result = SDL_TRUE;
|
||||
}
|
||||
X11_XFree(tooltype_name_info);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Non-Wacom device? */
|
||||
|
||||
/* We assume that a device is an eraser if its name contains the string "eraser".
|
||||
* Unfortunately there doesn't seem to be a clean way to distinguish these cases (as of 2022-03). */
|
||||
|
||||
SDL_strlcpy(dev_name, devicename, PEN_ERASER_ID_MAXLEN);
|
||||
/* lowercase device name string so we can use strstr() */
|
||||
for (k = 0; dev_name[k]; ++k) {
|
||||
dev_name[k] = tolower(dev_name[k]);
|
||||
}
|
||||
|
||||
return (SDL_strstr(dev_name, PEN_ERASER_NAME_TAG)) ? SDL_TRUE : SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Gets GUID and other identifying information for the device using the best known method */
|
||||
static pen_identity xinput2_identify_pen(SDL_VideoDevice *_this, int deviceid, char *name)
|
||||
{
|
||||
pen_identity pident;
|
||||
|
||||
pident.devicetype_id = 0ul;
|
||||
pident.serial = 0ul;
|
||||
pident.deviceid = deviceid;
|
||||
pident.heuristic_type = SDL_PEN_TYPE_PEN;
|
||||
SDL_memset(pident.guid.data, 0, sizeof(pident.guid.data));
|
||||
|
||||
if (xinput2_pen_is_eraser(_this, deviceid, name)) {
|
||||
pident.heuristic_type = SDL_PEN_TYPE_ERASER;
|
||||
}
|
||||
|
||||
if (xinput2_wacom_deviceid(_this, deviceid, &pident.devicetype_id, &pident.serial)) {
|
||||
pident.vendor = SDL_PEN_VENDOR_WACOM;
|
||||
SDL_PenUpdateGUIDForWacom(&pident.guid, pident.devicetype_id, pident.serial);
|
||||
|
||||
#if DEBUG_PEN
|
||||
printf("[pen] Pen %d reports Wacom device_id %x\n",
|
||||
deviceid, pident.devicetype_id);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
pident.vendor = SDL_PEN_VENDOR_UNKNOWN;
|
||||
}
|
||||
if (!pident.serial) {
|
||||
/* If the pen has a serial number, we can move it across tablets and retain its identity.
|
||||
Otherwise, we use the evdev ID as part of its GUID, which may mean that we identify it with the tablet. */
|
||||
xinput2_pen_update_generic_guid(_this, &pident, deviceid);
|
||||
}
|
||||
SDL_PenUpdateGUIDForType(&pident.guid, pident.heuristic_type);
|
||||
return pident;
|
||||
}
|
||||
|
||||
static void xinput2_pen_free_deviceinfo(Uint32 deviceid, void *x11_peninfo, void *context)
|
||||
{
|
||||
SDL_free(x11_peninfo);
|
||||
}
|
||||
|
||||
static void xinput2_merge_deviceinfo(xinput2_pen *dest, xinput2_pen *src)
|
||||
{
|
||||
*dest = *src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill in vendor-specific device information, if available
|
||||
*
|
||||
* For Wacom pens: identify number of buttons and extra axis (if present)
|
||||
*
|
||||
* \param _this global state
|
||||
* \param dev The device to analyse
|
||||
* \param pen The pen to initialise
|
||||
* \param pident Pen identity information
|
||||
* \param[out] valuator_5 Meaning of the valuator with offset 5, if any
|
||||
* (written only if known and if the device has a 6th axis,
|
||||
* e.g., for the Wacom Art Pen and Wacom Airbrush Pen)
|
||||
* \param[out] axes Bitmask of all possibly supported axes
|
||||
*
|
||||
* This function identifies Wacom device types through a Wacom-specific device ID.
|
||||
* It then fills in pen details from an internal database.
|
||||
* If the device seems to be a Wacom pen/eraser but can't be identified, the function
|
||||
* leaves "axes" untouched and sets the other outputs to common defaults.
|
||||
*
|
||||
* There is no explicit support for other vendors, though vendors that
|
||||
* emulate the Wacom API might be supported.
|
||||
*
|
||||
* Unsupported devices will keep the default settings.
|
||||
*/
|
||||
static void xinput2_vendor_peninfo(SDL_VideoDevice *_this, const XIDeviceInfo *dev, SDL_Pen *pen, pen_identity pident, int *valuator_5, Uint32 *axes)
|
||||
{
|
||||
switch (pident.vendor) {
|
||||
case SDL_PEN_VENDOR_WACOM:
|
||||
{
|
||||
if (SDL_PenModifyForWacomID(pen, pident.devicetype_id, axes)) {
|
||||
if (*axes & SDL_PEN_AXIS_SLIDER_MASK) {
|
||||
/* Air Brush Pen or eraser */
|
||||
*valuator_5 = SDL_PEN_AXIS_SLIDER;
|
||||
} else if (*axes & SDL_PEN_AXIS_ROTATION_MASK) {
|
||||
/* Art Pen or eraser, or 6D Art Pen */
|
||||
*valuator_5 = SDL_PEN_AXIS_ROTATION;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
#if DEBUG_PEN
|
||||
printf("[pen] Could not identify wacom pen %d with device id %x, using default settings\n",
|
||||
pident.deviceid, pident.devicetype_id);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
#if DEBUG_PEN
|
||||
printf("[pen] Pen %d is not from a known vendor\n", pident.deviceid);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fall back to default heuristics for identifying device type */
|
||||
|
||||
SDL_strlcpy(pen->name, dev->name, SDL_PEN_MAX_NAME);
|
||||
|
||||
pen->type = pident.heuristic_type;
|
||||
}
|
||||
|
||||
/* Does this device have a valuator for pressure sensitivity? */
|
||||
static SDL_bool xinput2_device_is_pen(SDL_VideoDevice *_this, const XIDeviceInfo *dev)
|
||||
{
|
||||
int classct;
|
||||
|
||||
pen_atoms_ensure_initialized(_this);
|
||||
|
||||
for (classct = 0; classct < dev->num_classes; ++classct) {
|
||||
const XIAnyClassInfo *classinfo = dev->classes[classct];
|
||||
|
||||
switch (classinfo->type) {
|
||||
case XIValuatorClass:
|
||||
{
|
||||
XIValuatorClassInfo *val_classinfo = (XIValuatorClassInfo *)classinfo;
|
||||
Atom vname = val_classinfo->label;
|
||||
|
||||
if (vname == pen_atoms.abs_pressure) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
void X11_InitPen(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
|
||||
int i;
|
||||
XIDeviceInfo *device_info;
|
||||
int num_device_info;
|
||||
|
||||
device_info = X11_XIQueryDevice(data->display, XIAllDevices, &num_device_info);
|
||||
if (!device_info) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reset the device id -> pen map */
|
||||
if (pen_map.entries) {
|
||||
SDL_free(pen_map.entries);
|
||||
pen_map.entries = NULL;
|
||||
pen_map.num_entries = 0;
|
||||
}
|
||||
|
||||
SDL_PenGCMark();
|
||||
|
||||
for (i = 0; i < num_device_info; ++i) {
|
||||
const XIDeviceInfo *dev = &device_info[i];
|
||||
int classct;
|
||||
xinput2_pen pen_device;
|
||||
Uint32 capabilities = 0;
|
||||
Uint32 axis_mask = ~0; /* Permitted axes (default: all) */
|
||||
int valuator_5_axis = -1; /* For Wacom devices, the 6th valuator (offset 5) has a model-specific meaning */
|
||||
pen_identity pident;
|
||||
SDL_PenID pen_id;
|
||||
SDL_Pen *pen;
|
||||
int old_num_pens_known = pen_map.num_pens_known;
|
||||
int k;
|
||||
|
||||
/* Only track physical devices that are enabled and look like pens */
|
||||
if (dev->use != XISlavePointer || dev->enabled == 0 || !xinput2_device_is_pen(_this, dev)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pen_device.slider_bias = 0.0f;
|
||||
pen_device.rotation_bias = 0.0f;
|
||||
for (k = 0; k < SDL_PEN_NUM_AXES; ++k) {
|
||||
pen_device.valuator_for_axis[k] = SDL_PEN_AXIS_VALUATOR_MISSING;
|
||||
}
|
||||
|
||||
pident = xinput2_identify_pen(_this, dev->deviceid, dev->name);
|
||||
|
||||
pen_id = SDL_GetPenFromGUID(pident.guid);
|
||||
if (pen_id == SDL_PEN_INVALID) {
|
||||
/* We have never met this pen */
|
||||
pen_id = ++pen_map.num_pens_known; /* start at 1 */
|
||||
}
|
||||
pen = SDL_PenModifyBegin(pen_id);
|
||||
|
||||
/* Complement XF86 driver information with vendor-specific details */
|
||||
xinput2_vendor_peninfo(_this, dev, pen, pident, &valuator_5_axis, &axis_mask);
|
||||
|
||||
for (classct = 0; classct < dev->num_classes; ++classct) {
|
||||
const XIAnyClassInfo *classinfo = dev->classes[classct];
|
||||
|
||||
switch (classinfo->type) {
|
||||
case XIValuatorClass:
|
||||
{
|
||||
XIValuatorClassInfo *val_classinfo = (XIValuatorClassInfo *)classinfo;
|
||||
Sint8 valuator_nr = val_classinfo->number;
|
||||
Atom vname = val_classinfo->label;
|
||||
int axis = -1;
|
||||
|
||||
float min = val_classinfo->min;
|
||||
float max = val_classinfo->max;
|
||||
|
||||
if (vname == pen_atoms.abs_pressure) {
|
||||
axis = SDL_PEN_AXIS_PRESSURE;
|
||||
} else if (vname == pen_atoms.abs_tilt_x) {
|
||||
axis = SDL_PEN_AXIS_XTILT;
|
||||
} else if (vname == pen_atoms.abs_tilt_y) {
|
||||
axis = SDL_PEN_AXIS_YTILT;
|
||||
}
|
||||
|
||||
if (axis == -1 && valuator_nr == 5) {
|
||||
/* Wacom model-specific axis support */
|
||||
/* The meaning of the various axes is highly underspecitied in Xinput2.
|
||||
* As of 2023-08-26, Wacom seems to be the only vendor to support these axes, so the code below
|
||||
* captures the de-facto standard. */
|
||||
axis = valuator_5_axis;
|
||||
|
||||
switch (axis) {
|
||||
case SDL_PEN_AXIS_SLIDER:
|
||||
/* cf. xinput2_wacom_peninfo for how this axis is used.
|
||||
In all current cases, our API wants this value in 0..1, but the xf86 driver
|
||||
starts at a negative offset, so we normalise here. */
|
||||
pen_device.slider_bias = -min;
|
||||
max -= min;
|
||||
min = 0.0f;
|
||||
break;
|
||||
|
||||
case SDL_PEN_AXIS_ROTATION:
|
||||
/* The "0" value points to the left, rather than up, so we must
|
||||
rotate 90 degrees counter-clockwise to have 0 point to the top. */
|
||||
|
||||
pen_device.rotation_bias = -90.0f;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (axis >= 0) {
|
||||
capabilities |= SDL_PEN_AXIS_CAPABILITY(axis);
|
||||
|
||||
pen_device.valuator_for_axis[axis] = valuator_nr;
|
||||
pen_device.axis_min[axis] = min;
|
||||
pen_device.axis_max[axis] = max;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We have a pen if and only if the device measures pressure */
|
||||
if (capabilities & SDL_PEN_AXIS_PRESSURE_MASK) {
|
||||
xinput2_pen *xinput2_deviceinfo;
|
||||
Uint64 guid_a, guid_b;
|
||||
|
||||
/* Done collecting data, write to pen */
|
||||
SDL_PenModifyAddCapabilities(pen, capabilities);
|
||||
pen->guid = pident.guid;
|
||||
|
||||
if (pen->deviceinfo) {
|
||||
/* Updating a known pen */
|
||||
xinput2_deviceinfo = (xinput2_pen *)pen->deviceinfo;
|
||||
xinput2_merge_deviceinfo(xinput2_deviceinfo, &pen_device);
|
||||
} else {
|
||||
/* Registering a new pen */
|
||||
xinput2_deviceinfo = SDL_malloc(sizeof(xinput2_pen));
|
||||
SDL_memcpy(xinput2_deviceinfo, &pen_device, sizeof(xinput2_pen));
|
||||
}
|
||||
pen->deviceinfo = xinput2_deviceinfo;
|
||||
|
||||
#if DEBUG_PEN
|
||||
printf("[pen] pen %d [%04x] valuators pressure=%d, xtilt=%d, ytilt=%d [%s]\n",
|
||||
pen->header.id, pen->header.flags,
|
||||
pen_device.valuator_for_axis[SDL_PEN_AXIS_PRESSURE],
|
||||
pen_device.valuator_for_axis[SDL_PEN_AXIS_XTILT],
|
||||
pen_device.valuator_for_axis[SDL_PEN_AXIS_YTILT],
|
||||
pen->name);
|
||||
#endif
|
||||
SDL_memcpy(&guid_a, &pen->guid.data[0], 8);
|
||||
SDL_memcpy(&guid_b, &pen->guid.data[8], 8);
|
||||
if (!(guid_a | guid_b)) {
|
||||
#if DEBUG_PEN
|
||||
printf("[pen] (pen eliminated due to zero GUID)\n");
|
||||
#endif
|
||||
pen->type = SDL_PEN_TYPE_NONE;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Not a pen, mark for deletion */
|
||||
pen->type = SDL_PEN_TYPE_NONE;
|
||||
}
|
||||
SDL_PenModifyEnd(pen, SDL_TRUE);
|
||||
|
||||
if (pen->type != SDL_PEN_TYPE_NONE) {
|
||||
const int map_pos = pen_map.num_entries;
|
||||
|
||||
/* We found a pen: add mapping */
|
||||
if (pen_map.entries == NULL) {
|
||||
pen_map.entries = SDL_calloc(sizeof(struct pen_device_id_mapping), 1);
|
||||
pen_map.num_entries = 1;
|
||||
} else {
|
||||
pen_map.num_entries += 1;
|
||||
pen_map.entries = SDL_realloc(pen_map.entries,
|
||||
pen_map.num_entries * (sizeof(struct pen_device_id_mapping)));
|
||||
}
|
||||
pen_map.entries[map_pos].deviceid = dev->deviceid;
|
||||
pen_map.entries[map_pos].pen_id = pen_id;
|
||||
} else {
|
||||
/* Revert pen number allocation */
|
||||
pen_map.num_pens_known = old_num_pens_known;
|
||||
}
|
||||
}
|
||||
X11_XIFreeDeviceInfo(device_info);
|
||||
|
||||
SDL_PenGCSweep(NULL, xinput2_pen_free_deviceinfo);
|
||||
}
|
||||
|
||||
static void xinput2_normalize_pen_axes(const SDL_Pen *peninfo,
|
||||
const xinput2_pen *xpen,
|
||||
/* inout-mode paramters: */
|
||||
float *coords)
|
||||
{
|
||||
int axis;
|
||||
|
||||
/* Normalise axes */
|
||||
for (axis = 0; axis < SDL_PEN_NUM_AXES; ++axis) {
|
||||
int valuator = xpen->valuator_for_axis[axis];
|
||||
if (valuator != SDL_PEN_AXIS_VALUATOR_MISSING) {
|
||||
float value = coords[axis];
|
||||
float min = xpen->axis_min[axis];
|
||||
float max = xpen->axis_max[axis];
|
||||
|
||||
if (axis == SDL_PEN_AXIS_SLIDER) {
|
||||
value += xpen->slider_bias;
|
||||
}
|
||||
|
||||
/* min ... 0 ... max */
|
||||
if (min < 0.0) {
|
||||
/* Normalise so that 0 remains 0.0 */
|
||||
if (value < 0) {
|
||||
value = value / (-min);
|
||||
} else {
|
||||
if (max == 0.0) {
|
||||
value = 0.0f;
|
||||
} else {
|
||||
value = value / max;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* 0 ... min ... max */
|
||||
/* including 0.0 = min */
|
||||
if (max == 0.0) {
|
||||
value = 0.0f;
|
||||
} else {
|
||||
value = (value - min) / max;
|
||||
}
|
||||
}
|
||||
|
||||
switch (axis) {
|
||||
case SDL_PEN_AXIS_XTILT:
|
||||
case SDL_PEN_AXIS_YTILT:
|
||||
if (peninfo->info.max_tilt > 0.0f) {
|
||||
value *= peninfo->info.max_tilt; /* normalise to physical max */
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_PEN_AXIS_ROTATION:
|
||||
/* normalised to -1..1, so let's convert to degrees */
|
||||
value *= 180.0;
|
||||
value += xpen->rotation_bias;
|
||||
|
||||
/* handle simple over/underflow */
|
||||
if (value >= 180.0f) {
|
||||
value -= 360.0f;
|
||||
} else if (value < -180.0f) {
|
||||
value += 360.0f;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
coords[axis] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void X11_PenAxesFromValuators(const SDL_Pen *peninfo,
|
||||
const double *input_values, const unsigned char *mask, const int mask_len,
|
||||
/* out-mode parameters: */
|
||||
float axis_values[SDL_PEN_NUM_AXES])
|
||||
{
|
||||
const xinput2_pen *pen = (xinput2_pen *)peninfo->deviceinfo;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SDL_PEN_NUM_AXES; ++i) {
|
||||
const int valuator = pen->valuator_for_axis[i];
|
||||
if (valuator == SDL_PEN_AXIS_VALUATOR_MISSING || valuator >= mask_len * 8 || !(XIMaskIsSet(mask, valuator))) {
|
||||
axis_values[i] = 0.0f;
|
||||
} else {
|
||||
axis_values[i] = input_values[valuator];
|
||||
}
|
||||
}
|
||||
xinput2_normalize_pen_axes(peninfo, pen, axis_values);
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
54
external/sdl/SDL/src/video/x11/SDL_x11pen.h
vendored
Normal file
54
external/sdl/SDL/src/video/x11/SDL_x11pen.h
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef SDL_x11pen_h_
|
||||
#define SDL_x11pen_h_
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||
|
||||
#include "SDL_x11video.h"
|
||||
#include "../../events/SDL_pen_c.h"
|
||||
|
||||
/* Pressure-sensitive pen */
|
||||
|
||||
/* Forward definition for SDL_x11video.h */
|
||||
struct SDL_VideoData;
|
||||
|
||||
/* Function definitions */
|
||||
|
||||
/* Detect XINPUT2 devices that are pens / erasers, or update the list after hotplugging */
|
||||
extern void X11_InitPen(SDL_VideoDevice *_this);
|
||||
|
||||
/* Converts XINPUT2 valuators into pen axis information, including normalisation */
|
||||
extern void X11_PenAxesFromValuators(const SDL_Pen *pen,
|
||||
const double *input_values, const unsigned char *mask, const int mask_len,
|
||||
/* out-mode parameters: */
|
||||
float axis_values[SDL_PEN_NUM_AXES]);
|
||||
|
||||
/* Map X11 device ID to pen ID */
|
||||
extern int X11_PenIDFromDeviceID(int deviceid);
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */
|
||||
|
||||
#endif /* SDL_x11pen_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
98
external/sdl/SDL/src/video/x11/SDL_x11shape.c
vendored
98
external/sdl/SDL/src/video/x11/SDL_x11shape.c
vendored
@ -1,98 +0,0 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11
|
||||
|
||||
#include "SDL_x11video.h"
|
||||
#include "SDL_x11shape.h"
|
||||
#include "SDL_x11window.h"
|
||||
#include "../SDL_shape_internals.h"
|
||||
|
||||
SDL_WindowShaper *X11_CreateShaper(SDL_Window *window)
|
||||
{
|
||||
SDL_WindowShaper *result = NULL;
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XSHAPE
|
||||
SDL_ShapeData *data = NULL;
|
||||
|
||||
if (SDL_X11_HAVE_XSHAPE) { /* Make sure X server supports it. */
|
||||
result = SDL_malloc(sizeof(SDL_WindowShaper));
|
||||
if (result == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
result->window = window;
|
||||
result->mode.mode = ShapeModeDefault;
|
||||
result->mode.parameters.binarizationCutoff = 1;
|
||||
data = SDL_malloc(sizeof(SDL_ShapeData));
|
||||
if (data == NULL) {
|
||||
SDL_free(result);
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
result->driverdata = data;
|
||||
data->bitmapsize = 0;
|
||||
data->bitmap = NULL;
|
||||
window->shaper = result;
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int X11_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode)
|
||||
{
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XSHAPE
|
||||
SDL_ShapeData *data = NULL;
|
||||
SDL_WindowData *windowdata = NULL;
|
||||
Pixmap shapemask;
|
||||
#endif
|
||||
|
||||
if (shaper == NULL || shape == NULL || shaper->driverdata == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XSHAPE
|
||||
if (shape->format->Amask == 0 && SDL_SHAPEMODEALPHA(shape_mode->mode)) {
|
||||
return -2;
|
||||
}
|
||||
if (shape->w != shaper->window->w || shape->h != shaper->window->h) {
|
||||
return -3;
|
||||
}
|
||||
data = shaper->driverdata;
|
||||
|
||||
/* Assume that shaper->alphacutoff already has a value, because SDL_SetWindowShape() should have given it one. */
|
||||
SDL_CalculateShapeBitmap(shaper->mode, shape, data->bitmap, 8);
|
||||
|
||||
windowdata = shaper->window->driverdata;
|
||||
shapemask = X11_XCreateBitmapFromData(windowdata->videodata->display, windowdata->xwindow, data->bitmap, shaper->window->w, shaper->window->h);
|
||||
|
||||
X11_XShapeCombineMask(windowdata->videodata->display, windowdata->xwindow, ShapeBounding, 0, 0, shapemask, ShapeSet);
|
||||
X11_XSync(windowdata->videodata->display, False);
|
||||
|
||||
X11_XFreePixmap(windowdata->videodata->display, shapemask);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_X11 */
|
37
external/sdl/SDL/src/video/x11/SDL_x11shape.h
vendored
37
external/sdl/SDL/src/video/x11/SDL_x11shape.h
vendored
@ -1,37 +0,0 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_x11shape_h_
|
||||
#define SDL_x11shape_h_
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *bitmap;
|
||||
Uint32 bitmapsize;
|
||||
} SDL_ShapeData;
|
||||
|
||||
extern SDL_WindowShaper *X11_CreateShaper(SDL_Window *window);
|
||||
extern int X11_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode);
|
||||
|
||||
#endif /* SDL_x11shape_h_ */
|
11
external/sdl/SDL/src/video/x11/SDL_x11sym.h
vendored
11
external/sdl/SDL/src/video/x11/SDL_x11sym.h
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -193,11 +193,19 @@ SDL_X11_SYM(void,XkbFreeKeyboard,(XkbDescPtr a,unsigned int b, Bool c),(a,b,c),)
|
||||
SDL_X11_SYM(Bool,XkbSetDetectableAutoRepeat,(Display* a, Bool b, Bool* c),(a,b,c),return)
|
||||
#endif
|
||||
|
||||
/* XKeycodeToKeysym is a deprecated function */
|
||||
#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
#if NeedWidePrototypes
|
||||
SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,unsigned int b,int c),(a,b,c),return)
|
||||
#else
|
||||
SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,KeyCode b,int c),(a,b,c),return)
|
||||
#endif
|
||||
#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef X_HAVE_UTF8_STRING
|
||||
SDL_X11_MODULE(UTF8)
|
||||
@ -281,6 +289,7 @@ SDL_X11_SYM(Status,XIQueryVersion,(Display *a,int *b,int *c),(a,b,c),return)
|
||||
SDL_X11_SYM(XIEventMask*,XIGetSelectedEvents,(Display *a,Window b,int *c),(a,b,c),return)
|
||||
SDL_X11_SYM(Bool,XIGetClientPointer,(Display *a,Window b,int *c),(a,b,c),return)
|
||||
SDL_X11_SYM(Bool,XIWarpPointer,(Display *a,int b,Window c,Window d,double e,double f,int g,int h,double i,double j),(a,b,c,d,e,f,g,h,i,j),return)
|
||||
SDL_X11_SYM(Status,XIGetProperty,(Display *a,int b,Atom c,long d,long e,Bool f, Atom g, Atom *h, int *i, unsigned long *j, unsigned long *k, unsigned char **l),(a,b,c,d,e,f,g,h,i,j,k,l),return);
|
||||
#endif
|
||||
|
||||
/* XRandR support */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
41
external/sdl/SDL/src/video/x11/SDL_x11video.c
vendored
41
external/sdl/SDL/src/video/x11/SDL_x11video.c
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -24,16 +24,16 @@
|
||||
|
||||
#include <unistd.h> /* For getpid() and readlink() */
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../SDL_pixels_c.h"
|
||||
#include "../../core/linux/SDL_system_theme.h"
|
||||
#include "../SDL_pixels_c.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#include "SDL_x11video.h"
|
||||
#include "SDL_x11framebuffer.h"
|
||||
#include "SDL_x11shape.h"
|
||||
#include "SDL_x11pen.h"
|
||||
#include "SDL_x11touch.h"
|
||||
#include "SDL_x11xinput2.h"
|
||||
#include "SDL_x11video.h"
|
||||
#include "SDL_x11xfixes.h"
|
||||
#include "SDL_x11xinput2.h"
|
||||
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
#include "SDL_x11opengles.h"
|
||||
@ -79,7 +79,7 @@ static int X11_SafetyNetErrHandler(Display *d, XErrorEvent *e)
|
||||
if (!safety_net_triggered) {
|
||||
safety_net_triggered = SDL_TRUE;
|
||||
device = SDL_GetVideoDevice();
|
||||
if (device != NULL) {
|
||||
if (device) {
|
||||
int i;
|
||||
for (i = 0; i < device->num_displays; i++) {
|
||||
SDL_VideoDisplay *display = device->displays[i];
|
||||
@ -90,7 +90,7 @@ static int X11_SafetyNetErrHandler(Display *d, XErrorEvent *e)
|
||||
}
|
||||
}
|
||||
|
||||
if (orig_x11_errhandler != NULL) {
|
||||
if (orig_x11_errhandler) {
|
||||
return orig_x11_errhandler(d, e); /* probably terminate. */
|
||||
}
|
||||
|
||||
@ -115,21 +115,19 @@ static SDL_VideoDevice *X11_CreateDevice(void)
|
||||
/* Open the display first to be sure that X11 is available */
|
||||
x11_display = X11_XOpenDisplay(display);
|
||||
|
||||
if (x11_display == NULL) {
|
||||
if (!x11_display) {
|
||||
SDL_X11_UnloadSymbols();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice));
|
||||
if (device == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
if (!device) {
|
||||
return NULL;
|
||||
}
|
||||
data = (struct SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData));
|
||||
if (data == NULL) {
|
||||
if (!data) {
|
||||
SDL_free(device);
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
device->driverdata = data;
|
||||
@ -142,7 +140,7 @@ static SDL_VideoDevice *X11_CreateDevice(void)
|
||||
|
||||
data->display = x11_display;
|
||||
data->request_display = X11_XOpenDisplay(display);
|
||||
if (data->request_display == NULL) {
|
||||
if (!data->request_display) {
|
||||
X11_XCloseDisplay(data->display);
|
||||
SDL_free(device->driverdata);
|
||||
SDL_free(device);
|
||||
@ -180,7 +178,6 @@ static SDL_VideoDevice *X11_CreateDevice(void)
|
||||
device->SendWakeupEvent = X11_SendWakeupEvent;
|
||||
|
||||
device->CreateSDLWindow = X11_CreateWindow;
|
||||
device->CreateSDLWindowFrom = X11_CreateWindowFrom;
|
||||
device->SetWindowTitle = X11_SetWindowTitle;
|
||||
device->SetWindowIcon = X11_SetWindowIcon;
|
||||
device->SetWindowPosition = X11_SetWindowPosition;
|
||||
@ -207,20 +204,17 @@ static SDL_VideoDevice *X11_CreateDevice(void)
|
||||
device->CreateWindowFramebuffer = X11_CreateWindowFramebuffer;
|
||||
device->UpdateWindowFramebuffer = X11_UpdateWindowFramebuffer;
|
||||
device->DestroyWindowFramebuffer = X11_DestroyWindowFramebuffer;
|
||||
device->GetWindowWMInfo = X11_GetWindowWMInfo;
|
||||
device->SetWindowHitTest = X11_SetWindowHitTest;
|
||||
device->AcceptDragAndDrop = X11_AcceptDragAndDrop;
|
||||
device->FlashWindow = X11_FlashWindow;
|
||||
device->ShowWindowSystemMenu = X11_ShowWindowSystemMenu;
|
||||
device->SetWindowFocusable = X11_SetWindowFocusable;
|
||||
device->SyncWindow = X11_SyncWindow;
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XFIXES
|
||||
device->SetWindowMouseRect = X11_SetWindowMouseRect;
|
||||
#endif /* SDL_VIDEO_DRIVER_X11_XFIXES */
|
||||
|
||||
device->shape_driver.CreateShaper = X11_CreateShaper;
|
||||
device->shape_driver.SetWindowShape = X11_SetWindowShape;
|
||||
|
||||
#ifdef SDL_VIDEO_OPENGL_GLX
|
||||
device->GL_LoadLibrary = X11_GL_LoadLibrary;
|
||||
device->GL_GetProcAddress = X11_GL_GetProcAddress;
|
||||
@ -281,7 +275,8 @@ static SDL_VideoDevice *X11_CreateDevice(void)
|
||||
device->system_theme = SDL_SystemTheme_Get();
|
||||
#endif
|
||||
|
||||
device->quirk_flags = VIDEO_DEVICE_QUIRK_HAS_POPUP_WINDOW_SUPPORT;
|
||||
device->device_caps = VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT |
|
||||
VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS;
|
||||
|
||||
return device;
|
||||
}
|
||||
@ -433,6 +428,10 @@ int X11_VideoInit(SDL_VideoDevice *_this)
|
||||
|
||||
X11_InitTouch(_this);
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||
X11_InitPen(_this);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -459,7 +458,7 @@ void X11_VideoQuit(SDL_VideoDevice *_this)
|
||||
|
||||
SDL_bool X11_UseDirectColorVisuals(void)
|
||||
{
|
||||
return SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ? SDL_FALSE : SDL_TRUE;
|
||||
return (SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") == NULL);
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_X11 */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
38
external/sdl/SDL/src/video/x11/SDL_x11vulkan.c
vendored
38
external/sdl/SDL/src/video/x11/SDL_x11vulkan.c
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -57,10 +57,10 @@ int X11_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path)
|
||||
}
|
||||
|
||||
/* Load the Vulkan loader library */
|
||||
if (path == NULL) {
|
||||
if (!path) {
|
||||
path = SDL_getenv("SDL_VULKAN_LIBRARY");
|
||||
}
|
||||
if (path == NULL) {
|
||||
if (!path) {
|
||||
path = DEFAULT_VULKAN;
|
||||
}
|
||||
_this->vulkan_config.loader_handle = SDL_LoadObject(path);
|
||||
@ -84,7 +84,7 @@ int X11_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path)
|
||||
(PFN_vkEnumerateInstanceExtensionProperties)
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties,
|
||||
&extensionCount);
|
||||
if (extensions == NULL) {
|
||||
if (!extensions) {
|
||||
goto fail;
|
||||
}
|
||||
for (i = 0; i < extensionCount; i++) {
|
||||
@ -108,7 +108,7 @@ int X11_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path)
|
||||
goto fail;
|
||||
} else {
|
||||
const char *libX11XCBLibraryName = SDL_getenv("SDL_X11_XCB_LIBRARY");
|
||||
if (libX11XCBLibraryName == NULL) {
|
||||
if (!libX11XCBLibraryName) {
|
||||
libX11XCBLibraryName = "libX11-xcb.so";
|
||||
}
|
||||
videoData->vulkan_xlib_xcb_library = SDL_LoadObject(libX11XCBLibraryName);
|
||||
@ -142,35 +142,35 @@ void X11_Vulkan_UnloadLibrary(SDL_VideoDevice *_this)
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool X11_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
|
||||
unsigned *count,
|
||||
const char **names)
|
||||
char const* const* X11_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
|
||||
Uint32 *count)
|
||||
{
|
||||
SDL_VideoData *videoData = _this->driverdata;
|
||||
if (!_this->vulkan_config.loader_handle) {
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
if (videoData->vulkan_xlib_xcb_library) {
|
||||
static const char *const extensionsForXCB[] = {
|
||||
VK_KHR_SURFACE_EXTENSION_NAME,
|
||||
VK_KHR_XCB_SURFACE_EXTENSION_NAME,
|
||||
};
|
||||
return SDL_Vulkan_GetInstanceExtensions_Helper(
|
||||
count, names, SDL_arraysize(extensionsForXCB), extensionsForXCB);
|
||||
if(count) {
|
||||
*count = SDL_arraysize(extensionsForXCB);
|
||||
}
|
||||
return extensionsForXCB;
|
||||
} else {
|
||||
static const char *const extensionsForXlib[] = {
|
||||
VK_KHR_SURFACE_EXTENSION_NAME,
|
||||
VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
|
||||
};
|
||||
return SDL_Vulkan_GetInstanceExtensions_Helper(
|
||||
count, names, SDL_arraysize(extensionsForXlib), extensionsForXlib);
|
||||
if(count) {
|
||||
*count = SDL_arraysize(extensionsForXlib);
|
||||
}
|
||||
return extensionsForXlib;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool X11_Vulkan_CreateSurface(SDL_VideoDevice *_this,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
const struct VkAllocationCallbacks *allocator,
|
||||
VkSurfaceKHR *surface)
|
||||
{
|
||||
SDL_VideoData *videoData = _this->driverdata;
|
||||
@ -200,8 +200,7 @@ SDL_bool X11_Vulkan_CreateSurface(SDL_VideoDevice *_this,
|
||||
return SDL_FALSE;
|
||||
}
|
||||
createInfo.window = (xcb_window_t)windowData->xwindow;
|
||||
result = vkCreateXcbSurfaceKHR(instance, &createInfo,
|
||||
NULL, surface);
|
||||
result = vkCreateXcbSurfaceKHR(instance, &createInfo, allocator, surface);
|
||||
if (result != VK_SUCCESS) {
|
||||
SDL_SetError("vkCreateXcbSurfaceKHR failed: %s", SDL_Vulkan_GetResultString(result));
|
||||
return SDL_FALSE;
|
||||
@ -222,8 +221,7 @@ SDL_bool X11_Vulkan_CreateSurface(SDL_VideoDevice *_this,
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
|
||||
createInfo.dpy = videoData->display;
|
||||
createInfo.window = (xcb_window_t)windowData->xwindow;
|
||||
result = vkCreateXlibSurfaceKHR(instance, &createInfo,
|
||||
NULL, surface);
|
||||
result = vkCreateXlibSurfaceKHR(instance, &createInfo, allocator, surface);
|
||||
if (result != VK_SUCCESS) {
|
||||
SDL_SetError("vkCreateXlibSurfaceKHR failed: %s", SDL_Vulkan_GetResultString(result));
|
||||
return SDL_FALSE;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -32,12 +32,12 @@ typedef xcb_connection_t *(*PFN_XGetXCBConnection)(Display *dpy);
|
||||
|
||||
int X11_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path);
|
||||
void X11_Vulkan_UnloadLibrary(SDL_VideoDevice *_this);
|
||||
SDL_bool X11_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
|
||||
unsigned *count,
|
||||
const char **names);
|
||||
char const* const* X11_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
|
||||
Uint32 *count);
|
||||
SDL_bool X11_Vulkan_CreateSurface(SDL_VideoDevice *_this,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
const struct VkAllocationCallbacks *allocator,
|
||||
VkSurfaceKHR *surface);
|
||||
|
||||
#endif
|
||||
|
755
external/sdl/SDL/src/video/x11/SDL_x11window.c
vendored
755
external/sdl/SDL/src/video/x11/SDL_x11window.c
vendored
File diff suppressed because it is too large
Load Diff
31
external/sdl/SDL/src/video/x11/SDL_x11window.h
vendored
31
external/sdl/SDL/src/video/x11/SDL_x11window.h
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -79,13 +79,31 @@ struct SDL_WindowData
|
||||
PointerBarrier barrier[4];
|
||||
SDL_Rect barrier_rect;
|
||||
#endif /* SDL_VIDEO_DRIVER_X11_XFIXES */
|
||||
SDL_Rect expected;
|
||||
SDL_DisplayMode requested_fullscreen_mode;
|
||||
|
||||
enum
|
||||
{
|
||||
X11_PENDING_OP_NONE = 0x00,
|
||||
X11_PENDING_OP_RESTORE = 0x01,
|
||||
X11_PENDING_OP_MINIMIZE = 0x02,
|
||||
X11_PENDING_OP_MAXIMIZE = 0x04,
|
||||
X11_PENDING_OP_FULLSCREEN = 0x08,
|
||||
X11_PENDING_OP_MOVE = 0x10,
|
||||
X11_PENDING_OP_RESIZE = 0x20
|
||||
} pending_operation;
|
||||
|
||||
SDL_bool window_was_maximized;
|
||||
SDL_bool disable_size_position_events;
|
||||
SDL_bool previous_borders_nonzero;
|
||||
SDL_bool toggle_borders;
|
||||
SDL_HitTestResult hit_test_result;
|
||||
};
|
||||
|
||||
extern void X11_SetNetWMState(SDL_VideoDevice *_this, Window xwindow, Uint32 flags);
|
||||
extern Uint32 X11_GetNetWMState(SDL_VideoDevice *_this, SDL_Window *window, Window xwindow);
|
||||
|
||||
extern int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int X11_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window, const void *data);
|
||||
extern int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props);
|
||||
extern char *X11_GetWindowTitle(SDL_VideoDevice *_this, Window xwindow);
|
||||
extern void X11_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int X11_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon);
|
||||
@ -106,19 +124,20 @@ extern void X11_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void X11_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool bordered);
|
||||
extern void X11_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable);
|
||||
extern void X11_SetWindowAlwaysOnTop(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool on_top);
|
||||
extern void X11_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
|
||||
extern int X11_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
|
||||
extern void *X11_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t *size);
|
||||
extern void X11_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
|
||||
extern void X11_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
|
||||
extern void X11_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int X11_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info);
|
||||
extern int X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
|
||||
extern void X11_AcceptDragAndDrop(SDL_Window *window, SDL_bool accept);
|
||||
extern int X11_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation);
|
||||
extern void X11_ShowWindowSystemMenu(SDL_Window *window, int x, int y);
|
||||
extern int X11_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int X11_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool focusable);
|
||||
|
||||
int SDL_X11_SetWindowTitle(Display *display, Window xwindow, char *title);
|
||||
void X11_UpdateWindowPosition(SDL_Window *window);
|
||||
void X11_UpdateWindowPosition(SDL_Window *window, SDL_bool use_current_position);
|
||||
void X11_SetWindowMinMax(SDL_Window *window, SDL_bool use_current);
|
||||
|
||||
#endif /* SDL_x11window_h_ */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
199
external/sdl/SDL/src/video/x11/SDL_x11xinput2.c
vendored
199
external/sdl/SDL/src/video/x11/SDL_x11xinput2.c
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -22,9 +22,12 @@
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11
|
||||
|
||||
#include "SDL_x11pen.h"
|
||||
#include "SDL_x11video.h"
|
||||
#include "SDL_x11xinput2.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "../../events/SDL_pen_c.h"
|
||||
#include "../../events/SDL_touch_c.h"
|
||||
|
||||
#define MAX_AXIS 16
|
||||
@ -74,19 +77,25 @@ static SDL_bool xinput2_version_atleast(const int version, const int wantmajor,
|
||||
return version >= ((wantmajor * 1000) + wantminor);
|
||||
}
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||
static SDL_Window *xinput2_get_sdlwindow(SDL_VideoData *videodata, Window window)
|
||||
static SDL_WindowData *xinput2_get_sdlwindowdata(SDL_VideoData *videodata, Window window)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < videodata->numwindows; i++) {
|
||||
SDL_WindowData *d = videodata->windowlist[i];
|
||||
if (d->xwindow == window) {
|
||||
return d->window;
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static SDL_Window *xinput2_get_sdlwindow(SDL_VideoData *videodata, Window window)
|
||||
{
|
||||
const SDL_WindowData *windowdata = xinput2_get_sdlwindowdata(videodata, window);
|
||||
return windowdata ? windowdata->window : NULL;
|
||||
}
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||
static void xinput2_normalize_touch_coordinates(SDL_Window *window, double in_x, double in_y, float *out_x, float *out_y)
|
||||
{
|
||||
if (window) {
|
||||
@ -188,10 +197,10 @@ static void xinput2_remove_device_info(SDL_VideoData *videodata, const int devic
|
||||
SDL_XInput2DeviceInfo *prev = NULL;
|
||||
SDL_XInput2DeviceInfo *devinfo;
|
||||
|
||||
for (devinfo = videodata->mouse_device_info; devinfo != NULL; devinfo = devinfo->next) {
|
||||
for (devinfo = videodata->mouse_device_info; devinfo; devinfo = devinfo->next) {
|
||||
if (devinfo->device_id == device_id) {
|
||||
SDL_assert((devinfo == videodata->mouse_device_info) == (prev == NULL));
|
||||
if (prev == NULL) {
|
||||
if (!prev) {
|
||||
videodata->mouse_device_info = devinfo->next;
|
||||
} else {
|
||||
prev->next = devinfo->next;
|
||||
@ -212,10 +221,10 @@ static SDL_XInput2DeviceInfo *xinput2_get_device_info(SDL_VideoData *videodata,
|
||||
int axis = 0;
|
||||
int i;
|
||||
|
||||
for (devinfo = videodata->mouse_device_info; devinfo != NULL; devinfo = devinfo->next) {
|
||||
for (devinfo = videodata->mouse_device_info; devinfo; devinfo = devinfo->next) {
|
||||
if (devinfo->device_id == device_id) {
|
||||
SDL_assert((devinfo == videodata->mouse_device_info) == (prev == NULL));
|
||||
if (prev != NULL) { /* move this to the front of the list, assuming we'll get more from this one. */
|
||||
if (prev) { /* move this to the front of the list, assuming we'll get more from this one. */
|
||||
prev->next = devinfo->next;
|
||||
devinfo->next = videodata->mouse_device_info;
|
||||
videodata->mouse_device_info = devinfo;
|
||||
@ -227,13 +236,12 @@ static SDL_XInput2DeviceInfo *xinput2_get_device_info(SDL_VideoData *videodata,
|
||||
|
||||
/* don't know about this device yet, query and cache it. */
|
||||
devinfo = (SDL_XInput2DeviceInfo *)SDL_calloc(1, sizeof(SDL_XInput2DeviceInfo));
|
||||
if (devinfo == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
if (!devinfo) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xidevinfo = X11_XIQueryDevice(videodata->display, device_id, &i);
|
||||
if (xidevinfo == NULL) {
|
||||
if (!xidevinfo) {
|
||||
SDL_free(devinfo);
|
||||
return NULL;
|
||||
}
|
||||
@ -246,7 +254,7 @@ static SDL_XInput2DeviceInfo *xinput2_get_device_info(SDL_VideoData *videodata,
|
||||
for (i = 0; i < xidevinfo->num_classes; i++) {
|
||||
const XIValuatorClassInfo *v = (const XIValuatorClassInfo *)xidevinfo->classes[i];
|
||||
if (v->type == XIValuatorClass) {
|
||||
devinfo->relative[axis] = (v->mode == XIModeRelative) ? SDL_TRUE : SDL_FALSE;
|
||||
devinfo->relative[axis] = (v->mode == XIModeRelative);
|
||||
devinfo->minval[axis] = v->min;
|
||||
devinfo->maxval[axis] = v->max;
|
||||
if (++axis >= 2) {
|
||||
@ -262,18 +270,51 @@ static SDL_XInput2DeviceInfo *xinput2_get_device_info(SDL_VideoData *videodata,
|
||||
|
||||
return devinfo;
|
||||
}
|
||||
|
||||
static void xinput2_pen_ensure_window(SDL_VideoDevice *_this, const SDL_Pen *pen, Window window)
|
||||
{
|
||||
/* When "flipping" a Wacom eraser pen, we get an XI_DeviceChanged event
|
||||
* with the newly-activated pen, but this event is global for the display.
|
||||
* We won't get a window until the pen starts triggering motion or
|
||||
* button events, so we instead hook the pen to its window at that point. */
|
||||
const SDL_WindowData *windowdata = X11_FindWindow(_this, window);
|
||||
if (windowdata) {
|
||||
SDL_SendPenWindowEvent(0, pen->header.id, windowdata->window);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie)
|
||||
int X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
|
||||
{
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||
SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
|
||||
|
||||
if (cookie->extension != xinput2_opcode) {
|
||||
return 0;
|
||||
}
|
||||
switch (cookie->evtype) {
|
||||
case XI_PropertyEvent:
|
||||
case XI_DeviceChanged:
|
||||
{
|
||||
X11_InitPen(_this);
|
||||
} break;
|
||||
|
||||
case XI_Enter:
|
||||
case XI_Leave:
|
||||
{
|
||||
const XIEnterEvent *enterev = (const XIEnterEvent *)cookie->data;
|
||||
const SDL_WindowData *windowdata = X11_FindWindow(_this, enterev->event);
|
||||
const SDL_Pen *pen = SDL_GetPenPtr(X11_PenIDFromDeviceID(enterev->sourceid));
|
||||
SDL_Window *window = (windowdata && (cookie->evtype == XI_Enter)) ? windowdata->window : NULL;
|
||||
if (pen) {
|
||||
SDL_SendPenWindowEvent(0, pen->header.id, window);
|
||||
}
|
||||
} break;
|
||||
|
||||
case XI_RawMotion:
|
||||
{
|
||||
const XIRawEvent *rawev = (const XIRawEvent *)cookie->data;
|
||||
const SDL_bool is_pen = X11_PenIDFromDeviceID(rawev->sourceid) != SDL_PEN_INVALID;
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_XInput2DeviceInfo *devinfo;
|
||||
double coords[2];
|
||||
@ -281,13 +322,18 @@ int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie
|
||||
int i;
|
||||
|
||||
videodata->global_mouse_changed = SDL_TRUE;
|
||||
if (is_pen) {
|
||||
return 0; /* Pens check for XI_Motion instead */
|
||||
}
|
||||
|
||||
/* Non-pen: */
|
||||
|
||||
if (!mouse->relative_mode || mouse->relative_mode_warp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
devinfo = xinput2_get_device_info(videodata, rawev->deviceid);
|
||||
if (devinfo == NULL) {
|
||||
if (!devinfo) {
|
||||
return 0; /* oh well. */
|
||||
}
|
||||
|
||||
@ -317,6 +363,7 @@ int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie
|
||||
xinput2_remove_device_info(videodata, hierev->info[i].deviceid);
|
||||
}
|
||||
}
|
||||
X11_InitPen(_this);
|
||||
} break;
|
||||
|
||||
case XI_RawButtonPress:
|
||||
@ -326,29 +373,108 @@ int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie
|
||||
case XI_RawTouchUpdate:
|
||||
case XI_RawTouchEnd:
|
||||
#endif
|
||||
{
|
||||
videodata->global_mouse_changed = SDL_TRUE;
|
||||
break;
|
||||
} break;
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||
/* With multitouch, register to receive XI_Motion (which desctivates MotionNotify),
|
||||
* so that we can distinguish real mouse motions from synthetic one. */
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
{
|
||||
const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data;
|
||||
const SDL_Pen *pen = SDL_GetPenPtr(X11_PenIDFromDeviceID(xev->deviceid));
|
||||
const int button = xev->detail;
|
||||
const SDL_bool pressed = (cookie->evtype == XI_ButtonPress) ? SDL_TRUE : SDL_FALSE;
|
||||
|
||||
if (pen) {
|
||||
xinput2_pen_ensure_window(_this, pen, xev->event);
|
||||
|
||||
/* Only report button event; if there was also pen movement / pressure changes, we expect
|
||||
an XI_Motion event first anyway */
|
||||
if (button == 1) {
|
||||
/* button 1 is the pen tip */
|
||||
if (pressed && SDL_PenPerformHitTest()) {
|
||||
/* Check whether we should handle window resize / move events */
|
||||
SDL_WindowData *windowdata = X11_FindWindow(_this, xev->event);
|
||||
if (windowdata && X11_TriggerHitTestAction(_this, windowdata, pen->last.x, pen->last.y)) {
|
||||
SDL_SendWindowEvent(windowdata->window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0);
|
||||
return 1; /* Don't pass on this event */
|
||||
}
|
||||
}
|
||||
SDL_SendPenTipEvent(0, pen->header.id,
|
||||
pressed ? SDL_PRESSED : SDL_RELEASED);
|
||||
} else {
|
||||
SDL_SendPenButton(0, pen->header.id,
|
||||
pressed ? SDL_PRESSED : SDL_RELEASED,
|
||||
button - 1);
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
/* Otherwise assume a regular mouse */
|
||||
SDL_WindowData *windowdata = xinput2_get_sdlwindowdata(videodata, xev->event);
|
||||
|
||||
if (xev->deviceid != xev->sourceid) {
|
||||
/* Discard events from "Master" devices to avoid duplicates. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pressed) {
|
||||
X11_HandleButtonPress(_this, windowdata, button,
|
||||
xev->event_x, xev->event_y, xev->time);
|
||||
} else {
|
||||
X11_HandleButtonRelease(_this, windowdata, button);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
/* Register to receive XI_Motion (which deactivates MotionNotify), so that we can distinguish
|
||||
real mouse motions from synthetic ones, for multitouch and pen support. */
|
||||
case XI_Motion:
|
||||
{
|
||||
const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data;
|
||||
const SDL_Pen *pen = SDL_GetPenPtr(X11_PenIDFromDeviceID(xev->deviceid));
|
||||
#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||
int pointer_emulated = (xev->flags & XIPointerEmulated);
|
||||
#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH */
|
||||
|
||||
if (xev->deviceid != xev->sourceid) {
|
||||
/* Discard events from "Master" devices to avoid duplicates. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pen) {
|
||||
SDL_PenStatusInfo pen_status;
|
||||
|
||||
pen_status.x = xev->event_x;
|
||||
pen_status.y = xev->event_y;
|
||||
|
||||
X11_PenAxesFromValuators(pen,
|
||||
xev->valuators.values, xev->valuators.mask, xev->valuators.mask_len,
|
||||
&pen_status.axes[0]);
|
||||
|
||||
xinput2_pen_ensure_window(_this, pen, xev->event);
|
||||
|
||||
SDL_SendPenMotion(0, pen->header.id,
|
||||
SDL_TRUE,
|
||||
&pen_status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||
if (!pointer_emulated) {
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
if (!mouse->relative_mode || mouse->relative_mode_warp) {
|
||||
SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
|
||||
if (window) {
|
||||
X11_ProcessHitTest(_this, window->driverdata, (float)xev->event_x, (float)xev->event_y, SDL_FALSE);
|
||||
SDL_SendMouseMotion(0, window, 0, 0, (float)xev->event_x, (float)xev->event_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH */
|
||||
} break;
|
||||
|
||||
#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||
case XI_TouchBegin:
|
||||
{
|
||||
const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data;
|
||||
@ -376,10 +502,9 @@ int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie
|
||||
SDL_SendTouchMotion(0, xev->sourceid, xev->detail, window, x, y, 1.0);
|
||||
return 1;
|
||||
} break;
|
||||
|
||||
#endif
|
||||
#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH */
|
||||
}
|
||||
#endif
|
||||
#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -460,6 +585,38 @@ int X11_Xinput2IsInitialized(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
SDL_bool X11_Xinput2SelectMouse(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||
const SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
|
||||
XIEventMask eventmask;
|
||||
unsigned char mask[4] = { 0, 0, 0, 0 };
|
||||
SDL_WindowData *window_data = (SDL_WindowData *)window->driverdata;
|
||||
|
||||
eventmask.mask_len = sizeof(mask);
|
||||
eventmask.mask = mask;
|
||||
eventmask.deviceid = XIAllDevices;
|
||||
|
||||
XISetMask(mask, XI_ButtonPress);
|
||||
XISetMask(mask, XI_ButtonRelease);
|
||||
XISetMask(mask, XI_Motion);
|
||||
XISetMask(mask, XI_Enter);
|
||||
XISetMask(mask, XI_Leave);
|
||||
/* Hotplugging: */
|
||||
XISetMask(mask, XI_DeviceChanged);
|
||||
XISetMask(mask, XI_HierarchyChanged);
|
||||
XISetMask(mask, XI_PropertyEvent); /* E.g., when swapping tablet pens */
|
||||
|
||||
if (X11_XISelectEvents(data->display,
|
||||
window_data->xwindow,
|
||||
&eventmask, 1) == Success) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_INPUT, "Could not enable XInput2 mouse event handling\n");
|
||||
#endif
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
int X11_Xinput2IsMultitouchSupported(void)
|
||||
{
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -32,11 +32,12 @@ typedef struct XGenericEventCookie XGenericEventCookie;
|
||||
|
||||
extern void X11_InitXinput2(SDL_VideoDevice *_this);
|
||||
extern void X11_InitXinput2Multitouch(SDL_VideoDevice *_this);
|
||||
extern int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie);
|
||||
extern int X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie);
|
||||
extern int X11_Xinput2IsInitialized(void);
|
||||
extern int X11_Xinput2IsMultitouchSupported(void);
|
||||
extern void X11_Xinput2SelectTouch(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void X11_Xinput2GrabTouch(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void X11_Xinput2UngrabTouch(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern SDL_bool X11_Xinput2SelectMouse(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
|
||||
#endif /* SDL_x11xinput2_h_ */
|
||||
|
Reference in New Issue
Block a user