From c3531efba873d603001a050a52895ab80e53f4ef Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Thu, 7 May 2020 08:55:42 +0800 Subject: [PATCH 28/95] 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 | 58 ++++++++-- desktop-shell/shell.h | 2 + include/libweston/libweston.h | 14 +++ libweston/compositor.c | 10 +- libweston/desktop/surface.c | 195 ++++++++++++++++++++++++++++++++++ 5 files changed, 267 insertions(+), 12 deletions(-) diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c index e7dca8f..971f07c 100644 --- a/desktop-shell/shell.c +++ b/desktop-shell/shell.c @@ -1711,10 +1711,17 @@ static void shell_surface_update_layer(struct shell_surface *shsurf) { struct weston_layer_entry *new_layer_link; + struct weston_surface *surface = + weston_desktop_surface_get_surface(shsurf->desktop_surface); new_layer_link = shell_surface_calculate_layer_link(shsurf); assert(new_layer_link); + 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; + weston_view_move_to_layer(shsurf->view, new_layer_link); shell_surface_update_child_surface_layers(shsurf); } @@ -1914,8 +1921,9 @@ shell_set_view_fullscreen(struct shell_surface *shsurf) assert(weston_desktop_surface_get_fullscreen(shsurf->desktop_surface)); - weston_view_move_to_layer(shsurf->view, - &shsurf->shell->fullscreen_layer.view_list); + shsurf->state.lowered = false; + + shell_surface_update_layer(shsurf); weston_shell_utils_center_on_output(shsurf->view, shsurf->output); @@ -1923,12 +1931,11 @@ shell_set_view_fullscreen(struct shell_surface *shsurf) shsurf->fullscreen.black_view = weston_shell_utils_curtain_create(ec, &curtain_params); } + weston_view_set_output(shsurf->fullscreen.black_view->view, shsurf->fullscreen_output); weston_view_move_to_layer(shsurf->fullscreen.black_view->view, &shsurf->view->layer_link); - - shsurf->state.lowered = false; } static void @@ -2378,6 +2385,17 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface, return; } + if (surface->flags & SURFACE_ACTIVATE) { + struct weston_seat *seat; + + surface->flags &= ~SURFACE_ACTIVATE; + + wl_list_for_each(seat, &surface->compositor->seat_list,link) { + activate(shell, shsurf->view, seat, + WESTON_ACTIVATE_FLAG_CONFIGURE); + } + } + if (buf_offset.c.x == 0 && buf_offset.c.y == 0 && shsurf->last_width == surface->width && shsurf->last_height == surface->height && @@ -3105,6 +3123,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)); @@ -3614,10 +3636,8 @@ void lower_fullscreen_layer(struct desktop_shell *shell, struct weston_output *lowering_output) { - struct workspace *ws; struct weston_view *view, *prev; - ws = get_current_workspace(shell); wl_list_for_each_reverse_safe(view, prev, &shell->fullscreen_layer.view_list.link, layer_link.link) { @@ -3635,10 +3655,10 @@ lower_fullscreen_layer(struct desktop_shell *shell, if (shsurf->fullscreen.black_view) weston_view_move_to_layer(shsurf->fullscreen.black_view->view, NULL); - /* Lower the view to the workspace layer */ - weston_view_move_to_layer(view, &ws->layer.view_list); - shsurf->state.lowered = true; + + /* Lower the view to the workspace layer */ + shell_surface_update_layer(shsurf); } } @@ -3662,7 +3682,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); @@ -3682,6 +3702,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 && @@ -3704,6 +3727,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_set_view_fullscreen(shsurf); @@ -3712,7 +3736,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) { assert(shell->focus_animation_type == ANIMATION_DIM_LAYER); ws = get_current_workspace(shell); animate_focus_change(shell, ws, get_default_view(old_es), get_default_view(es)); @@ -3821,6 +3845,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); @@ -4598,6 +4624,8 @@ shell_for_each_layer(struct desktop_shell *shell, func(shell, &shell->lock_layer, data); func(shell, &shell->input_panel_layer, data); func(shell, &shell->workspace.layer, data); + func(shell, &shell->top_layer, data); + func(shell, &shell->bottom_layer, data); } static void @@ -4898,6 +4926,8 @@ shell_destroy(struct wl_listener *listener, void *data) workspace_destroy(&shell->workspace); + 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); @@ -5056,6 +5086,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); @@ -5063,6 +5095,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_list_init(&shell->seat_list); wl_list_init(&shell->shsurf_list); diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h index fc34eb4..055fe97 100644 --- a/desktop-shell/shell.h +++ b/desktop-shell/shell.h @@ -97,6 +97,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 e9e74ba..5342af8 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -1978,6 +1978,15 @@ 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, + SURFACE_ACTIVATE = 1 << 5, +}; + struct weston_surface { struct wl_resource *resource; struct wl_signal destroy_signal; /* callback argument: this surface */ @@ -2102,6 +2111,11 @@ struct weston_surface { * this list. */ struct wl_list cm_feedback_surface_resource_list; struct wl_resource *cm_surface; + + /* Hacky surface flags */ + enum weston_surface_flags flags; + + double alpha; }; struct weston_subsurface { diff --git a/libweston/compositor.c b/libweston/compositor.c index d888bb0..463e211 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -727,7 +727,7 @@ weston_view_create_internal(struct weston_surface *surface) pixman_region32_init(&view->visible); - view->alpha = 1.0; + view->alpha = surface->alpha; pixman_region32_init(&view->transform.opaque); wl_list_init(&view->geometry.transformation_list); @@ -1032,6 +1032,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); @@ -2660,6 +2662,12 @@ weston_compositor_pick_view(struct weston_compositor *compositor, if (!weston_view_takes_input_at_point(view, surf_pos)) continue; + if (view->surface->flags & SURFACE_BLOCKED) + break; + + if (view->surface->flags & SURFACE_TRANS_INPUT) + continue; + return view; } return NULL; diff --git a/libweston/desktop/surface.c b/libweston/desktop/surface.c index d365d95..2ab99ef 100644 --- a/libweston/desktop/surface.c +++ b/libweston/desktop/surface.c @@ -755,12 +755,204 @@ weston_desktop_surface_set_position(struct weston_desktop_surface *surface, weston_view_set_position(view->view, pos); } +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")) { + struct weston_coord_surface zero; + + wsurface->flags |= SURFACE_ACTIVATE; + + zero = weston_coord_surface(0, 0, wsurface); + weston_desktop_api_committed(surface->desktop, + surface, zero); + } 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; @@ -777,6 +969,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; -- 2.20.1