From 039ea8b5e8a647ab67ae23e25570362d207326a2 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Thu, 7 May 2020 08:55:42 +0800 Subject: [PATCH 20/74] HACK: Support setting surface flags activate and alpha Support setting surface flags activate and alpha through app_id or title, for example: xdg_toplevel_set_app_id("flags=stay-on-top|stay-on-bottom|no-focus") xdg_toplevel_set_title("requests=activate") xdg_toplevel_set_app_id("attrs=alpha:0.5") Signed-off-by: Jeffy Chen --- desktop-shell/shell.c | 29 ++++- desktop-shell/shell.h | 2 + include/libweston/libweston.h | 13 +++ libweston-desktop/surface.c | 193 ++++++++++++++++++++++++++++++++++ libweston/compositor.c | 10 +- 5 files changed, 244 insertions(+), 3 deletions(-) diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c index e5c2f0c..aedb1e9 100644 --- a/desktop-shell/shell.c +++ b/desktop-shell/shell.c @@ -1895,6 +1895,11 @@ shell_surface_update_layer(struct shell_surface *shsurf) new_layer_link = shell_surface_calculate_layer_link(shsurf); + if (surface->flags & SURFACE_STAY_ON_TOP) + new_layer_link = &shsurf->shell->top_layer.view_list; + else if (surface->flags & SURFACE_STAY_ON_BOTTOM) + new_layer_link = &shsurf->shell->bottom_layer.view_list; + if (new_layer_link == NULL) return; if (new_layer_link == &shsurf->view->layer_link) @@ -3220,6 +3225,10 @@ resume_desktop(struct desktop_shell *shell) weston_layer_set_position(&shell->panel_layer, WESTON_LAYER_POSITION_UI); weston_layer_set_position(&ws->layer, WESTON_LAYER_POSITION_NORMAL); + weston_layer_set_position(&shell->top_layer, + WESTON_LAYER_POSITION_TOP_UI); + weston_layer_set_position(&shell->bottom_layer, + WESTON_LAYER_POSITION_BOTTOM_UI); restore_focus_state(shell, get_current_workspace(shell)); @@ -3781,7 +3790,7 @@ activate(struct desktop_shell *shell, struct weston_view *view, struct weston_surface *main_surface; struct focus_state *state; struct workspace *ws; - struct weston_surface *old_es; + struct weston_surface *old_es = NULL; struct shell_surface *shsurf, *shsurf_child; struct shell_seat *shseat = get_shell_seat(seat); @@ -3801,6 +3810,9 @@ activate(struct desktop_shell *shell, struct weston_view *view, if (shsurf->output) lower_fullscreen_layer(shell, shsurf->output); + if (view->surface->flags & SURFACE_NO_FOCUS) + goto no_focus; + weston_view_activate_input(view, seat, flags); if (shseat && shseat->focused_surface) { @@ -3821,6 +3833,7 @@ activate(struct desktop_shell *shell, struct weston_view *view, old_es = state->keyboard_focus; focus_state_set_focus(state, es); +no_focus: if (weston_desktop_surface_get_fullscreen(shsurf->desktop_surface) && flags & WESTON_ACTIVATE_FLAG_CONFIGURE) shell_configure_fullscreen(shsurf); @@ -3829,7 +3842,7 @@ activate(struct desktop_shell *shell, struct weston_view *view, * order as appropriate. */ shell_surface_update_layer(shsurf); - if (shell->focus_animation_type != ANIMATION_NONE) { + if (old_es && shell->focus_animation_type != ANIMATION_NONE) { ws = get_current_workspace(shell); animate_focus_change(shell, ws, get_default_view(old_es), get_default_view(es)); } @@ -3942,6 +3955,8 @@ lock(struct desktop_shell *shell) if (shell->showing_input_panels) weston_layer_unset_position(&shell->input_panel_layer); weston_layer_unset_position(&ws->layer); + weston_layer_unset_position(&shell->top_layer); + weston_layer_unset_position(&shell->bottom_layer); weston_layer_set_position(&shell->lock_layer, WESTON_LAYER_POSITION_LOCK); @@ -4822,6 +4837,8 @@ shell_for_each_layer(struct desktop_shell *shell, func(shell, &shell->background_layer, data); func(shell, &shell->lock_layer, data); func(shell, &shell->input_panel_layer, data); + func(shell, &shell->top_layer, data); + func(shell, &shell->bottom_layer, data); wl_array_for_each(ws, &shell->workspaces.array) func(shell, &(*ws)->layer, data); @@ -5115,6 +5132,8 @@ shell_destroy(struct wl_listener *listener, void *data) workspace_destroy(*ws); wl_array_release(&shell->workspaces.array); + desktop_shell_destroy_layer(&shell->bottom_layer); + desktop_shell_destroy_layer(&shell->top_layer); desktop_shell_destroy_layer(&shell->panel_layer); desktop_shell_destroy_layer(&shell->background_layer); desktop_shell_destroy_layer(&shell->lock_layer); @@ -5270,6 +5289,8 @@ wet_shell_init(struct weston_compositor *ec, weston_layer_init(&shell->background_layer, ec); weston_layer_init(&shell->lock_layer, ec); weston_layer_init(&shell->input_panel_layer, ec); + weston_layer_init(&shell->top_layer, ec); + weston_layer_init(&shell->bottom_layer, ec); weston_layer_set_position(&shell->fullscreen_layer, WESTON_LAYER_POSITION_FULLSCREEN); @@ -5277,6 +5298,10 @@ wet_shell_init(struct weston_compositor *ec, WESTON_LAYER_POSITION_UI); weston_layer_set_position(&shell->background_layer, WESTON_LAYER_POSITION_BACKGROUND); + weston_layer_set_position(&shell->top_layer, + WESTON_LAYER_POSITION_TOP_UI); + weston_layer_set_position(&shell->bottom_layer, + WESTON_LAYER_POSITION_BOTTOM_UI); wl_array_init(&shell->workspaces.array); wl_list_init(&shell->workspaces.client_list); diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h index b06b906..e0a0620 100644 --- a/desktop-shell/shell.h +++ b/desktop-shell/shell.h @@ -148,6 +148,8 @@ struct desktop_shell { struct weston_layer background_layer; struct weston_layer lock_layer; struct weston_layer input_panel_layer; + struct weston_layer top_layer; + struct weston_layer bottom_layer; struct wl_listener pointer_focus_listener; struct weston_surface *grab_surface; diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index 24e44a2..7bc01e3 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -1469,6 +1469,14 @@ struct weston_pointer_constraint { struct wl_listener surface_activate_listener; }; +enum weston_surface_flags { + SURFACE_NO_FOCUS = 1 << 0, + SURFACE_STAY_ON_TOP = 1 << 1, + SURFACE_STAY_ON_BOTTOM = 1 << 2, + SURFACE_BLOCKED = 1 << 3, + SURFACE_TRANS_INPUT = 1 << 4, +}; + struct weston_surface { struct wl_resource *resource; struct wl_signal destroy_signal; /* callback argument: this surface */ @@ -1575,6 +1583,11 @@ struct weston_surface { /* Transparent hole region(excluding it's lower subsurface area) */ pixman_region32_t hole; + + /* Hacky surface flags */ + enum weston_surface_flags flags; + + double alpha; }; struct weston_subsurface { diff --git a/libweston-desktop/surface.c b/libweston-desktop/surface.c index 21ff080..e86ef52 100644 --- a/libweston-desktop/surface.c +++ b/libweston-desktop/surface.c @@ -695,12 +695,202 @@ weston_desktop_surface_set_position(struct weston_desktop_surface *surface, weston_view_set_position(view->view, x, y); } +static bool +weston_desktop_surface_set_flags(struct weston_desktop_surface *surface, + char *s) +{ + struct weston_surface *wsurface = surface->surface; + char *p; + +#define SURFACE_FLAG_PREFIX "flags=" + s = strstr(s, SURFACE_FLAG_PREFIX); + if (!s) + return false; + + s += strlen(SURFACE_FLAG_PREFIX); + + p = strtok(s, "|"); + while (p) { + enum weston_surface_flags flag = 0; + bool clear = false; + + switch (p[0]) { + case ';': + /* fall through */ + case '&': + return true; + case '-': + clear = true; + /* fall through */ + case '+': + p++; + default: + break; + } + + if (!strcmp(p, "no-focus")) + flag = SURFACE_NO_FOCUS; + else if (!strcmp(p, "stay-on-top")) + flag = SURFACE_STAY_ON_TOP; + else if (!strcmp(p, "stay-on-bottom")) + flag = SURFACE_STAY_ON_BOTTOM; + else if (!strcmp(p, "blocked")) + flag = SURFACE_BLOCKED; + else if (!strcmp(p, "trans-input")) + flag = SURFACE_TRANS_INPUT; + else + weston_log("%s: warning: unsupported flag: %s\n", + __func__, p); + + if (clear) + wsurface->flags &= ~flag; + else + wsurface->flags |= flag; + + p = strtok(NULL, "|"); + }; + + return true; +} + +static bool +weston_desktop_surface_set_requests(struct weston_desktop_surface *surface, + char *s) +{ + struct weston_surface *wsurface = surface->surface; + char *p; + +#define SURFACE_REQUEST_PREFIX "requests=" + s = strstr(s, SURFACE_REQUEST_PREFIX); + if (!s) + return false; + + s += strlen(SURFACE_REQUEST_PREFIX); + + p = strtok(s, "|"); + while (p) { + switch (p[0]) { + case ';': + /* fall through */ + case '&': + return true; + default: + break; + } + + if (!strcmp(p, "activate")) { + if (weston_surface_is_mapped(wsurface)) + weston_surface_unmap(wsurface); + + weston_desktop_api_committed(surface->desktop, + surface, 0, 0); + } else { + weston_log("%s: warning: unsupported request: %s\n", + __func__, p); + } + + p = strtok(NULL, "|"); + }; + + return true; +} + +static void +weston_surface_set_alpha(struct weston_surface *wsurface, float alpha) +{ + struct weston_subsurface *sub; + struct weston_view *view; + + wsurface->alpha = alpha; + wsurface->is_opaque = !(alpha < 1.0); + + wl_list_for_each(view, &wsurface->views, + surface_link) { + view->alpha = alpha; + weston_view_geometry_dirty(view); + } + + wl_list_for_each(sub, &wsurface->subsurface_list, + parent_link) { + if (sub->surface != wsurface) + weston_surface_set_alpha(sub->surface, alpha); + } +} + +static bool +weston_desktop_surface_set_attrs(struct weston_desktop_surface *surface, + char *s) +{ + struct weston_surface *wsurface = surface->surface; + char *p; + +#define SURFACE_ATTRS_PREFIX "attrs=" + s = strstr(s, SURFACE_ATTRS_PREFIX); + if (!s) + return false; + + s += strlen(SURFACE_ATTRS_PREFIX); + + p = strtok(s, "|"); + while (p) { + switch (p[0]) { + case ';': + /* fall through */ + case '&': + return true; + default: + break; + } + +#define SURFACE_ATTR_ALPHA "alpha:" + if (!strncmp(p, SURFACE_ATTR_ALPHA, + strlen(SURFACE_ATTR_ALPHA))) { + double alpha = atof(p + strlen(SURFACE_ATTR_ALPHA)); + + weston_surface_set_alpha(wsurface, alpha); + } else { + weston_log("%s: warning: unsupported attr: %s\n", + __func__, p); + } + + p = strtok(NULL, "|"); + }; + + return true; +} + +static bool +weston_desktop_surface_handle_config(struct weston_desktop_surface *surface, + const char *s) +{ + char *tmp; + bool handled = false; + + tmp = strdup(s); + if (tmp == NULL) + return false; + + handled |= weston_desktop_surface_set_flags(surface, tmp); + + strcpy(tmp, s); + handled |= weston_desktop_surface_set_requests(surface, tmp); + + strcpy(tmp, s); + handled |= weston_desktop_surface_set_attrs(surface, tmp); + + free(tmp); + return handled; +} + void weston_desktop_surface_set_title(struct weston_desktop_surface *surface, const char *title) { char *tmp, *old; + if (weston_desktop_surface_handle_config(surface, title)) + return; + tmp = strdup(title); if (tmp == NULL) return; @@ -717,6 +907,9 @@ weston_desktop_surface_set_app_id(struct weston_desktop_surface *surface, { char *tmp, *old; + if (weston_desktop_surface_handle_config(surface, app_id)) + return; + tmp = strdup(app_id); if (tmp == NULL) return; diff --git a/libweston/compositor.c b/libweston/compositor.c index 0aa9d1a..b959424 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -412,7 +412,7 @@ weston_view_create(struct weston_surface *surface) pixman_region32_init(&view->clip); - view->alpha = 1.0; + view->alpha = surface->alpha; pixman_region32_init(&view->transform.opaque); wl_list_init(&view->geometry.transformation_list); @@ -608,6 +608,8 @@ weston_surface_create(struct weston_compositor *compositor) surface->compositor = compositor; surface->ref_count = 1; + surface->alpha = 1.0; + surface->buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL; surface->buffer_viewport.buffer.scale = 1; surface->buffer_viewport.buffer.src_width = wl_fixed_from_int(-1); @@ -2217,6 +2219,12 @@ weston_compositor_pick_view(struct weston_compositor *compositor, view_ix, view_iy, NULL)) continue; + if (view->surface->flags & SURFACE_BLOCKED) + break; + + if (view->surface->flags & SURFACE_TRANS_INPUT) + continue; + *vx = view_x; *vy = view_y; return view; -- 2.20.1