SDL  2.0
SDL_waylandevents.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2017 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 "../../core/unix/SDL_poll.h"
31 #include "../../events/SDL_sysevents.h"
32 #include "../../events/SDL_events_c.h"
33 #include "../../events/scancodes_xfree86.h"
34 
35 #include "SDL_waylandvideo.h"
36 #include "SDL_waylandevents_c.h"
37 #include "SDL_waylandwindow.h"
38 
39 #include "SDL_waylanddyn.h"
40 
43 
44 #include <linux/input.h>
45 #include <sys/select.h>
46 #include <sys/mman.h>
47 #include <poll.h>
48 #include <unistd.h>
49 #include <xkbcommon/xkbcommon.h>
50 
51 struct SDL_WaylandInput {
52  SDL_VideoData *display;
53  struct wl_seat *seat;
54  struct wl_pointer *pointer;
55  struct wl_touch *touch;
56  struct wl_keyboard *keyboard;
57  SDL_WaylandDataDevice *data_device;
58  struct zwp_relative_pointer_v1 *relative_pointer;
59  SDL_WindowData *pointer_focus;
60  SDL_WindowData *keyboard_focus;
61 
62  /* Last motion location */
63  wl_fixed_t sx_w;
64  wl_fixed_t sy_w;
65 
66  double dx_frac;
67  double dy_frac;
68 
69  struct {
70  struct xkb_keymap *keymap;
71  struct xkb_state *state;
72  } xkb;
73 };
74 
75 struct SDL_WaylandTouchPoint {
77  float x;
78  float y;
79  struct wl_surface* surface;
80 
81  struct SDL_WaylandTouchPoint* prev;
82  struct SDL_WaylandTouchPoint* next;
83 };
84 
85 struct SDL_WaylandTouchPointList {
86  struct SDL_WaylandTouchPoint* head;
87  struct SDL_WaylandTouchPoint* tail;
88 };
89 
90 static struct SDL_WaylandTouchPointList touch_points = {NULL, NULL};
91 
92 static void
93 touch_add(SDL_TouchID id, float x, float y, struct wl_surface *surface)
94 {
95  struct SDL_WaylandTouchPoint* tp = SDL_malloc(sizeof(struct SDL_WaylandTouchPoint));
96 
97  tp->id = id;
98  tp->x = x;
99  tp->y = y;
100  tp->surface = surface;
101 
102  if (touch_points.tail) {
103  touch_points.tail->next = tp;
104  tp->prev = touch_points.tail;
105  } else {
106  touch_points.head = tp;
107  tp->prev = NULL;
108  }
109 
110  touch_points.tail = tp;
111  tp->next = NULL;
112 }
113 
114 static void
115 touch_update(SDL_TouchID id, float x, float y)
116 {
117  struct SDL_WaylandTouchPoint* tp = touch_points.head;
118 
119  while (tp) {
120  if (tp->id == id) {
121  tp->x = x;
122  tp->y = y;
123  }
124 
125  tp = tp->next;
126  }
127 }
128 
129 static void
130 touch_del(SDL_TouchID id, float* x, float* y)
131 {
132  struct SDL_WaylandTouchPoint* tp = touch_points.head;
133 
134  while (tp) {
135  if (tp->id == id) {
136  *x = tp->x;
137  *y = tp->y;
138 
139  if (tp->prev) {
140  tp->prev->next = tp->next;
141  } else {
142  touch_points.head = tp->next;
143  }
144 
145  if (tp->next) {
146  tp->next->prev = tp->prev;
147  } else {
148  touch_points.tail = tp->prev;
149  }
150 
151  SDL_free(tp);
152  }
153 
154  tp = tp->next;
155  }
156 }
157 
158 static struct wl_surface*
159 touch_surface(SDL_TouchID id)
160 {
161  struct SDL_WaylandTouchPoint* tp = touch_points.head;
162 
163  while (tp) {
164  if (tp->id == id) {
165  return tp->surface;
166  }
167 
168  tp = tp->next;
169  }
170 
171  return NULL;
172 }
173 
174 void
176 {
178 
179  if (SDL_IOReady(WAYLAND_wl_display_get_fd(d->display), SDL_FALSE, 0)) {
180  WAYLAND_wl_display_dispatch(d->display);
181  }
182  else
183  {
184  WAYLAND_wl_display_dispatch_pending(d->display);
185  }
186 }
187 
188 static void
189 pointer_handle_enter(void *data, struct wl_pointer *pointer,
190  uint32_t serial, struct wl_surface *surface,
191  wl_fixed_t sx_w, wl_fixed_t sy_w)
192 {
193  struct SDL_WaylandInput *input = data;
195 
196  if (!surface) {
197  /* enter event for a window we've just destroyed */
198  return;
199  }
200 
201  /* This handler will be called twice in Wayland 1.4
202  * Once for the window surface which has valid user data
203  * and again for the mouse cursor surface which does not have valid user data
204  * We ignore the later
205  */
206 
207  window = (SDL_WindowData *)wl_surface_get_user_data(surface);
208 
209  if (window) {
210  input->pointer_focus = window;
211  SDL_SetMouseFocus(window->sdlwindow);
212  }
213 }
214 
215 static void
216 pointer_handle_leave(void *data, struct wl_pointer *pointer,
217  uint32_t serial, struct wl_surface *surface)
218 {
219  struct SDL_WaylandInput *input = data;
220 
221  if (input->pointer_focus) {
223  input->pointer_focus = NULL;
224  }
225 }
226 
227 static void
228 pointer_handle_motion(void *data, struct wl_pointer *pointer,
229  uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w)
230 {
231  struct SDL_WaylandInput *input = data;
232  SDL_WindowData *window = input->pointer_focus;
233  input->sx_w = sx_w;
234  input->sy_w = sy_w;
235  if (input->pointer_focus) {
236  const int sx = wl_fixed_to_int(sx_w);
237  const int sy = wl_fixed_to_int(sy_w);
238  SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
239  }
240 }
241 
242 static SDL_bool
243 ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
244 {
245  SDL_WindowData *window_data = input->pointer_focus;
246  SDL_Window *window = window_data->sdlwindow;
247 
248  if (window->hit_test) {
249  const SDL_Point point = { wl_fixed_to_int(input->sx_w), wl_fixed_to_int(input->sy_w) };
250  const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
251  static const uint32_t directions[] = {
256  };
257  switch (rc) {
259  wl_shell_surface_move(window_data->shell_surface, input->seat, serial);
260  return SDL_TRUE;
261 
270  wl_shell_surface_resize(window_data->shell_surface, input->seat, serial, directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
271  return SDL_TRUE;
272 
273  default: return SDL_FALSE;
274  }
275  }
276 
277  return SDL_FALSE;
278 }
279 
280 static void
281 pointer_handle_button_common(struct SDL_WaylandInput *input, uint32_t serial,
282  uint32_t time, uint32_t button, uint32_t state_w)
283 {
284  SDL_WindowData *window = input->pointer_focus;
285  enum wl_pointer_button_state state = state_w;
286  uint32_t sdl_button;
287 
288  if (input->pointer_focus) {
289  switch (button) {
290  case BTN_LEFT:
291  sdl_button = SDL_BUTTON_LEFT;
292  if (ProcessHitTest(input, serial)) {
293  return; /* don't pass this event on to app. */
294  }
295  break;
296  case BTN_MIDDLE:
297  sdl_button = SDL_BUTTON_MIDDLE;
298  break;
299  case BTN_RIGHT:
300  sdl_button = SDL_BUTTON_RIGHT;
301  break;
302  case BTN_SIDE:
303  sdl_button = SDL_BUTTON_X1;
304  break;
305  case BTN_EXTRA:
306  sdl_button = SDL_BUTTON_X2;
307  break;
308  default:
309  return;
310  }
311 
312  Wayland_data_device_set_serial(input->data_device, serial);
313 
314  SDL_SendMouseButton(window->sdlwindow, 0,
315  state ? SDL_PRESSED : SDL_RELEASED, sdl_button);
316  }
317 }
318 
319 static void
320 pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
321  uint32_t time, uint32_t button, uint32_t state_w)
322 {
323  struct SDL_WaylandInput *input = data;
324 
325  pointer_handle_button_common(input, serial, time, button, state_w);
326 }
327 
328 static void
329 pointer_handle_axis_common(struct SDL_WaylandInput *input,
330  uint32_t time, uint32_t axis, wl_fixed_t value)
331 {
332  SDL_WindowData *window = input->pointer_focus;
333  enum wl_pointer_axis a = axis;
334  float x, y;
335 
336  if (input->pointer_focus) {
337  switch (a) {
339  x = 0;
340  y = (float)wl_fixed_to_double(value);
341  break;
343  x = (float)wl_fixed_to_double(value);
344  y = 0;
345  break;
346  default:
347  return;
348  }
349 
351  }
352 }
353 
354 static void
355 pointer_handle_axis(void *data, struct wl_pointer *pointer,
356  uint32_t time, uint32_t axis, wl_fixed_t value)
357 {
358  struct SDL_WaylandInput *input = data;
359 
360  pointer_handle_axis_common(input, time, axis, value);
361 }
362 
363 static const struct wl_pointer_listener pointer_listener = {
364  pointer_handle_enter,
365  pointer_handle_leave,
366  pointer_handle_motion,
367  pointer_handle_button,
368  pointer_handle_axis,
369  NULL, /* frame */
370  NULL, /* axis_source */
371  NULL, /* axis_stop */
372  NULL, /* axis_discrete */
373 };
374 
375 static void
376 touch_handler_down(void *data, struct wl_touch *touch, unsigned int serial,
377  unsigned int timestamp, struct wl_surface *surface,
378  int id, wl_fixed_t fx, wl_fixed_t fy)
379 {
380  float x, y;
382 
383  window = (SDL_WindowData *)wl_surface_get_user_data(surface);
384 
385  x = wl_fixed_to_double(fx) / window->sdlwindow->w;
386  y = wl_fixed_to_double(fy) / window->sdlwindow->h;
387 
388  touch_add(id, x, y, surface);
389  SDL_SendTouch(1, (SDL_FingerID)id, SDL_TRUE, x, y, 1.0f);
390 }
391 
392 static void
393 touch_handler_up(void *data, struct wl_touch *touch, unsigned int serial,
394  unsigned int timestamp, int id)
395 {
396  float x = 0, y = 0;
397 
398  touch_del(id, &x, &y);
399  SDL_SendTouch(1, (SDL_FingerID)id, SDL_FALSE, x, y, 0.0f);
400 }
401 
402 static void
403 touch_handler_motion(void *data, struct wl_touch *touch, unsigned int timestamp,
404  int id, wl_fixed_t fx, wl_fixed_t fy)
405 {
406  float x, y;
408 
409  window = (SDL_WindowData *)wl_surface_get_user_data(touch_surface(id));
410 
411  x = wl_fixed_to_double(fx) / window->sdlwindow->w;
412  y = wl_fixed_to_double(fy) / window->sdlwindow->h;
413 
414  touch_update(id, x, y);
415  SDL_SendTouchMotion(1, (SDL_FingerID)id, x, y, 1.0f);
416 }
417 
418 static void
419 touch_handler_frame(void *data, struct wl_touch *touch)
420 {
421 
422 }
423 
424 static void
425 touch_handler_cancel(void *data, struct wl_touch *touch)
426 {
427 
428 }
429 
430 static const struct wl_touch_listener touch_listener = {
431  touch_handler_down,
432  touch_handler_up,
433  touch_handler_motion,
434  touch_handler_frame,
435  touch_handler_cancel,
436  NULL, /* shape */
437  NULL, /* orientation */
438 };
439 
440 static void
441 keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
443 {
444  struct SDL_WaylandInput *input = data;
445  char *map_str;
446 
447  if (!data) {
448  close(fd);
449  return;
450  }
451 
452  if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
453  close(fd);
454  return;
455  }
456 
457  map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
458  if (map_str == MAP_FAILED) {
459  close(fd);
460  return;
461  }
462 
463  input->xkb.keymap = WAYLAND_xkb_keymap_new_from_string(input->display->xkb_context,
464  map_str,
465  XKB_KEYMAP_FORMAT_TEXT_V1,
466  0);
467  munmap(map_str, size);
468  close(fd);
469 
470  if (!input->xkb.keymap) {
471  fprintf(stderr, "failed to compile keymap\n");
472  return;
473  }
474 
475  input->xkb.state = WAYLAND_xkb_state_new(input->xkb.keymap);
476  if (!input->xkb.state) {
477  fprintf(stderr, "failed to create XKB state\n");
478  WAYLAND_xkb_keymap_unref(input->xkb.keymap);
479  input->xkb.keymap = NULL;
480  return;
481  }
482 }
483 
484 static void
485 keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
486  uint32_t serial, struct wl_surface *surface,
487  struct wl_array *keys)
488 {
489  struct SDL_WaylandInput *input = data;
491 
492  if (!surface) {
493  /* enter event for a window we've just destroyed */
494  return;
495  }
496 
497  window = wl_surface_get_user_data(surface);
498 
499  if (window) {
500  input->keyboard_focus = window;
501  window->keyboard_device = input;
503  }
504 }
505 
506 static void
507 keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
508  uint32_t serial, struct wl_surface *surface)
509 {
511 }
512 
513 static void
514 keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
515  uint32_t serial, uint32_t time, uint32_t key,
516  uint32_t state_w)
517 {
518  struct SDL_WaylandInput *input = data;
519  SDL_WindowData *window = input->keyboard_focus;
520  enum wl_keyboard_key_state state = state_w;
521  const xkb_keysym_t *syms;
522  uint32_t scancode;
523  char text[8];
524  int size;
525 
527  scancode = xfree86_scancode_table2[key];
528 
529  // TODO when do we get WL_KEYBOARD_KEY_STATE_REPEAT?
530  if (scancode != SDL_SCANCODE_UNKNOWN)
532  SDL_PRESSED : SDL_RELEASED, scancode);
533  }
534 
535  if (!window || window->keyboard_device != input || !input->xkb.state)
536  return;
537 
538  // TODO can this happen?
539  if (WAYLAND_xkb_state_key_get_syms(input->xkb.state, key + 8, &syms) != 1)
540  return;
541 
542  if (state) {
543  size = WAYLAND_xkb_keysym_to_utf8(syms[0], text, sizeof text);
544 
545  if (size > 0) {
546  text[size] = 0;
547 
548  Wayland_data_device_set_serial(input->data_device, serial);
549 
550  SDL_SendKeyboardText(text);
551  }
552  }
553 }
554 
555 static void
556 keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
557  uint32_t serial, uint32_t mods_depressed,
558  uint32_t mods_latched, uint32_t mods_locked,
559  uint32_t group)
560 {
561  struct SDL_WaylandInput *input = data;
562 
563  WAYLAND_xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched,
564  mods_locked, 0, 0, group);
565 }
566 
567 static const struct wl_keyboard_listener keyboard_listener = {
568  keyboard_handle_keymap,
569  keyboard_handle_enter,
570  keyboard_handle_leave,
571  keyboard_handle_key,
572  keyboard_handle_modifiers,
573  NULL, /* repeat_info */
574 };
575 
576 static void
577 seat_handle_capabilities(void *data, struct wl_seat *seat,
578  enum wl_seat_capability caps)
579 {
580  struct SDL_WaylandInput *input = data;
581 
582  if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) {
583  input->pointer = wl_seat_get_pointer(seat);
584  input->display->pointer = input->pointer;
585  wl_pointer_set_user_data(input->pointer, input);
586  wl_pointer_add_listener(input->pointer, &pointer_listener,
587  input);
588  } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) {
589  wl_pointer_destroy(input->pointer);
590  input->pointer = NULL;
591  }
592 
593  if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch) {
594  SDL_AddTouch(1, "wayland_touch");
595  input->touch = wl_seat_get_touch(seat);
596  wl_touch_set_user_data(input->touch, input);
597  wl_touch_add_listener(input->touch, &touch_listener,
598  input);
599  } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->touch) {
600  SDL_DelTouch(1);
601  wl_touch_destroy(input->touch);
602  input->touch = NULL;
603  }
604 
605  if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) {
606  input->keyboard = wl_seat_get_keyboard(seat);
607  wl_keyboard_set_user_data(input->keyboard, input);
608  wl_keyboard_add_listener(input->keyboard, &keyboard_listener,
609  input);
610  } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) {
611  wl_keyboard_destroy(input->keyboard);
612  input->keyboard = NULL;
613  }
614 }
615 
616 static const struct wl_seat_listener seat_listener = {
617  seat_handle_capabilities,
618  NULL, /* name */
619 };
620 
621 static void
622 data_source_handle_target(void *data, struct wl_data_source *wl_data_source,
623  const char *mime_type)
624 {
625 }
626 
627 static void
628 data_source_handle_send(void *data, struct wl_data_source *wl_data_source,
629  const char *mime_type, int32_t fd)
630 {
631  Wayland_data_source_send((SDL_WaylandDataSource *)data, mime_type, fd);
632 }
633 
634 static void
635 data_source_handle_cancelled(void *data, struct wl_data_source *wl_data_source)
636 {
638 }
639 
640 static void
641 data_source_handle_dnd_drop_performed(void *data, struct wl_data_source *wl_data_source)
642 {
643 }
644 
645 static void
646 data_source_handle_dnd_finished(void *data, struct wl_data_source *wl_data_source)
647 {
648 }
649 
650 static void
651 data_source_handle_action(void *data, struct wl_data_source *wl_data_source,
652  uint32_t dnd_action)
653 {
654 }
655 
656 static const struct wl_data_source_listener data_source_listener = {
657  data_source_handle_target,
658  data_source_handle_send,
659  data_source_handle_cancelled,
660  data_source_handle_dnd_drop_performed, // Version 3
661  data_source_handle_dnd_finished, // Version 3
662  data_source_handle_action, // Version 3
663 };
664 
667 {
668  SDL_WaylandDataSource *data_source = NULL;
669  SDL_VideoData *driver_data = NULL;
670  struct wl_data_source *id = NULL;
671 
672  if (_this == NULL || _this->driverdata == NULL) {
673  SDL_SetError("Video driver uninitialized");
674  } else {
675  driver_data = _this->driverdata;
676 
677  if (driver_data->data_device_manager != NULL) {
679  driver_data->data_device_manager);
680  }
681 
682  if (id == NULL) {
683  SDL_SetError("Wayland unable to create data source");
684  } else {
685  data_source = SDL_calloc(1, sizeof *data_source);
686  if (data_source == NULL) {
687  SDL_OutOfMemory();
689  } else {
690  WAYLAND_wl_list_init(&(data_source->mimes));
691  data_source->source = id;
692  wl_data_source_set_user_data(id, data_source);
693  wl_data_source_add_listener(id, &data_source_listener,
694  data_source);
695  }
696  }
697  }
698  return data_source;
699 }
700 
701 static void
702 data_offer_handle_offer(void *data, struct wl_data_offer *wl_data_offer,
703  const char *mime_type)
704 {
705  SDL_WaylandDataOffer *offer = data;
706  Wayland_data_offer_add_mime(offer, mime_type);
707 }
708 
709 static void
710 data_offer_handle_source_actions(void *data, struct wl_data_offer *wl_data_offer,
711  uint32_t source_actions)
712 {
713 }
714 
715 static void
716 data_offer_handle_actions(void *data, struct wl_data_offer *wl_data_offer,
717  uint32_t dnd_action)
718 {
719 }
720 
721 static const struct wl_data_offer_listener data_offer_listener = {
722  data_offer_handle_offer,
723  data_offer_handle_source_actions, // Version 3
724  data_offer_handle_actions, // Version 3
725 };
726 
727 static void
728 data_device_handle_data_offer(void *data, struct wl_data_device *wl_data_device,
729  struct wl_data_offer *id)
730 {
731  SDL_WaylandDataOffer *data_offer = NULL;
732 
733  data_offer = SDL_calloc(1, sizeof *data_offer);
734  if (data_offer == NULL) {
735  SDL_OutOfMemory();
736  } else {
737  data_offer->offer = id;
738  data_offer->data_device = data;
739  WAYLAND_wl_list_init(&(data_offer->mimes));
740  wl_data_offer_set_user_data(id, data_offer);
741  wl_data_offer_add_listener(id, &data_offer_listener, data_offer);
742  }
743 }
744 
745 static void
746 data_device_handle_enter(void *data, struct wl_data_device *wl_data_device,
747  uint32_t serial, struct wl_surface *surface,
748  wl_fixed_t x, wl_fixed_t y, struct wl_data_offer *id)
749 {
750  SDL_WaylandDataDevice *data_device = data;
751  SDL_bool has_mime = SDL_FALSE;
753 
754  data_device->drag_serial = serial;
755 
756  if (id != NULL) {
757  data_device->drag_offer = wl_data_offer_get_user_data(id);
758 
759  /* TODO: SDL Support more mime types */
760  has_mime = Wayland_data_offer_has_mime(
761  data_device->drag_offer, FILE_MIME);
762 
763  /* If drag_mime is NULL this will decline the offer */
764  wl_data_offer_accept(id, serial,
765  (has_mime == SDL_TRUE) ? FILE_MIME : NULL);
766 
767  /* SDL only supports "copy" style drag and drop */
768  if (has_mime == SDL_TRUE) {
770  }
772  dnd_action, dnd_action);
773  }
774 }
775 
776 static void
777 data_device_handle_leave(void *data, struct wl_data_device *wl_data_device)
778 {
779  SDL_WaylandDataDevice *data_device = data;
781 
782  if (data_device->selection_offer != NULL) {
783  data_device->selection_offer = NULL;
785  }
786 }
787 
788 static void
789 data_device_handle_motion(void *data, struct wl_data_device *wl_data_device,
790  uint32_t time, wl_fixed_t x, wl_fixed_t y)
791 {
792 }
793 
794 static void
795 data_device_handle_drop(void *data, struct wl_data_device *wl_data_device)
796 {
797  SDL_WaylandDataDevice *data_device = data;
798  void *buffer = NULL;
799  size_t length = 0;
800 
801  const char *current_uri = NULL;
802  const char *last_char = NULL;
803  char *current_char = NULL;
804 
805  if (data_device->drag_offer != NULL) {
806  /* TODO: SDL Support more mime types */
807  buffer = Wayland_data_offer_receive(data_device->drag_offer,
808  &length, FILE_MIME, SDL_FALSE);
809 
810  /* uri-list */
811  current_uri = (const char *)buffer;
812  last_char = (const char *)buffer + length;
813  for (current_char = buffer; current_char < last_char; ++current_char) {
814  if (*current_char == '\n' || *current_char == 0) {
815  if (*current_uri != 0 && *current_uri != '#') {
816  *current_char = 0;
817  SDL_SendDropFile(NULL, current_uri);
818  }
819  current_uri = (const char *)current_char + 1;
820  }
821  }
822 
823  SDL_free(buffer);
824  }
825 }
826 
827 static void
828 data_device_handle_selection(void *data, struct wl_data_device *wl_data_device,
829  struct wl_data_offer *id)
830 {
831  SDL_WaylandDataDevice *data_device = data;
832  SDL_WaylandDataOffer *offer = NULL;
833 
834  if (id != NULL) {
835  offer = wl_data_offer_get_user_data(id);
836  }
837 
838  if (data_device->selection_offer != offer) {
840  data_device->selection_offer = offer;
841  }
842 
844 }
845 
846 static const struct wl_data_device_listener data_device_listener = {
847  data_device_handle_data_offer,
848  data_device_handle_enter,
849  data_device_handle_leave,
850  data_device_handle_motion,
851  data_device_handle_drop,
852  data_device_handle_selection
853 };
854 
855 void
857 {
858  struct SDL_WaylandInput *input;
859  SDL_WaylandDataDevice *data_device = NULL;
860 
861  input = SDL_calloc(1, sizeof *input);
862  if (input == NULL)
863  return;
864 
865  input->display = d;
866  input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, 1);
867  input->sx_w = wl_fixed_from_int(0);
868  input->sy_w = wl_fixed_from_int(0);
869  d->input = input;
870 
871  if (d->data_device_manager != NULL) {
872  data_device = SDL_calloc(1, sizeof *data_device);
873  if (data_device == NULL) {
874  return;
875  }
876 
878  d->data_device_manager, input->seat
879  );
880  data_device->video_data = d;
881 
882  if (data_device->data_device == NULL) {
883  SDL_free(data_device);
884  } else {
885  wl_data_device_set_user_data(data_device->data_device, data_device);
887  &data_device_listener, data_device);
888  input->data_device = data_device;
889  }
890  }
891 
892  wl_seat_add_listener(input->seat, &seat_listener, input);
893  wl_seat_set_user_data(input->seat, input);
894 
895  WAYLAND_wl_display_flush(d->display);
896 }
897 
899 {
900  struct SDL_WaylandInput *input = d->input;
901 
902  if (!input)
903  return;
904 
905  if (input->data_device != NULL) {
906  Wayland_data_device_clear_selection(input->data_device);
907  if (input->data_device->selection_offer != NULL) {
908  Wayland_data_offer_destroy(input->data_device->selection_offer);
909  }
910  if (input->data_device->drag_offer != NULL) {
911  Wayland_data_offer_destroy(input->data_device->drag_offer);
912  }
913  if (input->data_device->data_device != NULL) {
914  wl_data_device_release(input->data_device->data_device);
915  }
916  SDL_free(input->data_device);
917  }
918 
919  if (input->keyboard)
920  wl_keyboard_destroy(input->keyboard);
921 
922  if (input->pointer)
923  wl_pointer_destroy(input->pointer);
924 
925  if (input->touch) {
926  SDL_DelTouch(1);
927  wl_touch_destroy(input->touch);
928  }
929 
930  if (input->seat)
931  wl_seat_destroy(input->seat);
932 
933  if (input->xkb.state)
934  WAYLAND_xkb_state_unref(input->xkb.state);
935 
936  if (input->xkb.keymap)
937  WAYLAND_xkb_keymap_unref(input->xkb.keymap);
938 
939  SDL_free(input);
940  d->input = NULL;
941 }
942 
943 SDL_WaylandDataDevice* Wayland_get_data_device(struct SDL_WaylandInput *input)
944 {
945  if (input == NULL) {
946  return NULL;
947  }
948 
949  return input->data_device;
950 }
951 
953 {
955  wl_registry_bind(d->registry, id,
957 }
958 
960 {
963 }
964 
966 {
968  wl_registry_bind(d->registry, id,
970 }
971 
973 {
974  if (d->pointer_constraints)
976 }
977 
978 static void
979 relative_pointer_handle_relative_motion(void *data,
980  struct zwp_relative_pointer_v1 *pointer,
981  uint32_t time_hi,
982  uint32_t time_lo,
983  wl_fixed_t dx_w,
984  wl_fixed_t dy_w,
985  wl_fixed_t dx_unaccel_w,
986  wl_fixed_t dy_unaccel_w)
987 {
988  struct SDL_WaylandInput *input = data;
989  SDL_VideoData *d = input->display;
990  SDL_WindowData *window = input->pointer_focus;
991  double dx_unaccel;
992  double dy_unaccel;
993  double dx;
994  double dy;
995 
996  dx_unaccel = wl_fixed_to_double(dx_unaccel_w);
997  dy_unaccel = wl_fixed_to_double(dy_unaccel_w);
998 
999  /* Add left over fraction from last event. */
1000  dx_unaccel += input->dx_frac;
1001  dy_unaccel += input->dy_frac;
1002 
1003  input->dx_frac = modf(dx_unaccel, &dx);
1004  input->dy_frac = modf(dy_unaccel, &dy);
1005 
1006  if (input->pointer_focus && d->relative_mouse_mode) {
1007  SDL_SendMouseMotion(window->sdlwindow, 0, 1, (int)dx, (int)dy);
1008  }
1009 }
1010 
1011 static const struct zwp_relative_pointer_v1_listener relative_pointer_listener = {
1012  relative_pointer_handle_relative_motion,
1013 };
1014 
1015 static void
1016 locked_pointer_locked(void *data,
1017  struct zwp_locked_pointer_v1 *locked_pointer)
1018 {
1019 }
1020 
1021 static void
1022 locked_pointer_unlocked(void *data,
1023  struct zwp_locked_pointer_v1 *locked_pointer)
1024 {
1025 }
1026 
1027 static const struct zwp_locked_pointer_v1_listener locked_pointer_listener = {
1028  locked_pointer_locked,
1029  locked_pointer_unlocked,
1030 };
1031 
1032 static void
1033 lock_pointer_to_window(SDL_Window *window,
1034  struct SDL_WaylandInput *input)
1035 {
1036  SDL_WindowData *w = window->driverdata;
1037  SDL_VideoData *d = input->display;
1038  struct zwp_locked_pointer_v1 *locked_pointer;
1039 
1040  if (w->locked_pointer)
1041  return;
1042 
1043  locked_pointer =
1045  w->surface,
1046  input->pointer,
1047  NULL,
1049  zwp_locked_pointer_v1_add_listener(locked_pointer,
1050  &locked_pointer_listener,
1051  window);
1052 
1053  w->locked_pointer = locked_pointer;
1054 }
1055 
1056 int Wayland_input_lock_pointer(struct SDL_WaylandInput *input)
1057 {
1059  SDL_VideoData *d = input->display;
1060  SDL_Window *window;
1061  struct zwp_relative_pointer_v1 *relative_pointer;
1062 
1063  if (!d->relative_pointer_manager)
1064  return -1;
1065 
1066  if (!d->pointer_constraints)
1067  return -1;
1068 
1069  if (!input->relative_pointer) {
1070  relative_pointer =
1073  input->pointer);
1074  zwp_relative_pointer_v1_add_listener(relative_pointer,
1075  &relative_pointer_listener,
1076  input);
1077  input->relative_pointer = relative_pointer;
1078  }
1079 
1080  for (window = vd->windows; window; window = window->next)
1081  lock_pointer_to_window(window, input);
1082 
1083  d->relative_mouse_mode = 1;
1084 
1085  return 0;
1086 }
1087 
1088 int Wayland_input_unlock_pointer(struct SDL_WaylandInput *input)
1089 {
1091  SDL_VideoData *d = input->display;
1092  SDL_Window *window;
1093  SDL_WindowData *w;
1094 
1095  for (window = vd->windows; window; window = window->next) {
1096  w = window->driverdata;
1097  if (w->locked_pointer)
1099  w->locked_pointer = NULL;
1100  }
1101 
1102  zwp_relative_pointer_v1_destroy(input->relative_pointer);
1103  input->relative_pointer = NULL;
1104 
1105  d->relative_mouse_mode = 0;
1106 
1107  return 0;
1108 }
1109 
1110 #endif /* SDL_VIDEO_DRIVER_WAYLAND */
1111 
1112 /* vi: set ts=4 sw=4 expandtab: */
static struct wl_data_source * wl_data_device_manager_create_data_source(struct wl_data_device_manager *wl_data_device_manager)
SDL_Window * next
Definition: SDL_sysvideo.h:114
ssize_t Wayland_data_source_send(SDL_WaylandDataSource *source, const char *mime_type, int fd)
int Wayland_input_unlock_pointer(struct SDL_WaylandInput *input)
GLboolean GLuint group
void Wayland_display_destroy_pointer_constraints(SDL_VideoData *d)
GLuint id
struct zwp_relative_pointer_manager_v1 * relative_pointer_manager
SDL_Texture * button
void Wayland_display_destroy_relative_pointer_manager(SDL_VideoData *d)
int SDL_IOReady(int fd, SDL_bool forWrite, int timeoutMS)
Definition: SDL_poll.c:39
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:630
EGLSurface EGLnsecsANDROID time
Definition: eglext.h:518
SDL_bool Wayland_data_offer_has_mime(SDL_WaylandDataOffer *offer, const char *mime_type)
void * hit_test_data
Definition: SDL_sysvideo.h:107
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
signed int int32_t
static void wl_pointer_destroy(struct wl_pointer *wl_pointer)
Sint64 SDL_FingerID
Definition: SDL_touch.h:42
int SDL_SendDropFile(SDL_Window *window, const char *file)
struct wl_display * display
const struct wl_interface zwp_relative_pointer_manager_v1_interface
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
EGLSurface surface
Definition: eglext.h:248
The structure that defines a point.
Definition: SDL_rect.h:48
static void * wl_registry_bind(struct wl_registry *wl_registry, uint32_t name, const struct wl_interface *interface, uint32_t version)
int SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down, float x, float y, float pressure)
Definition: SDL_touch.c:222
static struct wl_data_device * wl_data_device_manager_get_data_device(struct wl_data_device_manager *wl_data_device_manager, struct wl_seat *seat)
static void wl_data_offer_set_user_data(struct wl_data_offer *wl_data_offer, void *user_data)
static int wl_data_source_add_listener(struct wl_data_source *wl_data_source, const struct wl_data_source_listener *listener, void *data)
GLfloat f
static const SDL_Scancode xfree86_scancode_table2[]
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
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:151
struct wl_data_source * source
struct SDL_WaylandInput * input
static int zwp_relative_pointer_v1_add_listener(struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1, const struct zwp_relative_pointer_v1_listener *listener, void *data)
static void wl_seat_destroy(struct wl_seat *wl_seat)
static struct wl_touch * wl_seat_get_touch(struct wl_seat *wl_seat)
SDL_Surface * surface
int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
Definition: SDL_keyboard.c:679
int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, float x, float y, float pressure)
Definition: SDL_touch.c:284
void Wayland_display_add_relative_pointer_manager(SDL_VideoData *d, uint32_t id)
static SDL_VideoDevice * _this
Definition: SDL_video.c:121
SDL_HitTestResult
Possible return values from the SDL_HitTest callback.
Definition: SDL_video.h:991
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
static void wl_data_offer_accept(struct wl_data_offer *wl_data_offer, uint32_t serial, const char *mime_type)
struct SDL_WaylandInput * keyboard_device
void(* offer)(void *data, struct wl_data_offer *wl_data_offer, const char *mime_type)
void Wayland_data_offer_destroy(SDL_WaylandDataOffer *offer)
const struct wl_interface zwp_pointer_constraints_v1_interface
GLuint64 key
Definition: gl2ext.h:2192
struct wl_data_device_manager * data_device_manager
GLenum GLenum GLenum input
static void * wl_data_offer_get_user_data(struct wl_data_offer *wl_data_offer)
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:237
#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
static void zwp_pointer_constraints_v1_destroy(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1)
void Wayland_data_source_destroy(SDL_WaylandDataSource *source)
#define _THIS
int SDL_SendClipboardUpdate(void)
int SDL_SendKeyboardText(const char *text)
Definition: SDL_keyboard.c:789
#define SDL_free
#define FILE_MIME
int Wayland_data_device_set_serial(SDL_WaylandDataDevice *device, uint32_t serial)
static struct zwp_locked_pointer_v1 * zwp_pointer_constraints_v1_lock_pointer(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1, struct wl_surface *surface, struct wl_pointer *pointer, struct wl_region *region, uint32_t lifetime)
SDL_Window * sdlwindow
struct wl_shell_surface * shell_surface
GLubyte GLubyte GLubyte GLubyte w
GLsizei const GLfloat * value
void SDL_DelTouch(SDL_TouchID id)
Definition: SDL_touch.c:337
Sint64 SDL_TouchID
Definition: SDL_touch.h:41
SDL_WaylandDataSource * Wayland_data_source_create(_THIS)
#define SDL_BUTTON_MIDDLE
Definition: SDL_mouse.h:283
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
static void wl_seat_set_user_data(struct wl_seat *wl_seat, void *user_data)
static void zwp_relative_pointer_manager_v1_destroy(struct zwp_relative_pointer_manager_v1 *zwp_relative_pointer_manager_v1)
SDL_Window * windows
Definition: SDL_sysvideo.h:313
static struct wl_pointer * wl_seat_get_pointer(struct wl_seat *wl_seat)
static int wl_touch_add_listener(struct wl_touch *wl_touch, const struct wl_touch_listener *listener, void *data)
GLsizei const void * pointer
static void wl_touch_set_user_data(struct wl_touch *wl_touch, void *user_data)
static void wl_data_offer_set_actions(struct wl_data_offer *wl_data_offer, uint32_t dnd_actions, uint32_t preferred_action)
static int wl_pointer_add_listener(struct wl_pointer *wl_pointer, const struct wl_pointer_listener *listener, void *data)
static int wl_data_offer_add_listener(struct wl_data_offer *wl_data_offer, const struct wl_data_offer_listener *listener, void *data)
int SDL_AddTouch(SDL_TouchID touchID, const char *name)
Definition: SDL_touch.c:136
int Wayland_data_offer_add_mime(SDL_WaylandDataOffer *offer, const char *mime_type)
GLsizeiptr size
static int wl_seat_add_listener(struct wl_seat *wl_seat, const struct wl_seat_listener *listener, void *data)
struct zwp_locked_pointer_v1 * locked_pointer
void Wayland_display_add_input(SDL_VideoData *d, uint32_t id)
static void * wl_surface_get_user_data(struct wl_surface *wl_surface)
SDL_WaylandDataDevice * Wayland_get_data_device(struct SDL_WaylandInput *input)
static void wl_data_device_release(struct wl_data_device *wl_data_device)
static void zwp_relative_pointer_v1_destroy(struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1)
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:139
GLuint buffer
SDL_EventEntry * tail
Definition: SDL_events.c:83
static int zwp_locked_pointer_v1_add_listener(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1, const struct zwp_locked_pointer_v1_listener *listener, void *data)
int SDL_SendMouseWheel(SDL_Window *window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction)
Definition: SDL_mouse.c:512
SDL_HitTest hit_test
Definition: SDL_sysvideo.h:106
unsigned int uint32_t
static void wl_data_device_set_user_data(struct wl_data_device *wl_data_device, void *user_data)
struct wl_data_device * data_device
static int wl_keyboard_add_listener(struct wl_keyboard *wl_keyboard, const struct wl_keyboard_listener *listener, void *data)
#define SDL_SetError
static void zwp_locked_pointer_v1_destroy(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1)
static char text[MAX_TEXT_LENGTH]
Definition: testime.c:47
SDL_WaylandDataOffer * selection_offer
#define SDL_calloc
static int wl_data_device_add_listener(struct wl_data_device *wl_data_device, const struct wl_data_device_listener *listener, void *data)
void Wayland_display_destroy_input(SDL_VideoData *d)
void Wayland_PumpEvents(_THIS)
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
The type used to identify a window.
Definition: SDL_sysvideo.h:73
static void wl_keyboard_destroy(struct wl_keyboard *wl_keyboard)
struct wl_registry * registry
struct wl_data_offer * offer
static void wl_data_source_destroy(struct wl_data_source *wl_data_source)
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:586
const struct wl_interface wl_seat_interface
static struct zwp_relative_pointer_v1 * zwp_relative_pointer_manager_v1_get_relative_pointer(struct zwp_relative_pointer_manager_v1 *zwp_relative_pointer_manager_v1, struct wl_pointer *pointer)
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
int Wayland_data_device_clear_selection(SDL_WaylandDataDevice *device)
static void wl_data_source_set_user_data(struct wl_data_source *wl_data_source, void *user_data)
#define SDL_malloc
void * driverdata
Definition: SDL_sysvideo.h:111
static void wl_pointer_set_user_data(struct wl_pointer *wl_pointer, void *user_data)
#define SDL_PRESSED
Definition: SDL_events.h:50
static void wl_keyboard_set_user_data(struct wl_keyboard *wl_keyboard, void *user_data)
SDL_EventEntry * head
Definition: SDL_events.c:82
GLuint GLsizei GLsizei * length
#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
void * Wayland_data_offer_receive(SDL_WaylandDataOffer *offer, size_t *length, const char *mime_type, SDL_bool null_terminate)
static void wl_shell_surface_move(struct wl_shell_surface *wl_shell_surface, struct wl_seat *seat, uint32_t serial)
int SDL_SendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
Definition: SDL_mouse.c:506
SDL_WaylandDataOffer * drag_offer
GLuint64 GLenum GLint fd
Definition: gl2ext.h:1508
static struct wl_keyboard * wl_seat_get_keyboard(struct wl_seat *wl_seat)
static void wl_touch_destroy(struct wl_touch *wl_touch)