1From c4b8f02cca601a25767de29392940f0dc5ef2e24 Mon Sep 17 00:00:00 2001
2From: Jeffy Chen <jeffy.chen@rock-chips.com>
3Date: Thu, 7 May 2020 08:55:42 +0800
4Subject: [PATCH 20/79] HACK: Support setting surface flags activate and alpha
5
6Support setting surface flags activate and alpha through app_id or
7title, for example:
8
9xdg_toplevel_set_app_id("flags=stay-on-top|stay-on-bottom|no-focus")
10xdg_toplevel_set_title("requests=activate")
11xdg_toplevel_set_app_id("attrs=alpha:0.5")
12
13Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
14---
15 desktop-shell/shell.c         |  29 ++++-
16 desktop-shell/shell.h         |   2 +
17 include/libweston/libweston.h |  13 +++
18 libweston-desktop/surface.c   | 193 ++++++++++++++++++++++++++++++++++
19 libweston/compositor.c        |  10 +-
20 5 files changed, 244 insertions(+), 3 deletions(-)
21
22diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
23index 8b4ed45..4cb29dd 100644
24--- a/desktop-shell/shell.c
25+++ b/desktop-shell/shell.c
26@@ -1895,6 +1895,11 @@ shell_surface_update_layer(struct shell_surface *shsurf)
27
28 	new_layer_link = shell_surface_calculate_layer_link(shsurf);
29
30+	if (surface->flags & SURFACE_STAY_ON_TOP)
31+		new_layer_link = &shsurf->shell->top_layer.view_list;
32+	else if (surface->flags & SURFACE_STAY_ON_BOTTOM)
33+		new_layer_link = &shsurf->shell->bottom_layer.view_list;
34+
35 	if (new_layer_link == NULL)
36 		return;
37 	if (new_layer_link == &shsurf->view->layer_link)
38@@ -3220,6 +3225,10 @@ resume_desktop(struct desktop_shell *shell)
39 	weston_layer_set_position(&shell->panel_layer,
40 				  WESTON_LAYER_POSITION_UI);
41 	weston_layer_set_position(&ws->layer, WESTON_LAYER_POSITION_NORMAL);
42+	weston_layer_set_position(&shell->top_layer,
43+				  WESTON_LAYER_POSITION_TOP_UI);
44+	weston_layer_set_position(&shell->bottom_layer,
45+				  WESTON_LAYER_POSITION_BOTTOM_UI);
46
47 	restore_focus_state(shell, get_current_workspace(shell));
48
49@@ -3781,7 +3790,7 @@ activate(struct desktop_shell *shell, struct weston_view *view,
50 	struct weston_surface *main_surface;
51 	struct focus_state *state;
52 	struct workspace *ws;
53-	struct weston_surface *old_es;
54+	struct weston_surface *old_es = NULL;
55 	struct shell_surface *shsurf, *shsurf_child;
56 	struct shell_seat *shseat = get_shell_seat(seat);
57
58@@ -3801,6 +3810,9 @@ activate(struct desktop_shell *shell, struct weston_view *view,
59 	if (shsurf->output)
60 		lower_fullscreen_layer(shell, shsurf->output);
61
62+	if (view->surface->flags & SURFACE_NO_FOCUS)
63+		goto no_focus;
64+
65 	weston_view_activate_input(view, seat, flags);
66
67 	if (shseat && shseat->focused_surface) {
68@@ -3821,6 +3833,7 @@ activate(struct desktop_shell *shell, struct weston_view *view,
69 	old_es = state->keyboard_focus;
70 	focus_state_set_focus(state, es);
71
72+no_focus:
73 	if (weston_desktop_surface_get_fullscreen(shsurf->desktop_surface) &&
74 	    flags & WESTON_ACTIVATE_FLAG_CONFIGURE)
75 		shell_configure_fullscreen(shsurf);
76@@ -3829,7 +3842,7 @@ activate(struct desktop_shell *shell, struct weston_view *view,
77 	 * order as appropriate. */
78 	shell_surface_update_layer(shsurf);
79
80-	if (shell->focus_animation_type != ANIMATION_NONE) {
81+	if (old_es && shell->focus_animation_type != ANIMATION_NONE) {
82 		ws = get_current_workspace(shell);
83 		animate_focus_change(shell, ws, get_default_view(old_es), get_default_view(es));
84 	}
85@@ -3942,6 +3955,8 @@ lock(struct desktop_shell *shell)
86 	if (shell->showing_input_panels)
87 		weston_layer_unset_position(&shell->input_panel_layer);
88 	weston_layer_unset_position(&ws->layer);
89+	weston_layer_unset_position(&shell->top_layer);
90+	weston_layer_unset_position(&shell->bottom_layer);
91
92 	weston_layer_set_position(&shell->lock_layer,
93 				  WESTON_LAYER_POSITION_LOCK);
94@@ -4822,6 +4837,8 @@ shell_for_each_layer(struct desktop_shell *shell,
95 	func(shell, &shell->background_layer, data);
96 	func(shell, &shell->lock_layer, data);
97 	func(shell, &shell->input_panel_layer, data);
98+	func(shell, &shell->top_layer, data);
99+	func(shell, &shell->bottom_layer, data);
100
101 	wl_array_for_each(ws, &shell->workspaces.array)
102 		func(shell, &(*ws)->layer, data);
103@@ -5115,6 +5132,8 @@ shell_destroy(struct wl_listener *listener, void *data)
104 		workspace_destroy(*ws);
105 	wl_array_release(&shell->workspaces.array);
106
107+	desktop_shell_destroy_layer(&shell->bottom_layer);
108+	desktop_shell_destroy_layer(&shell->top_layer);
109 	desktop_shell_destroy_layer(&shell->panel_layer);
110 	desktop_shell_destroy_layer(&shell->background_layer);
111 	desktop_shell_destroy_layer(&shell->lock_layer);
112@@ -5270,6 +5289,8 @@ wet_shell_init(struct weston_compositor *ec,
113 	weston_layer_init(&shell->background_layer, ec);
114 	weston_layer_init(&shell->lock_layer, ec);
115 	weston_layer_init(&shell->input_panel_layer, ec);
116+	weston_layer_init(&shell->top_layer, ec);
117+	weston_layer_init(&shell->bottom_layer, ec);
118
119 	weston_layer_set_position(&shell->fullscreen_layer,
120 				  WESTON_LAYER_POSITION_FULLSCREEN);
121@@ -5277,6 +5298,10 @@ wet_shell_init(struct weston_compositor *ec,
122 				  WESTON_LAYER_POSITION_UI);
123 	weston_layer_set_position(&shell->background_layer,
124 				  WESTON_LAYER_POSITION_BACKGROUND);
125+	weston_layer_set_position(&shell->top_layer,
126+				  WESTON_LAYER_POSITION_TOP_UI);
127+	weston_layer_set_position(&shell->bottom_layer,
128+				  WESTON_LAYER_POSITION_BOTTOM_UI);
129
130 	wl_array_init(&shell->workspaces.array);
131 	wl_list_init(&shell->workspaces.client_list);
132diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h
133index b06b906..e0a0620 100644
134--- a/desktop-shell/shell.h
135+++ b/desktop-shell/shell.h
136@@ -148,6 +148,8 @@ struct desktop_shell {
137 	struct weston_layer background_layer;
138 	struct weston_layer lock_layer;
139 	struct weston_layer input_panel_layer;
140+	struct weston_layer top_layer;
141+	struct weston_layer bottom_layer;
142
143 	struct wl_listener pointer_focus_listener;
144 	struct weston_surface *grab_surface;
145diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h
146index 24e44a2..7bc01e3 100644
147--- a/include/libweston/libweston.h
148+++ b/include/libweston/libweston.h
149@@ -1469,6 +1469,14 @@ struct weston_pointer_constraint {
150 	struct wl_listener surface_activate_listener;
151 };
152
153+enum weston_surface_flags {
154+	SURFACE_NO_FOCUS	= 1 << 0,
155+	SURFACE_STAY_ON_TOP	= 1 << 1,
156+	SURFACE_STAY_ON_BOTTOM	= 1 << 2,
157+	SURFACE_BLOCKED		= 1 << 3,
158+	SURFACE_TRANS_INPUT	= 1 << 4,
159+};
160+
161 struct weston_surface {
162 	struct wl_resource *resource;
163 	struct wl_signal destroy_signal; /* callback argument: this surface */
164@@ -1575,6 +1583,11 @@ struct weston_surface {
165
166 	/* Transparent hole region(excluding it's lower subsurface area) */
167 	pixman_region32_t hole;
168+
169+	/* Hacky surface flags */
170+	enum weston_surface_flags flags;
171+
172+	double alpha;
173 };
174
175 struct weston_subsurface {
176diff --git a/libweston-desktop/surface.c b/libweston-desktop/surface.c
177index 21ff080..e86ef52 100644
178--- a/libweston-desktop/surface.c
179+++ b/libweston-desktop/surface.c
180@@ -695,12 +695,202 @@ weston_desktop_surface_set_position(struct weston_desktop_surface *surface,
181 		weston_view_set_position(view->view, x, y);
182 }
183
184+static bool
185+weston_desktop_surface_set_flags(struct weston_desktop_surface *surface,
186+				 char *s)
187+{
188+	struct weston_surface *wsurface = surface->surface;
189+	char *p;
190+
191+#define SURFACE_FLAG_PREFIX "flags="
192+	s = strstr(s, SURFACE_FLAG_PREFIX);
193+	if (!s)
194+		return false;
195+
196+	s += strlen(SURFACE_FLAG_PREFIX);
197+
198+	p = strtok(s, "|");
199+	while (p) {
200+		enum weston_surface_flags flag = 0;
201+		bool clear = false;
202+
203+		switch (p[0]) {
204+		case ';':
205+			/* fall through */
206+		case '&':
207+			return true;
208+		case '-':
209+			clear = true;
210+			/* fall through */
211+		case '+':
212+			p++;
213+		default:
214+			break;
215+		}
216+
217+		if (!strcmp(p, "no-focus"))
218+			flag = SURFACE_NO_FOCUS;
219+		else if (!strcmp(p, "stay-on-top"))
220+			flag = SURFACE_STAY_ON_TOP;
221+		else if (!strcmp(p, "stay-on-bottom"))
222+			flag = SURFACE_STAY_ON_BOTTOM;
223+		else if (!strcmp(p, "blocked"))
224+			flag = SURFACE_BLOCKED;
225+		else if (!strcmp(p, "trans-input"))
226+			flag = SURFACE_TRANS_INPUT;
227+		else
228+			weston_log("%s: warning: unsupported flag: %s\n",
229+				   __func__, p);
230+
231+		if (clear)
232+			wsurface->flags &= ~flag;
233+		else
234+			wsurface->flags |= flag;
235+
236+		p = strtok(NULL, "|");
237+	};
238+
239+	return true;
240+}
241+
242+static bool
243+weston_desktop_surface_set_requests(struct weston_desktop_surface *surface,
244+				    char *s)
245+{
246+	struct weston_surface *wsurface = surface->surface;
247+	char *p;
248+
249+#define SURFACE_REQUEST_PREFIX "requests="
250+	s = strstr(s, SURFACE_REQUEST_PREFIX);
251+	if (!s)
252+		return false;
253+
254+	s += strlen(SURFACE_REQUEST_PREFIX);
255+
256+	p = strtok(s, "|");
257+	while (p) {
258+		switch (p[0]) {
259+		case ';':
260+			/* fall through */
261+		case '&':
262+			return true;
263+		default:
264+			break;
265+		}
266+
267+		if (!strcmp(p, "activate")) {
268+			if (weston_surface_is_mapped(wsurface))
269+				weston_surface_unmap(wsurface);
270+
271+			weston_desktop_api_committed(surface->desktop,
272+						     surface, 0, 0);
273+		} else {
274+			weston_log("%s: warning: unsupported request: %s\n",
275+				   __func__, p);
276+		}
277+
278+		p = strtok(NULL, "|");
279+	};
280+
281+	return true;
282+}
283+
284+static void
285+weston_surface_set_alpha(struct weston_surface *wsurface, float alpha)
286+{
287+	struct weston_subsurface *sub;
288+	struct weston_view *view;
289+
290+	wsurface->alpha = alpha;
291+	wsurface->is_opaque = !(alpha < 1.0);
292+
293+	wl_list_for_each(view, &wsurface->views,
294+			 surface_link) {
295+		view->alpha = alpha;
296+		weston_view_geometry_dirty(view);
297+	}
298+
299+	wl_list_for_each(sub, &wsurface->subsurface_list,
300+			 parent_link) {
301+		if (sub->surface != wsurface)
302+			weston_surface_set_alpha(sub->surface, alpha);
303+	}
304+}
305+
306+static bool
307+weston_desktop_surface_set_attrs(struct weston_desktop_surface *surface,
308+				 char *s)
309+{
310+	struct weston_surface *wsurface = surface->surface;
311+	char *p;
312+
313+#define SURFACE_ATTRS_PREFIX "attrs="
314+	s = strstr(s, SURFACE_ATTRS_PREFIX);
315+	if (!s)
316+		return false;
317+
318+	s += strlen(SURFACE_ATTRS_PREFIX);
319+
320+	p = strtok(s, "|");
321+	while (p) {
322+		switch (p[0]) {
323+		case ';':
324+			/* fall through */
325+		case '&':
326+			return true;
327+		default:
328+			break;
329+		}
330+
331+#define SURFACE_ATTR_ALPHA "alpha:"
332+		if (!strncmp(p, SURFACE_ATTR_ALPHA,
333+			     strlen(SURFACE_ATTR_ALPHA))) {
334+			double alpha = atof(p + strlen(SURFACE_ATTR_ALPHA));
335+
336+			weston_surface_set_alpha(wsurface, alpha);
337+		} else {
338+			weston_log("%s: warning: unsupported attr: %s\n",
339+				   __func__, p);
340+		}
341+
342+		p = strtok(NULL, "|");
343+	};
344+
345+	return true;
346+}
347+
348+static bool
349+weston_desktop_surface_handle_config(struct weston_desktop_surface *surface,
350+				     const char *s)
351+{
352+	char *tmp;
353+	bool handled = false;
354+
355+	tmp = strdup(s);
356+	if (tmp == NULL)
357+		return false;
358+
359+	handled |= weston_desktop_surface_set_flags(surface, tmp);
360+
361+	strcpy(tmp, s);
362+	handled |= weston_desktop_surface_set_requests(surface, tmp);
363+
364+	strcpy(tmp, s);
365+	handled |= weston_desktop_surface_set_attrs(surface, tmp);
366+
367+	free(tmp);
368+	return handled;
369+}
370+
371 void
372 weston_desktop_surface_set_title(struct weston_desktop_surface *surface,
373 				 const char *title)
374 {
375 	char *tmp, *old;
376
377+	if (weston_desktop_surface_handle_config(surface, title))
378+		return;
379+
380 	tmp = strdup(title);
381 	if (tmp == NULL)
382 		return;
383@@ -717,6 +907,9 @@ weston_desktop_surface_set_app_id(struct weston_desktop_surface *surface,
384 {
385 	char *tmp, *old;
386
387+	if (weston_desktop_surface_handle_config(surface, app_id))
388+		return;
389+
390 	tmp = strdup(app_id);
391 	if (tmp == NULL)
392 		return;
393diff --git a/libweston/compositor.c b/libweston/compositor.c
394index 0aa9d1a..b959424 100644
395--- a/libweston/compositor.c
396+++ b/libweston/compositor.c
397@@ -412,7 +412,7 @@ weston_view_create(struct weston_surface *surface)
398
399 	pixman_region32_init(&view->clip);
400
401-	view->alpha = 1.0;
402+	view->alpha = surface->alpha;
403 	pixman_region32_init(&view->transform.opaque);
404
405 	wl_list_init(&view->geometry.transformation_list);
406@@ -608,6 +608,8 @@ weston_surface_create(struct weston_compositor *compositor)
407 	surface->compositor = compositor;
408 	surface->ref_count = 1;
409
410+	surface->alpha = 1.0;
411+
412 	surface->buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
413 	surface->buffer_viewport.buffer.scale = 1;
414 	surface->buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
415@@ -2217,6 +2219,12 @@ weston_compositor_pick_view(struct weston_compositor *compositor,
416 						    view_ix, view_iy, NULL))
417 			continue;
418
419+		if (view->surface->flags & SURFACE_BLOCKED)
420+			break;
421+
422+		if (view->surface->flags & SURFACE_TRANS_INPUT)
423+			continue;
424+
425 		*vx = view_x;
426 		*vy = view_y;
427 		return view;
428--
4292.20.1
430
431