SDL  2.0
SDL_waylandevents.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 
22 #include "../../SDL_internal.h"
23 
24 #if SDL_VIDEO_DRIVER_WAYLAND
25 
26 #include "SDL_stdinc.h"
27 #include "SDL_assert.h"
28 #include "SDL_log.h"
29 
30 #include "../../events/SDL_sysevents.h"
31 #include "../../events/SDL_events_c.h"
32 #include "../../events/scancodes_xfree86.h"
33 
34 #include "SDL_waylandvideo.h"
35 #include "SDL_waylandevents_c.h"
36 #include "SDL_waylandwindow.h"
37 
38 #include "SDL_waylanddyn.h"
39 
40 #include "pointer-constraints-unstable-v1-client-protocol.h"
41 #include "relative-pointer-unstable-v1-client-protocol.h"
42 
43 #include <linux/input.h>
44 #include <sys/select.h>
45 #include <sys/mman.h>
46 #include <poll.h>
47 #include <unistd.h>
48 #include <xkbcommon/xkbcommon.h>
49 
50 struct SDL_WaylandInput {
51  SDL_VideoData *display;
52  struct wl_seat *seat;
53  struct wl_pointer *pointer;
54  struct wl_keyboard *keyboard;
55  struct zwp_relative_pointer_v1 *relative_pointer;
56  SDL_WindowData *pointer_focus;
57  SDL_WindowData *keyboard_focus;
58 
59  /* Last motion location */
60  wl_fixed_t sx_w;
61  wl_fixed_t sy_w;
62 
63  double dx_frac;
64  double dy_frac;
65 
66  struct {
67  struct xkb_keymap *keymap;
68  struct xkb_state *state;
69  } xkb;
70 };
71 
72 void
74 {
76  struct pollfd pfd[1];
77 
78  pfd[0].fd = WAYLAND_wl_display_get_fd(d->display);
79  pfd[0].events = POLLIN;
80  poll(pfd, 1, 0);
81 
82  if (pfd[0].revents & POLLIN)
83  WAYLAND_wl_display_dispatch(d->display);
84  else
85  WAYLAND_wl_display_dispatch_pending(d->display);
86 }
87 
88 static void
89 pointer_handle_enter(void *data, struct wl_pointer *pointer,
90  uint32_t serial, struct wl_surface *surface,
91  wl_fixed_t sx_w, wl_fixed_t sy_w)
92 {
93  struct SDL_WaylandInput *input = data;
95 
96  if (!surface) {
97  /* enter event for a window we've just destroyed */
98  return;
99  }
100 
101  /* This handler will be called twice in Wayland 1.4
102  * Once for the window surface which has valid user data
103  * and again for the mouse cursor surface which does not have valid user data
104  * We ignore the later
105  */
106 
107  window = (SDL_WindowData *)wl_surface_get_user_data(surface);
108 
109  if (window) {
110  input->pointer_focus = window;
111  SDL_SetMouseFocus(window->sdlwindow);
112  }
113 }
114 
115 static void
116 pointer_handle_leave(void *data, struct wl_pointer *pointer,
117  uint32_t serial, struct wl_surface *surface)
118 {
119  struct SDL_WaylandInput *input = data;
120 
121  if (input->pointer_focus) {
123  input->pointer_focus = NULL;
124  }
125 }
126 
127 static void
128 pointer_handle_motion(void *data, struct wl_pointer *pointer,
129  uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w)
130 {
131  struct SDL_WaylandInput *input = data;
132  SDL_WindowData *window = input->pointer_focus;
133  input->sx_w = sx_w;
134  input->sy_w = sy_w;
135  if (input->pointer_focus) {
136  const int sx = wl_fixed_to_int(sx_w);
137  const int sy = wl_fixed_to_int(sy_w);
138  SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
139  }
140 }
141 
142 static SDL_bool
143 ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
144 {
145  SDL_WindowData *window_data = input->pointer_focus;
146  SDL_Window *window = window_data->sdlwindow;
147 
148  if (window->hit_test) {
149  const SDL_Point point = { wl_fixed_to_int(input->sx_w), wl_fixed_to_int(input->sy_w) };
150  const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
151  static const uint32_t directions[] = {
152  WL_SHELL_SURFACE_RESIZE_TOP_LEFT, WL_SHELL_SURFACE_RESIZE_TOP,
153  WL_SHELL_SURFACE_RESIZE_TOP_RIGHT, WL_SHELL_SURFACE_RESIZE_RIGHT,
154  WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT, WL_SHELL_SURFACE_RESIZE_BOTTOM,
155  WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT, WL_SHELL_SURFACE_RESIZE_LEFT
156  };
157  switch (rc) {
159  wl_shell_surface_move(window_data->shell_surface, input->seat, serial);
160  return SDL_TRUE;
161 
170  wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
171  return SDL_TRUE;
172 
173  default: return SDL_FALSE;
174  }
175  }
176 
177  return SDL_FALSE;
178 }
179 
180 static void
181 pointer_handle_button_common(struct SDL_WaylandInput *input, uint32_t serial,
182  uint32_t time, uint32_t button, uint32_t state_w)
183 {
184  SDL_WindowData *window = input->pointer_focus;
185  enum wl_pointer_button_state state = state_w;
186  uint32_t sdl_button;
187 
188  if (input->pointer_focus) {
189  switch (button) {
190  case BTN_LEFT:
191  sdl_button = SDL_BUTTON_LEFT;
192  if (ProcessHitTest(input, serial)) {
193  return; /* don't pass this event on to app. */
194  }
195  break;
196  case BTN_MIDDLE:
197  sdl_button = SDL_BUTTON_MIDDLE;
198  break;
199  case BTN_RIGHT:
200  sdl_button = SDL_BUTTON_RIGHT;
201  break;
202  case BTN_SIDE:
203  sdl_button = SDL_BUTTON_X1;
204  break;
205  case BTN_EXTRA:
206  sdl_button = SDL_BUTTON_X2;
207  break;
208  default:
209  return;
210  }
211 
212  SDL_SendMouseButton(window->sdlwindow, 0,
213  state ? SDL_PRESSED : SDL_RELEASED, sdl_button);
214  }
215 }
216 
217 static void
218 pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
219  uint32_t time, uint32_t button, uint32_t state_w)
220 {
221  struct SDL_WaylandInput *input = data;
222 
223  pointer_handle_button_common(input, serial, time, button, state_w);
224 }
225 
226 static void
227 pointer_handle_axis_common(struct SDL_WaylandInput *input,
228  uint32_t time, uint32_t axis, wl_fixed_t value)
229 {
230  SDL_WindowData *window = input->pointer_focus;
231  enum wl_pointer_axis a = axis;
232  int x, y;
233 
234  if (input->pointer_focus) {
235  switch (a) {
236  case WL_POINTER_AXIS_VERTICAL_SCROLL:
237  x = 0;
238  y = wl_fixed_to_int(value);
239  break;
240  case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
241  x = wl_fixed_to_int(value);
242  y = 0;
243  break;
244  default:
245  return;
246  }
247 
249  }
250 }
251 
252 static void
253 pointer_handle_axis(void *data, struct wl_pointer *pointer,
254  uint32_t time, uint32_t axis, wl_fixed_t value)
255 {
256  struct SDL_WaylandInput *input = data;
257 
258  pointer_handle_axis_common(input, time, axis, value);
259 }
260 
261 static const struct wl_pointer_listener pointer_listener = {
262  pointer_handle_enter,
263  pointer_handle_leave,
264  pointer_handle_motion,
265  pointer_handle_button,
266  pointer_handle_axis,
267 };
268 
269 static void
270 keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
271  uint32_t format, int fd, uint32_t size)
272 {
273  struct SDL_WaylandInput *input = data;
274  char *map_str;
275 
276  if (!data) {
277  close(fd);
278  return;
279  }
280 
281  if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
282  close(fd);
283  return;
284  }
285 
286  map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
287  if (map_str == MAP_FAILED) {
288  close(fd);
289  return;
290  }
291 
292  input->xkb.keymap = WAYLAND_xkb_keymap_new_from_string(input->display->xkb_context,
293  map_str,
294  XKB_KEYMAP_FORMAT_TEXT_V1,
295  0);
296  munmap(map_str, size);
297  close(fd);
298 
299  if (!input->xkb.keymap) {
300  fprintf(stderr, "failed to compile keymap\n");
301  return;
302  }
303 
304  input->xkb.state = WAYLAND_xkb_state_new(input->xkb.keymap);
305  if (!input->xkb.state) {
306  fprintf(stderr, "failed to create XKB state\n");
307  WAYLAND_xkb_keymap_unref(input->xkb.keymap);
308  input->xkb.keymap = NULL;
309  return;
310  }
311 }
312 
313 static void
314 keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
315  uint32_t serial, struct wl_surface *surface,
316  struct wl_array *keys)
317 {
318  struct SDL_WaylandInput *input = data;
320 
321  if (!surface) {
322  /* enter event for a window we've just destroyed */
323  return;
324  }
325 
326  window = wl_surface_get_user_data(surface);
327 
328  if (window) {
329  input->keyboard_focus = window;
330  window->keyboard_device = input;
332  }
333 }
334 
335 static void
336 keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
337  uint32_t serial, struct wl_surface *surface)
338 {
340 }
341 
342 static void
343 keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
344  uint32_t serial, uint32_t time, uint32_t key,
345  uint32_t state_w)
346 {
347  struct SDL_WaylandInput *input = data;
348  SDL_WindowData *window = input->keyboard_focus;
349  enum wl_keyboard_key_state state = state_w;
350  const xkb_keysym_t *syms;
351  uint32_t scancode;
352  char text[8];
353  int size;
354 
356  scancode = xfree86_scancode_table2[key];
357 
358  // TODO when do we get WL_KEYBOARD_KEY_STATE_REPEAT?
359  if (scancode != SDL_SCANCODE_UNKNOWN)
360  SDL_SendKeyboardKey(state == WL_KEYBOARD_KEY_STATE_PRESSED ?
361  SDL_PRESSED : SDL_RELEASED, scancode);
362  }
363 
364  if (!window || window->keyboard_device != input || !input->xkb.state)
365  return;
366 
367  // TODO can this happen?
368  if (WAYLAND_xkb_state_key_get_syms(input->xkb.state, key + 8, &syms) != 1)
369  return;
370 
371  if (state) {
372  size = WAYLAND_xkb_keysym_to_utf8(syms[0], text, sizeof text);
373 
374  if (size > 0) {
375  text[size] = 0;
376  SDL_SendKeyboardText(text);
377  }
378  }
379 }
380 
381 static void
382 keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
383  uint32_t serial, uint32_t mods_depressed,
384  uint32_t mods_latched, uint32_t mods_locked,
385  uint32_t group)
386 {
387  struct SDL_WaylandInput *input = data;
388 
389  WAYLAND_xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched,
390  mods_locked, 0, 0, group);
391 }
392 
393 static const struct wl_keyboard_listener keyboard_listener = {
394  keyboard_handle_keymap,
395  keyboard_handle_enter,
396  keyboard_handle_leave,
397  keyboard_handle_key,
398  keyboard_handle_modifiers,
399 };
400 
401 static void
402 seat_handle_capabilities(void *data, struct wl_seat *seat,
403  enum wl_seat_capability caps)
404 {
405  struct SDL_WaylandInput *input = data;
406 
407  if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) {
408  input->pointer = wl_seat_get_pointer(seat);
409  input->display->pointer = input->pointer;
410  wl_pointer_set_user_data(input->pointer, input);
411  wl_pointer_add_listener(input->pointer, &pointer_listener,
412  input);
413  } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) {
414  wl_pointer_destroy(input->pointer);
415  input->pointer = NULL;
416  }
417 
418  if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) {
419  input->keyboard = wl_seat_get_keyboard(seat);
420  wl_keyboard_set_user_data(input->keyboard, input);
421  wl_keyboard_add_listener(input->keyboard, &keyboard_listener,
422  input);
423  } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) {
424  wl_keyboard_destroy(input->keyboard);
425  input->keyboard = NULL;
426  }
427 }
428 
429 static const struct wl_seat_listener seat_listener = {
430  seat_handle_capabilities,
431 };
432 
433 void
435 {
436  struct SDL_WaylandInput *input;
437 
438  input = SDL_calloc(1, sizeof *input);
439  if (input == NULL)
440  return;
441 
442  input->display = d;
443  input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, 1);
444  input->sx_w = wl_fixed_from_int(0);
445  input->sy_w = wl_fixed_from_int(0);
446  d->input = input;
447 
448  wl_seat_add_listener(input->seat, &seat_listener, input);
449  wl_seat_set_user_data(input->seat, input);
450 
451  WAYLAND_wl_display_flush(d->display);
452 }
453 
455 {
456  struct SDL_WaylandInput *input = d->input;
457 
458  if (!input)
459  return;
460 
461  if (input->keyboard)
462  wl_keyboard_destroy(input->keyboard);
463 
464  if (input->pointer)
465  wl_pointer_destroy(input->pointer);
466 
467  if (input->seat)
468  wl_seat_destroy(input->seat);
469 
470  if (input->xkb.state)
471  WAYLAND_xkb_state_unref(input->xkb.state);
472 
473  if (input->xkb.keymap)
474  WAYLAND_xkb_keymap_unref(input->xkb.keymap);
475 
476  SDL_free(input);
477  d->input = NULL;
478 }
479 
481 {
483  wl_registry_bind(d->registry, id,
484  &zwp_relative_pointer_manager_v1_interface, 1);
485 }
486 
488 {
490  zwp_relative_pointer_manager_v1_destroy(d->relative_pointer_manager);
491 }
492 
494 {
496  wl_registry_bind(d->registry, id,
497  &zwp_pointer_constraints_v1_interface, 1);
498 }
499 
501 {
502  if (d->pointer_constraints)
503  zwp_pointer_constraints_v1_destroy(d->pointer_constraints);
504 }
505 
506 static void
507 relative_pointer_handle_relative_motion(void *data,
508  struct zwp_relative_pointer_v1 *pointer,
509  uint32_t time_hi,
510  uint32_t time_lo,
511  wl_fixed_t dx_w,
512  wl_fixed_t dy_w,
513  wl_fixed_t dx_unaccel_w,
514  wl_fixed_t dy_unaccel_w)
515 {
516  struct SDL_WaylandInput *input = data;
517  SDL_VideoData *d = input->display;
518  SDL_WindowData *window = input->pointer_focus;
519  double dx_unaccel;
520  double dy_unaccel;
521  double dx;
522  double dy;
523 
524  dx_unaccel = wl_fixed_to_double(dx_unaccel_w);
525  dy_unaccel = wl_fixed_to_double(dy_unaccel_w);
526 
527  /* Add left over fraction from last event. */
528  dx_unaccel += input->dx_frac;
529  dy_unaccel += input->dy_frac;
530 
531  input->dx_frac = modf(dx_unaccel, &dx);
532  input->dy_frac = modf(dy_unaccel, &dy);
533 
534  if (input->pointer_focus && d->relative_mouse_mode) {
535  SDL_SendMouseMotion(window->sdlwindow, 0, 1, (int)dx, (int)dy);
536  }
537 }
538 
539 static const struct zwp_relative_pointer_v1_listener relative_pointer_listener = {
540  relative_pointer_handle_relative_motion,
541 };
542 
543 static void
544 locked_pointer_locked(void *data,
545  struct zwp_locked_pointer_v1 *locked_pointer)
546 {
547 }
548 
549 static void
550 locked_pointer_unlocked(void *data,
551  struct zwp_locked_pointer_v1 *locked_pointer)
552 {
553 }
554 
555 static const struct zwp_locked_pointer_v1_listener locked_pointer_listener = {
556  locked_pointer_locked,
557  locked_pointer_unlocked,
558 };
559 
560 static void
561 lock_pointer_to_window(SDL_Window *window,
562  struct SDL_WaylandInput *input)
563 {
564  SDL_WindowData *w = window->driverdata;
565  SDL_VideoData *d = input->display;
566  struct zwp_locked_pointer_v1 *locked_pointer;
567 
568  if (w->locked_pointer)
569  return;
570 
571  locked_pointer =
572  zwp_pointer_constraints_v1_lock_pointer(d->pointer_constraints,
573  w->surface,
574  input->pointer,
575  NULL,
576  ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
577  zwp_locked_pointer_v1_add_listener(locked_pointer,
578  &locked_pointer_listener,
579  window);
580 
581  w->locked_pointer = locked_pointer;
582 }
583 
584 int Wayland_input_lock_pointer(struct SDL_WaylandInput *input)
585 {
587  SDL_VideoData *d = input->display;
589  struct zwp_relative_pointer_v1 *relative_pointer;
590 
591  if (!d->relative_pointer_manager)
592  return -1;
593 
594  if (!d->pointer_constraints)
595  return -1;
596 
597  if (!input->relative_pointer) {
598  relative_pointer =
599  zwp_relative_pointer_manager_v1_get_relative_pointer(
601  input->pointer);
602  zwp_relative_pointer_v1_add_listener(relative_pointer,
603  &relative_pointer_listener,
604  input);
605  input->relative_pointer = relative_pointer;
606  }
607 
608  for (window = vd->windows; window; window = window->next)
609  lock_pointer_to_window(window, input);
610 
611  d->relative_mouse_mode = 1;
612 
613  return 0;
614 }
615 
616 int Wayland_input_unlock_pointer(struct SDL_WaylandInput *input)
617 {
619  SDL_VideoData *d = input->display;
621  SDL_WindowData *w;
622 
623  for (window = vd->windows; window; window = window->next) {
624  w = window->driverdata;
625  if (w->locked_pointer)
626  zwp_locked_pointer_v1_destroy(w->locked_pointer);
627  w->locked_pointer = NULL;
628  }
629 
630  zwp_relative_pointer_v1_destroy(input->relative_pointer);
631  input->relative_pointer = NULL;
632 
633  d->relative_mouse_mode = 0;
634 
635  return 0;
636 }
637 
638 #endif /* SDL_VIDEO_DRIVER_WAYLAND */
639 
640 /* vi: set ts=4 sw=4 expandtab: */
SDL_Window * next
Definition: SDL_sysvideo.h:112
int Wayland_input_unlock_pointer(struct SDL_WaylandInput *input)
GLboolean GLuint group
void Wayland_display_destroy_pointer_constraints(SDL_VideoData *d)
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1565
struct zwp_relative_pointer_manager_v1 * relative_pointer_manager
SDL_Texture * button
void Wayland_display_destroy_relative_pointer_manager(SDL_VideoData *d)
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:612
void * hit_test_data
Definition: SDL_sysvideo.h:105
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1567
struct wl_display * display
static SDL_Window * window
void Wayland_display_add_pointer_constraints(SDL_VideoData *d, uint32_t id)
#define SDL_BUTTON_RIGHT
Definition: SDL_mouse.h:284
struct xkb_state * state
The structure that defines a point.
Definition: SDL_rect.h:48
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
static const SDL_Scancode xfree86_scancode_table2[]
int Wayland_input_lock_pointer(struct SDL_WaylandInput *input)
SDL_Texture * axis
#define SDL_BUTTON_X1
Definition: SDL_mouse.h:285
void SDL_SetMouseFocus(SDL_Window *window)
Definition: SDL_mouse.c:103
struct SDL_WaylandInput * input
GLsizeiptr size
SDL_Surface * surface
GLsizei const void * pointer
int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
Definition: SDL_keyboard.c:661
void Wayland_display_add_relative_pointer_manager(SDL_VideoData *d, uint32_t id)
static SDL_VideoDevice * _this
Definition: SDL_video.c:118
SDL_HitTestResult
Possible return values from the SDL_HitTest callback.
Definition: SDL_video.h:967
struct SDL_WaylandInput * keyboard_device
void * SDL_calloc(size_t nmemb, size_t size)
GLenum GLenum GLenum input
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1567
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:188
#define SDL_BUTTON_LEFT
Definition: SDL_mouse.h:282
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 ** d
GLsizei const GLfloat * value
#define _THIS
int SDL_SendKeyboardText(const char *text)
Definition: SDL_keyboard.c:774
void SDL_free(void *mem)
SDL_Window * sdlwindow
struct wl_shell_surface * shell_surface
#define SDL_BUTTON_MIDDLE
Definition: SDL_mouse.h:283
SDL_Window * windows
Definition: SDL_sysvideo.h:294
struct zwp_locked_pointer_v1 * locked_pointer
void Wayland_display_add_input(SDL_VideoData *d, uint32_t id)
#define NULL
Definition: begin_code.h:143
SDL_bool
Definition: SDL_stdinc.h:130
SDL_HitTest hit_test
Definition: SDL_sysvideo.h:104
unsigned int uint32_t
static char text[MAX_TEXT_LENGTH]
Definition: testime.c:47
void Wayland_display_destroy_input(SDL_VideoData *d)
void Wayland_PumpEvents(_THIS)
The type used to identify a window.
Definition: SDL_sysvideo.h:71
struct wl_registry * registry
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:571
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:90
int SDL_SendMouseWheel(SDL_Window *window, SDL_MouseID mouseID, int x, int y, SDL_MouseWheelDirection direction)
Definition: SDL_mouse.c:420
GLubyte GLubyte GLubyte GLubyte w
void * driverdata
Definition: SDL_sysvideo.h:109
#define SDL_PRESSED
Definition: SDL_events.h:50
#define SDL_BUTTON_X2
Definition: SDL_mouse.h:286
struct zwp_pointer_constraints_v1 * pointer_constraints
GLboolean GLboolean GLboolean GLboolean a
#define SDL_RELEASED
Definition: SDL_events.h:49
int SDL_SendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
Definition: SDL_mouse.c:414