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-client-protocol.h"
44 #include "xdg-shell-unstable-v6-client-protocol.h"
46 #include <linux/input.h>
47 #include <sys/select.h>
51 #include <xkbcommon/xkbcommon.h>
53 struct SDL_WaylandInput {
57 struct wl_touch *touch;
58 struct wl_keyboard *keyboard;
60 struct zwp_relative_pointer_v1 *relative_pointer;
72 struct xkb_keymap *keymap;
73 struct xkb_state *
state;
83 } pointer_curr_axis_info;
86 struct SDL_WaylandTouchPoint {
92 struct SDL_WaylandTouchPoint* prev;
93 struct SDL_WaylandTouchPoint* next;
96 struct SDL_WaylandTouchPointList {
97 struct SDL_WaylandTouchPoint*
head;
98 struct SDL_WaylandTouchPoint*
tail;
101 static struct SDL_WaylandTouchPointList touch_points = {
NULL,
NULL};
106 struct SDL_WaylandTouchPoint* tp =
SDL_malloc(
sizeof(
struct SDL_WaylandTouchPoint));
113 if (touch_points.tail) {
114 touch_points.tail->next = tp;
115 tp->prev = touch_points.tail;
117 touch_points.head = tp;
121 touch_points.tail = tp;
128 struct SDL_WaylandTouchPoint* tp = touch_points.head;
143 struct SDL_WaylandTouchPoint* tp = touch_points.head;
152 tp->prev->next = tp->next;
154 touch_points.head = tp->next;
158 tp->next->prev = tp->prev;
160 touch_points.tail = tp->prev;
164 struct SDL_WaylandTouchPoint *next = tp->next;
174 static struct wl_surface*
177 struct SDL_WaylandTouchPoint* tp = touch_points.head;
196 WAYLAND_wl_display_flush(
d->display);
199 err = WAYLAND_wl_display_dispatch(
d->display);
201 err = WAYLAND_wl_display_dispatch_pending(
d->display);
203 if (err == -1 && !
d->display_disconnected) {
207 d->display_disconnected = 1;
215 pointer_handle_enter(
void *
data,
struct wl_pointer *
pointer,
217 wl_fixed_t sx_w, wl_fixed_t sy_w)
242 pointer_handle_leave(
void *
data,
struct wl_pointer *
pointer,
247 if (
input->pointer_focus) {
254 pointer_handle_motion(
void *
data,
struct wl_pointer *
pointer,
261 if (
input->pointer_focus) {
262 const int sx = wl_fixed_to_int(sx_w);
263 const int sy = wl_fixed_to_int(sy_w);
269 ProcessHitTest(
struct SDL_WaylandInput *
input,
uint32_t serial)
278 static const uint32_t directions_wl[] = {
279 WL_SHELL_SURFACE_RESIZE_TOP_LEFT, WL_SHELL_SURFACE_RESIZE_TOP,
280 WL_SHELL_SURFACE_RESIZE_TOP_RIGHT, WL_SHELL_SURFACE_RESIZE_RIGHT,
281 WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT, WL_SHELL_SURFACE_RESIZE_BOTTOM,
282 WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT, WL_SHELL_SURFACE_RESIZE_LEFT
287 const uint32_t *directions_zxdg = directions_wl;
291 if (
input->display->shell.xdg) {
293 }
else if (
input->display->shell.zxdg) {
308 if (
input->display->shell.xdg) {
310 }
else if (
input->display->shell.zxdg) {
325 pointer_handle_button_common(
struct SDL_WaylandInput *
input,
uint32_t serial,
329 enum wl_pointer_button_state
state = state_w;
332 if (
input->pointer_focus) {
336 if (ProcessHitTest(
input, serial)) {
373 pointer_handle_axis_common_v1(
struct SDL_WaylandInput *
input,
377 enum wl_pointer_axis
a =
axis;
380 if (
input->pointer_focus) {
382 case WL_POINTER_AXIS_VERTICAL_SCROLL:
384 y = 0 - (float)wl_fixed_to_double(
value);
386 case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
387 x = 0 - (float)wl_fixed_to_double(
value);
399 pointer_handle_axis_common(
struct SDL_WaylandInput *
input,
SDL_bool discrete,
402 enum wl_pointer_axis
a =
axis;
404 if (
input->pointer_focus) {
406 case WL_POINTER_AXIS_VERTICAL_SCROLL:
411 }
else if(
input->pointer_curr_axis_info.is_y_discrete) {
416 input->pointer_curr_axis_info.y = 0 - (float)wl_fixed_to_double(
value);
418 case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
423 }
else if(
input->pointer_curr_axis_info.is_x_discrete) {
428 input->pointer_curr_axis_info.x = 0 - (float)wl_fixed_to_double(
value);
435 pointer_handle_axis(
void *
data,
struct wl_pointer *
pointer,
440 if(wl_seat_interface.version >= 5)
447 pointer_handle_frame(
void *
data,
struct wl_pointer *
pointer)
451 float x =
input->pointer_curr_axis_info.x,
y =
input->pointer_curr_axis_info.y;
454 memset(&
input->pointer_curr_axis_info, 0,
sizeof input->pointer_curr_axis_info);
456 if(
x == 0.0
f &&
y == 0.0
f)
463 pointer_handle_axis_source(
void *
data,
struct wl_pointer *
pointer,
470 pointer_handle_axis_stop(
void *
data,
struct wl_pointer *
pointer,
477 pointer_handle_axis_discrete(
void *
data,
struct wl_pointer *
pointer,
486 static const struct wl_pointer_listener pointer_listener = {
487 pointer_handle_enter,
488 pointer_handle_leave,
489 pointer_handle_motion,
490 pointer_handle_button,
492 pointer_handle_frame,
493 pointer_handle_axis_source,
494 pointer_handle_axis_stop,
495 pointer_handle_axis_discrete,
499 touch_handler_down(
void *
data,
struct wl_touch *touch,
unsigned int serial,
500 unsigned int timestamp,
struct wl_surface *
surface,
501 int id, wl_fixed_t fx, wl_fixed_t fy)
504 const double dblx = wl_fixed_to_double(fx);
505 const double dbly = wl_fixed_to_double(fy);
515 touch_handler_up(
void *
data,
struct wl_touch *touch,
unsigned int serial,
516 unsigned int timestamp,
int id)
533 touch_handler_motion(
void *
data,
struct wl_touch *touch,
unsigned int timestamp,
534 int id, wl_fixed_t fx, wl_fixed_t fy)
537 const double dblx = wl_fixed_to_double(fx);
538 const double dbly = wl_fixed_to_double(fy);
542 touch_update(
id,
x,
y);
547 touch_handler_frame(
void *
data,
struct wl_touch *touch)
553 touch_handler_cancel(
void *
data,
struct wl_touch *touch)
558 static const struct wl_touch_listener touch_listener = {
561 touch_handler_motion,
563 touch_handler_cancel,
569 keyboard_handle_keymap(
void *
data,
struct wl_keyboard *keyboard,
580 if (
format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
585 map_str = mmap(
NULL,
size, PROT_READ, MAP_SHARED,
fd, 0);
586 if (map_str == MAP_FAILED) {
591 input->xkb.keymap = WAYLAND_xkb_keymap_new_from_string(
input->display->xkb_context,
593 XKB_KEYMAP_FORMAT_TEXT_V1,
595 munmap(map_str,
size);
598 if (!
input->xkb.keymap) {
599 fprintf(stderr,
"failed to compile keymap\n");
603 input->xkb.state = WAYLAND_xkb_state_new(
input->xkb.keymap);
604 if (!
input->xkb.state) {
605 fprintf(stderr,
"failed to create XKB state\n");
606 WAYLAND_xkb_keymap_unref(
input->xkb.keymap);
613 keyboard_handle_enter(
void *
data,
struct wl_keyboard *keyboard,
615 struct wl_array *keys)
635 keyboard_handle_leave(
void *
data,
struct wl_keyboard *keyboard,
642 keyboard_handle_key(
void *
data,
struct wl_keyboard *keyboard,
648 enum wl_keyboard_key_state
state = state_w;
649 const xkb_keysym_t *syms;
667 if (WAYLAND_xkb_state_key_get_syms(
input->xkb.state,
key + 8, &syms) != 1)
671 size = WAYLAND_xkb_keysym_to_utf8(syms[0],
text,
sizeof text);
684 keyboard_handle_modifiers(
void *
data,
struct wl_keyboard *keyboard,
691 WAYLAND_xkb_state_update_mask(
input->xkb.state, mods_depressed, mods_latched,
692 mods_locked, 0, 0,
group);
696 keyboard_handle_repeat_info(
void *
data,
struct wl_keyboard *wl_keyboard,
702 static const struct wl_keyboard_listener keyboard_listener = {
703 keyboard_handle_keymap,
704 keyboard_handle_enter,
705 keyboard_handle_leave,
707 keyboard_handle_modifiers,
708 keyboard_handle_repeat_info,
712 seat_handle_capabilities(
void *
data,
struct wl_seat *seat,
713 enum wl_seat_capability caps)
717 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !
input->pointer) {
718 input->pointer = wl_seat_get_pointer(seat);
719 memset(&
input->pointer_curr_axis_info, 0,
sizeof input->pointer_curr_axis_info);
721 wl_pointer_set_user_data(
input->pointer,
input);
722 wl_pointer_add_listener(
input->pointer, &pointer_listener,
724 }
else if (!(caps & WL_SEAT_CAPABILITY_POINTER) &&
input->pointer) {
725 wl_pointer_destroy(
input->pointer);
730 if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !
input->touch) {
732 input->touch = wl_seat_get_touch(seat);
734 wl_touch_add_listener(
input->touch, &touch_listener,
736 }
else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) &&
input->touch) {
738 wl_touch_destroy(
input->touch);
742 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !
input->keyboard) {
743 input->keyboard = wl_seat_get_keyboard(seat);
744 wl_keyboard_set_user_data(
input->keyboard,
input);
745 wl_keyboard_add_listener(
input->keyboard, &keyboard_listener,
747 }
else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) &&
input->keyboard) {
748 wl_keyboard_destroy(
input->keyboard);
754 seat_handle_name(
void *
data,
struct wl_seat *wl_seat,
const char *
name)
759 static const struct wl_seat_listener seat_listener = {
760 seat_handle_capabilities,
765 data_source_handle_target(
void *
data,
struct wl_data_source *wl_data_source,
766 const char *mime_type)
771 data_source_handle_send(
void *
data,
struct wl_data_source *wl_data_source,
778 data_source_handle_cancelled(
void *
data,
struct wl_data_source *wl_data_source)
784 data_source_handle_dnd_drop_performed(
void *
data,
struct wl_data_source *wl_data_source)
789 data_source_handle_dnd_finished(
void *
data,
struct wl_data_source *wl_data_source)
794 data_source_handle_action(
void *
data,
struct wl_data_source *wl_data_source,
799 static const struct wl_data_source_listener data_source_listener = {
800 data_source_handle_target,
801 data_source_handle_send,
802 data_source_handle_cancelled,
803 data_source_handle_dnd_drop_performed,
804 data_source_handle_dnd_finished,
805 data_source_handle_action,
813 struct wl_data_source *
id =
NULL;
821 id = wl_data_device_manager_create_data_source(
828 data_source =
SDL_calloc(1,
sizeof *data_source);
829 if (data_source ==
NULL) {
831 wl_data_source_destroy(
id);
833 WAYLAND_wl_list_init(&(data_source->
mimes));
835 wl_data_source_set_user_data(
id, data_source);
836 wl_data_source_add_listener(
id, &data_source_listener,
845 data_offer_handle_offer(
void *
data,
struct wl_data_offer *wl_data_offer,
846 const char *mime_type)
853 data_offer_handle_source_actions(
void *
data,
struct wl_data_offer *wl_data_offer,
859 data_offer_handle_actions(
void *
data,
struct wl_data_offer *wl_data_offer,
864 static const struct wl_data_offer_listener data_offer_listener = {
865 data_offer_handle_offer,
866 data_offer_handle_source_actions,
867 data_offer_handle_actions,
871 data_device_handle_data_offer(
void *
data,
struct wl_data_device *wl_data_device,
872 struct wl_data_offer *
id)
876 data_offer =
SDL_calloc(1,
sizeof *data_offer);
877 if (data_offer ==
NULL) {
882 WAYLAND_wl_list_init(&(data_offer->
mimes));
883 wl_data_offer_set_user_data(
id, data_offer);
884 wl_data_offer_add_listener(
id, &data_offer_listener, data_offer);
889 data_device_handle_enter(
void *
data,
struct wl_data_device *wl_data_device,
891 wl_fixed_t
x, wl_fixed_t
y,
struct wl_data_offer *
id)
895 uint32_t dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
900 data_device->
drag_offer = wl_data_offer_get_user_data(
id);
907 wl_data_offer_accept(
id, serial,
912 dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
916 dnd_action, dnd_action);
922 data_device_handle_leave(
void *
data,
struct wl_data_device *wl_data_device)
934 data_device_handle_motion(
void *
data,
struct wl_data_device *wl_data_device,
940 data_device_handle_drop(
void *
data,
struct wl_data_device *wl_data_device)
946 const char *current_uri =
NULL;
947 const char *last_char =
NULL;
948 char *current_char =
NULL;
956 current_uri = (
const char *)
buffer;
958 for (current_char =
buffer; current_char < last_char; ++current_char) {
959 if (*current_char ==
'\n' || *current_char == 0) {
960 if (*current_uri != 0 && *current_uri !=
'#') {
964 current_uri = (
const char *)current_char + 1;
973 data_device_handle_selection(
void *
data,
struct wl_data_device *wl_data_device,
974 struct wl_data_offer *
id)
980 offer = wl_data_offer_get_user_data(
id);
991 static const struct wl_data_device_listener data_device_listener = {
992 data_device_handle_data_offer,
993 data_device_handle_enter,
994 data_device_handle_leave,
995 data_device_handle_motion,
996 data_device_handle_drop,
997 data_device_handle_selection
1003 struct SDL_WaylandInput *
input;
1011 if (wl_seat_interface.version >= 5)
1012 input->seat = wl_registry_bind(
d->registry,
id, &wl_seat_interface, 5);
1014 input->seat = wl_registry_bind(
d->registry,
id, &wl_seat_interface, 1);
1015 input->sx_w = wl_fixed_from_int(0);
1016 input->sy_w = wl_fixed_from_int(0);
1019 if (
d->data_device_manager !=
NULL) {
1020 data_device =
SDL_calloc(1,
sizeof *data_device);
1021 if (data_device ==
NULL) {
1025 data_device->
data_device = wl_data_device_manager_get_data_device(
1026 d->data_device_manager,
input->seat
1033 wl_data_device_set_user_data(data_device->
data_device, data_device);
1034 wl_data_device_add_listener(data_device->
data_device,
1035 &data_device_listener, data_device);
1036 input->data_device = data_device;
1040 wl_seat_add_listener(
input->seat, &seat_listener,
input);
1043 WAYLAND_wl_display_flush(
d->display);
1048 struct SDL_WaylandInput *
input =
d->input;
1055 if (
input->data_device->selection_offer !=
NULL) {
1058 if (
input->data_device->drag_offer !=
NULL) {
1061 if (
input->data_device->data_device !=
NULL) {
1062 wl_data_device_release(
input->data_device->data_device);
1067 if (
input->keyboard)
1068 wl_keyboard_destroy(
input->keyboard);
1071 wl_pointer_destroy(
input->pointer);
1075 wl_touch_destroy(
input->touch);
1079 wl_seat_destroy(
input->seat);
1081 if (
input->xkb.state)
1082 WAYLAND_xkb_state_unref(
input->xkb.state);
1084 if (
input->xkb.keymap)
1085 WAYLAND_xkb_keymap_unref(
input->xkb.keymap);
1097 return input->data_device;
1103 d->relative_pointer_manager =
1104 wl_registry_bind(
d->registry,
id,
1105 &zwp_relative_pointer_manager_v1_interface, 1);
1110 if (
d->relative_pointer_manager)
1111 zwp_relative_pointer_manager_v1_destroy(
d->relative_pointer_manager);
1116 d->pointer_constraints =
1117 wl_registry_bind(
d->registry,
id,
1118 &zwp_pointer_constraints_v1_interface, 1);
1123 if (
d->pointer_constraints)
1124 zwp_pointer_constraints_v1_destroy(
d->pointer_constraints);
1128 relative_pointer_handle_relative_motion(
void *
data,
1129 struct zwp_relative_pointer_v1 *
pointer,
1134 wl_fixed_t dx_unaccel_w,
1135 wl_fixed_t dy_unaccel_w)
1145 dx_unaccel = wl_fixed_to_double(dx_unaccel_w);
1146 dy_unaccel = wl_fixed_to_double(dy_unaccel_w);
1149 dx_unaccel +=
input->dx_frac;
1150 dy_unaccel +=
input->dy_frac;
1152 input->dx_frac = modf(dx_unaccel, &dx);
1153 input->dy_frac = modf(dy_unaccel, &dy);
1155 if (
input->pointer_focus &&
d->relative_mouse_mode) {
1160 static const struct zwp_relative_pointer_v1_listener relative_pointer_listener = {
1161 relative_pointer_handle_relative_motion,
1165 locked_pointer_locked(
void *
data,
1166 struct zwp_locked_pointer_v1 *locked_pointer)
1171 locked_pointer_unlocked(
void *
data,
1172 struct zwp_locked_pointer_v1 *locked_pointer)
1176 static const struct zwp_locked_pointer_v1_listener locked_pointer_listener = {
1177 locked_pointer_locked,
1178 locked_pointer_unlocked,
1183 struct SDL_WaylandInput *
input)
1187 struct zwp_locked_pointer_v1 *locked_pointer;
1189 if (
w->locked_pointer)
1193 zwp_pointer_constraints_v1_lock_pointer(
d->pointer_constraints,
1197 ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
1198 zwp_locked_pointer_v1_add_listener(locked_pointer,
1199 &locked_pointer_listener,
1202 w->locked_pointer = locked_pointer;
1210 struct zwp_relative_pointer_v1 *relative_pointer;
1212 if (!
d->relative_pointer_manager)
1215 if (!
d->pointer_constraints)
1218 if (!
input->pointer)
1221 if (!
input->relative_pointer) {
1223 zwp_relative_pointer_manager_v1_get_relative_pointer(
1224 d->relative_pointer_manager,
1226 zwp_relative_pointer_v1_add_listener(relative_pointer,
1227 &relative_pointer_listener,
1229 input->relative_pointer = relative_pointer;
1235 d->relative_mouse_mode = 1;
1249 if (
w->locked_pointer)
1250 zwp_locked_pointer_v1_destroy(
w->locked_pointer);
1251 w->locked_pointer =
NULL;
1254 zwp_relative_pointer_v1_destroy(
input->relative_pointer);
1257 d->relative_mouse_mode = 0;