diff --git a/digesting_libdecor.c b/digesting_libdecor.c index eeb49d8..e8858f7 100755 --- a/digesting_libdecor.c +++ b/digesting_libdecor.c @@ -99,7 +99,14 @@ pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, seat->pointer_y = wl_fixed_to_int(y); seat->serial = serial; seat->pointer_focus = surface; - ctx.active = component_slot_from_wl_surface(surface); + + ctx.active = 0; + for (int i = 1; i < COMPONENT_SLOT_COUNT; i += 1){ + if (ctx.component_slot[i].wl_surface == surface){ + ctx.active = i; + break; + } + } ctx.pointer_enter = 1; } @@ -679,29 +686,6 @@ int main(){ } } - /* re-render cursor */ - { - struct wl_cursor *cursor = ctx.cursor_left_ptr; - if (ctx.active == COMPONENT_SLOT_SHADOW && - (ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ - enum libdecor_resize_edge edge = edge_from_pos(ctx.seat->pointer_x, ctx.seat->pointer_y); - if (edge != LIBDECOR_RESIZE_EDGE_NONE){ - cursor = ctx.cursors[edge - 1]; - } - } - ctx.seat->current_cursor = cursor; - } - - if (ctx.seat->current_cursor != 0){ - struct wl_cursor_image *image = ctx.seat->current_cursor->images[0]; - struct wl_buffer *buffer = wl_cursor_image_get_buffer(image); - wl_surface_set_buffer_scale(ctx.seat->cursor_surface, 1); - wl_surface_attach(ctx.seat->cursor_surface, buffer, 0, 0); - wl_surface_damage_buffer(ctx.seat->cursor_surface, 0, 0, image->width, image->height); - wl_surface_commit(ctx.seat->cursor_surface); - wl_pointer_set_cursor(ctx.seat->wl_pointer, ctx.seat->serial, ctx.seat->cursor_surface, image->hotspot_x, image->hotspot_y); - } - #if 1 if (ctx.pointer_leave){ ctx.pointer_leave = 0; @@ -899,7 +883,9 @@ int main(){ if (cmpnt->wl_surface == 0){ cmpnt->wl_surface = wl_compositor_create_surface(ctx.wl_compositor); wl_proxy_set_tag((struct wl_proxy *)cmpnt->wl_surface, &libdecor_gtk_proxy_tag); - cmpnt->wl_subsurface = wl_subcompositor_get_subsurface(ctx.wl_subcompositor, cmpnt->wl_surface, ctx.wl_surface); + cmpnt->wl_subsurface = + wl_subcompositor_get_subsurface(ctx.wl_subcompositor, + cmpnt->wl_surface, ctx.wl_surface); } } @@ -924,6 +910,8 @@ int main(){ gtk_window_set_titlebar(GTK_WINDOW(ctx.window), ctx.header); gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(ctx.header), TRUE); + + gtk_widget_show_all(ctx.window); } if (!csd && ctx.csd_active){ @@ -962,113 +950,74 @@ int main(){ } } - bool shadow = 0; - bool title_bar = 0; Sides2D csd_size = {0}; + Sides2D csd_size_bounds = {0}; + csd_size_bounds.x[1] = (1 << 30); + csd_size_bounds.y[1] = (1 << 30); if (csd){ - enum decoration_type csd_decoration_type = DECORATION_TYPE_ALL; - if (ctx.frame_window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN){ - csd_decoration_type = DECORATION_TYPE_NONE; - } - else if (ctx.frame_window_state & (LIBDECOR_WINDOW_STATE_MAXIMIZED | - LIBDECOR_WINDOW_STATE_TILED_LEFT | - LIBDECOR_WINDOW_STATE_TILED_RIGHT | - LIBDECOR_WINDOW_STATE_TILED_TOP | - LIBDECOR_WINDOW_STATE_TILED_BOTTOM)){ - csd_decoration_type = DECORATION_TYPE_TITLE_ONLY; - } - switch (csd_decoration_type){ - case DECORATION_TYPE_NONE: break; - case DECORATION_TYPE_ALL: { shadow = 1; title_bar = 1; }break; - case DECORATION_TYPE_TITLE_ONLY: { title_bar = 1; }break; - } - - if (!shadow){ - struct border_component *cmpnt = &ctx.component_slot[COMPONENT_SLOT_SHADOW]; - if (cmpnt->wl_surface != 0){ - wl_surface_attach(cmpnt->wl_surface, 0, 0, 0); - wl_surface_commit(cmpnt->wl_surface); - } - } - if (!title_bar){ - struct border_component *cmpnt = &ctx.component_slot[COMPONENT_SLOT_HEADER]; - if (cmpnt->wl_surface != 0){ - wl_surface_attach(cmpnt->wl_surface, 0, 0, 0); - wl_surface_commit(cmpnt->wl_surface); - } - } - - if (title_bar){ - enum libdecor_window_state state = ctx.frame_window_state; - - gtk_window_set_resizable(GTK_WINDOW(ctx.window), (ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE) != 0); - - gtk_widget_show_all(ctx.window); + if (csd_show_title_from_state(ctx.frame_window_state)){ gtk_widget_get_preferred_height(ctx.header, 0, &csd_size.y[0]); - if (!(state & LIBDECOR_WINDOW_STATE_ACTIVE)){ - gtk_widget_set_state_flags(ctx.window, GTK_STATE_FLAG_BACKDROP, true); - } - else{ - gtk_widget_unset_state_flags(ctx.window, GTK_STATE_FLAG_BACKDROP); - } - GtkStyleContext *style = gtk_widget_get_style_context(ctx.window); - if (!(ctx.frame_window_state & LIBDECOR_WINDOW_STATE_NON_FLOATING)){ - gtk_style_context_remove_class(style, "maximized"); - } - else{ - gtk_style_context_add_class(style, "maximized"); - } - gtk_widget_show_all(ctx.window); + gtk_header_bar_set_title(GTK_HEADER_BAR(ctx.header), ""); + gtk_widget_get_preferred_width(ctx.header, 0, &csd_size_bounds.x[0]); + gtk_header_bar_set_title(GTK_HEADER_BAR(ctx.header), ctx.title); } } + int csd_w = csd_size.x[0] + csd_size.x[1]; + int csd_h = csd_size.y[0] + csd_size.y[1]; + if (ctx.has_cached_config){ if (ctx.cached_config.initialized && ctx.cached_config.window_width != 0 && ctx.cached_config.window_height != 0){ - int w = ctx.cached_config.window_width; - int h = ctx.cached_config.window_height; - if (csd){ - w -= csd_size.x[0] + csd_size.x[1]; - h -= csd_size.y[0] + csd_size.y[1]; - } - ctx.w = w; - ctx.h = h; + ctx.w = ctx.cached_config.window_width - csd_w; + ctx.h = ctx.cached_config.window_height - csd_h; } } + Sides2D true_size_bounds; + { + true_size_bounds.x[0] = CLAMP_BOT(ctx.size_bounds.x[0], csd_size_bounds.x[0]); + true_size_bounds.y[0] = CLAMP_BOT(ctx.size_bounds.y[0], csd_size_bounds.y[0]); + true_size_bounds.x[1] = CLAMP_TOP(ctx.size_bounds.x[1], csd_size_bounds.x[1]); + true_size_bounds.y[1] = CLAMP_TOP(ctx.size_bounds.y[1], csd_size_bounds.y[1]); + } + + ctx.w = CLAMP_(true_size_bounds.x[0], ctx.w, true_size_bounds.x[1]); + ctx.h = CLAMP_(true_size_bounds.y[0], ctx.h, true_size_bounds.y[1]); + if (csd){ - if (shadow){ - Extent2D extent = {0}; - { - extent.x = -(int)SHADOW_MARGIN; - extent.y = -(int)(SHADOW_MARGIN + csd_size.y[0]); - extent.w = ctx.w + 2*SHADOW_MARGIN; - extent.h = csd_size.y[0] + ctx.h + 2*SHADOW_MARGIN; - } + { + enum component_slot slot = COMPONENT_SLOT_SHADOW; + struct border_component *cmpnt = &ctx.component_slot[COMPONENT_SLOT_SHADOW]; - struct wl_region *input_region = wl_compositor_create_region(ctx.wl_compositor); - wl_region_add(input_region, 0, 0, extent.w, extent.h); - wl_region_subtract(input_region, -extent.x, -extent.y, ctx.w, ctx.h); - wl_surface_set_input_region(ctx.component_slot[COMPONENT_SLOT_SHADOW].wl_surface, input_region); - wl_region_destroy(input_region); - - { - enum component_slot slot = COMPONENT_SLOT_SHADOW; - struct border_component *component = &ctx.component_slot[slot]; - border_component_reallocate(component, extent.w, extent.h); - - memset(component->data, 0, component->data_size); + if (csd_show_shadow_from_state(ctx.frame_window_state)){ + Extent2D extent = {0}; { - int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, component->width); - cairo_surface_t *surface = cairo_image_surface_create_for_data(component->data, CAIRO_FORMAT_ARGB32, component->width, component->height, stride); + extent.x = -(int)SHADOW_MARGIN; + extent.y = -(int)(SHADOW_MARGIN + csd_size.y[0]); + extent.w = ctx.w + 2*SHADOW_MARGIN; + extent.h = csd_size.y[0] + ctx.h + 2*SHADOW_MARGIN; + } + + struct wl_region *input_region = wl_compositor_create_region(ctx.wl_compositor); + wl_region_add(input_region, 0, 0, extent.w, extent.h); + wl_region_subtract(input_region, -extent.x, -extent.y, ctx.w, ctx.h); + wl_surface_set_input_region(cmpnt->wl_surface, input_region); + wl_region_destroy(input_region); + + border_component_reallocate(cmpnt, extent.w, extent.h); + memset(cmpnt->data, 0, cmpnt->data_size); + { + int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, cmpnt->width); + cairo_surface_t *surface = cairo_image_surface_create_for_data(cmpnt->data, CAIRO_FORMAT_ARGB32, cmpnt->width, cmpnt->height, stride); cairo_t *cr = cairo_create(surface); cairo_surface_set_device_scale(surface, 1, 1); render_shadow(cr, ctx.shadow_blur, -(int)SHADOW_MARGIN/2, -(int)SHADOW_MARGIN/2, - component->width + SHADOW_MARGIN, component->height + SHADOW_MARGIN, + cmpnt->width + SHADOW_MARGIN, cmpnt->height + SHADOW_MARGIN, 64, 64); cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_rectangle(cr, -extent.x, -extent.y, ctx.w, ctx.h); @@ -1078,87 +1027,103 @@ int main(){ cairo_surface_destroy(surface); } - wl_surface_attach(component->wl_surface, component->wl_buffer, 0, 0); - wl_surface_set_buffer_scale(component->wl_surface, 1); - wl_surface_commit(component->wl_surface); - wl_surface_damage_buffer(component->wl_surface, 0, 0, extent.w, extent.h); - wl_subsurface_set_position(component->wl_subsurface, extent.x, extent.y); + wl_surface_attach(cmpnt->wl_surface, cmpnt->wl_buffer, 0, 0); + wl_surface_set_buffer_scale(cmpnt->wl_surface, 1); + wl_surface_damage_buffer(cmpnt->wl_surface, 0, 0, extent.w, extent.h); + wl_subsurface_set_position(cmpnt->wl_subsurface, extent.x, extent.y); } + else{ + wl_surface_attach(cmpnt->wl_surface, 0, 0, 0); + } + wl_surface_commit(cmpnt->wl_surface); } - if (title_bar){ - Extent2D extent = {0}; - { - extent.x = 0; - extent.y = -csd_size.y[0]; - extent.w = ctx.w; - extent.h = csd_size.y[0]; - } + { + enum component_slot slot = COMPONENT_SLOT_HEADER; + struct border_component *cmpnt = &ctx.component_slot[slot]; - { - GtkAllocation allocation = {0, 0, ctx.w, csd_size.y[0]}; - gtk_widget_size_allocate(ctx.header, &allocation); - } - - { - enum component_slot slot = COMPONENT_SLOT_HEADER; - struct border_component *component = &ctx.component_slot[slot]; - border_component_reallocate(component, extent.w, extent.h); - - memset(component->data, 0, component->data_size); + if (csd_show_title_from_state(ctx.frame_window_state)){ + Extent2D extent = {0}; { - int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, component->width); - cairo_surface_t *surface = cairo_image_surface_create_for_data(component->data, CAIRO_FORMAT_ARGB32, component->width, component->height, stride); + extent.x = 0; + extent.y = -csd_size.y[0]; + extent.w = ctx.w; + extent.h = csd_size.y[0]; + } + + gtk_window_set_resizable(GTK_WINDOW(ctx.window), (ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE) != 0); + if (!(ctx.frame_window_state & LIBDECOR_WINDOW_STATE_ACTIVE)){ + gtk_widget_set_state_flags(ctx.window, GTK_STATE_FLAG_BACKDROP, true); + } + else{ + gtk_widget_unset_state_flags(ctx.window, GTK_STATE_FLAG_BACKDROP); + } + GtkStyleContext *style = gtk_widget_get_style_context(ctx.window); + if (!(ctx.frame_window_state & LIBDECOR_WINDOW_STATE_NON_FLOATING)){ + gtk_style_context_remove_class(style, "maximized"); + } + else{ + gtk_style_context_add_class(style, "maximized"); + } + + { + GtkAllocation allocation = {0, 0, ctx.w, csd_size.y[0]}; + gtk_widget_size_allocate(ctx.header, &allocation); + } + + border_component_reallocate(cmpnt, extent.w, extent.h); + memset(cmpnt->data, 0, cmpnt->data_size); + { + int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, cmpnt->width); + cairo_surface_t *surface = + cairo_image_surface_create_for_data(cmpnt->data, CAIRO_FORMAT_ARGB32, + cmpnt->width, cmpnt->height, stride); cairo_t *cr = cairo_create(surface); cairo_surface_set_device_scale(surface, 1, 1); + /* background */ { - /* background */ - { - GtkAllocation allocation; - gtk_widget_get_allocation(GTK_WIDGET(ctx.header), &allocation); - GtkStyleContext* style = gtk_widget_get_style_context(ctx.header); - gtk_render_background(style, cr, allocation.x, allocation.y, allocation.width, allocation.height); + GtkAllocation allocation; + gtk_widget_get_allocation(GTK_WIDGET(ctx.header), &allocation); + 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 = find_widget_by_type(ctx.header, HEADER_TITLE); + GtkAllocation allocation; + gtk_widget_get_allocation(label, &allocation); + 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_draw(label, cr2); + cairo_destroy(cr2); + cairo_surface_destroy(label_surface); + } + + /* buttons */ + { + enum header_element buttons[3] = {0}; + size_t nbuttons = 0; + if (ctx.frame_capabilities & LIBDECOR_ACTION_MINIMIZE){ + buttons[nbuttons] = HEADER_MIN; + nbuttons += 1; } - - /* title */ - { - GtkWidget *label = find_widget_by_type(ctx.header, HEADER_TITLE); - - GtkAllocation allocation; - gtk_widget_get_allocation(label, &allocation); - - 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, cr2); - cairo_destroy(cr2); - cairo_surface_destroy(label_surface); + if (ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE){ + buttons[nbuttons] = HEADER_MAX; + nbuttons += 1; } - - /* buttons */ - { - enum header_element buttons[3] = {0}; - size_t nbuttons = 0; - - if ((ctx.frame_capabilities & LIBDECOR_ACTION_MINIMIZE)){ - buttons[nbuttons] = HEADER_MIN; - nbuttons += 1; - } - if ((ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ - buttons[nbuttons] = HEADER_MAX; - nbuttons += 1; - } - if ((ctx.frame_capabilities & LIBDECOR_ACTION_CLOSE)){ - buttons[nbuttons] = HEADER_CLOSE; - nbuttons += 1; - } - - for (int i = 0; i < nbuttons; i += 1){ - enum header_element button_type = buttons[i]; - draw_header_button(cr, surface, button_type); - } + if (ctx.frame_capabilities & LIBDECOR_ACTION_CLOSE){ + buttons[nbuttons] = HEADER_CLOSE; + nbuttons += 1; + } + for (int i = 0; i < nbuttons; i += 1){ + draw_header_button(cr, surface, buttons[i]); } } @@ -1166,13 +1131,17 @@ int main(){ cairo_surface_destroy(surface); } - wl_surface_attach(component->wl_surface, component->wl_buffer, 0, 0); - wl_surface_set_buffer_scale(component->wl_surface, 1); - wl_surface_commit(component->wl_surface); - wl_surface_damage_buffer(component->wl_surface, 0, 0, extent.w, extent.h); - wl_subsurface_set_position(component->wl_subsurface, extent.x, extent.y); + wl_surface_attach(cmpnt->wl_surface, cmpnt->wl_buffer, 0, 0); + wl_surface_set_buffer_scale(cmpnt->wl_surface, 1); + wl_surface_damage_buffer(cmpnt->wl_surface, 0, 0, extent.w, extent.h); + wl_subsurface_set_position(cmpnt->wl_subsurface, extent.x, extent.y); } + else{ + wl_surface_attach(cmpnt->wl_surface, 0, 0, 0); + } + wl_surface_commit(cmpnt->wl_surface); } + } if (!(ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ @@ -1183,8 +1152,8 @@ int main(){ int csd_added_w = csd_size.x[0] + csd_size.x[1]; int csd_added_h = csd_size.y[0] + csd_size.y[1]; for (int i = 0; i < 2; i += 1){ - int mw = ctx.size_bounds.x[i] + csd_added_w; - int mh = ctx.size_bounds.y[i] + csd_added_h; + int mw = true_size_bounds.x[i] + csd_added_w; + int mh = true_size_bounds.y[i] + csd_added_h; if (i == 0){ xdg_toplevel_set_min_size(ctx.xdg_toplevel, mw, mh); } @@ -1206,17 +1175,39 @@ int main(){ } xdg_surface_set_window_geometry(ctx.xdg_surface, extent.x, extent.y, extent.w, extent.h); } + + wl_surface_commit(ctx.wl_surface); + if (ctx.has_cached_config){ + ctx.has_cached_config = 0; + memset(&ctx.cached_config, 0, sizeof ctx.cached_config); + xdg_surface_ack_configure(ctx.xdg_surface, ctx.cached_config.serial); + } + + wl_egl_window_resize(ctx.wl_egl_window, ctx.w, ctx.h, 0, 0); } - wl_surface_commit(ctx.wl_surface); - - if (ctx.has_cached_config){ - ctx.has_cached_config = 0; - memset(&ctx.cached_config, 0, sizeof ctx.cached_config); - xdg_surface_ack_configure(ctx.xdg_surface, ctx.cached_config.serial); + /* re-render cursor */ + { + struct wl_cursor *cursor = ctx.cursor_left_ptr; + if (ctx.active == COMPONENT_SLOT_SHADOW && + (ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ + enum libdecor_resize_edge edge = edge_from_pos(ctx.seat->pointer_x, ctx.seat->pointer_y); + if (edge != LIBDECOR_RESIZE_EDGE_NONE){ + cursor = ctx.cursors[edge - 1]; + } + } + ctx.seat->current_cursor = cursor; } - wl_egl_window_resize(ctx.wl_egl_window, ctx.w, ctx.h, 0, 0); + if (ctx.seat->current_cursor != 0){ + struct wl_cursor_image *image = ctx.seat->current_cursor->images[0]; + struct wl_buffer *buffer = wl_cursor_image_get_buffer(image); + wl_surface_set_buffer_scale(ctx.seat->cursor_surface, 1); + wl_surface_attach(ctx.seat->cursor_surface, buffer, 0, 0); + wl_surface_damage_buffer(ctx.seat->cursor_surface, 0, 0, image->width, image->height); + wl_surface_commit(ctx.seat->cursor_surface); + wl_pointer_set_cursor(ctx.seat->wl_pointer, ctx.seat->serial, ctx.seat->cursor_surface, image->hotspot_x, image->hotspot_y); + } /* app update & render */ { @@ -1686,18 +1677,6 @@ toggle_maximized(void){ } } -static enum component_slot -component_slot_from_wl_surface(const struct wl_surface *surface){ - enum component_slot result = 0; - for (int i = 1; i < COMPONENT_SLOT_COUNT; i += 1){ - if (ctx.component_slot[i].wl_surface == surface){ - result = i; - break; - } - } - return(result); -} - static void draw_header_button(cairo_t *cr, cairo_surface_t *surface, enum header_element button_type){ @@ -2008,3 +1987,20 @@ desktop_settings_get_color_scheme(){ #endif +int +csd_show_title_from_state(enum libdecor_window_state state){ + int result = (!(state & LIBDECOR_WINDOW_STATE_FULLSCREEN)); + return(result); +} + +int +csd_show_shadow_from_state(enum libdecor_window_state state){ + int result = (!(state & (LIBDECOR_WINDOW_STATE_FULLSCREEN | + LIBDECOR_WINDOW_STATE_MAXIMIZED | + LIBDECOR_WINDOW_STATE_TILED_LEFT | + LIBDECOR_WINDOW_STATE_TILED_RIGHT | + LIBDECOR_WINDOW_STATE_TILED_TOP | + LIBDECOR_WINDOW_STATE_TILED_BOTTOM))); + return(result); +} + diff --git a/digesting_libdecor.h b/digesting_libdecor.h index 8bdb385..d6b8216 100644 --- a/digesting_libdecor.h +++ b/digesting_libdecor.h @@ -152,12 +152,6 @@ struct header_element_data{ GtkWidget *widget; }; -enum decoration_type { - DECORATION_TYPE_NONE, - DECORATION_TYPE_ALL, - DECORATION_TYPE_TITLE_ONLY -}; - enum component_slot { COMPONENT_SLOT_NONE, COMPONENT_SLOT_SHADOW, @@ -267,7 +261,6 @@ static struct wl_cursor* wl_cursor_from_pos(int x, int y); static void draw_header_button(cairo_t *cr, cairo_surface_t *surface, enum header_element button_type); static bool own_proxy(void *proxy); -static enum component_slot component_slot_from_wl_surface(const struct wl_surface *surface); static struct header_element_data get_header_focus(const GtkHeaderBar *header_bar, int x, int y); static void draw_title_bar(void); static enum libdecor_resize_edge edge_from_pos(int x, int y); @@ -369,4 +362,7 @@ typedef struct Ctx{ } titlebar_gesture; } Ctx; +int csd_show_title_from_state(enum libdecor_window_state state); +int csd_show_shadow_from_state(enum libdecor_window_state state); + #endif //DIGESTING_LIBDECOR_H