1From b88835ba3042212cba6c5ecc9c8069f2f6525e4a 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 23/93] 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/compositor.c        |  10 +-
19 libweston/desktop/surface.c   | 193 ++++++++++++++++++++++++++++++++++
20 5 files changed, 244 insertions(+), 3 deletions(-)
21
22diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
23index be36b70..463c64e 100644
24--- a/desktop-shell/shell.c
25+++ b/desktop-shell/shell.c
26@@ -1431,6 +1431,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@@ -2787,6 +2792,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@@ -3360,7 +3369,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@@ -3380,6 +3389,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@@ -3402,6 +3414,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@@ -3410,7 +3423,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@@ -3504,6 +3517,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@@ -4318,6 +4333,8 @@ shell_for_each_layer(struct desktop_shell *shell,
95 	func(shell, &shell->lock_layer, data);
96 	func(shell, &shell->input_panel_layer, data);
97 	func(shell, &shell->workspace.layer, data);
98+	func(shell, &shell->top_layer, data);
99+	func(shell, &shell->bottom_layer, data);
100 }
101
102 static void
103@@ -4615,6 +4632,8 @@ shell_destroy(struct wl_listener *listener, void *data)
104
105 	workspace_destroy(&shell->workspace);
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@@ -4742,6 +4761,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@@ -4749,6 +4770,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_list_init(&shell->seat_list);
131
132diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h
133index e9e123e..6876cf3 100644
134--- a/desktop-shell/shell.h
135+++ b/desktop-shell/shell.h
136@@ -100,6 +100,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 84b16fe..a41ffba 100644
147--- a/include/libweston/libweston.h
148+++ b/include/libweston/libweston.h
149@@ -1635,6 +1635,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@@ -1741,6 +1749,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/compositor.c b/libweston/compositor.c
177index 877e7a7..09d4805 100644
178--- a/libweston/compositor.c
179+++ b/libweston/compositor.c
180@@ -415,7 +415,7 @@ weston_view_create(struct weston_surface *surface)
181
182 	pixman_region32_init(&view->clip);
183
184-	view->alpha = 1.0;
185+	view->alpha = surface->alpha;
186 	pixman_region32_init(&view->transform.opaque);
187
188 	wl_list_init(&view->geometry.transformation_list);
189@@ -611,6 +611,8 @@ weston_surface_create(struct weston_compositor *compositor)
190 	surface->compositor = compositor;
191 	surface->ref_count = 1;
192
193+	surface->alpha = 1.0;
194+
195 	surface->buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
196 	surface->buffer_viewport.buffer.scale = 1;
197 	surface->buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
198@@ -2253,6 +2255,12 @@ weston_compositor_pick_view(struct weston_compositor *compositor,
199 						    view_ix, view_iy, NULL))
200 			continue;
201
202+		if (view->surface->flags & SURFACE_BLOCKED)
203+			break;
204+
205+		if (view->surface->flags & SURFACE_TRANS_INPUT)
206+			continue;
207+
208 		*vx = view_x;
209 		*vy = view_y;
210 		return view;
211diff --git a/libweston/desktop/surface.c b/libweston/desktop/surface.c
212index 54e493c..aeac8f7 100644
213--- a/libweston/desktop/surface.c
214+++ b/libweston/desktop/surface.c
215@@ -705,12 +705,202 @@ weston_desktop_surface_set_position(struct weston_desktop_surface *surface,
216 		weston_view_set_position(view->view, x, y);
217 }
218
219+static bool
220+weston_desktop_surface_set_flags(struct weston_desktop_surface *surface,
221+				 char *s)
222+{
223+	struct weston_surface *wsurface = surface->surface;
224+	char *p;
225+
226+#define SURFACE_FLAG_PREFIX "flags="
227+	s = strstr(s, SURFACE_FLAG_PREFIX);
228+	if (!s)
229+		return false;
230+
231+	s += strlen(SURFACE_FLAG_PREFIX);
232+
233+	p = strtok(s, "|");
234+	while (p) {
235+		enum weston_surface_flags flag = 0;
236+		bool clear = false;
237+
238+		switch (p[0]) {
239+		case ';':
240+			/* fall through */
241+		case '&':
242+			return true;
243+		case '-':
244+			clear = true;
245+			/* fall through */
246+		case '+':
247+			p++;
248+		default:
249+			break;
250+		}
251+
252+		if (!strcmp(p, "no-focus"))
253+			flag = SURFACE_NO_FOCUS;
254+		else if (!strcmp(p, "stay-on-top"))
255+			flag = SURFACE_STAY_ON_TOP;
256+		else if (!strcmp(p, "stay-on-bottom"))
257+			flag = SURFACE_STAY_ON_BOTTOM;
258+		else if (!strcmp(p, "blocked"))
259+			flag = SURFACE_BLOCKED;
260+		else if (!strcmp(p, "trans-input"))
261+			flag = SURFACE_TRANS_INPUT;
262+		else
263+			weston_log("%s: warning: unsupported flag: %s\n",
264+				   __func__, p);
265+
266+		if (clear)
267+			wsurface->flags &= ~flag;
268+		else
269+			wsurface->flags |= flag;
270+
271+		p = strtok(NULL, "|");
272+	};
273+
274+	return true;
275+}
276+
277+static bool
278+weston_desktop_surface_set_requests(struct weston_desktop_surface *surface,
279+				    char *s)
280+{
281+	struct weston_surface *wsurface = surface->surface;
282+	char *p;
283+
284+#define SURFACE_REQUEST_PREFIX "requests="
285+	s = strstr(s, SURFACE_REQUEST_PREFIX);
286+	if (!s)
287+		return false;
288+
289+	s += strlen(SURFACE_REQUEST_PREFIX);
290+
291+	p = strtok(s, "|");
292+	while (p) {
293+		switch (p[0]) {
294+		case ';':
295+			/* fall through */
296+		case '&':
297+			return true;
298+		default:
299+			break;
300+		}
301+
302+		if (!strcmp(p, "activate")) {
303+			if (weston_surface_is_mapped(wsurface))
304+				weston_surface_unmap(wsurface);
305+
306+			weston_desktop_api_committed(surface->desktop,
307+						     surface, 0, 0);
308+		} else {
309+			weston_log("%s: warning: unsupported request: %s\n",
310+				   __func__, p);
311+		}
312+
313+		p = strtok(NULL, "|");
314+	};
315+
316+	return true;
317+}
318+
319+static void
320+weston_surface_set_alpha(struct weston_surface *wsurface, float alpha)
321+{
322+	struct weston_subsurface *sub;
323+	struct weston_view *view;
324+
325+	wsurface->alpha = alpha;
326+	wsurface->is_opaque = !(alpha < 1.0);
327+
328+	wl_list_for_each(view, &wsurface->views,
329+			 surface_link) {
330+		view->alpha = alpha;
331+		weston_view_geometry_dirty(view);
332+	}
333+
334+	wl_list_for_each(sub, &wsurface->subsurface_list,
335+			 parent_link) {
336+		if (sub->surface != wsurface)
337+			weston_surface_set_alpha(sub->surface, alpha);
338+	}
339+}
340+
341+static bool
342+weston_desktop_surface_set_attrs(struct weston_desktop_surface *surface,
343+				 char *s)
344+{
345+	struct weston_surface *wsurface = surface->surface;
346+	char *p;
347+
348+#define SURFACE_ATTRS_PREFIX "attrs="
349+	s = strstr(s, SURFACE_ATTRS_PREFIX);
350+	if (!s)
351+		return false;
352+
353+	s += strlen(SURFACE_ATTRS_PREFIX);
354+
355+	p = strtok(s, "|");
356+	while (p) {
357+		switch (p[0]) {
358+		case ';':
359+			/* fall through */
360+		case '&':
361+			return true;
362+		default:
363+			break;
364+		}
365+
366+#define SURFACE_ATTR_ALPHA "alpha:"
367+		if (!strncmp(p, SURFACE_ATTR_ALPHA,
368+			     strlen(SURFACE_ATTR_ALPHA))) {
369+			double alpha = atof(p + strlen(SURFACE_ATTR_ALPHA));
370+
371+			weston_surface_set_alpha(wsurface, alpha);
372+		} else {
373+			weston_log("%s: warning: unsupported attr: %s\n",
374+				   __func__, p);
375+		}
376+
377+		p = strtok(NULL, "|");
378+	};
379+
380+	return true;
381+}
382+
383+static bool
384+weston_desktop_surface_handle_config(struct weston_desktop_surface *surface,
385+				     const char *s)
386+{
387+	char *tmp;
388+	bool handled = false;
389+
390+	tmp = strdup(s);
391+	if (tmp == NULL)
392+		return false;
393+
394+	handled |= weston_desktop_surface_set_flags(surface, tmp);
395+
396+	strcpy(tmp, s);
397+	handled |= weston_desktop_surface_set_requests(surface, tmp);
398+
399+	strcpy(tmp, s);
400+	handled |= weston_desktop_surface_set_attrs(surface, tmp);
401+
402+	free(tmp);
403+	return handled;
404+}
405+
406 void
407 weston_desktop_surface_set_title(struct weston_desktop_surface *surface,
408 				 const char *title)
409 {
410 	char *tmp, *old;
411
412+	if (weston_desktop_surface_handle_config(surface, title))
413+		return;
414+
415 	tmp = strdup(title);
416 	if (tmp == NULL)
417 		return;
418@@ -727,6 +917,9 @@ weston_desktop_surface_set_app_id(struct weston_desktop_surface *surface,
419 {
420 	char *tmp, *old;
421
422+	if (weston_desktop_surface_handle_config(surface, app_id))
423+		return;
424+
425 	tmp = strdup(app_id);
426 	if (tmp == NULL)
427 		return;
428--
4292.20.1
430
431