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
+
+
+
+ False
+ True
+ 2
+
+
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