From 37aa31f045046014352259bcb168a7358b28c04f Mon Sep 17 00:00:00 2001 From: yagi-tan <66814493+yagi-tan@users.noreply.github.com> Date: Fri, 31 Oct 2025 18:01:30 +0900 Subject: [PATCH] Add fixed-width tab label option in GTK3 Currently, tab label maximum width option is ignored when building with GTK3, resulting in unlimited tab label width. This commit will add option to either use fixed-width tab label as per maximum width or fit-to-text up to maximum width, similar to GTK2. --- data/ui/pref.glade | 19 ++++++++++++++++++- src/app-config.c | 6 ++++++ src/app-config.h | 3 +++ src/pref.c | 3 +++ src/tab-page.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 70 insertions(+), 4 deletions(-) diff --git a/data/ui/pref.glade b/data/ui/pref.glade index 9ceb6237..51114b32 100644 --- a/data/ui/pref.glade +++ b/data/ui/pref.glade @@ -1111,6 +1111,23 @@ 1 + + + Use _fixed-width tab label + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + 0 + True + + + False + True + 2 + + True @@ -1165,7 +1182,7 @@ False True - 2 + 3 diff --git a/src/app-config.c b/src/app-config.c index 37785832..5dfd1ff4 100644 --- a/src/app-config.c +++ b/src/app-config.c @@ -678,6 +678,9 @@ void fm_app_config_load_from_key_file(FmAppConfig* cfg, GKeyFile* kf) /* ui */ fm_key_file_get_bool(kf, "ui", "always_show_tabs", &cfg->always_show_tabs); +#if GTK_CHECK_VERSION(3, 0, 0) + fm_key_file_get_bool(kf, "ui", "fixed_width_tab", &cfg->fixed_width_tab); +#endif fm_key_file_get_int(kf, "ui", "hide_close_btn", &cfg->hide_close_btn); fm_key_file_get_int(kf, "ui", "max_tab_chars", &cfg->max_tab_chars); @@ -1119,6 +1122,9 @@ void fm_app_config_save_profile(FmAppConfig* cfg, const char* name) g_string_append(buf, "\n[ui]\n"); g_string_append_printf(buf, "always_show_tabs=%d\n", cfg->always_show_tabs); +#if GTK_CHECK_VERSION(3, 0, 0) + g_string_append_printf(buf, "fixed_width_tab=%d\n", cfg->fixed_width_tab); +#endif g_string_append_printf(buf, "max_tab_chars=%d\n", cfg->max_tab_chars); /* g_string_append_printf(buf, "hide_close_btn=%d\n", cfg->hide_close_btn); */ g_string_append_printf(buf, "win_width=%d\n", cfg->win_width); diff --git a/src/app-config.h b/src/app-config.h index 3abb6d30..c100fddb 100644 --- a/src/app-config.h +++ b/src/app-config.h @@ -115,6 +115,9 @@ struct _FmAppConfig /* ui */ gboolean always_show_tabs; +#if GTK_CHECK_VERSION(3, 0, 0) + gboolean fixed_width_tab; +#endif gboolean hide_close_btn; int max_tab_chars; int win_width; diff --git a/src/pref.c b/src/pref.c index c16d470b..907821c1 100644 --- a/src/pref.c +++ b/src/pref.c @@ -789,6 +789,9 @@ void fm_edit_preference( GtkWindow* parent, int page ) /* 'Layout' tab */ INIT_BOOL(builder, FmAppConfig, hide_close_btn, NULL); INIT_BOOL(builder, FmAppConfig, always_show_tabs, NULL); +#if GTK_CHECK_VERSION(3, 0, 0) + INIT_BOOL_SHOW(builder, FmAppConfig, fixed_width_tab, NULL); +#endif INIT_SPIN(builder, FmAppConfig, max_tab_chars, NULL); #if FM_CHECK_VERSION(1, 0, 2) diff --git a/src/tab-page.c b/src/tab-page.c index 5c98dc63..b565cfe5 100644 --- a/src/tab-page.c +++ b/src/tab-page.c @@ -846,6 +846,37 @@ static void update_files_popup(FmFolderView* fv, GtkWindow* win, gtk_action_set_visible(gtk_action_group_get_action(act_grp, "Term"), FALSE); } +/* update tab label after changing directory/filter */ +static void update_tab_label(FmTabLabel *tab_label, const char *disp_name) +{ +#if GTK_CHECK_VERSION(3, 0, 0) + /* tab width dynamically follows string length up to max_tab_chars */ + if (!app_config->fixed_width_tab) + { + glong len = g_utf8_strlen(disp_name, -1); + + /* Pango sometimes ellipsizes string with length below max_tab_chars due to it using + average character width instead of string character count, so here we handle it manually. + This still has problem in handling i18n characters (e.g. CJK) where ellipsization + results in far lower (around half max_tab_chars) character count. In GTK2 it's even worse; + text just cuts off in the middle without ellipses when using PANGO_ELLIPSIZE_NONE. + Thus this feature is GTK3 only. */ + if (len <= app_config->max_tab_chars) + { + gtk_label_set_width_chars(tab_label->label, len); + gtk_label_set_ellipsize(tab_label->label, PANGO_ELLIPSIZE_NONE); + } + else + { + gtk_label_set_width_chars(tab_label->label, app_config->max_tab_chars); + gtk_label_set_ellipsize(tab_label->label, PANGO_ELLIPSIZE_END); + } + } +#endif + + fm_tab_label_set_text(tab_label, disp_name); +} + static gboolean open_folder_func(GAppLaunchContext* ctx, GList* folder_infos, gpointer user_data, GError** err) { FmMainWin* win = FM_MAIN_WIN(user_data); @@ -964,8 +995,14 @@ static void fm_tab_page_init(FmTabPage *page) /* create tab label */ tab_label = (FmTabLabel*)fm_tab_label_new(""); +#if GTK_CHECK_VERSION(3, 0, 0) + if (app_config->fixed_width_tab) + { + gtk_label_set_width_chars(tab_label->label, app_config->max_tab_chars); + gtk_label_set_ellipsize(tab_label->label, PANGO_ELLIPSIZE_END); + } +#else gtk_label_set_max_width_chars(tab_label->label, app_config->max_tab_chars); -#if ! GTK_CHECK_VERSION(3, 0, 0) gtk_label_set_ellipsize(tab_label->label, PANGO_ELLIPSIZE_END); #endif page->tab_label = tab_label; @@ -1030,7 +1067,7 @@ static void fm_tab_page_chdir_without_history(FmTabPage* page, FmPath* path) disp_name = text; } #endif - fm_tab_label_set_text(page->tab_label, disp_name); + update_tab_label(page->tab_label, disp_name); g_free(disp_name); #if FM_CHECK_VERSION(1, 2, 0) @@ -1449,7 +1486,7 @@ void fm_tab_page_set_filter_pattern(FmTabPage *page, const char *pattern) g_free(disp_name); disp_name = text; } - fm_tab_label_set_text(page->tab_label, disp_name); + update_tab_label(page->tab_label, disp_name); g_free(disp_name); } #endif