diff --git a/render.c b/render.c index 346b5351..c7d702b8 100644 --- a/render.c +++ b/render.c @@ -38,6 +38,10 @@ static struct { static void fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data); +#define shm_cookie_grid(term) ((unsigned long)((uintptr_t)term + 0)) +#define shm_cookie_search(term) ((unsigned long)((uintptr_t)term + 1)) +#define shm_cookie_csd(term, n) ((unsigned long)((uintptr_t)term + 2 + (n))) + struct renderer * render_init(struct fdm *fdm, struct wayland *wayl) { @@ -655,6 +659,45 @@ render_worker_thread(void *_ctx) return -1; } +static void +render_csd(struct terminal *term) +{ + LOG_INFO("rendering CSD"); + + const int border_width = 2 * term->scale; + const int title_height = 20 * term->scale; + + const int geom[5][4] = { + {-border_width, -title_height, term->width + 2 * border_width, title_height}, + }; + + for (size_t i = 0; i < 1; i++) { + const int x = geom[i][0]; + const int y = geom[i][1]; + const int width = geom[i][2]; + const int height = geom[i][3]; + + unsigned long cookie = shm_cookie_csd(term, 0); + struct buffer *buf = shm_get_buffer(term->wl->shm, width, height, cookie); + + pixman_color_t color = color_hex_to_pixman(0xffffff); + pixman_image_t *src = pixman_image_create_solid_fill(&color); + + pixman_image_fill_rectangles( + PIXMAN_OP_SRC, buf->pix, &color, 1, + &(pixman_rectangle16_t){0, 0, buf->width, buf->height}); + pixman_image_unref(src); + + wl_subsurface_set_position( + term->window->csd.sub_surface[i], x, y); + + wl_surface_attach(term->window->csd.surface[i], buf->wl_buf, 0, 0); + wl_surface_damage_buffer(term->window->csd.surface[i], 0, 0, buf->width, buf->height); + wl_surface_set_buffer_scale(term->window->csd.surface[i], term->scale); + wl_surface_commit(term->window->csd.surface[i]); + } +} + static void frame_callback( void *data, struct wl_callback *wl_callback, uint32_t callback_data); @@ -675,10 +718,13 @@ grid_render(struct terminal *term) gettimeofday(&start_time, NULL); #endif + if (term->window->use_csd) + render_csd(term); + assert(term->width > 0); assert(term->height > 0); - unsigned long cookie = (uintptr_t)term; + unsigned long cookie = shm_cookie_grid(term); struct buffer *buf = shm_get_buffer( term->wl->shm, term->width, term->height, cookie); @@ -990,7 +1036,7 @@ render_search_box(struct terminal *term) const size_t visible_chars = (width - 2 * margin) / term->cell_width; size_t glyph_offset = term->render.search_glyph_offset; - unsigned long cookie = (uintptr_t)term + 1; + unsigned long cookie = shm_cookie_search(term); struct buffer *buf = shm_get_buffer(term->wl->shm, width, height, cookie); /* Background - yellow on empty/match, red on mismatch */ diff --git a/wayland.c b/wayland.c index 67757679..478d87b4 100644 --- a/wayland.c +++ b/wayland.c @@ -20,7 +20,7 @@ #include #define LOG_MODULE "wayland" -#define LOG_ENABLE_DBG 0 +#define LOG_ENABLE_DBG 1 #include "log.h" #include "config.h" @@ -537,13 +537,17 @@ xdg_toplevel_decoration_configure(void *data, struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1, uint32_t mode) { + struct wl_window *win = data; + switch (mode) { case ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE: - LOG_ERR("unimplemented: client-side decorations"); + LOG_DBG("using client-side decorations"); + win->use_csd = true; break; case ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE: LOG_DBG("using server-side decorations"); + win->use_csd = false; break; default: @@ -918,6 +922,12 @@ wayl_win_init(struct terminal *term) zxdg_toplevel_decoration_v1_add_listener( win->xdg_toplevel_decoration, &xdg_toplevel_decoration_listener, win); + for (size_t i = 0; i < 5; i++) { + win->csd.surface[i] = wl_compositor_create_surface(wayl->compositor); + win->csd.sub_surface[i] = wl_subcompositor_get_subsurface( + wayl->sub_compositor, win->csd.surface[i], win->surface); + } + /* Scrollback search box */ win->search_surface = wl_compositor_create_surface(wayl->compositor); win->search_sub_surface = wl_subcompositor_get_subsurface( @@ -951,14 +961,29 @@ wayl_win_destroy(struct wl_window *win) /* Scrollback search */ wl_surface_attach(win->search_surface, NULL, 0, 0); wl_surface_commit(win->search_surface); + + /* CSD */ + for (size_t i = 0; i < 5; i++) { + wl_surface_attach(win->csd.surface[i], NULL, 0, 0); + wl_surface_commit(win->csd.surface[i]); + } + wayl_roundtrip(win->term->wl); - /* Main window */ + /* Main window */ wl_surface_attach(win->surface, NULL, 0, 0); wl_surface_commit(win->surface); wayl_roundtrip(win->term->wl); tll_free(win->on_outputs); + + for (size_t i = 0; i < 5; i++) { + if (win->csd.sub_surface[i] != NULL) + wl_subsurface_destroy(win->csd.sub_surface[i]); + if (win->csd.surface[i] != NULL) + wl_surface_destroy(win->csd.surface[i]); + } + if (win->search_sub_surface != NULL) wl_subsurface_destroy(win->search_sub_surface); if (win->search_surface != NULL) diff --git a/wayland.h b/wayland.h index 83a84273..7de13850 100644 --- a/wayland.h +++ b/wayland.h @@ -91,6 +91,13 @@ struct wl_window { struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration; + bool use_csd; + + struct { + struct wl_surface *surface[5]; + struct wl_subsurface *sub_surface[5]; + } csd; + /* Scrollback search */ struct wl_surface *search_surface; struct wl_subsurface *search_sub_surface;