22 #include "../../SDL_internal.h" 24 #if SDL_VIDEO_DRIVER_WAYLAND 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" 41 #include "pointer-constraints-unstable-v1-client-protocol.h" 42 #include "relative-pointer-unstable-v1-client-protocol.h" 43 #include "xdg-shell-unstable-v6-client-protocol.h" 45 #include <linux/input.h> 46 #include <sys/select.h> 50 #include <xkbcommon/xkbcommon.h> 52 struct SDL_WaylandInput {
56 struct wl_touch *touch;
57 struct wl_keyboard *keyboard;
59 struct zwp_relative_pointer_v1 *relative_pointer;
71 struct xkb_keymap *keymap;
72 struct xkb_state *
state;
76 struct SDL_WaylandTouchPoint {
82 struct SDL_WaylandTouchPoint* prev;
83 struct SDL_WaylandTouchPoint* next;
86 struct SDL_WaylandTouchPointList {
87 struct SDL_WaylandTouchPoint*
head;
88 struct SDL_WaylandTouchPoint*
tail;
91 static struct SDL_WaylandTouchPointList touch_points = {
NULL,
NULL};
96 struct SDL_WaylandTouchPoint* tp =
SDL_malloc(
sizeof(
struct SDL_WaylandTouchPoint));
103 if (touch_points.tail) {
104 touch_points.tail->next = tp;
105 tp->prev = touch_points.tail;
107 touch_points.head = tp;
111 touch_points.tail = tp;
118 struct SDL_WaylandTouchPoint* tp = touch_points.head;
133 struct SDL_WaylandTouchPoint* tp = touch_points.head;
141 tp->prev->next = tp->next;
143 touch_points.head = tp->next;
147 tp->next->prev = tp->prev;
149 touch_points.tail = tp->prev;
159 static struct wl_surface*
162 struct SDL_WaylandTouchPoint* tp = touch_points.head;
181 WAYLAND_wl_display_dispatch(d->
display);
185 WAYLAND_wl_display_dispatch_pending(d->
display);
190 pointer_handle_enter(
void *
data,
struct wl_pointer *
pointer,
191 uint32_t serial,
struct wl_surface *surface,
192 wl_fixed_t sx_w, wl_fixed_t sy_w)
211 input->pointer_focus =
window;
217 pointer_handle_leave(
void *data,
struct wl_pointer *pointer,
218 uint32_t serial,
struct wl_surface *surface)
220 struct SDL_WaylandInput *input =
data;
222 if (input->pointer_focus) {
224 input->pointer_focus =
NULL;
229 pointer_handle_motion(
void *data,
struct wl_pointer *pointer,
232 struct SDL_WaylandInput *input =
data;
236 if (input->pointer_focus) {
237 const int sx = wl_fixed_to_int(sx_w);
238 const int sy = wl_fixed_to_int(sy_w);
244 ProcessHitTest(
struct SDL_WaylandInput *input,
uint32_t serial)
250 const SDL_Point point = { wl_fixed_to_int(input->sx_w), wl_fixed_to_int(input->sy_w) };
253 static const uint32_t directions_wl[] = {
254 WL_SHELL_SURFACE_RESIZE_TOP_LEFT, WL_SHELL_SURFACE_RESIZE_TOP,
255 WL_SHELL_SURFACE_RESIZE_TOP_RIGHT, WL_SHELL_SURFACE_RESIZE_RIGHT,
256 WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT, WL_SHELL_SURFACE_RESIZE_BOTTOM,
257 WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT, WL_SHELL_SURFACE_RESIZE_LEFT
262 const uint32_t *directions_zxdg = directions_wl;
266 if (input->display->shell.zxdg) {
269 wl_shell_surface_move(window_data->
shell_surface.
wl, input->seat, serial);
281 if (input->display->shell.zxdg) {
296 pointer_handle_button_common(
struct SDL_WaylandInput *input,
uint32_t serial,
300 enum wl_pointer_button_state
state = state_w;
303 if (input->pointer_focus) {
307 if (ProcessHitTest(input, serial)) {
335 pointer_handle_button(
void *data,
struct wl_pointer *pointer,
uint32_t serial,
338 struct SDL_WaylandInput *input =
data;
340 pointer_handle_button_common(input, serial, time, button, state_w);
344 pointer_handle_axis_common(
struct SDL_WaylandInput *input,
348 enum wl_pointer_axis
a =
axis;
351 if (input->pointer_focus) {
353 case WL_POINTER_AXIS_VERTICAL_SCROLL:
355 y = 0 - (float)wl_fixed_to_double(value);
357 case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
358 x = 0 - (float)wl_fixed_to_double(value);
370 pointer_handle_axis(
void *data,
struct wl_pointer *pointer,
373 struct SDL_WaylandInput *input =
data;
375 pointer_handle_axis_common(input, time, axis, value);
378 static const struct wl_pointer_listener pointer_listener = {
379 pointer_handle_enter,
380 pointer_handle_leave,
381 pointer_handle_motion,
382 pointer_handle_button,
391 touch_handler_down(
void *data,
struct wl_touch *touch,
unsigned int serial,
392 unsigned int timestamp,
struct wl_surface *surface,
393 int id, wl_fixed_t fx, wl_fixed_t fy)
400 x = wl_fixed_to_double(fx) / window->
sdlwindow->
w;
401 y = wl_fixed_to_double(fy) / window->
sdlwindow->
h;
403 touch_add(
id, x, y, surface);
408 touch_handler_up(
void *data,
struct wl_touch *touch,
unsigned int serial,
409 unsigned int timestamp,
int id)
413 touch_del(
id, &x, &y);
418 touch_handler_motion(
void *data,
struct wl_touch *touch,
unsigned int timestamp,
419 int id, wl_fixed_t fx, wl_fixed_t fy)
424 window = (
SDL_WindowData *)wl_surface_get_user_data(touch_surface(
id));
426 x = wl_fixed_to_double(fx) / window->
sdlwindow->
w;
427 y = wl_fixed_to_double(fy) / window->
sdlwindow->
h;
429 touch_update(
id, x, y);
434 touch_handler_frame(
void *data,
struct wl_touch *touch)
440 touch_handler_cancel(
void *data,
struct wl_touch *touch)
445 static const struct wl_touch_listener touch_listener = {
448 touch_handler_motion,
450 touch_handler_cancel,
456 keyboard_handle_keymap(
void *data,
struct wl_keyboard *keyboard,
459 struct SDL_WaylandInput *input =
data;
467 if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
472 map_str = mmap(
NULL, size, PROT_READ, MAP_SHARED, fd, 0);
473 if (map_str == MAP_FAILED) {
478 input->xkb.keymap = WAYLAND_xkb_keymap_new_from_string(input->display->xkb_context,
480 XKB_KEYMAP_FORMAT_TEXT_V1,
482 munmap(map_str, size);
485 if (!input->xkb.keymap) {
486 fprintf(stderr,
"failed to compile keymap\n");
490 input->xkb.state = WAYLAND_xkb_state_new(input->xkb.keymap);
491 if (!input->xkb.state) {
492 fprintf(stderr,
"failed to create XKB state\n");
493 WAYLAND_xkb_keymap_unref(input->xkb.keymap);
494 input->xkb.keymap =
NULL;
500 keyboard_handle_enter(
void *data,
struct wl_keyboard *keyboard,
501 uint32_t serial,
struct wl_surface *surface,
502 struct wl_array *keys)
504 struct SDL_WaylandInput *input =
data;
512 window = wl_surface_get_user_data(surface);
515 input->keyboard_focus =
window;
522 keyboard_handle_leave(
void *data,
struct wl_keyboard *keyboard,
523 uint32_t serial,
struct wl_surface *surface)
529 keyboard_handle_key(
void *data,
struct wl_keyboard *keyboard,
533 struct SDL_WaylandInput *input =
data;
535 enum wl_keyboard_key_state state = state_w;
536 const xkb_keysym_t *syms;
554 if (WAYLAND_xkb_state_key_get_syms(input->xkb.state, key + 8, &syms) != 1)
558 size = WAYLAND_xkb_keysym_to_utf8(syms[0], text,
sizeof text);
571 keyboard_handle_modifiers(
void *data,
struct wl_keyboard *keyboard,
576 struct SDL_WaylandInput *input =
data;
578 WAYLAND_xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched,
579 mods_locked, 0, 0, group);
582 static const struct wl_keyboard_listener keyboard_listener = {
583 keyboard_handle_keymap,
584 keyboard_handle_enter,
585 keyboard_handle_leave,
587 keyboard_handle_modifiers,
592 seat_handle_capabilities(
void *data,
struct wl_seat *seat,
593 enum wl_seat_capability caps)
595 struct SDL_WaylandInput *input =
data;
597 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) {
598 input->pointer = wl_seat_get_pointer(seat);
599 input->display->pointer = input->pointer;
600 wl_pointer_set_user_data(input->pointer, input);
601 wl_pointer_add_listener(input->pointer, &pointer_listener,
603 }
else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) {
604 wl_pointer_destroy(input->pointer);
605 input->pointer =
NULL;
606 input->display->pointer =
NULL;
609 if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch) {
611 input->touch = wl_seat_get_touch(seat);
612 wl_touch_set_user_data(input->touch, input);
613 wl_touch_add_listener(input->touch, &touch_listener,
615 }
else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->touch) {
617 wl_touch_destroy(input->touch);
621 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) {
622 input->keyboard = wl_seat_get_keyboard(seat);
623 wl_keyboard_set_user_data(input->keyboard, input);
624 wl_keyboard_add_listener(input->keyboard, &keyboard_listener,
626 }
else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) {
627 wl_keyboard_destroy(input->keyboard);
628 input->keyboard =
NULL;
632 static const struct wl_seat_listener seat_listener = {
633 seat_handle_capabilities,
638 data_source_handle_target(
void *data,
struct wl_data_source *wl_data_source,
639 const char *mime_type)
644 data_source_handle_send(
void *data,
struct wl_data_source *wl_data_source,
645 const char *mime_type,
int32_t fd)
651 data_source_handle_cancelled(
void *data,
struct wl_data_source *wl_data_source)
657 data_source_handle_dnd_drop_performed(
void *data,
struct wl_data_source *wl_data_source)
662 data_source_handle_dnd_finished(
void *data,
struct wl_data_source *wl_data_source)
667 data_source_handle_action(
void *data,
struct wl_data_source *wl_data_source,
672 static const struct wl_data_source_listener data_source_listener = {
673 data_source_handle_target,
674 data_source_handle_send,
675 data_source_handle_cancelled,
676 data_source_handle_dnd_drop_performed,
677 data_source_handle_dnd_finished,
678 data_source_handle_action,
686 struct wl_data_source *
id =
NULL;
694 id = wl_data_device_manager_create_data_source(
701 data_source =
SDL_calloc(1,
sizeof *data_source);
702 if (data_source ==
NULL) {
704 wl_data_source_destroy(
id);
706 WAYLAND_wl_list_init(&(data_source->
mimes));
708 wl_data_source_set_user_data(
id, data_source);
709 wl_data_source_add_listener(
id, &data_source_listener,
718 data_offer_handle_offer(
void *data,
struct wl_data_offer *wl_data_offer,
719 const char *mime_type)
726 data_offer_handle_source_actions(
void *data,
struct wl_data_offer *wl_data_offer,
732 data_offer_handle_actions(
void *data,
struct wl_data_offer *wl_data_offer,
737 static const struct wl_data_offer_listener data_offer_listener = {
738 data_offer_handle_offer,
739 data_offer_handle_source_actions,
740 data_offer_handle_actions,
744 data_device_handle_data_offer(
void *data,
struct wl_data_device *wl_data_device,
745 struct wl_data_offer *
id)
749 data_offer =
SDL_calloc(1,
sizeof *data_offer);
750 if (data_offer ==
NULL) {
755 WAYLAND_wl_list_init(&(data_offer->
mimes));
756 wl_data_offer_set_user_data(
id, data_offer);
757 wl_data_offer_add_listener(
id, &data_offer_listener, data_offer);
762 data_device_handle_enter(
void *data,
struct wl_data_device *wl_data_device,
763 uint32_t serial,
struct wl_surface *surface,
764 wl_fixed_t x, wl_fixed_t y,
struct wl_data_offer *
id)
768 uint32_t dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
773 data_device->
drag_offer = wl_data_offer_get_user_data(
id);
780 wl_data_offer_accept(
id, serial,
785 dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
788 dnd_action, dnd_action);
793 data_device_handle_leave(
void *data,
struct wl_data_device *wl_data_device)
805 data_device_handle_motion(
void *data,
struct wl_data_device *wl_data_device,
806 uint32_t time, wl_fixed_t x, wl_fixed_t y)
811 data_device_handle_drop(
void *data,
struct wl_data_device *wl_data_device)
817 const char *current_uri =
NULL;
818 const char *last_char =
NULL;
819 char *current_char =
NULL;
827 current_uri = (
const char *)buffer;
828 last_char = (
const char *)buffer + length;
829 for (current_char = buffer; current_char < last_char; ++current_char) {
830 if (*current_char ==
'\n' || *current_char == 0) {
831 if (*current_uri != 0 && *current_uri !=
'#') {
835 current_uri = (
const char *)current_char + 1;
844 data_device_handle_selection(
void *data,
struct wl_data_device *wl_data_device,
845 struct wl_data_offer *
id)
851 offer = wl_data_offer_get_user_data(
id);
862 static const struct wl_data_device_listener data_device_listener = {
863 data_device_handle_data_offer,
864 data_device_handle_enter,
865 data_device_handle_leave,
866 data_device_handle_motion,
867 data_device_handle_drop,
868 data_device_handle_selection
874 struct SDL_WaylandInput *
input;
882 input->seat = wl_registry_bind(d->
registry,
id, &wl_seat_interface, 1);
883 input->sx_w = wl_fixed_from_int(0);
884 input->sy_w = wl_fixed_from_int(0);
888 data_device =
SDL_calloc(1,
sizeof *data_device);
889 if (data_device ==
NULL) {
893 data_device->
data_device = wl_data_device_manager_get_data_device(
901 wl_data_device_set_user_data(data_device->
data_device, data_device);
902 wl_data_device_add_listener(data_device->
data_device,
903 &data_device_listener, data_device);
904 input->data_device = data_device;
908 wl_seat_add_listener(input->seat, &seat_listener, input);
909 wl_seat_set_user_data(input->seat, input);
911 WAYLAND_wl_display_flush(d->
display);
916 struct SDL_WaylandInput *input = d->
input;
921 if (input->data_device !=
NULL) {
923 if (input->data_device->selection_offer !=
NULL) {
926 if (input->data_device->drag_offer !=
NULL) {
929 if (input->data_device->data_device !=
NULL) {
930 wl_data_device_release(input->data_device->data_device);
936 wl_keyboard_destroy(input->keyboard);
939 wl_pointer_destroy(input->pointer);
943 wl_touch_destroy(input->touch);
947 wl_seat_destroy(input->seat);
949 if (input->xkb.state)
950 WAYLAND_xkb_state_unref(input->xkb.state);
952 if (input->xkb.keymap)
953 WAYLAND_xkb_keymap_unref(input->xkb.keymap);
965 return input->data_device;
973 &zwp_relative_pointer_manager_v1_interface, 1);
986 &zwp_pointer_constraints_v1_interface, 1);
996 relative_pointer_handle_relative_motion(
void *data,
997 struct zwp_relative_pointer_v1 *pointer,
1002 wl_fixed_t dx_unaccel_w,
1003 wl_fixed_t dy_unaccel_w)
1005 struct SDL_WaylandInput *input =
data;
1013 dx_unaccel = wl_fixed_to_double(dx_unaccel_w);
1014 dy_unaccel = wl_fixed_to_double(dy_unaccel_w);
1017 dx_unaccel += input->dx_frac;
1018 dy_unaccel += input->dy_frac;
1020 input->dx_frac = modf(dx_unaccel, &dx);
1021 input->dy_frac = modf(dy_unaccel, &dy);
1028 static const struct zwp_relative_pointer_v1_listener relative_pointer_listener = {
1029 relative_pointer_handle_relative_motion,
1033 locked_pointer_locked(
void *data,
1034 struct zwp_locked_pointer_v1 *locked_pointer)
1039 locked_pointer_unlocked(
void *data,
1040 struct zwp_locked_pointer_v1 *locked_pointer)
1044 static const struct zwp_locked_pointer_v1_listener locked_pointer_listener = {
1045 locked_pointer_locked,
1046 locked_pointer_unlocked,
1051 struct SDL_WaylandInput *input)
1055 struct zwp_locked_pointer_v1 *locked_pointer;
1065 ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
1066 zwp_locked_pointer_v1_add_listener(locked_pointer,
1067 &locked_pointer_listener,
1078 struct zwp_relative_pointer_v1 *relative_pointer;
1086 if (!input->relative_pointer) {
1088 zwp_relative_pointer_manager_v1_get_relative_pointer(
1091 zwp_relative_pointer_v1_add_listener(relative_pointer,
1092 &relative_pointer_listener,
1094 input->relative_pointer = relative_pointer;
1097 for (window = vd->
windows; window; window = window->
next)
1098 lock_pointer_to_window(window, input);
1112 for (window = vd->
windows; window; window = window->
next) {
1119 zwp_relative_pointer_v1_destroy(input->relative_pointer);
1120 input->relative_pointer =
NULL;
ssize_t Wayland_data_source_send(SDL_WaylandDataSource *source, const char *mime_type, int fd)
int Wayland_input_unlock_pointer(struct SDL_WaylandInput *input)
void Wayland_display_destroy_pointer_constraints(SDL_VideoData *d)
struct zwp_relative_pointer_manager_v1 * relative_pointer_manager
struct zxdg_toplevel_v6 * toplevel
void Wayland_display_destroy_relative_pointer_manager(SDL_VideoData *d)
int SDL_IOReady(int fd, SDL_bool forWrite, int timeoutMS)
void SDL_SetKeyboardFocus(SDL_Window *window)
union SDL_WindowData::@37 shell_surface
EGLSurface EGLnsecsANDROID time
SDL_bool Wayland_data_offer_has_mime(SDL_WaylandDataOffer *offer, const char *mime_type)
GLint GLint GLint GLint GLint x
struct wl_shell_surface * wl
int SDL_SendDropFile(SDL_Window *window, const char *file)
struct wl_display * display
void Wayland_display_add_pointer_constraints(SDL_VideoData *d, uint32_t id)
The structure that defines a point.
int SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down, float x, float y, float pressure)
static const SDL_Scancode xfree86_scancode_table2[]
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
union SDL_zxdg_shell_surface::@36 roleobj
int Wayland_input_lock_pointer(struct SDL_WaylandInput *input)
void SDL_SetMouseFocus(SDL_Window *window)
struct wl_data_source * source
struct SDL_WaylandInput * input
int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, float x, float y, float pressure)
void Wayland_display_add_relative_pointer_manager(SDL_VideoData *d, uint32_t id)
static SDL_VideoDevice * _this
SDL_HitTestResult
Possible return values from the SDL_HitTest callback.
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
struct SDL_WaylandInput * keyboard_device
void Wayland_data_offer_destroy(SDL_WaylandDataOffer *offer)
struct wl_data_device_manager * data_device_manager
GLenum GLenum GLenum input
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
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
void Wayland_data_source_destroy(SDL_WaylandDataSource *source)
int SDL_SendClipboardUpdate(void)
int SDL_SendKeyboardText(const char *text)
int Wayland_data_device_set_serial(SDL_WaylandDataDevice *device, uint32_t serial)
GLubyte GLubyte GLubyte GLubyte w
GLsizei const GLfloat * value
void SDL_DelTouch(SDL_TouchID id)
SDL_WaylandDataSource * Wayland_data_source_create(_THIS)
#define SDL_BUTTON_MIDDLE
GLint GLint GLint GLint GLint GLint y
GLsizei const void * pointer
int SDL_AddTouch(SDL_TouchID touchID, const char *name)
int Wayland_data_offer_add_mime(SDL_WaylandDataOffer *offer, const char *mime_type)
struct zwp_locked_pointer_v1 * locked_pointer
void Wayland_display_add_input(SDL_VideoData *d, uint32_t id)
SDL_WaylandDataDevice * Wayland_get_data_device(struct SDL_WaylandInput *input)
SDL_VideoData * video_data
#define SDL_OutOfMemory()
int SDL_SendMouseWheel(SDL_Window *window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction)
struct wl_data_device * data_device
static char text[MAX_TEXT_LENGTH]
SDL_WaylandDataOffer * selection_offer
SDL_zxdg_shell_surface zxdg
void Wayland_display_destroy_input(SDL_VideoData *d)
void Wayland_PumpEvents(_THIS)
EGLSurface EGLNativeWindowType * window
The type used to identify a window.
struct wl_registry * registry
struct wl_data_offer * offer
SDL_VideoDevice * SDL_GetVideoDevice(void)
#define SDL_arraysize(array)
int Wayland_data_device_clear_selection(SDL_WaylandDataDevice *device)
GLuint GLsizei GLsizei * length
struct zwp_pointer_constraints_v1 * pointer_constraints
GLboolean GLboolean GLboolean GLboolean a
void * Wayland_data_offer_receive(SDL_WaylandDataOffer *offer, size_t *length, const char *mime_type, SDL_bool null_terminate)
int SDL_SendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
SDL_WaylandDataOffer * drag_offer