mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-03-20 15:51:07 +01:00
x11: Implement precision/pixel scrolling
Manual rebase of #5382 with some changes for SDL3 (thanks @wooosh).
This commit is contained in:
@@ -416,6 +416,17 @@ macro(CheckX11)
|
|||||||
endif()
|
endif()
|
||||||
set(SDL_VIDEO_DRIVER_X11_XINPUT2 1)
|
set(SDL_VIDEO_DRIVER_X11_XINPUT2 1)
|
||||||
|
|
||||||
|
# Check for scroll info
|
||||||
|
check_c_source_compiles("
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xproto.h>
|
||||||
|
#include <X11/extensions/XInput2.h>
|
||||||
|
XIScrollClassInfo *s;
|
||||||
|
int main(int argc, char **argv) {}" HAVE_XINPUT2_SCROLLINFO)
|
||||||
|
if(HAVE_XINPUT2_SCROLLINFO)
|
||||||
|
set(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Check for multitouch
|
# Check for multitouch
|
||||||
check_c_source_compiles_static("
|
check_c_source_compiles_static("
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
|||||||
@@ -429,6 +429,7 @@
|
|||||||
#cmakedefine SDL_VIDEO_DRIVER_X11_XFIXES 1
|
#cmakedefine SDL_VIDEO_DRIVER_X11_XFIXES 1
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2 1
|
#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2 1
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH 1
|
#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH 1
|
||||||
|
#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO 1
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_X11_XRANDR 1
|
#cmakedefine SDL_VIDEO_DRIVER_X11_XRANDR 1
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1
|
#cmakedefine SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1
|
||||||
#cmakedefine SDL_VIDEO_DRIVER_X11_XSHAPE 1
|
#cmakedefine SDL_VIDEO_DRIVER_X11_XSHAPE 1
|
||||||
|
|||||||
@@ -468,6 +468,7 @@ void X11_VideoQuit(SDL_VideoDevice *_this)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
X11_QuitXinput2(_this);
|
||||||
X11_QuitModes(_this);
|
X11_QuitModes(_this);
|
||||||
X11_QuitKeyboard(_this);
|
X11_QuitKeyboard(_this);
|
||||||
X11_QuitMouse(_this);
|
X11_QuitMouse(_this);
|
||||||
|
|||||||
@@ -475,7 +475,7 @@ static void SetupWindowInput(SDL_VideoDevice *_this, SDL_Window *window)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
X11_Xinput2SelectTouch(_this, window);
|
X11_Xinput2Select(_this, window);
|
||||||
|
|
||||||
{
|
{
|
||||||
unsigned int x11_keyboard_events = KeyPressMask | KeyReleaseMask;
|
unsigned int x11_keyboard_events = KeyPressMask | KeyReleaseMask;
|
||||||
|
|||||||
@@ -45,6 +45,28 @@ static bool xinput2_multitouch_supported;
|
|||||||
* this extension */
|
* this extension */
|
||||||
static int xinput2_opcode;
|
static int xinput2_opcode;
|
||||||
|
|
||||||
|
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int number;
|
||||||
|
int scroll_type;
|
||||||
|
double prev_value;
|
||||||
|
double increment;
|
||||||
|
bool prev_value_valid;
|
||||||
|
} SDL_XInput2ScrollInfo;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int device_id;
|
||||||
|
int scroll_info_count;
|
||||||
|
SDL_XInput2ScrollInfo *scroll_info;
|
||||||
|
} SDL_XInput2ScrollableDevice;
|
||||||
|
|
||||||
|
static SDL_XInput2ScrollableDevice *scrollable_devices;
|
||||||
|
static int scrollable_device_count;
|
||||||
|
static bool xinput2_scrolling_supported;
|
||||||
|
#endif
|
||||||
|
|
||||||
static void parse_valuators(const double *input_values, const unsigned char *mask, int mask_len,
|
static void parse_valuators(const double *input_values, const unsigned char *mask, int mask_len,
|
||||||
double *output_values, int output_values_len)
|
double *output_values, int output_values_len)
|
||||||
{
|
{
|
||||||
@@ -95,6 +117,62 @@ static SDL_Window *xinput2_get_sdlwindow(SDL_VideoData *videodata, Window window
|
|||||||
return windowdata ? windowdata->window : NULL;
|
return windowdata ? windowdata->window : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO
|
||||||
|
static void xinput2_reset_scrollable_valuators(SDL_VideoData *videodata)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < scrollable_device_count; ++i) {
|
||||||
|
for (int j = 0; j < scrollable_devices[i].scroll_info_count; ++j) {
|
||||||
|
scrollable_devices[i].scroll_info[j].prev_value_valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xinput2_parse_scrollable_valuators(const XIDeviceEvent *xev)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < scrollable_device_count; ++i) {
|
||||||
|
const SDL_XInput2ScrollableDevice *sd = &scrollable_devices[i];
|
||||||
|
if (xev->sourceid == sd->device_id) {
|
||||||
|
int values_i = 0;
|
||||||
|
for (int j = 0; j < xev->valuators.mask_len * 8; ++j) {
|
||||||
|
if (!XIMaskIsSet(xev->valuators.mask, j)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int k = 0; k < sd->scroll_info_count; ++k) {
|
||||||
|
SDL_XInput2ScrollInfo *info = &sd->scroll_info[k];
|
||||||
|
if (info->number == j) {
|
||||||
|
const double current_val = xev->valuators.values[values_i];
|
||||||
|
const double delta = (info->prev_value - current_val) / info->increment;
|
||||||
|
/* Ignore very large jumps that can happen as a result of overflowing
|
||||||
|
* the maximum range, as the driver will reset the position to zero
|
||||||
|
* at "something that's close to 2^32".
|
||||||
|
*
|
||||||
|
* The first scroll event is meaningless by itself and must be discarded,
|
||||||
|
* as it is only useful for establishing a baseline for future deltas.
|
||||||
|
* This is a known deficiency of the XInput2 scroll protocol, and,
|
||||||
|
* unfortunately, there is nothing we can do about it.
|
||||||
|
*
|
||||||
|
* http://who-t.blogspot.com/2012/06/xi-21-protocol-design-issues.html
|
||||||
|
*/
|
||||||
|
if (info->prev_value_valid && SDL_fabs(delta) < (double)SDL_MAX_SINT32 * 0.95) {
|
||||||
|
const double x = info->scroll_type == XIScrollTypeHorizontal ? delta : 0;
|
||||||
|
const double y = info->scroll_type == XIScrollTypeVertical ? delta : 0;
|
||||||
|
|
||||||
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
|
SDL_SendMouseWheel(xev->time, mouse->focus, (SDL_MouseID)xev->sourceid, (float)x, (float)y, SDL_MOUSEWHEEL_NORMAL);
|
||||||
|
}
|
||||||
|
info->prev_value = current_val;
|
||||||
|
info->prev_value_valid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++values_i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO
|
||||||
|
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
#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)
|
static void xinput2_normalize_touch_coordinates(SDL_Window *window, double in_x, double in_y, float *out_x, float *out_y)
|
||||||
{
|
{
|
||||||
@@ -119,6 +197,24 @@ static void xinput2_normalize_touch_coordinates(SDL_Window *window, double in_x,
|
|||||||
|
|
||||||
#endif // SDL_VIDEO_DRIVER_X11_XINPUT2
|
#endif // SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||||
|
|
||||||
|
static bool X11_Xinput2IsMultitouchSupported(void)
|
||||||
|
{
|
||||||
|
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||||
|
return xinput2_initialized && xinput2_multitouch_supported;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool X11_Xinput2IsScrollingSupported(void)
|
||||||
|
{
|
||||||
|
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO
|
||||||
|
return xinput2_initialized && xinput2_scrolling_supported;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool X11_InitXinput2(SDL_VideoDevice *_this)
|
bool X11_InitXinput2(SDL_VideoDevice *_this)
|
||||||
{
|
{
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
|
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||||
@@ -126,7 +222,7 @@ bool X11_InitXinput2(SDL_VideoDevice *_this)
|
|||||||
|
|
||||||
int version = 0;
|
int version = 0;
|
||||||
XIEventMask eventmask;
|
XIEventMask eventmask;
|
||||||
unsigned char mask[4] = { 0, 0, 0, 0 };
|
unsigned char mask[5] = { 0, 0, 0, 0, 0 };
|
||||||
int event, err;
|
int event, err;
|
||||||
|
|
||||||
/* XInput2 is required for relative mouse mode, so you probably want to leave this enabled */
|
/* XInput2 is required for relative mouse mode, so you probably want to leave this enabled */
|
||||||
@@ -156,6 +252,10 @@ bool X11_InitXinput2(SDL_VideoDevice *_this)
|
|||||||
|
|
||||||
xinput2_initialized = true;
|
xinput2_initialized = true;
|
||||||
|
|
||||||
|
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO // Smooth scrolling needs XInput 2.1
|
||||||
|
xinput2_scrolling_supported = xinput2_version_atleast(version, 2, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH // Multitouch needs XInput 2.2
|
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH // Multitouch needs XInput 2.2
|
||||||
xinput2_multitouch_supported = xinput2_version_atleast(version, 2, 2);
|
xinput2_multitouch_supported = xinput2_version_atleast(version, 2, 2);
|
||||||
#endif
|
#endif
|
||||||
@@ -171,6 +271,12 @@ bool X11_InitXinput2(SDL_VideoDevice *_this)
|
|||||||
XISetMask(mask, XI_RawButtonPress);
|
XISetMask(mask, XI_RawButtonPress);
|
||||||
XISetMask(mask, XI_RawButtonRelease);
|
XISetMask(mask, XI_RawButtonRelease);
|
||||||
|
|
||||||
|
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO
|
||||||
|
if (X11_Xinput2IsScrollingSupported()) {
|
||||||
|
XISetMask(mask, XI_Motion);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||||
// Enable raw touch events if supported
|
// Enable raw touch events if supported
|
||||||
if (X11_Xinput2IsMultitouchSupported()) {
|
if (X11_Xinput2IsMultitouchSupported()) {
|
||||||
@@ -199,6 +305,18 @@ bool X11_InitXinput2(SDL_VideoDevice *_this)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void X11_QuitXinput2(SDL_VideoDevice *_this)
|
||||||
|
{
|
||||||
|
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO
|
||||||
|
for (int i = 0; i < scrollable_device_count; ++i) {
|
||||||
|
SDL_free(scrollable_devices[i].scroll_info);
|
||||||
|
}
|
||||||
|
SDL_free(scrollable_devices);
|
||||||
|
scrollable_devices = NULL;
|
||||||
|
scrollable_device_count = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
|
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||||
// xi2 device went away? take it out of the list.
|
// xi2 device went away? take it out of the list.
|
||||||
static void xinput2_remove_device_info(SDL_VideoData *videodata, const int device_id)
|
static void xinput2_remove_device_info(SDL_VideoData *videodata, const int device_id)
|
||||||
@@ -409,6 +527,11 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
|
|||||||
X11_PenHandle *pen = X11_FindPenByDeviceID(xev->sourceid);
|
X11_PenHandle *pen = X11_FindPenByDeviceID(xev->sourceid);
|
||||||
const int button = xev->detail;
|
const int button = xev->detail;
|
||||||
const bool down = (cookie->evtype == XI_ButtonPress);
|
const bool down = (cookie->evtype == XI_ButtonPress);
|
||||||
|
#if defined(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO) || defined(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH)
|
||||||
|
bool pointer_emulated = (xev->flags & XIPointerEmulated) != 0;
|
||||||
|
#else
|
||||||
|
bool pointer_emulated = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (pen) {
|
if (pen) {
|
||||||
if (xev->deviceid != xev->sourceid) {
|
if (xev->deviceid != xev->sourceid) {
|
||||||
@@ -429,8 +552,12 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
|
|||||||
|
|
||||||
/* Discard wheel events from "Master" devices to avoid duplicates,
|
/* Discard wheel events from "Master" devices to avoid duplicates,
|
||||||
* as coarse wheel events are stateless and can't be deduplicated.
|
* as coarse wheel events are stateless and can't be deduplicated.
|
||||||
|
*
|
||||||
|
* If the pointer emulation flag is set on a wheel event, it is being
|
||||||
|
* emulated from a scroll valuator, which will be handled natively.
|
||||||
*/
|
*/
|
||||||
if (xev->deviceid != xev->sourceid && X11_IsWheelEvent(button, &x_ticks, &y_ticks)) {
|
if ((pointer_emulated || xev->deviceid != xev->sourceid) &&
|
||||||
|
X11_IsWheelEvent(button, &x_ticks, &y_ticks)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,13 +570,19 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO
|
||||||
|
case XI_Enter:
|
||||||
|
xinput2_reset_scrollable_valuators(videodata);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Register to receive XI_Motion (which deactivates MotionNotify), so that we can distinguish
|
/* Register to receive XI_Motion (which deactivates MotionNotify), so that we can distinguish
|
||||||
real mouse motions from synthetic ones, for multitouch and pen support. */
|
real mouse motions from synthetic ones, for multitouch and pen support. */
|
||||||
case XI_Motion:
|
case XI_Motion:
|
||||||
{
|
{
|
||||||
const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data;
|
const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data;
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
#if defined(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO) || defined(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH)
|
||||||
bool pointer_emulated = ((xev->flags & XIPointerEmulated) != 0);
|
bool pointer_emulated = (xev->flags & XIPointerEmulated) != 0;
|
||||||
#else
|
#else
|
||||||
bool pointer_emulated = false;
|
bool pointer_emulated = false;
|
||||||
#endif
|
#endif
|
||||||
@@ -475,14 +608,22 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
|
|||||||
SDL_SendPenAxis(0, pen->pen, window, (SDL_PenAxis) i, axes[i]);
|
SDL_SendPenAxis(0, pen->pen, window, (SDL_PenAxis) i, axes[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!pointer_emulated && xev->deviceid == videodata->xinput_master_pointer_device) {
|
} else if (!pointer_emulated) {
|
||||||
// Use the master device for non-relative motion, as the slave devices can seemingly lag behind.
|
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
if (xev->deviceid == xev->sourceid) {
|
||||||
if (!mouse->relative_mode) {
|
xinput2_parse_scrollable_valuators(xev);
|
||||||
SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
|
}
|
||||||
if (window) {
|
#endif
|
||||||
X11_ProcessHitTest(_this, window->internal, (float)xev->event_x, (float)xev->event_y, false);
|
|
||||||
SDL_SendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, false, (float)xev->event_x, (float)xev->event_y);
|
if (xev->deviceid == videodata->xinput_master_pointer_device) {
|
||||||
|
// Use the master device for non-relative motion, as the slave devices can seemingly lag behind.
|
||||||
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
|
if (!mouse->relative_mode) {
|
||||||
|
SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
|
||||||
|
if (window) {
|
||||||
|
X11_ProcessHitTest(_this, window->internal, (float)xev->event_x, (float)xev->event_y, false);
|
||||||
|
SDL_SendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, false, (float)xev->event_x, (float)xev->event_y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -524,29 +665,36 @@ void X11_InitXinput2Multitouch(SDL_VideoDevice *_this)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void X11_Xinput2SelectTouch(SDL_VideoDevice *_this, SDL_Window *window)
|
void X11_Xinput2Select(SDL_VideoDevice *_this, SDL_Window *window)
|
||||||
{
|
{
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
#if defined(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO) || defined(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH)
|
||||||
SDL_VideoData *data = NULL;
|
SDL_VideoData *data = _this->internal;
|
||||||
|
SDL_WindowData *window_data = window->internal;
|
||||||
XIEventMask eventmask;
|
XIEventMask eventmask;
|
||||||
unsigned char mask[4] = { 0, 0, 0, 0 };
|
unsigned char mask[5] = { 0, 0, 0, 0, 0 };
|
||||||
SDL_WindowData *window_data = NULL;
|
|
||||||
|
|
||||||
if (!X11_Xinput2IsMultitouchSupported()) {
|
if (!X11_Xinput2IsScrollingSupported() && !X11_Xinput2IsMultitouchSupported()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = _this->internal;
|
|
||||||
window_data = window->internal;
|
|
||||||
|
|
||||||
eventmask.deviceid = XIAllMasterDevices;
|
eventmask.deviceid = XIAllMasterDevices;
|
||||||
eventmask.mask_len = sizeof(mask);
|
eventmask.mask_len = sizeof(mask);
|
||||||
eventmask.mask = mask;
|
eventmask.mask = mask;
|
||||||
|
|
||||||
XISetMask(mask, XI_TouchBegin);
|
if (X11_Xinput2IsScrollingSupported()) {
|
||||||
XISetMask(mask, XI_TouchUpdate);
|
/* Track enter events that inform us that we need to update
|
||||||
XISetMask(mask, XI_TouchEnd);
|
* the previous scroll coordinates since we cannot track
|
||||||
XISetMask(mask, XI_Motion);
|
* them outside our window.
|
||||||
|
*/
|
||||||
|
XISetMask(mask, XI_Enter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (X11_Xinput2IsMultitouchSupported()) {
|
||||||
|
XISetMask(mask, XI_TouchBegin);
|
||||||
|
XISetMask(mask, XI_TouchUpdate);
|
||||||
|
XISetMask(mask, XI_TouchEnd);
|
||||||
|
XISetMask(mask, XI_Motion);
|
||||||
|
}
|
||||||
|
|
||||||
X11_XISelectEvents(data->display, window_data->xwindow, &eventmask, 1);
|
X11_XISelectEvents(data->display, window_data->xwindow, &eventmask, 1);
|
||||||
#endif
|
#endif
|
||||||
@@ -610,15 +758,6 @@ bool X11_Xinput2SelectMouseAndKeyboard(SDL_VideoDevice *_this, SDL_Window *windo
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool X11_Xinput2IsMultitouchSupported(void)
|
|
||||||
{
|
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
|
||||||
return xinput2_initialized && xinput2_multitouch_supported;
|
|
||||||
#else
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void X11_Xinput2GrabTouch(SDL_VideoDevice *_this, SDL_Window *window)
|
void X11_Xinput2GrabTouch(SDL_VideoDevice *_this, SDL_Window *window)
|
||||||
{
|
{
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||||
@@ -748,6 +887,16 @@ void X11_Xinput2UpdateDevices(SDL_VideoDevice *_this, bool initial_check)
|
|||||||
old_mice = SDL_GetMice(&old_mouse_count);
|
old_mice = SDL_GetMice(&old_mouse_count);
|
||||||
old_touch_devices = SDL_GetTouchDevices(&old_touch_count);
|
old_touch_devices = SDL_GetTouchDevices(&old_touch_count);
|
||||||
|
|
||||||
|
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO
|
||||||
|
// Scroll devices don't get add/remove events, so just rebuild the list.
|
||||||
|
for (int i = 0; i < scrollable_device_count; ++i) {
|
||||||
|
SDL_free(scrollable_devices[i].scroll_info);
|
||||||
|
}
|
||||||
|
SDL_free(scrollable_devices);
|
||||||
|
scrollable_devices = NULL;
|
||||||
|
scrollable_device_count = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
for (int i = 0; i < ndevices; i++) {
|
for (int i = 0; i < ndevices; i++) {
|
||||||
XIDeviceInfo *dev = &info[i];
|
XIDeviceInfo *dev = &info[i];
|
||||||
|
|
||||||
@@ -778,6 +927,54 @@ void X11_Xinput2UpdateDevices(SDL_VideoDevice *_this, bool initial_check)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO
|
||||||
|
SDL_XInput2ScrollableDevice *sd = NULL;
|
||||||
|
int allocated_scroll_info_count = 0;
|
||||||
|
|
||||||
|
for (int j = 0; j < dev->num_classes; j++) {
|
||||||
|
const XIAnyClassInfo *class = dev->classes[j];
|
||||||
|
const XIScrollClassInfo *s = (XIScrollClassInfo *)class;
|
||||||
|
|
||||||
|
if (class->type != XIScrollClass) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate a new scrollable device.
|
||||||
|
if (!sd) {
|
||||||
|
scrollable_devices = SDL_realloc(scrollable_devices, (scrollable_device_count + 1) * sizeof(SDL_XInput2ScrollableDevice));
|
||||||
|
if (!scrollable_devices) {
|
||||||
|
// No memory; so just skip this.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sd = &scrollable_devices[scrollable_device_count];
|
||||||
|
++scrollable_device_count;
|
||||||
|
|
||||||
|
SDL_zerop(sd);
|
||||||
|
sd->device_id = dev->deviceid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate new scroll info entries two at a time, as they typically come in a horizontal/vertical pair.
|
||||||
|
if (sd->scroll_info_count == allocated_scroll_info_count) {
|
||||||
|
sd->scroll_info = SDL_realloc(sd->scroll_info, (allocated_scroll_info_count + 2) * sizeof(SDL_XInput2ScrollInfo));
|
||||||
|
if (!sd->scroll_info) {
|
||||||
|
// No memory; just skip this.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
allocated_scroll_info_count += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_XInput2ScrollInfo *scroll_info = &sd->scroll_info[sd->scroll_info_count];
|
||||||
|
++sd->scroll_info_count;
|
||||||
|
|
||||||
|
SDL_zerop(scroll_info);
|
||||||
|
scroll_info->number = s->number;
|
||||||
|
scroll_info->scroll_type = s->scroll_type;
|
||||||
|
scroll_info->increment = s->increment;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||||
for (int j = 0; j < dev->num_classes; j++) {
|
for (int j = 0; j < dev->num_classes; j++) {
|
||||||
Uint64 touchID;
|
Uint64 touchID;
|
||||||
|
|||||||
@@ -31,11 +31,11 @@ typedef struct XGenericEventCookie XGenericEventCookie;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern bool X11_InitXinput2(SDL_VideoDevice *_this);
|
extern bool X11_InitXinput2(SDL_VideoDevice *_this);
|
||||||
|
extern void X11_QuitXinput2(SDL_VideoDevice *_this);
|
||||||
extern void X11_InitXinput2Multitouch(SDL_VideoDevice *_this);
|
extern void X11_InitXinput2Multitouch(SDL_VideoDevice *_this);
|
||||||
extern void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie);
|
extern void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie);
|
||||||
extern bool X11_Xinput2IsInitialized(void);
|
extern bool X11_Xinput2IsInitialized(void);
|
||||||
extern bool X11_Xinput2IsMultitouchSupported(void);
|
extern void X11_Xinput2Select(SDL_VideoDevice *_this, SDL_Window *window);
|
||||||
extern void X11_Xinput2SelectTouch(SDL_VideoDevice *_this, SDL_Window *window);
|
|
||||||
extern void X11_Xinput2GrabTouch(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 void X11_Xinput2UngrabTouch(SDL_VideoDevice *_this, SDL_Window *window);
|
||||||
extern bool X11_Xinput2SelectMouseAndKeyboard(SDL_VideoDevice *_this, SDL_Window *window);
|
extern bool X11_Xinput2SelectMouseAndKeyboard(SDL_VideoDevice *_this, SDL_Window *window);
|
||||||
|
|||||||
Reference in New Issue
Block a user