* Reload application icons properly when icon theme is changed.
authorHong Jen Yee (PCMan) <pcman.tw@gmail.com>
Wed, 2 Jul 2008 23:53:27 +0000 (23:53 +0000)
committerHong Jen Yee (PCMan) <pcman.tw@gmail.com>
Wed, 2 Jul 2008 23:53:27 +0000 (23:53 +0000)
* Some code cleanup.
* Fix invalid pointer in seperator plugin.
* Some minor fixes.

configure.ac
po/pt_BR.po
src/misc.c
src/misc.h
src/plugins/launchbar.c
src/plugins/menu.c
src/plugins/ptk-app-menu.c
src/plugins/separator.c

index 3b61974..91dc636 100644 (file)
@@ -1,5 +1,5 @@
 AC_PREREQ(2.53)
-AC_INIT(lxpanel, 0.3.7, http://lxde.org/)
+AC_INIT(lxpanel, 0.3.8, http://lxde.org/)
 AM_INIT_AUTOMAKE
 AC_CONFIG_SRCDIR([src/bg.c])
 AC_CONFIG_HEADER([config.h])
index ab02521..6df504b 100644 (file)
@@ -8,7 +8,7 @@ msgstr ""
 "Project-Id-Version: lxpanel\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2008-04-20 23:19+0800\n"
-"PO-Revision-Date: 2008-05-05 19:17-0300\n"
+"PO-Revision-Date: 2008-05-22 12:45-0300\n"
 "Last-Translator: \n"
 "Language-Team: Slovak <sk-i18n@lists.linux.sk>\n"
 "MIME-Version: 1.0\n"
@@ -711,7 +711,7 @@ msgstr "Protocolo:"
 
 #: ../src/plugins/netstat/netstat.c:294
 #: ../src/plugins/netstat/netstat.c:305
-msgid "Broadcast:"
+msgid "Boradcast:"
 msgstr "Transmissão:"
 
 #: ../src/plugins/netstat/netstat.c:296
@@ -935,11 +935,20 @@ msgstr "carregamento finalizado"
 msgid "not charging"
 msgstr "não carregado"
 
-#: ../src/plugins/batt/batt.c:346
+#: ../src/plugins/batt/batt.c:341
+msgid "charging"
+msgstr "carregada"
+
+#: ../src/plugins/batt/batt.c:348
 #, c-format
 msgid "Battery: %d%% charged, %d:%02d left"
 msgstr "Bateria: %d%% carregada, %d:%02d esquerda"
 
+#: ../src/plugins/batt/batt.c:355
+#, c-format
+msgid "Battery: %d%% charged"
+msgstr "Bateria: %d%% carregada"
+
 #: ../src/plugins/batt/batt.c:394
 #, c-format
 msgid "No batteries found"
index a22beeb..4d1e45e 100644 (file)
 #include <stdarg.h>
 
 #include "misc.h"
+#include "glib-mem.h"
 #include "panel.h"
 
-//#define DEBUG
 #include "dbg.h"
 
+/* data used by themed images buttons */
+typedef struct
+{
+    char* fname;
+    guint theme_changed_handler;
+    GdkPixbuf* pixbuf;
+    GdkPixbuf* hilight;
+    gulong hicolor;
+    gboolean keep_ratio;
+}ImgData;
+
+static GQuark img_data_id = 0;
 
 /* X11 data types */
 Atom a_UTF8_STRING;
@@ -268,7 +280,7 @@ extern  int
 lxpanel_get_line(char**fp, line *s)
 {
     gchar *tmp, *tmp2;
-    ENTER;
+
     s->type = LINE_NONE;
     if (!fp)
         RET(s->type);
@@ -297,10 +309,11 @@ lxpanel_get_line(char**fp, line *s)
             s->type = LINE_BLOCK_START;
         } else {
             ERR( "parser: unknown token: '%c'\n", *tmp2);
+            g_debug("\"%s\"", tmp2);
         }
         break;
     }
-    RET(s->type);
+    return s->type;
 }
 
 int
@@ -475,7 +488,6 @@ Xclimsgwm(Window win, Atom type, Atom arg)
 void *
 get_utf8_property(Window win, Atom atom)
 {
-
     Atom type;
     int format;
     gulong nitems;
@@ -971,24 +983,72 @@ gdk_pixbuf_scale_ratio(GdkPixbuf *p, int width, int height, GdkInterpType itype,
 
 }
 
+void img_data_free( ImgData* data )
+{
+    g_free( data->fname );
+    if( data->theme_changed_handler )
+        g_signal_handler_disconnect( gtk_icon_theme_get_default(), data->theme_changed_handler );
+    if( data->pixbuf )
+        g_object_unref( data->pixbuf );
+    if( data->hilight )
+        g_object_unref( data->hilight );
+    g_slice_free( ImgData, data );
+}
 
-GtkWidget *
-gtk_image_new_from_file_scaled(const gchar *file, gint width,
-      gint height, gboolean keep_ratio)
+static void on_theme_changed(GtkIconTheme* theme, GtkWidget* img)
 {
-    GtkWidget *img;
-    GdkPixbuf /*- *pb, -*/ *pb_scaled;
-    // gfloat w, h, rw, rh;
+    ImgData* data = (ImgData*)g_object_get_qdata( img, img_data_id );
+    /* g_debug("reload icon: %s", data->fname); */
+    _gtk_image_set_from_file_scaled( img, data->fname,
+                    img->allocation.width, img->allocation.height, data->keep_ratio );
+}
+
+/* FIXME: currently, the size of those images cannot be changed dynamically */
+static void on_img_size_allocated(GtkWidget* img, GtkAllocation *allocation, ImgData* data)
+{
+    if( img->allocation.width == allocation->width &&
+        img->allocation.height == allocation->height )
+        return;
+    g_signal_handlers_block_by_func( img, on_img_size_allocated, data );
+    /* g_debug("size-allocated: %d, %d", allocation->width, allocation->height); */
+    _gtk_image_set_from_file_scaled( img, data->fname,
+                    allocation->height, allocation->height, data->keep_ratio );
+    g_signal_handlers_unblock_by_func( img, on_img_size_allocated, data );
+}
+
+void
+_gtk_image_set_from_file_scaled( GtkWidget* img, const gchar *file, gint width,
+        gint height, gboolean keep_ratio)
+{
+    GdkPixbuf *pb_scaled;
     GtkIconInfo *inf = NULL;
+    ImgData* data = (ImgData*)g_object_get_qdata( img, img_data_id );
 
-    ENTER;
+    if( data->pixbuf )
+    {
+        g_object_unref( data->pixbuf );
+        data->pixbuf = NULL;
+    }
+    /* if there is a cached hilighted version of this pixbuf, free it */
+    if( data->hilight )
+    {
+        g_object_unref( data->hilight );
+        data->hilight = NULL;
+    }
+
+    /* if they are the same string, eliminate unnecessary copy. */
+    if( data->fname != file )
+    {
+        g_free( data->fname );
+        data->fname = g_strdup(file);
+    }
+    data->keep_ratio = TRUE;
 
     if( G_UNLIKELY( ! file ) )
         goto err;
 
-    if ( ! g_file_test(file, G_FILE_TEST_EXISTS))
+    if( ! g_file_test(file, G_FILE_TEST_EXISTS) )
     {
-        /* FIXME: should reload icon when theme gets changed */
         inf = gtk_icon_theme_lookup_icon(gtk_icon_theme_get_default(),
                                          file, MAX(width, height), 0);
         if( ! inf )
@@ -996,41 +1056,55 @@ gtk_image_new_from_file_scaled(const gchar *file, gint width,
         file = gtk_icon_info_get_filename(inf);
     }
 
-#if GTK_CHECK_VERSION( 2, 6, 0 )
     pb_scaled = gdk_pixbuf_new_from_file_at_scale( file, width, height,
                                                    keep_ratio, NULL );
     if( !pb_scaled )
         goto err;
-#else
-    if (!(pb = gdk_pixbuf_new_from_file(file, NULL)))
-        goto err;
 
-    if (keep_ratio) {
-        w = gdk_pixbuf_get_width(pb);
-        h = gdk_pixbuf_get_height(pb);
-        rw = w / width;
-        rh = h / height;
-        if (rw > rh)
-            height = h / rw;
-        else
-            width =  w / rh;
-    }
-    pb_scaled = gdk_pixbuf_scale_simple(pb, width, height,
-                                        GDK_INTERP_BILINEAR);
-    g_object_unref(pb);
-#endif
-    img = gtk_image_new_from_pixbuf(pb_scaled);
-    g_object_unref(pb_scaled);
+    data->pixbuf = pb_scaled;
+    gtk_image_set_from_pixbuf(img, pb_scaled);
 
-    if( inf )
+    if( inf ) /* This image is loaded from icon theme */
+    {
+        /* update the image when icon theme get changed */
+        if( ! data->theme_changed_handler )
+        {
+            data->theme_changed_handler = g_signal_connect( gtk_icon_theme_get_default(), "changed",
+                                            G_CALLBACK(on_theme_changed), img );
+        }
         gtk_icon_info_free ( inf );
+    }
+    else /* this is not loaded from icon theme */
+    {
+        if( data->theme_changed_handler )
+        {
+            g_signal_handler_disconnect( gtk_icon_theme_get_default(), data->theme_changed_handler );
+            data->theme_changed_handler = 0;
+        }
+    }
 
-    RET(img);
+    return;
 
  err:
-    img = gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE,
+    gtk_image_set_from_stock(img, GTK_STOCK_MISSING_IMAGE,
                                    GTK_ICON_SIZE_BUTTON);
-    RET(img);
+}
+
+GtkWidget *
+_gtk_image_new_from_file_scaled(const gchar *file, gint width,
+        gint height, gboolean keep_ratio)
+{
+    GtkWidget *img;
+    ImgData* data;
+
+    img = gtk_image_new();
+    data = g_slice_new0( ImgData );
+    if( G_UNLIKELY( 0 == img_data_id ) )
+        img_data_id = g_quark_from_static_string("ImgData");
+    g_object_set_qdata_full( img, img_data_id, data, img_data_free );
+    _gtk_image_set_from_file_scaled( img, file, width, height, keep_ratio );
+    g_signal_connect( img, "size-allocate", G_CALLBACK(on_img_size_allocated), data );
+    return img;
 }
 
 
@@ -1085,55 +1159,64 @@ static gboolean
 fb_button_enter (GtkImage *widget, GdkEventCrossing *event)
 {
     GdkPixbuf *dark, *light;
-    int i;
+    int i, height, rowstride;
     gulong hicolor;
     guchar *src, *up, extra[3];
+    ImgData* data;
 
-    ENTER;
     if (gtk_image_get_storage_type(widget) != GTK_IMAGE_PIXBUF)
-        RET(TRUE);
-    light = g_object_get_data(G_OBJECT(widget), "light");
-    dark = gtk_image_get_pixbuf(widget);
-    if (!light) {
-        hicolor = (gulong) g_object_get_data(G_OBJECT(widget), "hicolor");
+        return TRUE;
+
+    data = (ImgData*)g_object_get_qdata( widget, img_data_id );
+    if( G_UNLIKELY( ! data ) )
+        return TRUE;
+
+    if( ! data->hilight )
+    {
+        dark = data->pixbuf;
+        height = gdk_pixbuf_get_height( dark );
+        rowstride = gdk_pixbuf_get_rowstride( dark );
+        hicolor = data->hicolor;
+
         light = gdk_pixbuf_add_alpha(dark, FALSE, 0, 0, 0);
-        if (!light)
-            RET(TRUE);
-        src = gdk_pixbuf_get_pixels (light);
+        if( !light )
+            return TRUE;
+        src = gdk_pixbuf_get_pixels(light);
         for (i = 2; i >= 0; i--, hicolor >>= 8)
             extra[i] = hicolor & 0xFF;
-        for (up = src + gdk_pixbuf_get_height(light) * gdk_pixbuf_get_rowstride (light);
-             src < up; src+=4) {
+        for( up = src + height * rowstride; src < up; src+=4 )
+        {
             if (src[3] == 0)
                 continue;
-            for (i = 0; i < 3; i++) {
+            for (i = 0; i < 3; i++)
+            {
                 if (src[i] + extra[i] >= 255)
                     src[i] = 255;
                 else
                     src[i] += extra[i];
             }
         }
-        g_object_set_data_full (G_OBJECT(widget), "light", light, g_object_unref);
+        data->hilight = light;
     }
-    g_object_ref(dark);
-    g_object_set_data_full (G_OBJECT(widget), "dark", dark, g_object_unref);
-    gtk_image_set_from_pixbuf(widget, light);
-    RET(TRUE);
 
+    if( G_LIKELY( data->hilight ) )
+        gtk_image_set_from_pixbuf(widget, data->hilight);
+    return TRUE;
 }
 
 static gboolean
 fb_button_leave (GtkImage *widget, GdkEventCrossing *event, gpointer user_data)
 {
-    GdkPixbuf *dark;
+    ImgData* data;
 
-    ENTER;
     if (gtk_image_get_storage_type(widget) != GTK_IMAGE_PIXBUF)
-        RET(TRUE);
-    dark = g_object_get_data(G_OBJECT(widget), "dark");
-    if (dark)
-        gtk_image_set_from_pixbuf(widget, dark);
-    RET(TRUE);
+        return TRUE;
+
+    data = (ImgData*)g_object_get_qdata( widget, img_data_id );
+    if( data && data->pixbuf )
+        gtk_image_set_from_pixbuf(widget, data->pixbuf);
+
+    return TRUE;
 }
 
 
@@ -1142,16 +1225,18 @@ fb_button_new_from_file(gchar *fname, int width, int height, gulong hicolor, gbo
 {
     GtkWidget *b, *image;
     ENTER;
-//    b = gtk_vbox_new(FALSE, 0); //gtk_bgbox_new();
     b = gtk_event_box_new();
     gtk_container_set_border_width(GTK_CONTAINER(b), 0);
     GTK_WIDGET_UNSET_FLAGS (b, GTK_CAN_FOCUS);
 
-    image = gtk_image_new_from_file_scaled(fname, width, height, keep_ratio);
-    gtk_misc_set_alignment(GTK_MISC(image), 0, 0);
-    g_object_set_data(G_OBJECT(image), "hicolor", (gpointer)hicolor);
+    image = _gtk_image_new_from_file_scaled(fname, width, height, keep_ratio);
     gtk_misc_set_padding (GTK_MISC(image), 0, 0);
-    if (hicolor > 0) {
+
+    if(hicolor > 0)
+    {
+        ImgData* data = (ImgData*)g_object_get_qdata( image, img_data_id );
+        data->hicolor = hicolor;
+
         gtk_widget_add_events(b, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
         g_signal_connect_swapped (G_OBJECT (b), "enter-notify-event",
               G_CALLBACK (fb_button_enter), image);
@@ -1180,10 +1265,13 @@ fb_button_new_from_file_with_colorlabel(gchar *fname, int width, int height,
     GTK_WIDGET_UNSET_FLAGS (box, GTK_CAN_FOCUS);
     gtk_container_add(GTK_CONTAINER(b), box);
 
-    image = gtk_image_new_from_file_scaled(fname, width, height, keep_ratio);
-    g_object_set_data(G_OBJECT(image), "hicolor", (gpointer)hicolor);
+    image = _gtk_image_new_from_file_scaled(fname, width, height, keep_ratio);
     gtk_misc_set_padding (GTK_MISC(image), 0, 0);
-    if (hicolor > 0) {
+    if(hicolor > 0)
+    {
+        ImgData* data = (ImgData*)g_object_get_qdata( image, img_data_id );
+        data->hicolor = hicolor;
+
         gtk_widget_add_events(b, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
         g_signal_connect_swapped (G_OBJECT (b), "enter-notify-event",
               G_CALLBACK (fb_button_enter), image);
@@ -1219,10 +1307,13 @@ fb_button_new_from_file_with_label(gchar *fname, int width, int height,
     GTK_WIDGET_UNSET_FLAGS (box, GTK_CAN_FOCUS);
     gtk_container_add(GTK_CONTAINER(b), box);
 
-    image = gtk_image_new_from_file_scaled(fname, width, height, keep_ratio);
-    g_object_set_data(G_OBJECT(image), "hicolor", (gpointer)hicolor);
+    image = _gtk_image_new_from_file_scaled(fname, width, height, keep_ratio);
     gtk_misc_set_padding (GTK_MISC(image), 0, 0);
-    if (hicolor > 0) {
+    if(hicolor > 0)
+    {
+        ImgData* data = (ImgData*)g_object_get_qdata( image, img_data_id );
+        data->hicolor = hicolor;
+
         gtk_widget_add_events(b, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
         g_signal_connect_swapped (G_OBJECT (b), "enter-notify-event",
               G_CALLBACK (fb_button_enter), image);
index 23c777c..97fd323 100644 (file)
@@ -80,8 +80,10 @@ void calculate_position(Panel *np);
 gchar *expand_tilda(gchar *file);
 GdkPixbuf *gdk_pixbuf_scale_ratio(GdkPixbuf *p, int width, int height, GdkInterpType itype,
                                   gboolean keep_ratio);
-GtkWidget *gtk_image_new_from_file_scaled(const gchar *file, gint width, gint height,
+GtkWidget *_gtk_image_new_from_file_scaled(const gchar *file, gint width, gint height,
                                           gboolean keep_ratio);
+GtkWidget *_gtk_image_new_from_file_scaled(const gchar *file, gint width,
+                                           gint height, gboolean keep_ratio);
 void get_button_spacing(GtkRequisition *req, GtkContainer *parent, gchar *name);
 guint32 gcolor2rgb24(GdkColor *color);
 GtkWidget *fb_button_new_from_file(gchar *fname, int width, int height, gulong hicolor,
index 51ce140..3219c3b 100644 (file)
@@ -156,7 +156,6 @@ launchbar_destructor(Plugin *p)
     launchbar *lb = (launchbar *)p->priv;
 
     ENTER;
-    /* g_object_unref( lb->tips ); */
 
     gtk_widget_destroy(lb->box);
     g_slist_foreach( lb->btns, (GFunc)btn_free, NULL );
@@ -316,7 +315,6 @@ read_button(Plugin *p, char** fp)
         w = p->panel->aw;
         h = 10000;
     }
-
     button = fb_button_new_from_file( fname, w, h, 0x202020, TRUE );
     btn->widget = button;
 
@@ -336,7 +334,7 @@ read_button(Plugin *p, char** fp)
     g_signal_connect ( button, "drag_data_received",
           G_CALLBACK (drag_data_received_cb),  (gpointer) btn );
 
-    gtk_box_pack_start(GTK_BOX(lb->box), button, FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(lb->box), button, FALSE, TRUE, 0);
 
     /* append is more time-consuming, but we really care about the order. */
     lb->btns = g_slist_append( lb->btns, btn );
@@ -369,9 +367,6 @@ launchbar_constructor(Plugin *p, char **fp)
             "id=pcmanfm.desktop\n"
         "}\n"
         "button {\n"
-            "id=gnome-terminal.desktop\n"
-        "}\n"
-        "button {\n"
             "id=firefox.desktop\n"
         "}\n"
         "}\n";
@@ -385,12 +380,10 @@ launchbar_constructor(Plugin *p, char **fp)
         "}\n"
         "widget '*launchbar*' style 'launchbar-style'";
 
-    ENTER;
     gtk_rc_parse_string(launchbar_rc);
 
     p->pwid = gtk_event_box_new();
     GTK_WIDGET_SET_FLAGS( p->pwid, GTK_NO_WINDOW );
-
     gtk_widget_set_name(p->pwid, "launchbar");
     get_button_spacing(&req, GTK_CONTAINER(p->pwid), "");
 
@@ -438,12 +431,11 @@ launchbar_constructor(Plugin *p, char **fp)
         }
     }
 
-    RET(1);
+    return TRUE;
 
  error:
     launchbar_destructor(p);
-    RET(0);
-
+    return FALSE;
 }
 
 static void save_config( Plugin* p, FILE* fp )
index 813b717..63ae6c4 100644 (file)
@@ -238,7 +238,7 @@ make_button(Plugin *p, gchar *fname, gchar *name, GdkColor* tint, GtkWidget *men
         if( g_str_has_suffix( name, ".directory" ) )
         {
             GKeyFile* kf = g_key_file_new();
-            char* dir_file = g_build_filename( "desktop-directories", name, NULL ); 
+            char* dir_file = g_build_filename( "desktop-directories", name, NULL );
             if( g_key_file_load_from_data_dirs( kf, dir_file, NULL, 0, NULL ) )
             {
                 title = g_key_file_get_locale_string( kf, "Desktop Entry", "Name", NULL, NULL );
@@ -332,7 +332,7 @@ read_item(Plugin *p, char** fp)
     if (fname) {
         GtkWidget *img;
 
-        img = gtk_image_new_from_file_scaled(fname, m->iconsize, m->iconsize, TRUE);
+        img = _gtk_image_new_from_file_scaled(fname, m->iconsize, m->iconsize, TRUE);
         gtk_widget_show(img);
         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
         g_free(fname);
@@ -523,7 +523,7 @@ read_submenu(Plugin *p, char** fp, gboolean as_item)
         mi = gtk_image_menu_item_new_with_label(name ? name : "");
         if (fname) {
             GtkWidget *img;
-            img = gtk_image_new_from_file_scaled(fname, m->iconsize, m->iconsize, TRUE);
+            img = _gtk_image_new_from_file_scaled(fname, m->iconsize, m->iconsize, TRUE);
             gtk_widget_show(img);
             gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
             g_free(fname);
index 13d8284..5e63081 100644 (file)
@@ -268,7 +268,10 @@ static void  unload_old_icons( GtkWidget* menu )
     for( l = items; l; l = l->next )
     {
         GtkWidget* sub_menu = gtk_menu_item_get_submenu( GTK_MENU_ITEM(l->data) );
-        GtkWidget* img = gtk_image_menu_item_get_image( GTK_IMAGE_MENU_ITEM(l->data) );
+        GtkWidget* img;
+        if( ! GTK_IS_IMAGE_MENU_ITEM(l->data) )
+            continue;
+        img = gtk_image_menu_item_get_image( (GtkImageMenuItem*)l->data );
         if( ! g_object_get_qdata( G_OBJECT(l->data), PTK_APP_MENU_ITEM_ID ) )
             continue;
         if( img )
index bd220c3..ab8abfd 100644 (file)
@@ -49,7 +49,7 @@ separator_constructor(Plugin *p, char **fp)
             RET(0);
         }
     }
-    eb = gtk_event_box_new();
+    p->pwid = eb = gtk_event_box_new();
     GTK_WIDGET_SET_FLAGS( eb, GTK_NO_WINDOW );
     gtk_widget_add_events( p->pwid, GDK_BUTTON_PRESS_MASK );
     g_signal_connect( p->pwid, "button-press-event", G_CALLBACK( on_btn_press ), p );
@@ -62,7 +62,6 @@ separator_constructor(Plugin *p, char **fp)
     gtk_container_add (GTK_CONTAINER (eb), sep);
     p->priv = eb; /* just to alloc smth */
 
-    p->pwid = eb;
     RET(1);
 }