diff --git a/digesting_libdecor.c b/digesting_libdecor.c index 277f990..707f55b 100755 --- a/digesting_libdecor.c +++ b/digesting_libdecor.c @@ -560,34 +560,33 @@ const struct wl_registry_listener wl_registry_listener = { static void xdg_surface_configure(void *user_data, struct xdg_surface *xdg_surface, uint32_t serial){ - struct libdecor_configuration *configuration = ctx.pending_configuration; - ctx.pending_configuration = 0; - if (configuration == 0){ - configuration = calloc(1, sizeof *configuration); + struct libdecor_configuration config = {0}; + if (ctx.has_pending_config){ + ctx.has_pending_config = 0; + config = ctx.pending_config; } - - configuration->serial = serial; + config.serial = serial; { int w = ctx.w; int h = ctx.h; bool got_size = false; - if (configuration->initialized && - configuration->window_width != 0 && - configuration->window_height != 0){ + if (config.initialized && + config.window_width != 0 && + config.window_height != 0){ - w = configuration->window_width; - h = configuration->window_height; + w = config.window_width; + h = config.window_height; if (ctx.visible && ctx.decoration_mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE){ - ctx.frame_window_state = configuration->window_state; - Sides2D border_size = border_size_from_window_state(configuration->window_state); + ctx.frame_window_state = config.window_state; + Sides2D border_size = border_size_from_window_state(config.window_state); w -= border_size.x[0] + border_size.x[1]; h -= border_size.y[0] + border_size.y[1]; } - if (!(configuration->window_state & LIBDECOR_WINDOW_STATE_NON_FLOATING)){ + if (!(config.window_state & LIBDECOR_WINDOW_STATE_NON_FLOATING)){ if (ctx.size_bounds.x[0] > 0){ w = MAX(ctx.size_bounds.x[0], w); } @@ -606,21 +605,9 @@ xdg_surface_configure(void *user_data, struct xdg_surface *xdg_surface, uint32_t ctx.h = h; } - if (!ctx.configured){ - ctx.configured = 1; - if (configuration->initialized){ - ctx.frame_window_state = configuration->window_state; - } - libdecor_frame_commit(w, h); - xdg_surface_ack_configure(ctx.xdg_surface, configuration->serial); - } - else{ - ctx.has_cached_config = 1; - ctx.cached_config = *configuration; - } + ctx.has_cached_config = 1; + ctx.cached_config = config; } - - free(configuration); } const struct xdg_surface_listener xdg_surface_listener = { @@ -657,11 +644,11 @@ xdg_toplevel_configure(void *user_data, struct xdg_toplevel *xdg_toplevel, } } - ctx.pending_configuration = calloc(1, sizeof *ctx.pending_configuration); - ctx.pending_configuration->initialized = true; - ctx.pending_configuration->window_width = width; - ctx.pending_configuration->window_height = height; - ctx.pending_configuration->window_state = window_state; + ctx.has_pending_config = true; + ctx.pending_config.initialized = true; + ctx.pending_config.window_width = width; + ctx.pending_config.window_height = height; + ctx.pending_config.window_state = window_state; } static void @@ -1095,7 +1082,9 @@ int main(){ if (ctx.cached_config.initialized){ ctx.frame_window_state = ctx.cached_config.window_state; } - libdecor_frame_commit(ctx.w, ctx.h); + ctx.frame_content_width = ctx.w; + ctx.frame_content_height = ctx.h; + libdecor_frame_commit(); xdg_surface_ack_configure(ctx.xdg_surface, ctx.cached_config.serial); } @@ -1202,78 +1191,6 @@ free_border_component(struct border_component *border_component){ border_component->height = 0; } -void -update_client_side_rendering_state(void){ - if (ctx.visible && ctx.decoration_mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE){ - enum libdecor_window_state old_window_state; - enum libdecor_window_state new_window_state; - int old_content_width, old_content_height; - int new_content_width, new_content_height; - enum decoration_type old_decoration_type; - enum decoration_type new_decoration_type; - - old_window_state = ctx.gtk_window_state; - new_window_state = ctx.frame_window_state; - - old_content_width = ctx.gtk_content_width; - old_content_height = ctx.gtk_content_height; - new_content_width = ctx.frame_content_width; - new_content_height = ctx.frame_content_height; - - old_decoration_type = ctx.decoration_type; - new_decoration_type = decoration_type_from_window_state(new_window_state); - - if (old_decoration_type != new_decoration_type || - old_content_width != new_content_width || - old_content_height != new_content_height || - old_window_state != new_window_state){ - - ctx.gtk_content_width = new_content_width; - ctx.gtk_content_height = new_content_height; - ctx.gtk_window_state = new_window_state; - ctx.decoration_type = new_decoration_type; - - draw_decoration(); - - /* set fixed window size */ - if (!(ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ - ctx.size_bounds.x[0] = ctx.gtk_content_width; - ctx.size_bounds.y[0] = ctx.gtk_content_height; - ctx.size_bounds.x[1] = ctx.gtk_content_width; - ctx.size_bounds.y[1] = ctx.gtk_content_height; - } - } - } - else{ - g_clear_pointer(&ctx.header, gtk_widget_destroy); - g_clear_pointer(&ctx.window, gtk_widget_destroy); - - free_border_component(&ctx.component_slot[COMPONENT_SLOT_HEADER]); - free_border_component(&ctx.component_slot[COMPONENT_SLOT_SHADOW]); - ctx.shadow_showing = false; - - g_clear_pointer(&ctx.title, free); - - ctx.decoration_type = DECORATION_TYPE_NONE; - } - - { - Extent2D extent = {0}; - extent.w = ctx.frame_content_width; - extent.h = ctx.frame_content_height; - - if (ctx.visible && ctx.decoration_mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE){ - Sides2D border_size = border_size_from_window_state(ctx.frame_window_state); - extent.x = -border_size.x[0]; - extent.y = -border_size.y[0]; - extent.w += border_size.x[0] + border_size.x[1]; - extent.h += border_size.y[0] + border_size.y[1]; - } - - xdg_surface_set_window_geometry(ctx.xdg_surface, extent.x, extent.y, extent.w, extent.h); - } -} - static enum xdg_toplevel_resize_edge xdg_edge_from_edge(enum libdecor_resize_edge edge){ enum xdg_toplevel_resize_edge result = XDG_TOPLEVEL_RESIZE_EDGE_NONE; @@ -1302,36 +1219,35 @@ libdecor_frame_unset_fullscreen(void){ } void -libdecor_frame_commit(int w, int h){ +libdecor_frame_commit(void){ Sides2D border_size = border_size_from_window_state(ctx.frame_window_state); - int border_added_w = 0; - int border_added_h = 0; - if (ctx.visible && ctx.decoration_mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE){ - border_added_w = border_size.x[0] + border_size.x[1]; - border_added_h = border_size.y[0] + border_size.y[1]; + + bool csd = false; + if (ctx.visible && + ctx.decoration_mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE){ + csd = true; } - struct libdecor_state state = {0}; - state.content_width = w; - state.content_height = h; - state.window_state = ctx.frame_window_state; + if (!(ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ + int mw = ctx.frame_content_width; + int mh = ctx.frame_content_height; + xdg_toplevel_set_min_size(ctx.xdg_toplevel, mw, mh); + xdg_toplevel_set_max_size(ctx.xdg_toplevel, mw, mh); + } - ctx.frame_content_width = state.content_width; - ctx.frame_content_height = state.content_height; - { - if (!(ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ - ctx.size_bounds.x[0] = ctx.frame_content_width; - ctx.size_bounds.y[0] = ctx.frame_content_height; - ctx.size_bounds.x[1] = ctx.frame_content_width; - ctx.size_bounds.y[1] = ctx.frame_content_height; + else{ + int csd_added_w = 0; + int csd_added_h = 0; + if (csd){ + csd_added_w = border_size.x[0] + border_size.x[1]; + csd_added_h = border_size.y[0] + border_size.y[1]; } - for (int i = 0; i < 2; i += 1){ int mw = 0; int mh = 0; if (ctx.size_bounds.x[i] > 0 && ctx.size_bounds.y[i] > 0){ - mw = ctx.size_bounds.x[i] + border_added_w; - mh = ctx.size_bounds.y[i] + border_added_h; + mw = ctx.size_bounds.x[i] + csd_added_w; + mh = ctx.size_bounds.y[i] + csd_added_h; } if (i == 0){ xdg_toplevel_set_min_size(ctx.xdg_toplevel, mw, mh); @@ -1342,7 +1258,59 @@ libdecor_frame_commit(int w, int h){ } } - update_client_side_rendering_state(); + if (csd){ + enum libdecor_window_state old_window_state = ctx.gtk_window_state; + enum libdecor_window_state new_window_state = ctx.frame_window_state; + + int old_content_width = ctx.gtk_content_width; + int old_content_height = ctx.gtk_content_height; + int new_content_width = ctx.frame_content_width; + int new_content_height = ctx.frame_content_height; + + enum decoration_type old_decoration_type = ctx.decoration_type; + enum decoration_type new_decoration_type = decoration_type_from_window_state(new_window_state); + + if (old_decoration_type != new_decoration_type || + old_content_width != new_content_width || + old_content_height != new_content_height || + old_window_state != new_window_state){ + + ctx.gtk_content_width = new_content_width; + ctx.gtk_content_height = new_content_height; + ctx.gtk_window_state = new_window_state; + ctx.decoration_type = new_decoration_type; + + draw_decoration(); + } + } + else{ + g_clear_pointer(&ctx.header, gtk_widget_destroy); + g_clear_pointer(&ctx.window, gtk_widget_destroy); + + free_border_component(&ctx.component_slot[COMPONENT_SLOT_HEADER]); + free_border_component(&ctx.component_slot[COMPONENT_SLOT_SHADOW]); + ctx.shadow_showing = false; + + g_clear_pointer(&ctx.title, free); + + ctx.decoration_type = DECORATION_TYPE_NONE; + } + + { + Extent2D extent = {0}; + extent.w = ctx.frame_content_width; + extent.h = ctx.frame_content_height; + + if (csd){ + extent.x = -border_size.x[0]; + extent.y = -border_size.y[0]; + extent.w += border_size.x[0] + border_size.x[1]; + extent.h += border_size.y[0] + border_size.y[1]; + } + + xdg_surface_set_window_geometry(ctx.xdg_surface, extent.x, extent.y, + extent.w, extent.h); + } } void @@ -2088,6 +2056,7 @@ draw_border_component(enum component_slot slot){ if (slot < COMPONENT_SLOT_COUNT && ctx.component_slot[slot].wl_surface != 0){ Extent2D extent = extent2d_from_component_slot(slot); + if (slot == COMPONENT_SLOT_SHADOW && ctx.shadow_showing){ struct wl_region *input_region; Extent2D extent = extent2d_from_component_slot(COMPONENT_SLOT_SHADOW); @@ -2151,7 +2120,7 @@ draw_border_component(enum component_slot slot){ cairo_surface_set_device_scale(surface, 1, 1); switch (slot){ - default: case COMPONENT_SLOT_NONE: break; + default:break; case COMPONENT_SLOT_SHADOW: { render_shadow(cr, ctx.shadow_blur, @@ -2167,26 +2136,24 @@ draw_border_component(enum component_slot slot){ /* background */ { GtkAllocation allocation; - GtkStyleContext* style; gtk_widget_get_allocation(GTK_WIDGET(ctx.header), &allocation); - style = gtk_widget_get_style_context(ctx.header); + GtkStyleContext* style = gtk_widget_get_style_context(ctx.header); gtk_render_background(style, cr, allocation.x, allocation.y, allocation.width, allocation.height); } /* title */ { - GtkWidget *label; - GtkAllocation allocation; - cairo_surface_t *label_surface = NULL; - cairo_t *cr; + GtkWidget *label = find_widget_by_type(ctx.header, HEADER_TITLE).widget; - label = find_widget_by_type(ctx.header, HEADER_TITLE).widget; + GtkAllocation allocation; gtk_widget_get_allocation(label, &allocation); - label_surface = cairo_surface_create_for_rectangle(surface, allocation.x, allocation.y, allocation.width, allocation.height); - cr = cairo_create(label_surface); + + cairo_surface_t *label_surface = cairo_surface_create_for_rectangle(surface, allocation.x, allocation.y, allocation.width, allocation.height); + + cairo_t *cr2 = cairo_create(label_surface); gtk_widget_size_allocate(label, &allocation); - gtk_widget_draw(label, cr); - cairo_destroy(cr); + gtk_widget_draw(label, cr2); + cairo_destroy(cr2); cairo_surface_destroy(label_surface); } @@ -2208,7 +2175,7 @@ draw_border_component(enum component_slot slot){ nbuttons += 1; } - for (size_t i = 0; i < nbuttons; i += 1){ + for (int i = 0; i < nbuttons; i += 1){ enum header_element button_type = buttons[i]; draw_header_button(cr, surface, button_type); } @@ -2233,11 +2200,8 @@ draw_border_component(enum component_slot slot){ static void draw_title_bar(void){ - GtkAllocation allocation = {0, 0, ctx.gtk_content_width, 0}; enum libdecor_window_state state; GtkStyleContext *style; - int pref_width; - int W, H; state = ctx.frame_window_state; style = gtk_widget_get_style_context(ctx.window); @@ -2258,26 +2222,28 @@ draw_title_bar(void){ gtk_widget_show_all(ctx.window); - /* set default width, using an empty title to estimate its smallest admissible value */ - gtk_header_bar_set_title(GTK_HEADER_BAR(ctx.header), ""); - gtk_widget_get_preferred_width(ctx.header, NULL, &pref_width); - gtk_header_bar_set_title(GTK_HEADER_BAR(ctx.header), ctx.title); - if (ctx.size_bounds.x[0] < pref_width){ - ctx.size_bounds.x[0] = pref_width; - } - if (ctx.size_bounds.x[1] != 0 && - ctx.size_bounds.x[1] < ctx.size_bounds.x[0]){ - ctx.size_bounds.x[1] = ctx.size_bounds.x[0]; + int pref_width; + { + gtk_header_bar_set_title(GTK_HEADER_BAR(ctx.header), ""); + gtk_widget_get_preferred_width(ctx.header, NULL, &pref_width); + gtk_header_bar_set_title(GTK_HEADER_BAR(ctx.header), ctx.title); } - W = ctx.frame_content_width; - H = ctx.frame_content_height; - if (W < ctx.size_bounds.x[0]){ - W = ctx.size_bounds.x[0]; - libdecor_frame_commit(W, H); + ctx.size_bounds.x[0] = CLAMP_BOT(ctx.size_bounds.x[0], pref_width); + if (ctx.size_bounds.x[1] != 0){ + ctx.size_bounds.x[1] = CLAMP_BOT(ctx.size_bounds.x[1], ctx.size_bounds.x[0]); + } + + int w = ctx.frame_content_width; + int h = ctx.frame_content_height; + if (w < ctx.size_bounds.x[0]){ + w = ctx.size_bounds.x[0]; + ctx.frame_content_width = w; + ctx.frame_content_height = h; + libdecor_frame_commit(); } else{ - /* set default height */ + GtkAllocation allocation = {0, 0, ctx.gtk_content_width, 0}; gtk_widget_get_preferred_height(ctx.header, 0, &allocation.height); gtk_widget_size_allocate(ctx.header, &allocation); draw_border_component(COMPONENT_SLOT_HEADER); diff --git a/digesting_libdecor.h b/digesting_libdecor.h index 9fe009d..5f75f03 100644 --- a/digesting_libdecor.h +++ b/digesting_libdecor.h @@ -45,6 +45,9 @@ #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define CLAMP_BOT(a, b) MAX(a, b) +#define CLAMP_TOP(a, b) MIN(a, b) + #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) #define STREQL(a,b) (((a)==0 && (b)==0) || \ @@ -249,7 +252,7 @@ enum titlebar_gesture { // libdecor.h void libdecor_frame_show_window_menu(struct wl_seat *wl_seat, uint32_t serial, int x, int y); -void libdecor_frame_commit(int w, int h); +void libdecor_frame_commit(void); void libdecor_frame_set_fullscreen(struct wl_output *output); void libdecor_frame_unset_fullscreen(void); @@ -332,7 +335,6 @@ typedef struct Ctx{ struct xdg_toplevel *xdg_toplevel; struct zxdg_toplevel_decoration_v1 *toplevel_decoration; struct wl_egl_window *wl_egl_window; - int configured; int w; int h; int close_signal; @@ -342,13 +344,14 @@ typedef struct Ctx{ int has_cached_config; struct libdecor_configuration cached_config; + int has_pending_config; + struct libdecor_configuration pending_config; //struct libdecor_frame_private; char *title; Sides2D size_bounds; struct xdg_toplevel *parent; - struct libdecor_configuration *pending_configuration; int frame_content_width; int frame_content_height;