Implemented SDL_SetWindowMouseRect() on Wayland
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index f52b261..5f20b46 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -1670,11 +1670,12 @@ lock_pointer_to_window(SDL_Window *window,
w->locked_pointer = locked_pointer;
}
-static void pointer_confine_destroy(struct SDL_WaylandInput *input)
+static void pointer_confine_destroy(SDL_Window *window)
{
- if (input->confined_pointer) {
- zwp_confined_pointer_v1_destroy(input->confined_pointer);
- input->confined_pointer = NULL;
+ SDL_WindowData *w = window->driverdata;
+ if (w->confined_pointer) {
+ zwp_confined_pointer_v1_destroy(w->confined_pointer);
+ w->confined_pointer = NULL;
}
}
@@ -1696,7 +1697,8 @@ int Wayland_input_lock_pointer(struct SDL_WaylandInput *input)
/* If we have a pointer confine active, we must destroy it here because
* creating a locked pointer otherwise would be a protocol error. */
- pointer_confine_destroy(input);
+ for (window = vd->windows; window; window = window->next)
+ pointer_confine_destroy(window);
if (!input->relative_pointer) {
relative_pointer =
@@ -1736,8 +1738,8 @@ int Wayland_input_unlock_pointer(struct SDL_WaylandInput *input)
d->relative_mouse_mode = 0;
- if (input->confined_pointer_window)
- Wayland_input_confine_pointer(input->confined_pointer_window, input);
+ for (window = vd->windows; window; window = window->next)
+ Wayland_input_confine_pointer(input, window);
return 0;
}
@@ -1759,11 +1761,12 @@ static const struct zwp_confined_pointer_v1_listener confined_pointer_listener =
confined_pointer_unconfined,
};
-int Wayland_input_confine_pointer(SDL_Window *window, struct SDL_WaylandInput *input)
+int Wayland_input_confine_pointer(struct SDL_WaylandInput *input, SDL_Window *window)
{
SDL_WindowData *w = window->driverdata;
SDL_VideoData *d = input->display;
struct zwp_confined_pointer_v1 *confined_pointer;
+ struct wl_region *confine_rect;
if (!d->pointer_constraints)
return -1;
@@ -1773,34 +1776,45 @@ int Wayland_input_confine_pointer(SDL_Window *window, struct SDL_WaylandInput *i
/* A confine may already be active, in which case we should destroy it and
* create a new one. */
- if (input->confined_pointer)
- Wayland_input_unconfine_pointer(input);
-
- input->confined_pointer_window = window;
+ pointer_confine_destroy(window);
/* We cannot create a confine if the pointer is already locked. Defer until
* the pointer is unlocked. */
if (d->relative_mouse_mode)
return 0;
+ if (SDL_RectEmpty(&window->mouse_rect)) {
+ confine_rect = NULL;
+ } else {
+ confine_rect = wl_compositor_create_region(d->compositor);
+ wl_region_add(confine_rect,
+ window->mouse_rect.x,
+ window->mouse_rect.y,
+ window->mouse_rect.w,
+ window->mouse_rect.h);
+ }
+
confined_pointer =
zwp_pointer_constraints_v1_confine_pointer(d->pointer_constraints,
w->surface,
input->pointer,
- NULL,
+ confine_rect,
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
zwp_confined_pointer_v1_add_listener(confined_pointer,
&confined_pointer_listener,
window);
- input->confined_pointer = confined_pointer;
+ if (confine_rect != NULL) {
+ wl_region_destroy(confine_rect);
+ }
+
+ w->confined_pointer = confined_pointer;
return 0;
}
-int Wayland_input_unconfine_pointer(struct SDL_WaylandInput *input)
+int Wayland_input_unconfine_pointer(struct SDL_WaylandInput *input, SDL_Window *window)
{
- pointer_confine_destroy(input);
- input->confined_pointer_window = NULL;
+ pointer_confine_destroy(window);
return 0;
}
diff --git a/src/video/wayland/SDL_waylandevents_c.h b/src/video/wayland/SDL_waylandevents_c.h
index 699d2b3..ee905ce 100644
--- a/src/video/wayland/SDL_waylandevents_c.h
+++ b/src/video/wayland/SDL_waylandevents_c.h
@@ -50,8 +50,6 @@ struct SDL_WaylandInput {
SDL_WaylandDataDevice *data_device;
SDL_WaylandTextInput *text_input;
struct zwp_relative_pointer_v1 *relative_pointer;
- struct zwp_confined_pointer_v1 *confined_pointer;
- SDL_Window *confined_pointer_window;
SDL_WindowData *pointer_focus;
SDL_WindowData *keyboard_focus;
uint32_t pointer_enter_serial;
@@ -98,8 +96,8 @@ extern void Wayland_display_destroy_pointer_constraints(SDL_VideoData *d);
extern int Wayland_input_lock_pointer(struct SDL_WaylandInput *input);
extern int Wayland_input_unlock_pointer(struct SDL_WaylandInput *input);
-extern int Wayland_input_confine_pointer(SDL_Window *window, struct SDL_WaylandInput *input);
-extern int Wayland_input_unconfine_pointer(struct SDL_WaylandInput *input);
+extern int Wayland_input_confine_pointer(struct SDL_WaylandInput *input, SDL_Window *window);
+extern int Wayland_input_unconfine_pointer(struct SDL_WaylandInput *input, SDL_Window *window);
extern void Wayland_display_add_relative_pointer_manager(SDL_VideoData *d, uint32_t id);
extern void Wayland_display_destroy_relative_pointer_manager(SDL_VideoData *d);
diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index 71f6fa8..777a1fa 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -247,6 +247,7 @@ Wayland_CreateDevice(int devindex)
device->SetWindowFullscreen = Wayland_SetWindowFullscreen;
device->MaximizeWindow = Wayland_MaximizeWindow;
device->MinimizeWindow = Wayland_MinimizeWindow;
+ device->SetWindowMouseRect = Wayland_SetWindowMouseRect;
device->SetWindowMouseGrab = Wayland_SetWindowMouseGrab;
device->SetWindowKeyboardGrab = Wayland_SetWindowKeyboardGrab;
device->RestoreWindow = Wayland_RestoreWindow;
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index 02443ec..f4494de 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -1154,14 +1154,34 @@ Wayland_MinimizeWindow(_THIS, SDL_Window * window)
}
void
+Wayland_SetWindowMouseRect(_THIS, SDL_Window *window)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+ /* This may look suspiciously like SetWindowGrab, despite SetMouseRect not
+ * implicitly doing a grab. And you're right! Wayland doesn't let us mess
+ * around with mouse focus whatsoever, so it just happens to be that the
+ * work that we can do in these two functions ends up being the same.
+ *
+ * Just know that this call lets you confine with a rect, SetWindowGrab
+ * lets you confine without a rect.
+ */
+ if (SDL_RectEmpty(&window->mouse_rect) && !(window->flags & SDL_WINDOW_MOUSE_GRABBED)) {
+ Wayland_input_unconfine_pointer(data->input, window);
+ } else {
+ Wayland_input_confine_pointer(data->input, window);
+ }
+}
+
+void
Wayland_SetWindowMouseGrab(_THIS, SDL_Window *window, SDL_bool grabbed)
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
if (grabbed) {
- Wayland_input_confine_pointer(window, data->input);
- } else {
- Wayland_input_unconfine_pointer(data->input);
+ Wayland_input_confine_pointer(data->input, window);
+ } else if (SDL_RectEmpty(&window->mouse_rect)) {
+ Wayland_input_unconfine_pointer(data->input, window);
}
}
diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h
index 1aaa645..f665699 100644
--- a/src/video/wayland/SDL_waylandwindow.h
+++ b/src/video/wayland/SDL_waylandwindow.h
@@ -65,6 +65,7 @@ typedef struct {
struct SDL_WaylandInput *keyboard_device;
EGLSurface egl_surface;
struct zwp_locked_pointer_v1 *locked_pointer;
+ struct zwp_confined_pointer_v1 *confined_pointer;
struct zxdg_toplevel_decoration_v1 *server_decoration;
struct zwp_keyboard_shortcuts_inhibitor_v1 *key_inhibitor;
struct zwp_idle_inhibitor_v1 *idle_inhibitor;
@@ -93,6 +94,7 @@ extern void Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
SDL_bool fullscreen);
extern void Wayland_MaximizeWindow(_THIS, SDL_Window * window);
extern void Wayland_MinimizeWindow(_THIS, SDL_Window * window);
+extern void Wayland_SetWindowMouseRect(_THIS, SDL_Window * window);
extern void Wayland_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
extern void Wayland_SetWindowKeyboardGrab(_THIS, SDL_Window *window, SDL_bool grabbed);
extern void Wayland_RestoreWindow(_THIS, SDL_Window * window);