From 02ee1efdb45924ee76dca5b689929bd99ea569dd Mon Sep 17 00:00:00 2001 From: Nikita Tokarchuk Date: Fri, 19 Jul 2024 15:48:36 +0200 Subject: [PATCH] backport wl shell to 11 --- libweston/backend-wayland/wayland.c | 183 ++++++++++++++++++++-------- 1 file changed, 133 insertions(+), 50 deletions(-) diff --git a/libweston/backend-wayland/wayland.c b/libweston/backend-wayland/wayland.c index bb5648d5..9f13259a 100644 --- a/libweston/backend-wayland/wayland.c +++ b/libweston/backend-wayland/wayland.c @@ -76,6 +76,7 @@ struct wayland_backend { struct wl_display *wl_display; struct wl_registry *registry; struct wl_compositor *compositor; + struct wl_shell *shell; struct xdg_wm_base *xdg_wm_base; struct zwp_fullscreen_shell_v1 *fshell; struct wl_shm *shm; @@ -111,6 +112,7 @@ struct wayland_output { struct wl_output *output; uint32_t global_id; + struct wl_shell_surface *shell_surface; struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; int configure_width, configure_height; @@ -250,6 +252,7 @@ to_wayland_output(struct weston_output *base) { if (base->destroy != wayland_output_destroy) return NULL; + return container_of(base, struct wayland_output, base); } @@ -387,7 +390,6 @@ wayland_output_get_shm_buffer(struct wayland_output *output) area.height = output->base.current_mode->height; } - /* Address only the interior, excluding output decorations */ sb->pm_image = pixman_image_create_bits(PIXMAN_a8r8g8b8, area.width, area.height, (uint32_t *)(data + area.y * stride) + area.x, @@ -715,6 +717,11 @@ wayland_backend_destroy_output_surface(struct wayland_output *output) output->parent.xdg_surface = NULL; } + if (output->parent.shell_surface) { + wl_shell_surface_destroy(output->parent.shell_surface); + output->parent.shell_surface = NULL; + } + wl_surface_destroy(output->parent.surface); output->parent.surface = NULL; } @@ -736,11 +743,7 @@ static int wayland_output_disable(struct weston_output *base) { struct wayland_output *output = to_wayland_output(base); - struct wayland_backend *b; - - assert(output); - - b = to_wayland_backend(base->compositor); + struct wayland_backend *b = to_wayland_backend(base->compositor); if (!output->base.enabled) return 0; @@ -774,8 +777,6 @@ wayland_output_destroy(struct weston_output *base) { struct wayland_output *output = to_wayland_output(base); - assert(output); - wayland_output_disable(&output->base); weston_output_release(&output->base); @@ -787,6 +788,8 @@ wayland_output_destroy(struct weston_output *base) free(output); } +static const struct wl_shell_surface_listener shell_surface_listener; + #ifdef ENABLE_EGL static int wayland_output_init_gl_renderer(struct wayland_output *output) @@ -838,54 +841,64 @@ wayland_output_init_pixman_renderer(struct wayland_output *output) static void wayland_output_resize_surface(struct wayland_output *output) { - struct wayland_backend *b = to_wayland_backend(output->base.compositor); - /* Defaults for without frame: */ - struct weston_size fb_size = { - .width = output->base.current_mode->width, - .height = output->base.current_mode->height - }; - struct weston_geometry area = { - .x = 0, - .y = 0, - .width = fb_size.width, - .height = fb_size.height - }; - struct weston_geometry inp = area; - struct weston_geometry opa = area; + struct wayland_backend *b = + to_wayland_backend(output->base.compositor); + int32_t ix, iy, iwidth, iheight; + int32_t width, height; struct wl_region *region; - if (output->frame) { - frame_resize_inside(output->frame, area.width, area.height); - frame_interior(output->frame, &area.x, &area.y, NULL, NULL); - fb_size.width = frame_width(output->frame); - fb_size.height = frame_height(output->frame); + width = output->base.current_mode->width; + height = output->base.current_mode->height; - frame_input_rect(output->frame, &inp.x, &inp.y, - &inp.width, &inp.height); - frame_opaque_rect(output->frame, &opa.x, &opa.y, - &opa.width, &opa.height); - } + if (output->frame) { + frame_resize_inside(output->frame, width, height); + + frame_input_rect(output->frame, &ix, &iy, &iwidth, &iheight); + region = wl_compositor_create_region(b->parent.compositor); + wl_region_add(region, ix, iy, iwidth, iheight); + wl_surface_set_input_region(output->parent.surface, region); + wl_region_destroy(region); + + if (output->parent.xdg_surface) { + xdg_surface_set_window_geometry(output->parent.xdg_surface, + ix, + iy, + iwidth, + iheight); + } - region = wl_compositor_create_region(b->parent.compositor); - wl_region_add(region, inp.x, inp.y, inp.width, inp.height); - wl_surface_set_input_region(output->parent.surface, region); - wl_region_destroy(region); + frame_opaque_rect(output->frame, &ix, &iy, &iwidth, &iheight); + region = wl_compositor_create_region(b->parent.compositor); + wl_region_add(region, ix, iy, iwidth, iheight); + wl_surface_set_opaque_region(output->parent.surface, region); + wl_region_destroy(region); - if (output->parent.xdg_surface) { - xdg_surface_set_window_geometry(output->parent.xdg_surface, - inp.x, inp.y, - inp.width, inp.height); + width = frame_width(output->frame); + height = frame_height(output->frame); + } else { + region = wl_compositor_create_region(b->parent.compositor); + wl_region_add(region, 0, 0, width, height); + wl_surface_set_input_region(output->parent.surface, region); + wl_region_destroy(region); + + region = wl_compositor_create_region(b->parent.compositor); + wl_region_add(region, 0, 0, width, height); + wl_surface_set_opaque_region(output->parent.surface, region); + wl_region_destroy(region); + + if (output->parent.xdg_surface) { + xdg_surface_set_window_geometry(output->parent.xdg_surface, + 0, + 0, + width, + height); + } } - region = wl_compositor_create_region(b->parent.compositor); - wl_region_add(region, opa.x, opa.y, opa.width, opa.height); - wl_surface_set_opaque_region(output->parent.surface, region); - wl_region_destroy(region); - #ifdef ENABLE_EGL if (output->gl.egl_window) { wl_egl_window_resize(output->gl.egl_window, - fb_size.width, fb_size.height, 0, 0); + width, height, 0, 0); /* These will need to be re-created due to the resize */ gl_renderer->output_set_border(&output->base, @@ -940,6 +953,8 @@ wayland_output_set_windowed(struct wayland_output *output) if (output->parent.xdg_toplevel) { xdg_toplevel_unset_fullscreen(output->parent.xdg_toplevel); + } else if (output->parent.shell_surface) { + wl_shell_surface_set_toplevel(output->parent.shell_surface); } else { abort(); } @@ -949,6 +964,7 @@ wayland_output_set_windowed(struct wayland_output *output) static void wayland_output_set_fullscreen(struct wayland_output *output, + enum wl_shell_surface_fullscreen_method method, uint32_t framerate, struct wl_output *target) { if (output->frame) { @@ -960,6 +976,9 @@ wayland_output_set_fullscreen(struct wayland_output *output, if (output->parent.xdg_toplevel) { xdg_toplevel_set_fullscreen(output->parent.xdg_toplevel, target); + } else if (output->parent.shell_surface) { + wl_shell_surface_set_fullscreen(output->parent.shell_surface, + method, framerate, target); } else { abort(); } @@ -1089,7 +1108,7 @@ wayland_output_switch_mode(struct weston_output *output_base, b = to_wayland_backend(output_base->compositor); - if (output->parent.xdg_surface || !b->parent.fshell) + if (output->parent.xdg_surface || output->parent.shell_surface || !b->parent.fshell) return -1; mode = wayland_output_choose_mode(output, mode); @@ -1230,6 +1249,20 @@ wayland_backend_create_output_surface(struct wayland_output *output) weston_log("wayland-backend: Using xdg_wm_base\n"); } + else if (b->parent.shell) { + output->parent.shell_surface = + wl_shell_get_shell_surface(b->parent.shell, + output->parent.surface); + if (!output->parent.shell_surface) { + wl_surface_destroy(output->parent.surface); + return -1; + } + + wl_shell_surface_add_listener(output->parent.shell_surface, + &shell_surface_listener, output); + + weston_log("wayland-backend: Using wl_shell\n"); + } return 0; } @@ -1294,9 +1327,13 @@ wayland_output_enable(struct weston_output *base) output->parent.draw_initial_frame = true; } + } else { + wayland_output_set_fullscreen(output, + WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER, + output->mode.refresh, output->parent.output); } } else if (b->fullscreen) { - wayland_output_set_fullscreen(output, 0, NULL); + wayland_output_set_fullscreen(output, 0, 0, NULL); } else { wayland_output_set_windowed(output); } @@ -1578,10 +1615,13 @@ wayland_output_setup_fullscreen(struct wayland_output *output, return -1; /* What should size be set if conditional is false? */ - if (b->parent.xdg_wm_base) { + if (b->parent.xdg_wm_base || b->parent.shell) { if (output->parent.xdg_toplevel) xdg_toplevel_set_fullscreen(output->parent.xdg_toplevel, output->parent.output); + else if (output->parent.shell_surface) + wl_shell_surface_set_fullscreen(output->parent.shell_surface, + 0, 0, NULL); wl_display_roundtrip(b->parent.wl_display); @@ -1605,6 +1645,36 @@ err_set_size: return -1; } +static void +shell_surface_ping(void *data, struct wl_shell_surface *shell_surface, + uint32_t serial) +{ + wl_shell_surface_pong(shell_surface, serial); +} + +static void +shell_surface_configure(void *data, struct wl_shell_surface *shell_surface, + uint32_t edges, int32_t width, int32_t height) +{ + struct wayland_output *output = data; + + output->parent.configure_width = width; + output->parent.configure_height = height; + + /* FIXME: implement resizing */ +} + +static void +shell_surface_popup_done(void *data, struct wl_shell_surface *shell_surface) +{ +} + +static const struct wl_shell_surface_listener shell_surface_listener = { + shell_surface_ping, + shell_surface_configure, + shell_surface_popup_done +}; + /* Events received from the wayland-server this compositor is client of: */ /* parent input interface */ @@ -1782,6 +1852,9 @@ input_handle_button(void *data, struct wl_pointer *pointer, if (input->output->parent.xdg_toplevel) xdg_toplevel_move(input->output->parent.xdg_toplevel, input->parent.seat, serial); + else if (input->output->parent.shell_surface) + wl_shell_surface_move(input->output->parent.shell_surface, + input->parent.seat, serial); frame_status_clear(input->output->frame, FRAME_STATUS_MOVE); return; @@ -2135,6 +2208,9 @@ input_handle_touch_down(void *data, struct wl_touch *wl_touch, if (output->parent.xdg_toplevel) xdg_toplevel_move(output->parent.xdg_toplevel, input->parent.seat, serial); + else if (output->parent.shell_surface) + wl_shell_surface_move(output->parent.shell_surface, + input->parent.seat, serial); frame_status_clear(output->frame, FRAME_STATUS_MOVE); return; @@ -2647,6 +2723,10 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, &xdg_wm_base_interface, 1); xdg_wm_base_add_listener(b->parent.xdg_wm_base, &wm_base_listener, b); + } else if (strcmp(interface, "wl_shell") == 0) { + b->parent.shell = + wl_registry_bind(registry, name, + &wl_shell_interface, 1); } else if (strcmp(interface, "zwp_fullscreen_shell_v1") == 0) { b->parent.fshell = wl_registry_bind(registry, name, @@ -2741,6 +2821,9 @@ wayland_destroy(struct weston_compositor *ec) if (b->parent.xdg_wm_base) xdg_wm_base_destroy(b->parent.xdg_wm_base); + if (b->parent.shell) + wl_shell_destroy(b->parent.shell); + if (b->parent.fshell) zwp_fullscreen_shell_v1_release(b->parent.fshell); @@ -2808,7 +2891,7 @@ fullscreen_binding(struct weston_keyboard *keyboard, return; if (input->output->frame) - wayland_output_set_fullscreen(input->output, 0, NULL); + wayland_output_set_fullscreen(input->output, 0, 0, NULL); else wayland_output_set_windowed(input->output);