diff --git a/digesting_libdecor.c b/digesting_libdecor.c index 6bf7c03..2d9321d 100755 --- a/digesting_libdecor.c +++ b/digesting_libdecor.c @@ -345,6 +345,8 @@ const struct zxdg_toplevel_decoration_v1_listener xdg_toplevel_decoration_listener = { xdg_toplevel_decoration_configure, }; static GtkWidget* find_widget_by_type(GtkWidget *root, enum header_element type); +static void ensure_title_bar_surfaces(void); +static void ensure_component(struct border_component *cmpnt); int main(){ /* get desktop settings */ @@ -650,7 +652,17 @@ int main(){ } /* re-render cursor */ - ctx.seat->current_cursor = wl_cursor_from_pos(ctx.seat->pointer_x, ctx.seat->pointer_y); + { + 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); @@ -667,16 +679,10 @@ int main(){ ctx.titlebar_gesture.first_pressed_button = 0; ctx.hdr_focus.widget = 0; ctx.hdr_focus.type = HEADER_NONE; - draw_decoration(); - wl_surface_commit(ctx.wl_surface); } if (ctx.pointer_enter){ ctx.pointer_enter = 0; - if (ctx.active != 0){ - draw_decoration(); - wl_surface_commit(ctx.wl_surface); - } } if (ctx.pointer_motion){ @@ -720,9 +726,6 @@ int main(){ } } } - - draw_title_bar(); - wl_surface_commit(ctx.wl_surface); } if (ctx.pointer_button){ @@ -757,23 +760,21 @@ int main(){ xdg_toplevel_show_window_menu(ctx.xdg_toplevel, ctx.seat->wl_seat, ctx.seat->serial, ctx.seat->pointer_x, -title_height); ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_CONSUMED; } + else if (ctx.pointer_button_button == BTN_LEFT && + ctx.titlebar_gesture.first_pressed_button == BTN_LEFT && + ctx.pointer_button_time - ctx.titlebar_gesture.first_pressed_time < (uint32_t)ctx.double_click_time_ms){ + if ((ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ + toggle_maximized(); + } + ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_CONSUMED; + } else{ - if (ctx.pointer_button_button == BTN_LEFT && - ctx.titlebar_gesture.first_pressed_button == BTN_LEFT && - ctx.pointer_button_time - ctx.titlebar_gesture.first_pressed_time < (uint32_t)ctx.double_click_time_ms){ - if ((ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ - toggle_maximized(); - } - ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_CONSUMED; - } - else{ - ctx.titlebar_gesture.first_pressed_button = ctx.pointer_button_button; - ctx.titlebar_gesture.first_pressed_time = ctx.pointer_button_time; - ctx.titlebar_gesture.pressed_x = ctx.seat->pointer_x; - ctx.titlebar_gesture.pressed_y = ctx.seat->pointer_y; - ctx.titlebar_gesture.serial = ctx.seat->serial; - ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_BUTTON_PRESSED; - } + ctx.titlebar_gesture.first_pressed_button = ctx.pointer_button_button; + ctx.titlebar_gesture.first_pressed_time = ctx.pointer_button_time; + ctx.titlebar_gesture.pressed_x = ctx.seat->pointer_x; + ctx.titlebar_gesture.pressed_y = ctx.seat->pointer_y; + ctx.titlebar_gesture.serial = ctx.seat->serial; + ctx.titlebar_gesture.state = TITLEBAR_GESTURE_STATE_BUTTON_PRESSED; } ctx.titlebar_gesture.button_pressed_count = 1; @@ -781,12 +782,7 @@ int main(){ switch (ctx.hdr_focus.type){ case HEADER_MIN: case HEADER_MAX: - case HEADER_CLOSE: { - ctx.hdr_focus_is_active = 1; - draw_title_bar(); - wl_surface_commit(ctx.wl_surface); - }break; - + case HEADER_CLOSE: ctx.hdr_focus_is_active = 1; break; default: break; } } @@ -833,11 +829,6 @@ int main(){ else{ ctx.hdr_focus_is_active = 0; } - - if (GTK_IS_WIDGET(ctx.header)) { - draw_title_bar(); - wl_surface_commit(ctx.wl_surface); - } } }break; @@ -859,13 +850,10 @@ int main(){ default: break; } - } /* apply new surface config */ if (ctx.has_cached_config){ - ctx.has_cached_config = 0; - if (ctx.cached_config.initialized){ ctx.frame_window_state = ctx.cached_config.window_state; } @@ -900,8 +888,13 @@ int main(){ ctx.w = w; ctx.h = h; } - - frame_commit(); + } + + frame_commit(); + wl_surface_commit(ctx.wl_surface); + + if (ctx.has_cached_config){ + ctx.has_cached_config = 0; xdg_surface_ack_configure(ctx.xdg_surface, ctx.cached_config.serial); } @@ -978,6 +971,14 @@ decoration_type_from_window_state(enum libdecor_window_state window_state){ return(result); } +static void +hide_border_component(struct border_component *border_component){ + if (border_component->wl_surface){ + wl_surface_attach(border_component->wl_surface, 0, 0, 0); + wl_surface_commit(border_component->wl_surface); + } +} + void frame_commit(void){ bool csd = false; @@ -997,12 +998,8 @@ frame_commit(void){ } 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]; - } + int csd_added_w = border_size.x[0] + border_size.x[1]; + int 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; @@ -1021,9 +1018,76 @@ frame_commit(void){ if (csd){ ctx.decoration_type = decoration_type_from_window_state(ctx.frame_window_state); - draw_decoration(); + + bool shadow = 0; + bool title_bar = 0; + switch (ctx.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){ + ctx.component_slot[COMPONENT_SLOT_SHADOW].opaque = false; + ensure_component(&ctx.component_slot[COMPONENT_SLOT_SHADOW]); + draw_border_component(COMPONENT_SLOT_SHADOW); + ctx.shadow_showing = true; + } + else{ + hide_border_component(&ctx.component_slot[COMPONENT_SLOT_SHADOW]); + ctx.shadow_showing = false; + } + + if (title_bar){ + ensure_title_bar_surfaces(); + + enum libdecor_window_state state = ctx.frame_window_state; + + 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); + + 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); + } + + 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]); + } + + if (ctx.w < ctx.size_bounds.x[0]){ + ctx.w = ctx.size_bounds.x[0]; + frame_commit(); + } + else{ + GtkAllocation allocation = {0, 0, ctx.w, 0}; + gtk_widget_get_preferred_height(ctx.header, 0, &allocation.height); + gtk_widget_size_allocate(ctx.header, &allocation); + draw_border_component(COMPONENT_SLOT_HEADER); + } + } + else{ + hide_border_component(&ctx.component_slot[COMPONENT_SLOT_HEADER]); + } } else{ + ctx.decoration_type = DECORATION_TYPE_NONE; + g_clear_pointer(&ctx.header, gtk_widget_destroy); g_clear_pointer(&ctx.window, gtk_widget_destroy); @@ -1031,29 +1095,19 @@ frame_commit(void){ struct border_component * border_component = &ctx.component_slot[i]; if (border_component->wl_subsurface != 0){ wl_subsurface_destroy(border_component->wl_subsurface); - border_component->wl_subsurface = 0; } if (border_component->wl_surface != 0){ wl_surface_destroy(border_component->wl_surface); - border_component->wl_surface = 0; } if (border_component->wl_buffer != 0){ wl_buffer_destroy(border_component->wl_buffer); - border_component->wl_buffer = 0; } if (border_component->data != 0){ munmap(border_component->data, border_component->data_size); - border_component->data = 0; } - border_component->data_size = 0; - border_component->width = 0; - border_component->height = 0; } + memset(ctx.component_slot, 0, sizeof ctx.component_slot); ctx.shadow_showing = false; - - g_clear_pointer(&ctx.title, free); - - ctx.decoration_type = DECORATION_TYPE_NONE; } { @@ -1066,7 +1120,6 @@ frame_commit(void){ 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); } } @@ -1459,14 +1512,6 @@ toggle_maximized(void){ } } -static void -hide_border_component(struct border_component *border_component){ - if (border_component->wl_surface){ - wl_surface_attach(border_component->wl_surface, 0, 0, 0); - wl_surface_commit(border_component->wl_surface); - } -} - static enum component_slot component_slot_from_wl_surface(const struct wl_surface *surface){ enum component_slot result = 0; @@ -1490,8 +1535,6 @@ ensure_component(struct border_component *cmpnt){ static void ensure_title_bar_surfaces(void){ - GtkStyleContext *context_hdr; - ctx.component_slot[COMPONENT_SLOT_HEADER].opaque = false; ensure_component(&ctx.component_slot[COMPONENT_SLOT_HEADER]); @@ -1521,7 +1564,7 @@ ensure_title_bar_surfaces(void){ "show-close-button", TRUE, NULL); - context_hdr = gtk_widget_get_style_context(ctx.header); + GtkStyleContext *context_hdr = gtk_widget_get_style_context(ctx.header); gtk_style_context_add_class(context_hdr, GTK_STYLE_CLASS_TITLEBAR); gtk_style_context_add_class(context_hdr, "default-decoration"); @@ -1564,8 +1607,6 @@ extent2d_from_component_slot(enum component_slot slot){ static void draw_header_button(cairo_t *cr, cairo_surface_t *surface, enum header_element button_type){ - GtkWidget *button; - GtkAllocation allocation; gchar *icon_name; @@ -1574,7 +1615,8 @@ draw_header_button(cairo_t *cr, cairo_surface_t *surface, GtkAllocation allocation_icon; GtkIconInfo* icon_info; - double sx, sy; + double sx; + double sy; gint icon_width, icon_height; @@ -1586,12 +1628,12 @@ draw_header_button(cairo_t *cr, cairo_surface_t *surface, GtkBorder border; GtkBorder padding; - button = find_widget_by_type(ctx.header, button_type); - if (button){ + GtkWidget *button = find_widget_by_type(ctx.header, button_type); + if (button != 0){ GtkStyleContext *button_style = gtk_widget_get_style_context(button); - GtkStateFlags style_state = 0; /* change style based on window state and focus */ + GtkStateFlags style_state = 0; if (!(ctx.frame_window_state & LIBDECOR_WINDOW_STATE_ACTIVE)){ style_state |= GTK_STATE_FLAG_BACKDROP; } @@ -1622,9 +1664,9 @@ draw_header_button(cairo_t *cr, cairo_surface_t *surface, }break; case HEADER_MAX:{ - icon_name = (ctx.frame_window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED) ? - "window-restore-symbolic" : - "window-maximize-symbolic"; + icon_name = ((ctx.frame_window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED) ? + "window-restore-symbolic" : + "window-maximize-symbolic"); }break; case HEADER_CLOSE: { @@ -1638,7 +1680,7 @@ draw_header_button(cairo_t *cr, cairo_surface_t *surface, /* get scale */ cairo_surface_get_device_scale(surface, &sx, &sy); - scale = (sx+sy) / 2.0; + scale = (sx+sy)/2.0; /* get original icon dimensions */ icon_widget = gtk_bin_get_child(GTK_BIN(button)); @@ -1655,14 +1697,14 @@ draw_header_button(cairo_t *cr, cairo_surface_t *surface, /* icon pixel buffer*/ gtk_style_context_save(button_style); gtk_style_context_set_state(button_style, style_state); - icon_pixbuf = gtk_icon_info_load_symbolic_for_context( - icon_info, button_style, NULL, NULL); + icon_pixbuf = gtk_icon_info_load_symbolic_for_context(icon_info, button_style, 0, 0); icon_surface = gdk_cairo_surface_create_from_pixbuf(icon_pixbuf, scale, NULL); gtk_style_context_restore(button_style); /* dimensions and position */ gtk_style_context_get(button_style, gtk_style_context_get_state(button_style), - "min-width", &width, "min-height", &height, NULL); + "min-width", &width, + "min-height", &height, NULL); if (width < icon_width){ width = icon_width; @@ -1842,76 +1884,6 @@ draw_border_component(enum component_slot slot){ } } -static void -draw_title_bar(void){ - enum libdecor_window_state state = ctx.frame_window_state; - - 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); - - 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); - } - - 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]); - } - - if (ctx.w < ctx.size_bounds.x[0]){ - ctx.w = ctx.size_bounds.x[0]; - frame_commit(); - } - else{ - GtkAllocation allocation = {0, 0, ctx.w, 0}; - gtk_widget_get_preferred_height(ctx.header, 0, &allocation.height); - gtk_widget_size_allocate(ctx.header, &allocation); - draw_border_component(COMPONENT_SLOT_HEADER); - } -} - -static void -draw_decoration(void){ - switch (ctx.decoration_type){ - case DECORATION_TYPE_NONE: { - hide_border_component(&ctx.component_slot[COMPONENT_SLOT_SHADOW]); - ctx.shadow_showing = false; - hide_border_component(&ctx.component_slot[COMPONENT_SLOT_HEADER]); - }break; - - case DECORATION_TYPE_ALL: { - ctx.component_slot[COMPONENT_SLOT_SHADOW].opaque = false; - ensure_component(&ctx.component_slot[COMPONENT_SLOT_SHADOW]); - draw_border_component(COMPONENT_SLOT_SHADOW); - ctx.shadow_showing = true; - ensure_title_bar_surfaces(); - draw_title_bar(); - }break; - - case DECORATION_TYPE_TITLE_ONLY: { - hide_border_component(&ctx.component_slot[COMPONENT_SLOT_SHADOW]); - ctx.shadow_showing = false; - ensure_title_bar_surfaces(); - draw_title_bar(); - }break; - } -} - static Sides2D border_size_from_window_state(enum libdecor_window_state window_state){ Sides2D border_size = {0}; @@ -1960,19 +1932,6 @@ edge_from_pos(int x, int y){ return(result); } -static struct wl_cursor * -wl_cursor_from_pos(int x, int y){ - struct wl_cursor *result = ctx.cursor_left_ptr; - if (ctx.active == COMPONENT_SLOT_SHADOW && - (ctx.frame_capabilities & LIBDECOR_ACTION_RESIZE)){ - enum libdecor_resize_edge edge = edge_from_pos(x, y); - if (edge != LIBDECOR_RESIZE_EDGE_NONE){ - result = ctx.cursors[edge - 1]; - } - } - return(result); -} - //#include "desktop-settings.c" static bool diff --git a/digesting_libdecor.h b/digesting_libdecor.h index c978719..b86b378 100644 --- a/digesting_libdecor.h +++ b/digesting_libdecor.h @@ -270,7 +270,6 @@ static const char *libdecor_gtk_proxy_tag = "libdecor-gtk"; static Sides2D border_size_from_window_state(enum libdecor_window_state window_state); static struct wl_cursor* wl_cursor_from_pos(int x, int y); -static void draw_decoration(void); static void draw_header_button(cairo_t *cr, cairo_surface_t *surface, enum header_element button_type); static void draw_border_component(enum component_slot slot);