• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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