Use Pango native ellipsizing support; highlight the active window's menu item. For the ellipsis: I noticed that the width at which truncation occurs causes display oddness where the "remove workspace" text is somewhat longer than the truncated text. Also, it doesn't properly cope with UTF-8 because it assumes that one character == one byte. This patch fixes this. Ellipsized items still have tooltips, though the method by which they're acquired is different (needs to be handled when the menu item is mapped). For the highlight: I noticed a question about why the active window isn't #highlighted (in xine) and decided to have a look - this is the reason for #the markup usage. menulist_set_up_label() is needed by both changes, so it makes sense to me to lump them together. Signed-off-by: Darren Salt Index: plugins/windowlist/windowlist.c =================================================================== --- plugins/windowlist/windowlist.c (revision 22671) +++ plugins/windowlist/windowlist.c (working copy) @@ -36,6 +36,7 @@ #ifdef HAVE_CONFIG_H #include #endif +#include #include #include @@ -301,25 +302,86 @@ /** * Window List Menu functions **/ +struct menulist_menu_item_data_s { + GtkTooltips *tooltips; + GObject *menu_item; + GtkLabel *label; + char name[]; +}; + +static gboolean +menulist_menu_item_label_mapped (GtkWidget *item, GdkEvent *event, + struct menulist_menu_item_data_s *map_data) +{ + PangoLayout *layout = gtk_label_get_layout (map_data->label); + PangoEllipsizeMode mode = pango_layout_get_ellipsize (layout); + int ellipsized_width, full_width; + + /* get the possibly-ellipsized width of the text */ + pango_layout_get_size (layout, &ellipsized_width, NULL); + + /* temporarily replace the ellipsize mode - we want the full width */ + pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_NONE); + pango_layout_get_size (layout, &full_width, NULL); + pango_layout_set_ellipsize (layout, mode); + + /* if the widths differ, we have a truncated item which needs a tooltip */ + gtk_tooltips_set_tip (map_data->tooltips, item, + ellipsized_width != full_width + ? map_data->name : NULL, + NULL); + + /* restore the mode */ + return FALSE; +} + +static void +menulist_set_up_label (GtkWidget *widget, gpointer data) +{ + struct menulist_menu_item_data_s **map_data = data; + if (!map_data) + return; + + if (GTK_IS_LABEL (widget)) + { + GtkLabel *label = (*map_data)->label = GTK_LABEL (widget); + + gtk_label_set_use_markup (label, TRUE); + gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_MIDDLE); + gtk_label_set_max_width_chars (label, 24); + + g_signal_connect_data ((*map_data)->menu_item, "map-event", + G_CALLBACK (menulist_menu_item_label_mapped), + *map_data, (GClosureNotify) g_free, 0); + + *map_data = NULL; + } + else if (GTK_IS_CONTAINER (widget)) + { + gtk_container_forall (GTK_CONTAINER (widget), menulist_set_up_label, + data); + } +} + static GtkWidget * menulist_menu_item (NetkWindow *window, Windowlist *wl, gint size) { GtkWidget *mi; - const char *window_name = NULL; + char *window_name = NULL; GString *label; GdkPixbuf *icon = NULL, *tmp = NULL; - gboolean truncated = FALSE; + struct menulist_menu_item_data_s *map_data; - window_name = netk_window_get_name (window); + window_name = g_markup_escape_text (netk_window_get_name (window), -1); label = g_string_new (window_name); - - if (label->len >= 20) + g_free (window_name); + + if (netk_window_is_active (window)) { - g_string_truncate (label, 20); - g_string_append (label, " ..."); - truncated = TRUE; + g_string_prepend (label, ""); + g_string_append (label, ""); } if (netk_window_is_minimized (window)) @@ -368,16 +430,22 @@ mi = gtk_menu_item_new_with_label (text ? text : "?"); g_free (text); } - - if (truncated) - { - char *text = menulist_utf8_string ((char *)window_name); - gtk_tooltips_set_tip (wl->tooltips, mi, text ? text : "?", NULL); - g_free (text); - } g_string_free (label, TRUE); - + + window_name = (char *)netk_window_get_name (window); /* should be const */ + map_data = g_malloc (sizeof (struct menulist_menu_item_data_s) + + strlen (window_name) + 1); + map_data->tooltips = wl->tooltips; + map_data->menu_item = G_OBJECT (mi); + strcpy (map_data->name, window_name); + + gtk_container_forall (GTK_CONTAINER (mi), menulist_set_up_label, + &map_data); + + /* if the label was found, map_data is now NULL */ + g_free (map_data); + return mi; }