1 /*
2 * Copyright 2010-2012 Intel Corporation
3 * Copyright 2013 Raspberry Pi Foundation
4 * Copyright 2011-2012,2020 Collabora, Ltd.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26 #include "kiosk-shell-grab.h"
27 #include "shared/helpers.h"
28
29 struct kiosk_shell_grab {
30 struct kiosk_shell_surface *shsurf;
31 struct wl_listener shsurf_destroy_listener;
32
33 struct weston_pointer_grab pointer_grab;
34 struct weston_touch_grab touch_grab;
35 wl_fixed_t dx, dy;
36 bool active;
37 };
38
39 static void
40 kiosk_shell_grab_destroy(struct kiosk_shell_grab *shgrab);
41
42 /*
43 * pointer_move_grab_interface
44 */
45
46 static void
pointer_move_grab_focus(struct weston_pointer_grab * grab)47 pointer_move_grab_focus(struct weston_pointer_grab *grab)
48 {
49 }
50
51 static void
pointer_move_grab_axis(struct weston_pointer_grab * grab,const struct timespec * time,struct weston_pointer_axis_event * event)52 pointer_move_grab_axis(struct weston_pointer_grab *grab,
53 const struct timespec *time,
54 struct weston_pointer_axis_event *event)
55 {
56 }
57
58 static void
pointer_move_grab_axis_source(struct weston_pointer_grab * grab,uint32_t source)59 pointer_move_grab_axis_source(struct weston_pointer_grab *grab,
60 uint32_t source)
61 {
62 }
63
64 static void
pointer_move_grab_frame(struct weston_pointer_grab * grab)65 pointer_move_grab_frame(struct weston_pointer_grab *grab)
66 {
67 }
68
69 static void
pointer_move_grab_motion(struct weston_pointer_grab * pointer_grab,const struct timespec * time,struct weston_pointer_motion_event * event)70 pointer_move_grab_motion(struct weston_pointer_grab *pointer_grab,
71 const struct timespec *time,
72 struct weston_pointer_motion_event *event)
73 {
74 struct kiosk_shell_grab *shgrab =
75 container_of(pointer_grab, struct kiosk_shell_grab, pointer_grab);
76 struct weston_pointer *pointer = pointer_grab->pointer;
77 struct kiosk_shell_surface *shsurf = shgrab->shsurf;
78 struct weston_surface *surface;
79 int dx, dy;
80
81 weston_pointer_move(pointer, event);
82
83 if (!shsurf)
84 return;
85
86 surface = weston_desktop_surface_get_surface(shsurf->desktop_surface);
87
88 dx = wl_fixed_to_int(pointer->x + shgrab->dx);
89 dy = wl_fixed_to_int(pointer->y + shgrab->dy);
90
91 weston_view_set_position(shsurf->view, dx, dy);
92
93 weston_compositor_schedule_repaint(surface->compositor);
94 }
95
96 static void
pointer_move_grab_button(struct weston_pointer_grab * pointer_grab,const struct timespec * time,uint32_t button,uint32_t state_w)97 pointer_move_grab_button(struct weston_pointer_grab *pointer_grab,
98 const struct timespec *time,
99 uint32_t button, uint32_t state_w)
100 {
101 struct kiosk_shell_grab *shgrab =
102 container_of(pointer_grab, struct kiosk_shell_grab, pointer_grab);
103 struct weston_pointer *pointer = pointer_grab->pointer;
104 enum wl_pointer_button_state state = state_w;
105
106 if (pointer->button_count == 0 &&
107 state == WL_POINTER_BUTTON_STATE_RELEASED)
108 kiosk_shell_grab_destroy(shgrab);
109 }
110
111 static void
pointer_move_grab_cancel(struct weston_pointer_grab * pointer_grab)112 pointer_move_grab_cancel(struct weston_pointer_grab *pointer_grab)
113 {
114 struct kiosk_shell_grab *shgrab =
115 container_of(pointer_grab, struct kiosk_shell_grab, pointer_grab);
116
117 kiosk_shell_grab_destroy(shgrab);
118 }
119
120 static const struct weston_pointer_grab_interface pointer_move_grab_interface = {
121 pointer_move_grab_focus,
122 pointer_move_grab_motion,
123 pointer_move_grab_button,
124 pointer_move_grab_axis,
125 pointer_move_grab_axis_source,
126 pointer_move_grab_frame,
127 pointer_move_grab_cancel,
128 };
129
130 /*
131 * touch_move_grab_interface
132 */
133
134 static void
touch_move_grab_down(struct weston_touch_grab * grab,const struct timespec * time,int touch_id,wl_fixed_t x,wl_fixed_t y)135 touch_move_grab_down(struct weston_touch_grab *grab,
136 const struct timespec *time,
137 int touch_id, wl_fixed_t x, wl_fixed_t y)
138 {
139 }
140
141 static void
touch_move_grab_up(struct weston_touch_grab * touch_grab,const struct timespec * time,int touch_id)142 touch_move_grab_up(struct weston_touch_grab *touch_grab,
143 const struct timespec *time, int touch_id)
144 {
145 struct kiosk_shell_grab *shgrab =
146 container_of(touch_grab, struct kiosk_shell_grab, touch_grab);
147
148 if (touch_id == 0)
149 shgrab->active = false;
150
151 if (touch_grab->touch->num_tp == 0)
152 kiosk_shell_grab_destroy(shgrab);
153 }
154
155 static void
touch_move_grab_motion(struct weston_touch_grab * touch_grab,const struct timespec * time,int touch_id,wl_fixed_t x,wl_fixed_t y)156 touch_move_grab_motion(struct weston_touch_grab *touch_grab,
157 const struct timespec *time, int touch_id,
158 wl_fixed_t x, wl_fixed_t y)
159 {
160 struct kiosk_shell_grab *shgrab =
161 container_of(touch_grab, struct kiosk_shell_grab, touch_grab);
162 struct weston_touch *touch = touch_grab->touch;
163 struct kiosk_shell_surface *shsurf = shgrab->shsurf;
164 struct weston_surface *surface;
165 int dx, dy;
166
167 if (!shsurf || !shgrab->active)
168 return;
169
170 surface = weston_desktop_surface_get_surface(shsurf->desktop_surface);
171
172 dx = wl_fixed_to_int(touch->grab_x + shgrab->dx);
173 dy = wl_fixed_to_int(touch->grab_y + shgrab->dy);
174
175 weston_view_set_position(shsurf->view, dx, dy);
176
177 weston_compositor_schedule_repaint(surface->compositor);
178 }
179
180 static void
touch_move_grab_frame(struct weston_touch_grab * grab)181 touch_move_grab_frame(struct weston_touch_grab *grab)
182 {
183 }
184
185 static void
touch_move_grab_cancel(struct weston_touch_grab * touch_grab)186 touch_move_grab_cancel(struct weston_touch_grab *touch_grab)
187 {
188 struct kiosk_shell_grab *shgrab =
189 container_of(touch_grab, struct kiosk_shell_grab, touch_grab);
190
191 kiosk_shell_grab_destroy(shgrab);
192 }
193
194 static const struct weston_touch_grab_interface touch_move_grab_interface = {
195 touch_move_grab_down,
196 touch_move_grab_up,
197 touch_move_grab_motion,
198 touch_move_grab_frame,
199 touch_move_grab_cancel,
200 };
201
202 /*
203 * kiosk_shell_grab
204 */
205
206 static void
kiosk_shell_grab_handle_shsurf_destroy(struct wl_listener * listener,void * data)207 kiosk_shell_grab_handle_shsurf_destroy(struct wl_listener *listener, void *data)
208 {
209 struct kiosk_shell_grab *shgrab =
210 container_of(listener, struct kiosk_shell_grab,
211 shsurf_destroy_listener);
212
213 shgrab->shsurf = NULL;
214 }
215
216 static struct kiosk_shell_grab *
kiosk_shell_grab_create(struct kiosk_shell_surface * shsurf)217 kiosk_shell_grab_create(struct kiosk_shell_surface *shsurf)
218 {
219 struct kiosk_shell_grab *shgrab;
220
221 shgrab = zalloc(sizeof *shgrab);
222 if (!shgrab)
223 return NULL;
224
225 shgrab->shsurf = shsurf;
226 shgrab->shsurf_destroy_listener.notify =
227 kiosk_shell_grab_handle_shsurf_destroy;
228 wl_signal_add(&shsurf->destroy_signal,
229 &shgrab->shsurf_destroy_listener);
230
231 shsurf->grabbed = true;
232
233 return shgrab;
234 }
235
236 enum kiosk_shell_grab_result
kiosk_shell_grab_start_for_pointer_move(struct kiosk_shell_surface * shsurf,struct weston_pointer * pointer)237 kiosk_shell_grab_start_for_pointer_move(struct kiosk_shell_surface *shsurf,
238 struct weston_pointer *pointer)
239 {
240 struct kiosk_shell_grab *shgrab;
241
242 if (!shsurf)
243 return KIOSK_SHELL_GRAB_RESULT_ERROR;
244
245 if (shsurf->grabbed ||
246 weston_desktop_surface_get_fullscreen(shsurf->desktop_surface) ||
247 weston_desktop_surface_get_maximized(shsurf->desktop_surface))
248 return KIOSK_SHELL_GRAB_RESULT_IGNORED;
249
250 shgrab = kiosk_shell_grab_create(shsurf);
251 if (!shgrab)
252 return KIOSK_SHELL_GRAB_RESULT_ERROR;
253
254 shgrab->dx = wl_fixed_from_double(shsurf->view->geometry.x) -
255 pointer->grab_x;
256 shgrab->dy = wl_fixed_from_double(shsurf->view->geometry.y) -
257 pointer->grab_y;
258 shgrab->active = true;
259
260 weston_seat_break_desktop_grabs(pointer->seat);
261
262 shgrab->pointer_grab.interface = &pointer_move_grab_interface;
263 weston_pointer_start_grab(pointer, &shgrab->pointer_grab);
264
265 return KIOSK_SHELL_GRAB_RESULT_OK;
266 }
267
268 enum kiosk_shell_grab_result
kiosk_shell_grab_start_for_touch_move(struct kiosk_shell_surface * shsurf,struct weston_touch * touch)269 kiosk_shell_grab_start_for_touch_move(struct kiosk_shell_surface *shsurf,
270 struct weston_touch *touch)
271 {
272 struct kiosk_shell_grab *shgrab;
273
274 if (!shsurf)
275 return KIOSK_SHELL_GRAB_RESULT_ERROR;
276
277 if (shsurf->grabbed ||
278 weston_desktop_surface_get_fullscreen(shsurf->desktop_surface) ||
279 weston_desktop_surface_get_maximized(shsurf->desktop_surface))
280 return KIOSK_SHELL_GRAB_RESULT_IGNORED;
281
282 shgrab = kiosk_shell_grab_create(shsurf);
283 if (!shgrab)
284 return KIOSK_SHELL_GRAB_RESULT_ERROR;
285
286 shgrab->dx = wl_fixed_from_double(shsurf->view->geometry.x) -
287 touch->grab_x;
288 shgrab->dy = wl_fixed_from_double(shsurf->view->geometry.y) -
289 touch->grab_y;
290 shgrab->active = true;
291
292 weston_seat_break_desktop_grabs(touch->seat);
293
294 shgrab->touch_grab.interface = &touch_move_grab_interface;
295 weston_touch_start_grab(touch, &shgrab->touch_grab);
296
297 return KIOSK_SHELL_GRAB_RESULT_OK;
298 }
299
300 static void
kiosk_shell_grab_destroy(struct kiosk_shell_grab * shgrab)301 kiosk_shell_grab_destroy(struct kiosk_shell_grab *shgrab)
302 {
303 if (shgrab->shsurf) {
304 wl_list_remove(&shgrab->shsurf_destroy_listener.link);
305 shgrab->shsurf->grabbed = false;
306 }
307
308 if (shgrab->pointer_grab.pointer)
309 weston_pointer_end_grab(shgrab->pointer_grab.pointer);
310 else if (shgrab->touch_grab.touch)
311 weston_touch_end_grab(shgrab->touch_grab.touch);
312
313 free(shgrab);
314 }
315