From: Foxe Chen Date: Wed, 17 Jun 2026 19:53:57 +0000 (+0000) Subject: patch 9.2.0669: GTK4: toolbar can be improved X-Git-Tag: v9.2.0669^0 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=028314a8deced7dbb20aba569eaea7a36c47d050;p=thirdparty%2Fvim.git patch 9.2.0669: GTK4: toolbar can be improved Problem: GTK4: toolbar can be improved Solution: Implement gui_mch_menu_set_tip(), make the UI respect the 'toolbar' option (Foxe Chen). closes: #20541 Signed-off-by: Foxe Chen Signed-off-by: Christian Brabandt --- diff --git a/Filelist b/Filelist index 5526e539a8..1f36de4d43 100644 --- a/Filelist +++ b/Filelist @@ -515,6 +515,8 @@ SRC_UNIX = \ src/gui_gtk4_cb.h \ src/gui_gtk4_da.c \ src/gui_gtk4_da.h \ + src/gui_gtk4_tb.c \ + src/gui_gtk4_tb.h \ src/gui_gtk_res.xml \ src/gui_motif.c \ src/gui_xmdlg.c \ diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 244a7510fb..9743dea438 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 9.2. Last change: 2026 Jun 09 +*options.txt* For Vim version 9.2. Last change: 2026 Jun 17 VIM REFERENCE MANUAL by Bram Moolenaar @@ -9697,7 +9697,8 @@ A jump table for the options with a short description can be found at |Q_op|. icons Toolbar buttons are shown with icons. text Toolbar buttons shown with text. horiz Icon and text of a toolbar button are - horizontally arranged. {only in GTK+ 2 GUI} + horizontally arranged. + {only in GTK+ 2 and GTK 4 GUI} tooltips Tooltips are active for toolbar buttons. Tooltips refer to the popup help text which appears after the mouse cursor is placed over a toolbar button for a brief moment. diff --git a/src/Makefile b/src/Makefile index a5f23612c7..ef0cb85535 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1243,12 +1243,14 @@ GTK4_SRC = gui.c gui_gtk4.c gui_gtk4_f.c \ gui_gtk4_cb.c \ gui_gtk4_da.c \ gui_beval.o \ + gui_gtk4_tb.c \ $(GRESOURCE_SRC) GTK4_OBJ = objects/gui.o objects/gui_gtk4.o \ objects/gui_gtk4_f.o \ objects/gui_gtk4_cb.o \ objects/gui_gtk4_da.o \ objects/gui_beval.o \ + objects/gui_gtk4_tb.o \ $(GRESOURCE_OBJ) GTK4_DEFS = -DFEAT_GUI_GTK $(NARROW_PROTO) GTK4_IPATH = $(GUI_INC_LOC) @@ -1318,7 +1320,7 @@ HAIKUGUI_TESTTARGET = gui HAIKUGUI_BUNDLE = # All GUI files -ALL_GUI_SRC = gui.c gui_gtk.c gui_gtk_f.c gui_gtk4.c gui_gtk4_f.c gui_gtk4_cb.c gui_gtk4_da.c gui_motif.c gui_xmdlg.c gui_xmebw.c gui_gtk_x11.c gui_x11.c gui_haiku.cc +ALL_GUI_SRC = gui.c gui_gtk.c gui_gtk_f.c gui_gtk4.c gui_gtk4_f.c gui_gtk4_cb.c gui_gtk4_da.c gui_gtk4_tb.c gui_motif.c gui_xmdlg.c gui_xmebw.c gui_gtk_x11.c gui_x11.c gui_haiku.cc ALL_GUI_PRO = proto/gui.pro proto/gui_gtk.pro proto/gui_gtk4.pro proto/gui_motif.pro proto/gui_xmdlg.pro proto/gui_gtk_x11.pro proto/gui_x11.pro proto/gui_w32.pro proto/gui_photon.pro # }}} @@ -3416,6 +3418,9 @@ objects/gui_gtk4_cb.o: gui_gtk4_cb.c objects/gui_gtk4_da.o: gui_gtk4_da.c $(CCC) -o $@ gui_gtk4_da.c +objects/gui_gtk4_tb.o: gui_gtk4_tb.c + $(CCC) -o $@ gui_gtk4_tb.c + objects/gui_haiku.o: gui_haiku.cc $(CCC) -o $@ gui_haiku.cc @@ -4513,7 +4518,7 @@ objects/gui_gtk4.o: auto/osdef.h gui_gtk4.c vim.h protodef.h auto/config.h featu structs.h regexp.h gui.h libvterm/include/vterm.h \ libvterm/include/vterm_keycodes.h alloc.h ex_cmds.h spell.h proto.h \ globals.h errors.h gui_gtk4_f.h auto/gui_gtk_gresources.h \ - gui_gtk4_da.h + gui_gtk4_cb.h gui_gtk4_da.h gui_gtk4_tb.h objects/gui_gtk4_f.o: auto/osdef.h gui_gtk4_f.c vim.h protodef.h auto/config.h feature.h \ os_unix.h ascii.h keymap.h termdefs.h macros.h option.h \ beval.h structs.h regexp.h gui.h \ @@ -4529,6 +4534,11 @@ objects/gui_gtk4_da.o: auto/osdef.h gui_gtk4_da.c vim.h protodef.h auto/config.h beval.h structs.h regexp.h gui.h \ libvterm/include/vterm.h libvterm/include/vterm_keycodes.h alloc.h \ ex_cmds.h spell.h proto.h globals.h errors.h gui_gtk4_da.h +objects/gui_gtk4_tb.o: auto/osdef.h gui_gtk4_tb.c vim.h protodef.h auto/config.h feature.h \ + os_unix.h ascii.h keymap.h termdefs.h macros.h option.h \ + beval.h structs.h regexp.h gui.h \ + libvterm/include/vterm.h libvterm/include/vterm_keycodes.h alloc.h \ + ex_cmds.h spell.h proto.h globals.h errors.h gui_gtk4_tb.h objects/gui_gtk_f.o: auto/osdef.h gui_gtk_f.c vim.h protodef.h auto/config.h feature.h \ os_unix.h ascii.h keymap.h termdefs.h macros.h option.h \ beval.h structs.h regexp.h gui.h \ diff --git a/src/gui_gtk4.c b/src/gui_gtk4.c index 8a11027b70..27cf554226 100644 --- a/src/gui_gtk4.c +++ b/src/gui_gtk4.c @@ -33,6 +33,9 @@ #ifdef USE_GTK4_SNAPSHOT # include "gui_gtk4_da.h" #endif +#ifdef FEAT_TOOLBAR +# include "gui_gtk4_tb.h" +#endif /* * Geometry string parser, replacing XParseGeometry to remove X11 dependency. @@ -508,10 +511,11 @@ gui_mch_init(void) #endif #ifdef FEAT_TOOLBAR - gui.toolbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gui.toolbar = vim_toolbar_new(); gtk_widget_set_name(gui.toolbar, "vim-toolbar"); gtk_widget_set_visible(gui.toolbar, FALSE); gtk_box_append(GTK_BOX(vbox), gui.toolbar); + vim_toolbar_set_style(VIM_TOOLBAR(gui.toolbar), toolbar_flags, tbis_flags); #endif #ifdef FEAT_GUI_TABLINE @@ -973,7 +977,12 @@ gui_mch_enable_menu(int showit) gui_mch_show_toolbar(int showit) { if (gui.toolbar != NULL) + { gtk_widget_set_visible(gui.toolbar, showit); + if (showit) + vim_toolbar_set_style(VIM_TOOLBAR(gui.toolbar), + toolbar_flags, tbis_flags); + } } #endif @@ -4472,7 +4481,7 @@ gui_mch_add_menu(vimmenu_T *menu, int idx UNUSED) } void -gui_mch_add_menu_item(vimmenu_T *menu, int idx UNUSED) +gui_mch_add_menu_item(vimmenu_T *menu, int idx) { vimmenu_T *parent = menu->parent; @@ -4481,32 +4490,32 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx UNUSED) { if (menu_is_separator(menu->name)) { - GtkWidget *sep = gtk_separator_new(GTK_ORIENTATION_VERTICAL); - gtk_box_append(GTK_BOX(gui.toolbar), sep); - menu->id = sep; + menu->id = + vim_toolbar_insert_separator(VIM_TOOLBAR(gui.toolbar), idx); } else { GtkWidget *btn; GtkWidget *icon; + char_u *text; char_u *tooltip; - icon = create_toolbar_icon(menu); - btn = gtk_button_new(); - gtk_button_set_child(GTK_BUTTON(btn), icon); - gtk_widget_set_focusable(btn, FALSE); - gtk_widget_add_css_class(btn, "flat"); - + text = CONVERT_TO_UTF8(menu->dname); tooltip = CONVERT_TO_UTF8(menu->strings[MENU_INDEX_TIP]); - if (tooltip != NULL && utf_valid_string(tooltip, NULL)) - gtk_widget_set_tooltip_text(btn, (const gchar *)tooltip); - CONVERT_TO_UTF8_FREE(tooltip); + if (tooltip != NULL && !utf_valid_string(tooltip, NULL)) + CONVERT_TO_UTF8_FREE(tooltip); + + icon = create_toolbar_icon(menu); + btn = vim_toolbar_insert_button(VIM_TOOLBAR(gui.toolbar), + icon, (const char *)text, idx); + gtk_widget_set_tooltip_text(btn, (const gchar *)tooltip); g_signal_connect(btn, "clicked", G_CALLBACK(toolbar_button_clicked_cb), menu); - gtk_box_append(GTK_BOX(gui.toolbar), btn); menu->id = btn; + CONVERT_TO_UTF8_FREE(text); + CONVERT_TO_UTF8_FREE(tooltip); } return; } @@ -4523,7 +4532,8 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx UNUSED) { // GMenu doesn't have real separators; use a section GMenu *section = g_menu_new(); - g_menu_append_section(parent_menu, NULL, G_MENU_MODEL(section)); + g_menu_insert_section(parent_menu, idx, NULL, + G_MENU_MODEL(section)); g_object_unref(section); menu->id = NULL; } @@ -4552,7 +4562,7 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx UNUSED) label = CONVERT_TO_UTF8(menu->dname); vim_snprintf(detailed, sizeof(detailed), "menu.%s", action_name); - g_menu_append(parent_menu, (const char *)label, detailed); + g_menu_insert(parent_menu, idx, (const char *)label, detailed); CONVERT_TO_UTF8_FREE(label); menu->id = (GtkWidget *)1; // non-NULL marker @@ -4570,8 +4580,17 @@ gui_mch_toggle_tearoffs(int enable UNUSED) } void -gui_mch_menu_set_tip(vimmenu_T *menu UNUSED) +gui_mch_menu_set_tip(vimmenu_T *menu) { + char_u *tooltip; + + if (menu->id == NULL || menu->parent == NULL || gui.toolbar == NULL) + return; + + tooltip = CONVERT_TO_UTF8(menu->strings[MENU_INDEX_TIP]); + if (tooltip != NULL && utf_valid_string(tooltip, NULL)) + gtk_widget_set_tooltip_text(menu->id, (const char *)tooltip); + CONVERT_TO_UTF8_FREE(tooltip); } /* diff --git a/src/gui_gtk4_f.c b/src/gui_gtk4_f.c index cd71122b1e..52941874fb 100644 --- a/src/gui_gtk4_f.c +++ b/src/gui_gtk4_f.c @@ -69,7 +69,7 @@ vim_form_dispose(GObject *obj) static void vim_form_class_init(VimFormClass *class) { - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(class); GObjectClass *obj_class = G_OBJECT_CLASS(class); widget_class->snapshot = vim_form_snapshot; diff --git a/src/gui_gtk4_tb.c b/src/gui_gtk4_tb.c new file mode 100644 index 0000000000..e3ed80b471 --- /dev/null +++ b/src/gui_gtk4_tb.c @@ -0,0 +1,455 @@ +/* vi:set ts=8 sts=4 sw=4 noet: + * + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ + +#include "vim.h" + +#ifdef FEAT_TOOLBAR + +#include +#include "gui_gtk4_tb.h" + +/* + * GTK4 removed GtkToolbar, so this is our version of it. + */ +struct _VimToolbar +{ + GtkWidget parent; + + int style; // TOOLBAR_* flags + int iconsize; // TBIS_* values + + GList *items; + + GtkWidget *root; + GtkWidget *strip; + + GtkWidget *overflow_btn; + GtkWidget *overflow_box; +}; + +G_DEFINE_TYPE(VimToolbar, vim_toolbar, GTK_TYPE_WIDGET) + + static void vim_toolbar_size_allocate(GtkWidget *widget, int width, int height, int baseline); + static void vim_toolbar_measure(GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *minimum_baseline, int *natural_baseline); + + static void +vim_toolbar_dispose(GObject *object) +{ + VimToolbar *self = VIM_TOOLBAR(object); + + g_clear_list(&self->items, g_object_unref); + g_clear_pointer(&self->root, gtk_widget_unparent); + + G_OBJECT_CLASS(vim_toolbar_parent_class)->dispose(object); +} + + static void +vim_toolbar_class_init(VimToolbarClass *class) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(class); + GObjectClass *obj_class = G_OBJECT_CLASS(class); + + widget_class->size_allocate = vim_toolbar_size_allocate; + widget_class->measure = vim_toolbar_measure; + + obj_class->dispose = vim_toolbar_dispose; + + gtk_widget_class_set_css_name(widget_class, "toolbar"); +} + + static void +vim_toolbar_init(VimToolbar *self) +{ + GtkWidget *popover; + + self->style = TOOLBAR_ICONS | TOOLBAR_TOOLTIPS; + self->iconsize = TBIS_MEDIUM; + + self->root = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4); + gtk_widget_set_parent(self->root, GTK_WIDGET(self)); + + self->strip = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_hexpand(self->strip, TRUE); + gtk_widget_set_halign(self->strip, GTK_ALIGN_START); + gtk_widget_set_overflow(self->strip, GTK_OVERFLOW_HIDDEN); + gtk_box_append(GTK_BOX(self->root), self->strip); + + self->overflow_btn = gtk_menu_button_new(); + gtk_widget_set_hexpand(self->overflow_btn, FALSE); + gtk_widget_set_halign(self->overflow_btn, GTK_ALIGN_END); + gtk_widget_add_css_class(self->overflow_btn, "flat"); + gtk_box_append(GTK_BOX(self->root), self->overflow_btn); + g_object_set_data(G_OBJECT(self->overflow_btn), + "toolbar-width", GINT_TO_POINTER(-1)); + + popover = gtk_popover_new(); + self->overflow_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4); + gtk_popover_set_child(GTK_POPOVER(popover), self->overflow_box); + gtk_popover_set_has_arrow(GTK_POPOVER(popover), FALSE); + + gtk_menu_button_set_popover(GTK_MENU_BUTTON(self->overflow_btn), popover); +} + + GtkWidget * +vim_toolbar_new(void) +{ + return g_object_new(VIM_TYPE_TOOLBAR, NULL); +} + +/* + * Inser the widget at the given index, then queue a size allocate to check for + * overflowing items. + */ + static void +vim_toolbar_insert(VimToolbar *self, GtkWidget *widget, int idx) +{ + GtkWidget *cur_child = gtk_widget_get_first_child(self->strip); + int i = 0; + + while (cur_child != NULL && i != idx - 1) + { + cur_child = gtk_widget_get_next_sibling(cur_child); + i++; + } + + gtk_box_insert_child_after(GTK_BOX(self->strip), widget, cur_child); + self->items = g_list_insert(self->items, g_object_ref(widget), idx); + gtk_widget_queue_allocate(GTK_WIDGET(self)); +} + +/* + * Update "btn" according to "style" and "iconsize". + */ + static void +set_button_style(GtkWidget *btn, int style, int iconsize, gboolean invalidate) +{ + GtkWidget *box; + GtkWidget *icon; + GtkWidget *label; + + if (GTK_IS_SEPARATOR(btn)) + return; + + box = gtk_button_get_child(GTK_BUTTON(btn)); + if (style & TOOLBAR_HORIZ) + { + gtk_orientable_set_orientation(GTK_ORIENTABLE(box), + GTK_ORIENTATION_HORIZONTAL); + gtk_box_set_spacing(GTK_BOX(box), 8); + } + else + { + gtk_orientable_set_orientation(GTK_ORIENTABLE(box), + GTK_ORIENTATION_VERTICAL); + gtk_box_set_spacing(GTK_BOX(box), 4); + } + + gtk_widget_set_has_tooltip(btn, style & TOOLBAR_TOOLTIPS); + + icon = g_object_get_data(G_OBJECT(btn), "icon"); + if (icon != NULL) + { + if (style & TOOLBAR_ICONS) + { + GtkIconSize size; + + switch (iconsize) + { + case TBIS_TINY: + case TBIS_SMALL: + case TBIS_MEDIUM: + size = GTK_ICON_SIZE_NORMAL; + break; + case TBIS_LARGE: + case TBIS_HUGE: + case TBIS_GIANT: + size = GTK_ICON_SIZE_LARGE; + break; + default: + size = GTK_ICON_SIZE_NORMAL; + break; + } + gtk_image_set_icon_size(GTK_IMAGE(icon), size); + gtk_widget_set_visible(icon, TRUE); + } + else + gtk_widget_set_visible(icon, FALSE); + } + + label = g_object_get_data(G_OBJECT(btn), "label"); + if (label != NULL) + gtk_widget_set_visible(label, style & TOOLBAR_TEXT); + + // Used to cache width in toolbar ("self->strip"). -1 means not calculated + // yet. + if (invalidate) + g_object_set_data(G_OBJECT(btn), "toolbar-width", GINT_TO_POINTER(-1)); +} + +/* + * Add a new toolbar button at the given index and return the widget. "icon" and + * "text" may be NULL.. + */ + GtkWidget * +vim_toolbar_insert_button( + VimToolbar *self, + GtkWidget *icon, + const char *text, + int idx) +{ + GtkWidget *btn = gtk_button_new(); + GtkWidget *box; + + gtk_widget_add_css_class(btn, "flat"); + box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + + gtk_button_set_child(GTK_BUTTON(btn), box); + + if (icon != NULL) + { + gtk_widget_set_valign (icon, GTK_ALIGN_CENTER); + gtk_widget_set_vexpand (icon, TRUE); + gtk_box_append(GTK_BOX(box), icon); + g_object_set_data(G_OBJECT(btn), "icon", icon); + } + if (text != NULL) + { + GtkWidget *label = gtk_label_new(text); + + gtk_widget_set_valign (label, GTK_ALIGN_CENTER); + gtk_widget_set_vexpand (label, TRUE); + gtk_box_append(GTK_BOX(box), label); + g_object_set_data(G_OBJECT(btn), "label", label); + } + + set_button_style(btn, self->style, self->iconsize, TRUE); + + vim_toolbar_insert(self, btn, idx); + return btn; +} + +/* + * Insert a toolbar separator at the given index and return the widget. + */ + GtkWidget * +vim_toolbar_insert_separator(VimToolbar *self, int idx) +{ + GtkWidget *sep = gtk_separator_new(GTK_ORIENTATION_VERTICAL); + + g_object_set_data(G_OBJECT(sep), "toolbar-width", GINT_TO_POINTER(-1)); + vim_toolbar_insert(self, sep, idx); + return sep; +} + +/* + * Update the style and iconsize of the toolbar + */ + void +vim_toolbar_set_style(VimToolbar *self, int style, int iconsize) +{ + GtkWidget *cur_child = gtk_widget_get_first_child(self->strip); + + if (style == self->style && self->iconsize == iconsize) + return; + + self->style = style; + self->iconsize = iconsize; + + while (cur_child != NULL) + { + if (!GTK_IS_SEPARATOR(cur_child)) + set_button_style(cur_child, style, iconsize, TRUE); + cur_child = gtk_widget_get_next_sibling(cur_child); + } + + cur_child = gtk_widget_get_first_child(self->overflow_box); + while (cur_child != NULL) + { + if (!GTK_IS_SEPARATOR(cur_child)) + set_button_style(cur_child, style, iconsize, TRUE); + cur_child = gtk_widget_get_next_sibling(cur_child); + } + // Sizes may have changed + gtk_widget_queue_allocate(GTK_WIDGET(self)); +} + +/* + * If "overflow" is TRUE, then move "item" from the toolbar to the overflow, and + * vice versa. + */ + static void +vim_toolbar_move_item_to( + VimToolbar *self, + GtkWidget *item, + gboolean overflow) +{ + GtkBox *from, *to; + + to = overflow ? GTK_BOX(self->overflow_box) : GTK_BOX(self->strip); + if (gtk_widget_get_parent(item) == GTK_WIDGET(to)) + return; + + from = overflow ? GTK_BOX(self->strip) : GTK_BOX(self->overflow_box); + + gtk_box_remove(from, item); + gtk_box_append(to, item); + + if (GTK_IS_SEPARATOR(item)) + gtk_widget_set_visible(item, !overflow); + else + { + if (overflow) + { + int style = self->style; + + // Force set these flags for the overflow menu, to mimic what GTK3 + // GtkToolbar does. + style |= TOOLBAR_HORIZ; + style |= TOOLBAR_TEXT; + style |= TOOLBAR_ICONS; + set_button_style(item, style, self->iconsize, FALSE); + } + else + set_button_style(item, self->style, self->iconsize, FALSE); + } +} + + static int +get_item_width(GtkWidget *item) +{ + int toolbar_width = -1; + + // Always use cached width for item, because width in overflow menu is + // different (GtkBox is in horizontal layout). Also use it for separators, + // since if its not visible, then width is zero. + toolbar_width = GPOINTER_TO_INT( + g_object_get_data(G_OBJECT(item), "toolbar-width")); + + if (toolbar_width == -1) + { + GtkRequisition min_req, nat_req; + gtk_widget_get_preferred_size(item, &min_req, &nat_req); + toolbar_width = MAX(min_req.width, nat_req.width); + + // Save width for later + g_object_set_data(G_OBJECT(item), + "toolbar-width", GINT_TO_POINTER(toolbar_width)); + } + return toolbar_width; +} + + static void +vim_toolbar_size_allocate( + GtkWidget *widget, + int width, + int height, + int baseline) +{ + VimToolbar *self = VIM_TOOLBAR(widget); + GtkAllocation alloc; + int used = 0; + int avail; + GList *overflow_ele = NULL; + GtkWidget *child; + + avail = width - get_item_width(self->overflow_btn); + + for (GList *ele = self->items; ele != NULL; ele = ele->next) + { + GtkWidget *item = ele->data; + int toolbar_width = get_item_width(item); + + if (used + toolbar_width > avail) + { + overflow_ele = ele; + break; + } + else + vim_toolbar_move_item_to(self, item, FALSE); + used += toolbar_width; + } + + if (overflow_ele != NULL) + { + int remaining = width - used; + gboolean need_overflow_btn = FALSE; + + // Move all items in the overflow to the toolbar, so we can add them + // in the correct order back again. Also check if the overflow button is + // still needed (can fit all toolbar items by disabling it). + while ((child = gtk_widget_get_first_child(self->overflow_box)) + != NULL) + vim_toolbar_move_item_to(self, child, FALSE); + + for (GList *ele = overflow_ele; ele != NULL; ele = ele->next) + { + remaining -= get_item_width(ele->data); + if (remaining < 0) + { + need_overflow_btn = TRUE; + break; + } + } + + if (need_overflow_btn) + for (; overflow_ele != NULL; overflow_ele = overflow_ele->next) + vim_toolbar_move_item_to(self, overflow_ele->data, TRUE); + gtk_widget_set_visible(self->overflow_btn, need_overflow_btn); + } + else + gtk_widget_set_visible(self->overflow_btn, FALSE); + + alloc.x = alloc.y = 0; + alloc.width = width; + alloc.height = height; + + gtk_widget_size_allocate(self->root, &alloc, baseline); +} + + static void +vim_toolbar_measure( + GtkWidget *widget, + GtkOrientation orientation, + int for_size, + int *min, + int *nat, + int *min_baseline, + int *nat_baseline) +{ + VimToolbar *self = VIM_TOOLBAR(widget); + int strip_min = 0, strip_nat = 0; + int obtn_min = 0, obtn_nat = 0; + + gtk_widget_measure(self->strip, orientation, for_size, + &strip_min, &strip_nat, NULL, NULL); + gtk_widget_measure(self->overflow_btn, orientation, for_size, + &obtn_min, &obtn_nat, NULL, NULL); + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + if (min != NULL) + *min = obtn_min; + if (nat != NULL) + *nat = strip_nat + obtn_nat; + } + else + { + if (min != NULL) + *min = MAX(strip_min, obtn_min); + if (nat != NULL) + *nat = MAX(strip_nat, obtn_nat); + } + + if (min_baseline != NULL) + *min_baseline = -1; + if (nat_baseline != NULL) + *nat_baseline = -1; +} + +#endif // FEAT_TOOLBAR diff --git a/src/gui_gtk4_tb.h b/src/gui_gtk4_tb.h new file mode 100644 index 0000000000..d3ff4f782f --- /dev/null +++ b/src/gui_gtk4_tb.h @@ -0,0 +1,31 @@ +/* vi:set ts=8 sts=4 sw=4 noet: + * + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ + +#ifndef GUI_GTK4_TB_H +#define GUI_GTK4_TB_H + +#include "vim.h" + +#ifdef FEAT_TOOLBAR + +# include + +# define VIM_TYPE_TOOLBAR (vim_toolbar_get_type()) +G_DECLARE_FINAL_TYPE(VimToolbar, vim_toolbar, VIM, TOOLBAR, GtkWidget) + +typedef struct _VimToolbarItem VimToolbarItem; + +GtkWidget *vim_toolbar_new(void); +GtkWidget *vim_toolbar_insert_button(VimToolbar *self, GtkWidget *icon, const char *text, int idx); +GtkWidget *vim_toolbar_insert_separator(VimToolbar *self, int idx); +void vim_toolbar_set_style(VimToolbar *self, int style, int iconsize); + +#endif + +#endif diff --git a/src/version.c b/src/version.c index c404029ad8..e4f09bcab5 100644 --- a/src/version.c +++ b/src/version.c @@ -759,6 +759,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 669, /**/ 668, /**/