rpms/lxpanel/devel lxpanel-0.5.5-64-bit-clean-regression.patch, NONE, 1.1 lxpanel-0.5.5-Terminal-true.patch, NONE, 1.1 lxpanel-0.5.5-UI-draw-cell-renderer.patch, NONE, 1.1 lxpanel-0.5.5-clock-poll-interval.patch, NONE, 1.1 lxpanel-0.5.5-configuration-not-in-sync.patch, NONE, 1.1 lxpanel-0.5.5-enum-value.patch, NONE, 1.1 lxpanel-0.5.5-enum-values.patch, NONE, 1.1 lxpanel-0.5.5-icon-only-case.patch, NONE, 1.1 lxpanel-0.5.5-inconsist-group-count.patch, NONE, 1.1 lxpanel-0.5.5-keyboard-map-changes.patch, NONE, 1.1 lxpanel-0.5.5-lxpanelctl-config.patch, NONE, 1.1 lxpanel-0.5.5-menu-code-cleanup.patch, NONE, 1.1 lxpanel-0.5.5-number-of-visible-items.patch, NONE, 1.1 lxpanel-0.5.5-task-deletion-urgency-timer.patch, NONE, 1.1 lxpanel-0.5.5-update-translations.patch, NONE, 1.1 lxpanel-0.5.5-urgency-notification.patch, NONE, 1.1 lxpanel.spec, 1.32, 1.33 lxpanel-0.5.5-Fix-failure-to-honor-Terminal-true-in-menu-and-launc.patch, 1.1, NONE lxpanel-0.5.5-Fix-failure-to-react-to-keyboard-map-changes-initiat.patch, 1.1, NONE lxpanel-0.5.5-Implement-lxpanelctl-config-command-FR1992552.patch, 1.1, NONE lxpanel-0.5.5-load_menu-code-cleanup.patch, 1.1, NONE lxpanel-0.5.5-load_menu-return-number-of-visible-items-and-hide-em.patch, 1.1, NONE

Christoph Wickert cwickert at fedoraproject.org
Sat Mar 20 22:19:42 UTC 2010


Author: cwickert

Update of /cvs/pkgs/rpms/lxpanel/devel
In directory cvs01.phx2.fedoraproject.org:/tmp/cvs-serv6057/devel

Modified Files:
	lxpanel.spec 
Added Files:
	lxpanel-0.5.5-64-bit-clean-regression.patch 
	lxpanel-0.5.5-Terminal-true.patch 
	lxpanel-0.5.5-UI-draw-cell-renderer.patch 
	lxpanel-0.5.5-clock-poll-interval.patch 
	lxpanel-0.5.5-configuration-not-in-sync.patch 
	lxpanel-0.5.5-enum-value.patch lxpanel-0.5.5-enum-values.patch 
	lxpanel-0.5.5-icon-only-case.patch 
	lxpanel-0.5.5-inconsist-group-count.patch 
	lxpanel-0.5.5-keyboard-map-changes.patch 
	lxpanel-0.5.5-lxpanelctl-config.patch 
	lxpanel-0.5.5-menu-code-cleanup.patch 
	lxpanel-0.5.5-number-of-visible-items.patch 
	lxpanel-0.5.5-task-deletion-urgency-timer.patch 
	lxpanel-0.5.5-update-translations.patch 
	lxpanel-0.5.5-urgency-notification.patch 
Removed Files:
	lxpanel-0.5.5-Fix-failure-to-honor-Terminal-true-in-menu-and-launc.patch 
	lxpanel-0.5.5-Fix-failure-to-react-to-keyboard-map-changes-initiat.patch 
	lxpanel-0.5.5-Implement-lxpanelctl-config-command-FR1992552.patch 
	lxpanel-0.5.5-load_menu-code-cleanup.patch 
	lxpanel-0.5.5-load_menu-return-number-of-visible-items-and-hide-em.patch 
Log Message:
* Sat Mar 20 2010 Christoph Wickert <cwickert at fedoraproject.org> - 0.5.5-3
- Fix two race conditions (#554174 and #575053)
- Hide empty menus
- Lots of fixes
- Update translations from Transifex


lxpanel-0.5.5-64-bit-clean-regression.patch:
 pager.c   |    2 +-
 taskbar.c |    3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

--- NEW FILE lxpanel-0.5.5-64-bit-clean-regression.patch ---
>From 4aae3d92cdce6e212572a7b75749766ef1e1ffcb Mon Sep 17 00:00:00 2001
From: Marty Jack <martyj at linux.local>
Date: Tue, 16 Mar 2010 09:19:15 -0400
Subject: [PATCH 16/23] Fix a 64-bit clean regression

---
 src/plugins/pager.c   |    2 +-
 src/plugins/taskbar.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/plugins/pager.c b/src/plugins/pager.c
index a4e51ec..a12daa3 100644
--- a/src/plugins/pager.c
+++ b/src/plugins/pager.c
@@ -43,7 +43,7 @@ struct _task;
 struct _desk;
 struct _pager;
 
-#define ALL_DESKTOPS   (-1)
+#define ALL_DESKTOPS   0xFFFFFFFF		/* 64-bit clean */
 #define BORDER_WIDTH   2
 
 /* Structure representing a "task", an open window. */
diff --git a/src/plugins/taskbar.c b/src/plugins/taskbar.c
index a806e1b..15139e4 100644
--- a/src/plugins/taskbar.c
+++ b/src/plugins/taskbar.c
@@ -127,7 +127,7 @@ static gchar *taskbar_rc = "style 'taskbar-style'\n"
 #define DRAG_ACTIVE_DELAY    1000
 #define TASK_WIDTH_MAX       200
 #define TASK_PADDING         4
-#define ALL_WORKSPACES       (-1)
+#define ALL_WORKSPACES       0xFFFFFFFF		/* 64-bit clean */
 #define ICON_ONLY_EXTRA      6		/* Amount needed to have button lay out symmetrically */
 #define BUTTON_HEIGHT_EXTRA  4          /* Amount needed to have button not clip icon */
 
-- 
1.6.6.1


lxpanel-0.5.5-Terminal-true.patch:
 misc.c              |    6 ++++--
 plugins/launchbar.c |    7 ++++++-
 2 files changed, 10 insertions(+), 3 deletions(-)

--- NEW FILE lxpanel-0.5.5-Terminal-true.patch ---
>From c7f782401364bd8a8389ffa7a1666d90049113a8 Mon Sep 17 00:00:00 2001
From: Marty Jack <martyj at linux.local>
Date: Sun, 21 Feb 2010 06:45:39 -0500
Subject: [PATCH 6/9] Fix failure to honor Terminal=true in menu and launchbar (Bug2954636)

---
 src/misc.c              |    6 ++++--
 src/plugins/launchbar.c |    6 ++++++
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/misc.c b/src/misc.c
index 378c2cd..39f2c85 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -1558,12 +1558,14 @@ gboolean lxpanel_launch_app(const char* exec, GList* files, gboolean in_terminal
     cmd = translate_app_exec_to_command_line(exec, files);
     if( in_terminal )
     {
+	char * escaped_cmd = g_shell_quote(cmd);
         char* term_cmd;
         const char* term = lxpanel_get_terminal();
         if( strstr(term, "%s") )
-            term_cmd = g_strdup_printf(term, cmd);
+            term_cmd = g_strdup_printf(term, escaped_cmd);
         else
-            term_cmd = g_strconcat( term, " -e ", cmd, NULL );
+            term_cmd = g_strconcat( term, " -e ", escaped_cmd, NULL );
+	g_free(escaped_cmd);
         if( cmd != exec )
             g_free(cmd);
         cmd = term_cmd;
diff --git a/src/plugins/launchbar.c b/src/plugins/launchbar.c
index 7469694..feabe59 100644
--- a/src/plugins/launchbar.c
+++ b/src/plugins/launchbar.c
@@ -355,6 +355,10 @@ static int launchbutton_constructor(Plugin * p, char ** fp)
                     btn->customize_action = TRUE;
                     btn->action = g_strdup(s.t[1]);
                 }
+                else if (g_ascii_strcasecmp(s.t[0], "terminal") == 0)
+                {
+                    btn->use_terminal = str2num(bool_pair, s.t[1], 0);
+                }
                 else
                     ERR( "launchbar: unknown var %s\n", s.t[0]);
             }
@@ -846,6 +850,8 @@ static void launchbar_save_configuration(Plugin * p, FILE * fp)
             lxpanel_put_str(fp, "tooltip", btn->tooltip);
         if (btn->customize_action)
             lxpanel_put_str(fp, "action", btn->action);
+        if (btn->use_terminal)
+            lxpanel_put_bool(fp, "terminal", TRUE);
         lxpanel_put_line(fp, "}");
     }
 }
-- 
1.6.6.1


lxpanel-0.5.5-UI-draw-cell-renderer.patch:
 configurator.c |    7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

--- NEW FILE lxpanel-0.5.5-UI-draw-cell-renderer.patch ---
>From 8bf045c957395c4da6b9e3bbf6833581d9e0b365 Mon Sep 17 00:00:00 2001
From: Marty Jack <martyj at linux.local>
Date: Fri, 19 Mar 2010 22:47:37 -0400
Subject: [PATCH 22/23] Race condition in UI draw, cell renderer could be called after plugin structure deleted
 Fedora bug 556979, 575053

---
 src/configurator.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/configurator.c b/src/configurator.c
index 845bd46..88c9e80 100644
--- a/src/configurator.c
+++ b/src/configurator.c
@@ -637,12 +637,12 @@ static void on_remove_plugin( GtkButton* btn, GtkTreeView* view )
         if( gtk_tree_path_get_indices(tree_path)[0] >= gtk_tree_model_iter_n_children( model, NULL ) )
             gtk_tree_path_prev( tree_path );
         gtk_list_store_remove( GTK_LIST_STORE(model), &it );
+        gtk_tree_selection_select_path( tree_sel, tree_path );
+        gtk_tree_path_free( tree_path );
+
         p->plugins = g_list_remove( p->plugins, pl );
         plugin_delete(pl);
         panel_config_save(p);
-
-        gtk_tree_selection_select_path( tree_sel, tree_path );
-        gtk_tree_path_free( tree_path );
     }
 }
 
-- 
1.6.6.1


lxpanel-0.5.5-clock-poll-interval.patch:
 dclock.c |  138 ++++++++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 110 insertions(+), 28 deletions(-)

--- NEW FILE lxpanel-0.5.5-clock-poll-interval.patch ---
>From 3855f25de17c1a4b11e63a639ab387efb576271c Mon Sep 17 00:00:00 2001
From: Marty Jack <martyj at linux.local>
Date: Thu, 4 Mar 2010 09:05:42 -0500
Subject: [PATCH 10/23] Improve clock poll interval for format strings that do not change every second (Bug2923562).

---
 src/plugins/dclock.c |  137 ++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 110 insertions(+), 27 deletions(-)

diff --git a/src/plugins/dclock.c b/src/plugins/dclock.c
index fffefcd..6b0e4fa 100644
--- a/src/plugins/dclock.c
+++ b/src/plugins/dclock.c
@@ -45,12 +45,21 @@ typedef struct {
     gboolean bold;				/* True if bold font */
     gboolean icon_only;				/* True if icon only (no clock value) */
     guint timer;				/* Timer for periodic update */
-    char * prev_output;				/* Previous value of clock */
+    enum {
+	AWAITING_FIRST_CHANGE,			/* Experimenting to determine interval, waiting for first change */
+	AWAITING_SECOND_CHANGE,			/* Experimenting to determine interval, waiting for second change */
+	ONE_SECOND_INTERVAL,			/* Determined that one second interval is necessary */
+	ONE_MINUTE_INTERVAL			/* Determined that one minute interval is sufficient */
+    } expiration_interval;			
+    int experiment_count;			/* Count of experiments that have been done to determine interval */
+    char * prev_clock_value;			/* Previous value of clock */
+    char * prev_tooltip_value;			/* Previous value of tooltip */
 } DClockPlugin;
 
 static void dclock_popup_map(GtkWidget * widget, DClockPlugin * dc);
 static GtkWidget * dclock_create_calendar(DClockPlugin * dc);
 static gboolean dclock_button_press_event(GtkWidget * widget, GdkEventButton * evt, Plugin * plugin);
+static void dclock_timer_set(DClockPlugin * dc);
 static gboolean dclock_update_display(DClockPlugin * dc);
 static int dclock_constructor(Plugin * p, char ** fp);
 static void dclock_destructor(Plugin * p);
@@ -126,6 +135,28 @@ static gboolean dclock_button_press_event(GtkWidget * widget, GdkEventButton * e
     return TRUE;
 }
 
+/* Set the timer. */
+static void dclock_timer_set(DClockPlugin * dc)
+{
+    /* Get current time to millisecond resolution. */
+    int milliseconds = 1000;
+    struct timeval current_time;
+    if (gettimeofday(&current_time, NULL) >= 0)
+    {
+        /* Compute number of milliseconds until next second boundary. */
+        milliseconds = 1000 - (current_time.tv_usec / 1000);
+
+        /* If the expiration interval is the minute boundary,
+         * add number of milliseconds after that until next minute boundary. */
+        if (dc->expiration_interval == ONE_MINUTE_INTERVAL)
+        {
+            time_t seconds = 60 - (current_time.tv_sec - (current_time.tv_sec / 60) * 60) - 1;
+            milliseconds += seconds * 1000;
+        }
+    }
+    dc->timer = g_timeout_add(milliseconds, (GSourceFunc) dclock_update_display, (gpointer) dc);
+}
+
 /* Periodic timer callback.
  * Also used during initialization and configuration change to do a redraw. */
 static gboolean dclock_update_display(DClockPlugin * dc)
@@ -133,29 +164,28 @@ static gboolean dclock_update_display(DClockPlugin * dc)
     /* Determine the current time. */
     time_t now;
     time(&now);
-    struct tm * detail = localtime(&now);
+    struct tm * current_time = localtime(&now);
 
-    /* Determine the content of the clock label. */
-    char output[64];
-    strftime(output, sizeof(output),
-        ((dc->clock_format != NULL) ? dc->clock_format : DEFAULT_CLOCK_FORMAT), detail);
+    /* Determine the content of the clock label and tooltip. */
+    char clock_value[64];
+    char tooltip_value[64];
+    strftime(clock_value, sizeof(clock_value), dc->clock_format, current_time);
+    strftime(tooltip_value, sizeof(tooltip_value), dc->tooltip_format, current_time);
 
     /* When we write the clock value, it causes the panel to do a full relayout.
-     * Since this function is called once per second, we take the trouble to check if the string actually changed first. */
+     * Since this function may be called too often while the timing experiment is underway,
+     * we take the trouble to check if the string actually changed first. */
     if (( ! dc->icon_only)
-    && ((dc->prev_output == NULL) || (strcmp(dc->prev_output, output) != 0)))
+    && ((dc->prev_clock_value == NULL) || (strcmp(dc->prev_clock_value, clock_value) != 0)))
     {
-        g_free(dc->prev_output);
-        dc->prev_output = g_strdup(output);
-
         /* Convert "\n" escapes in the user's format string to newline characters. */
         char * newlines_converted = NULL;
-        if (strstr(output, "\\n") != NULL)
+        if (strstr(clock_value, "\\n") != NULL)
         {
-            newlines_converted = g_strdup(output);	/* Just to get enough space for the converted result */
+            newlines_converted = g_strdup(clock_value);	/* Just to get enough space for the converted result */
             char * p;
             char * q;
-            for (p = output, q = newlines_converted; *p != '\0'; p += 1)
+            for (p = clock_value, q = newlines_converted; *p != '\0'; p += 1)
             {
                 if ((p[0] == '\\') && (p[1] == 'n'))
                 {
@@ -168,7 +198,7 @@ static gboolean dclock_update_display(DClockPlugin * dc)
             *q = '\0';
         }
 
-        gchar * utf8 = g_locale_to_utf8(((newlines_converted != NULL) ? newlines_converted : output), -1, NULL, NULL, NULL);
+        gchar * utf8 = g_locale_to_utf8(((newlines_converted != NULL) ? newlines_converted : clock_value), -1, NULL, NULL, NULL);
         if (utf8 != NULL)
         {
             panel_draw_label_text(dc->plugin->panel, dc->clock_label, utf8, dc->bold, TRUE);
@@ -178,15 +208,66 @@ static gboolean dclock_update_display(DClockPlugin * dc)
     }
 
     /* Determine the content of the tooltip. */
-    strftime(output, sizeof(output),
-        ((dc->tooltip_format != NULL) ? dc->tooltip_format : DEFAULT_TIP_FORMAT), detail);
-    gchar * utf8 = g_locale_to_utf8(output, -1, NULL, NULL, NULL);
+    gchar * utf8 = g_locale_to_utf8(tooltip_value, -1, NULL, NULL, NULL);
     if (utf8 != NULL)
     {
         gtk_widget_set_tooltip_text(dc->plugin->pwid, utf8);
         g_free(utf8);
     }
-    return TRUE;
+
+    /* Conduct an experiment to see how often the value changes.
+     * Use this to decide whether we update the value every second or every minute.
+     * We need to account for the possibility that the experiment is being run when we cross a minute boundary. */
+    if (dc->expiration_interval < ONE_SECOND_INTERVAL)
+    {
+        if (dc->prev_clock_value == NULL)
+        {
+            /* Initiate the experiment. */
+            dc->prev_clock_value = g_strdup(clock_value);
+            dc->prev_tooltip_value = g_strdup(tooltip_value);
+        }
+        else
+        {
+            if ((strcmp(dc->prev_clock_value, clock_value) == 0)
+            && (strcmp(dc->prev_tooltip_value, tooltip_value) == 0))
+            {
+                dc->experiment_count += 1;
+                if (dc->experiment_count > 3)
+                {
+                    /* No change within 3 seconds.  Assume change no more often than once per minute. */
+                    dc->expiration_interval = 60;
+                    g_free(dc->prev_clock_value);
+                    g_free(dc->prev_tooltip_value);
+                    dc->prev_clock_value = NULL;
+                    dc->prev_tooltip_value = NULL;
+                }
+            }
+            else if (dc->expiration_interval == AWAITING_FIRST_CHANGE)
+            {
+                /* We have a change at the beginning of the experiment, but we do not know when the next change might occur.
+                 * Continue the experiment for 3 more seconds. */
+                dc->expiration_interval = AWAITING_SECOND_CHANGE;
+                dc->experiment_count = 0;
+                g_free(dc->prev_clock_value);
+                g_free(dc->prev_tooltip_value);
+                dc->prev_clock_value = g_strdup(clock_value);
+                dc->prev_tooltip_value = g_strdup(tooltip_value);
+            }
+            else
+            {
+                /* We have a second change.  End the experiment. */
+                dc->expiration_interval = ((dc->experiment_count > 3) ? 60 : 1);
+                g_free(dc->prev_clock_value);
+                g_free(dc->prev_tooltip_value);
+                dc->prev_clock_value = NULL;
+                dc->prev_tooltip_value = NULL;
+            }
+        }
+    }
+
+    /* Reset the timer and return. */
+    dclock_timer_set(dc);
+    return FALSE;
 }
 
 /* Plugin constructor. */
@@ -252,12 +333,13 @@ static int dclock_constructor(Plugin * p, char ** fp)
     /* Connect signals. */
     g_signal_connect(G_OBJECT (p->pwid), "button_press_event", G_CALLBACK(dclock_button_press_event), (gpointer) p);
 
-    /* Initialize the clock display */
+    /* Initialize the clock display. */
+    if (dc->clock_format == NULL)
+        dc->clock_format = g_strdup(DEFAULT_CLOCK_FORMAT);
+    if (dc->tooltip_format == NULL)
+        dc->tooltip_format = g_strdup(DEFAULT_TIP_FORMAT);
     dclock_apply_configuration(p);
 
-    /* Start a timer to refresh the clock display. */
-    dc->timer = g_timeout_add(1000, (GSourceFunc) dclock_update_display, (gpointer) dc);
-
     /* Show the widget and return. */
     gtk_widget_show(p->pwid);
     return 1;
@@ -280,7 +362,8 @@ static void dclock_destructor(Plugin * p)
     g_free(dc->clock_format);
     g_free(dc->tooltip_format);
     g_free(dc->action);
-    g_free(dc->prev_output);
+    g_free(dc->prev_clock_value);
+    g_free(dc->prev_tooltip_value);
     g_free(dc);
 }
 
@@ -302,9 +385,9 @@ static void dclock_apply_configuration(Plugin * p)
         gtk_widget_hide(dc->clock_icon);
     }
 
-    /* Update the display. */
-    g_free(dc->prev_output);	/* Force the update of the clock display */
-    dc->prev_output = NULL;
+    /* Rerun the experiment to determine update interval and update the display. */
+    dc->expiration_interval = AWAITING_FIRST_CHANGE;
+    dc->experiment_count = 0;
     dclock_update_display(dc);
 
     /* Hide the calendar. */
-- 
1.6.6.1


lxpanel-0.5.5-configuration-not-in-sync.patch:
 configurator.c |   15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

--- NEW FILE lxpanel-0.5.5-configuration-not-in-sync.patch ---
>From 60c77f707b58b82b009857b6dd17b9fb8effd360 Mon Sep 17 00:00:00 2001
From: Marty Jack <martyj at linux.local>
Date: Sun, 7 Mar 2010 12:25:26 -0500
Subject: [PATCH 15/23] Fix conditions where on-disk configuration was not in sync with actual configuration (Bug2920277)
 Replace show_all with show on toplevel to avoid situation where plugin loses control of children's visibility

---
 src/configurator.c |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/configurator.c b/src/configurator.c
index 3292d97..845bd46 100644
--- a/src/configurator.c
+++ b/src/configurator.c
@@ -510,10 +510,11 @@ static void on_add_plugin_response( GtkDialog* dlg,
                 if (pl->class->expand_default) pl->expand = TRUE;
                 plugin_start( pl, NULL );
                 p->plugins = g_list_append(p->plugins, pl);
-                /* FIXME: will show all cause problems? */
+                panel_config_save(p);
+
                 if (pl->pwid)
                 {
-                    gtk_widget_show_all( pl->pwid );
+                    gtk_widget_show(pl->pwid);
 
                     /* update background of the newly added plugin */
                     plugin_widget_set_background( pl->pwid, pl->panel );
@@ -536,10 +537,6 @@ static void on_add_plugin_response( GtkDialog* dlg,
             g_free( type );
         }
     }
-/*
-    gtk_widget_set_sensitive( (GtkWidget*)gtk_window_get_transient_for( (GtkWindow*)dlg ),
-                               TRUE );
-*/
     gtk_widget_destroy( (GtkWidget*)dlg );
 }
 
@@ -642,6 +639,7 @@ static void on_remove_plugin( GtkButton* btn, GtkTreeView* view )
         gtk_list_store_remove( GTK_LIST_STORE(model), &it );
         p->plugins = g_list_remove( p->plugins, pl );
         plugin_delete(pl);
+        panel_config_save(p);
 
         gtk_tree_selection_select_path( tree_sel, tree_path );
         gtk_tree_path_free( tree_path );
@@ -713,6 +711,7 @@ static void on_moveup_plugin(  GtkButton* btn, GtkTreeView* view )
             {
                 gtk_box_reorder_child( GTK_BOX(panel->box), pl->pwid, get_widget_index( panel, pl ) );
             }
+            panel_config_save(panel);
             return;
         }
         prev = it;
@@ -754,6 +753,7 @@ static void on_movedown_plugin(  GtkButton* btn, GtkTreeView* view )
     {
         gtk_box_reorder_child( GTK_BOX(panel->box), pl->pwid, get_widget_index( panel, pl ) );
     }
+    panel_config_save(panel);
 }
 
 static void
@@ -924,7 +924,7 @@ void panel_configure( Panel* p, int sel_page )
     /* transparancy */
     tint_clr = w = (GtkWidget*)gtk_builder_get_object( builder, "tint_clr" );
     gtk_color_button_set_color((GtkColorButton*)w, &p->gtintcolor);
-    gtk_color_button_set_alpha((GtkColorButton*)w, 256*p->alpha);
+    gtk_color_button_set_alpha((GtkColorButton*)w, 256 * p->alpha);
     if ( ! p->transparent )
         gtk_widget_set_sensitive( w, FALSE );
     g_signal_connect( w, "color-set", G_CALLBACK( on_tint_color_set ), p );
-- 
1.6.6.1


lxpanel-0.5.5-enum-value.patch:
 dclock.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

--- NEW FILE lxpanel-0.5.5-enum-value.patch ---
>From 2efc857c9638eb5d2313b7c1551f87c4b33ef3ff Mon Sep 17 00:00:00 2001
From: Marty Jack <martyj at linux.local>
Date: Thu, 4 Mar 2010 14:37:37 -0500
Subject: [PATCH 13/23] Fix typo in enum value

---
 src/plugins/dclock.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/src/plugins/dclock.c b/src/plugins/dclock.c
index 156a379..ed64896 100644
--- a/src/plugins/dclock.c
+++ b/src/plugins/dclock.c
@@ -261,7 +261,7 @@ static gboolean dclock_update_display(DClockPlugin * dc)
             else
             {
                 /* We have a second change.  End the experiment. */
-                dc->expiration_interval = ((dc->experiment_count > 3) ? ONE_MINUTE_INTERVAL : ONE_SECONDcd_INTERVAL);
+                dc->expiration_interval = ((dc->experiment_count > 3) ? ONE_MINUTE_INTERVAL : ONE_SECOND_INTERVAL);
                 g_free(dc->prev_clock_value);
                 g_free(dc->prev_tooltip_value);
                 dc->prev_clock_value = NULL;
-- 
1.6.6.1


lxpanel-0.5.5-enum-values.patch:
 dclock.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

--- NEW FILE lxpanel-0.5.5-enum-values.patch ---
>From 116746cf09628e3e8968a04b41c0f08aab06cb23 Mon Sep 17 00:00:00 2001
From: Marty Jack <martyj at linux.local>
Date: Thu, 4 Mar 2010 14:31:36 -0500
Subject: [PATCH 12/23] Fix typo in enum values

---
 src/plugins/dclock.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/plugins/dclock.c b/src/plugins/dclock.c
index f91e198..156a379 100644
--- a/src/plugins/dclock.c
+++ b/src/plugins/dclock.c
@@ -240,7 +240,7 @@ static gboolean dclock_update_display(DClockPlugin * dc)
                 if (dc->experiment_count > 3)
                 {
                     /* No change within 3 seconds.  Assume change no more often than once per minute. */
-                    dc->expiration_interval = 60;
+                    dc->expiration_interval = ONE_MINUTE_INTERVAL;
                     g_free(dc->prev_clock_value);
                     g_free(dc->prev_tooltip_value);
                     dc->prev_clock_value = NULL;
@@ -261,7 +261,7 @@ static gboolean dclock_update_display(DClockPlugin * dc)
             else
             {
                 /* We have a second change.  End the experiment. */
-                dc->expiration_interval = ((dc->experiment_count > 3) ? 60 : 1);
+                dc->expiration_interval = ((dc->experiment_count > 3) ? ONE_MINUTE_INTERVAL : ONE_SECONDcd_INTERVAL);
                 g_free(dc->prev_clock_value);
                 g_free(dc->prev_tooltip_value);
                 dc->prev_clock_value = NULL;
-- 
1.6.6.1


lxpanel-0.5.5-icon-only-case.patch:
 dclock.c |   14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

--- NEW FILE lxpanel-0.5.5-icon-only-case.patch ---
>From 8575ae11809c9d465a0ecba2b1ed79b4e7701f86 Mon Sep 17 00:00:00 2001
From: Marty Jack <martyj at linux.local>
Date: Thu, 4 Mar 2010 09:47:35 -0500
Subject: [PATCH 11/23] Polish previous change, improve icon-only case, add defensive check

---
 src/plugins/dclock.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/plugins/dclock.c b/src/plugins/dclock.c
index 6b0e4fa..f91e198 100644
--- a/src/plugins/dclock.c
+++ b/src/plugins/dclock.c
@@ -138,8 +138,9 @@ static gboolean dclock_button_press_event(GtkWidget * widget, GdkEventButton * e
 /* Set the timer. */
 static void dclock_timer_set(DClockPlugin * dc)
 {
-    /* Get current time to millisecond resolution. */
     int milliseconds = 1000;
+
+    /* Get current time to millisecond resolution. */
     struct timeval current_time;
     if (gettimeofday(&current_time, NULL) >= 0)
     {
@@ -154,6 +155,10 @@ static void dclock_timer_set(DClockPlugin * dc)
             milliseconds += seconds * 1000;
         }
     }
+
+    /* Be defensive, and set the timer. */
+    if (milliseconds <= 0)
+        milliseconds = 1000;
     dc->timer = g_timeout_add(milliseconds, (GSourceFunc) dclock_update_display, (gpointer) dc);
 }
 
@@ -228,7 +233,7 @@ static gboolean dclock_update_display(DClockPlugin * dc)
         }
         else
         {
-            if ((strcmp(dc->prev_clock_value, clock_value) == 0)
+            if (((dc->icon_only) || (strcmp(dc->prev_clock_value, clock_value) == 0))
             && (strcmp(dc->prev_tooltip_value, tooltip_value) == 0))
             {
                 dc->experiment_count += 1;
@@ -386,8 +391,12 @@ static void dclock_apply_configuration(Plugin * p)
     }
 
     /* Rerun the experiment to determine update interval and update the display. */
+    g_free(dc->prev_clock_value);
+    g_free(dc->prev_tooltip_value);
     dc->expiration_interval = AWAITING_FIRST_CHANGE;
     dc->experiment_count = 0;
+    dc->prev_clock_value = NULL;
+    dc->prev_tooltip_value = NULL;
     dclock_update_display(dc);
 
     /* Hide the calendar. */
-- 
1.6.6.1


lxpanel-0.5.5-inconsist-group-count.patch:
 xkb.c |  227 +++++++++++++++++++++++++++++-------------------------------------
 1 file changed, 100 insertions(+), 127 deletions(-)

--- NEW FILE lxpanel-0.5.5-inconsist-group-count.patch ---
>From 447ea0f5dcafb335348aef764a7d9c45febddc0b Mon Sep 17 00:00:00 2001
From: Marty Jack <martyj at linux.local>
Date: Sun, 7 Mar 2010 11:19:37 -0500
Subject: [PATCH 14/23] Correct the behavior when X server reports inconsistent group count (Report on forum, Sphinx)
 Also straighten out mistakes about correct free routine for the group/symbol name memory
 Simplify group and symbol name processing code

---
 src/plugins/xkb/xkb.c |  226 ++++++++++++++++++++++---------------------------
 1 files changed, 100 insertions(+), 126 deletions(-)

diff --git a/src/plugins/xkb/xkb.c b/src/plugins/xkb/xkb.c
index 898a931..838fd94 100644
--- a/src/plugins/xkb/xkb.c
+++ b/src/plugins/xkb/xkb.c
@@ -101,128 +101,109 @@ static void refresh_group_xkb(XkbPlugin * xkb)
 /* Initialize the keyboard description initially or after a NewKeyboard event. */
 static int initialize_keyboard_description(XkbPlugin * xkb)
 {
-    /* Free the strings. */
-    int i;
-    for (i = 0; i < XkbNumKbdGroups; i += 1)
-    {
-        g_free(xkb->group_names[i]);
-        g_free(xkb->symbol_names[i]);
-        xkb->group_names[i] = NULL;
-        xkb->symbol_names[i] = NULL;
-    }
-
-    /* Allocate a keyboard description structure. */
-    int status = False;
-    XkbDescRec * kbd_desc_ptr = XkbAllocKeyboard();
-    if (kbd_desc_ptr == NULL)
-    {
-        ERR("Failed to get keyboard description\n");
-        goto HastaLaVista;
-    }
-
-    /* Fetch information into the keyboard description. */
-    XkbGetControls(GDK_DISPLAY(), XkbAllControlsMask, kbd_desc_ptr);
-    XkbGetNames(GDK_DISPLAY(), XkbSymbolsNameMask, kbd_desc_ptr);
-    XkbGetNames(GDK_DISPLAY(), XkbGroupNamesMask, kbd_desc_ptr);
-
-    if (kbd_desc_ptr->names == NULL)
-    {
-        ERR("Failed to get keyboard description\n");
-        goto HastaLaVista;
-    }
-
-    /* Determine the group count either from the "ctrls" structure
-     * or by enumerating the "groups" structure.  Normally the
-     * "ctrls" structure is valid. */
-    const Atom * group_source = kbd_desc_ptr->names->groups;
-    if (kbd_desc_ptr->ctrls != NULL)
-        xkb->group_count = kbd_desc_ptr->ctrls->num_groups;
+    /* Allocate a keyboard description. */
+    XkbDescRec * xkb_desc = XkbAllocKeyboard();
+    if (xkb_desc == NULL)
+        g_warning("XkbAllocKeyboard failed\n");
     else
     {
-        for (
-          xkb->group_count = 0;
-          ((xkb->group_count < XkbNumKbdGroups) && (group_source[xkb->group_count] != None));
-          xkb->group_count++) ;
-    }
-    if (xkb->group_count == 0)
-        xkb->group_count = 1;
-    if (xkb->group_count > XkbNumKbdGroups)
-        xkb->group_count = XkbNumKbdGroups;
-
-    /* Determine the group names.  Trim off text beginning at a '('. */
-    const Atom * tmp_group_source = kbd_desc_ptr->names->groups;
-    for (i = 0; i < xkb->group_count; i++)
-    {
-        if (tmp_group_source[i] != None)
-        {
-            char * ptr = XGetAtomName(GDK_DISPLAY(), tmp_group_source[i]);
-            xkb->group_names[i] = ptr;
-            if ((ptr != NULL) && ((ptr = strchr(ptr, '('))) != NULL)
-                *ptr = '\0';
-        }
-    }
-
-    /* Fetch the symbol names. */
-    Atom sym_name_atom = kbd_desc_ptr->names->symbols;
-    char * sym_name;
-    if ((sym_name_atom == None)
-    || ((sym_name = XGetAtomName(GDK_DISPLAY(), sym_name_atom)) == NULL))
-        goto HastaLaVista;
-
-    /* Parse and store symbol names. */
-    int count = 0;
-    char * ptr;
-    for (ptr = strtok(sym_name, "+"); ptr != NULL; ptr = strtok(NULL, "+"))
-    {
-        char * ptr1 = strchr(ptr, '(');
-        if (ptr1 != NULL) *ptr1 = '\0';
-        ptr1 = strchr(ptr, '_');
-        if ((ptr1 != NULL) && ( ! g_ascii_isupper(ptr1[1]))) *ptr1 = '\0';
-        ptr1 = strchr(ptr, ':');
-        if (ptr1 != NULL) *ptr1 = '\0';
-
-        ptr1 = strrchr(ptr, '/');
-        if (ptr1 != NULL)
+        /* Read necessary values into the keyboard description. */
+        XkbGetControls(GDK_DISPLAY(), XkbAllControlsMask, xkb_desc);
+        XkbGetNames(GDK_DISPLAY(), XkbSymbolsNameMask | XkbGroupNamesMask, xkb_desc);
+        if ((xkb_desc->names == NULL) || (xkb_desc->ctrls == NULL) || (xkb_desc->names->groups == NULL))
+            g_warning("XkbGetControls/XkbGetNames failed\n");
+        else
         {
-            /* Filter out cases like pc/pc */
-            if (memcmp(ptr, ptr1 + 1, ptr1 - ptr) == 0) continue;
-            ptr = ptr1 + 1;
-        }
-
-        if (strncmp(ptr, "group", 5) == 0) continue;
-        if (strncmp(ptr, "inet", 4) == 0) continue;
-        /* Filter cases like pc(pc105) (Xorg 7.0 update) */
-        if (strncmp(ptr, "pc", 2) == 0) continue;
-        
-        xkb->symbol_names[count] = g_utf8_strup(ptr, -1);
-        count += 1;
-    }
+            /* Get the group name of each keyboard layout.  Infer the group count from the highest available. */
+            Atom * group_source = xkb_desc->names->groups;
+            int i;
+            for (i = 0; i < XkbNumKbdGroups; i += 1)
+            {
+                g_free(xkb->group_names[i]);
+                xkb->group_names[i] = NULL;
+                if (group_source[i] != None)
+                {
+                    xkb->group_count = i + 1;
+                    char * p = XGetAtomName(GDK_DISPLAY(), group_source[i]);
+                    xkb->group_names[i] = g_strdup(p);
+                    XFree(p);
+                }
+            }
 
-    /* Special cases. */
-    if ((count == 1) && (xkb->group_names[0] == NULL) && (strcmp(xkb->symbol_names[0], "jp") == 0))
-    {
-        xkb->group_count = 2;
-        xkb->symbol_names[1] = xkb->symbol_names[0];
-        xkb->symbol_names[0] = g_strdup("us");
-        xkb->group_names[0] = g_strdup("US/ASCII");
-        xkb->group_names[1] = g_strdup("Japanese");
-    }
-    else if (count < xkb->group_count)
-    {
-        /* Ensure that the names are fully initialized. */
-        int j = count, k = xkb->group_count;
-        while(--j >= 0) xkb->symbol_names[--k] = xkb->symbol_names[j];
-        while(--k >= 0) xkb->symbol_names[k] = g_strdup("en_US");
-    }
+            /* Reinitialize the symbol name storage. */
+            for (i = 0; i < XkbNumKbdGroups; i += 1)
+            {
+                g_free(xkb->symbol_names[i]);
+                xkb->symbol_names[i] = NULL;
+            }
 
-    /* Ensure that the names are fully initialized. */
-    for (i = 0; i < xkb->group_count; i++)
-    {
-        if (xkb->symbol_names[i] == NULL)
-        {
-            ERR("\nGroup Symbol %i is undefined, set to 'U/A' !\n", i+1);
-            xkb->symbol_names[i] = g_strdup("U/A");
+            /* Get the symbol name of all keyboard layouts.
+             * This is a plus-sign separated string. */
+            if (xkb_desc->names->symbols != None)
+            {
+                char * symbol_string = XGetAtomName(GDK_DISPLAY(), xkb_desc->names->symbols);
+                if (symbol_string != NULL)
+                {
+                    char * p = symbol_string;
+                    char * q = p;
+                    int symbol_group_number = 0;
+                    for ( ; ((*p != '\0') && (symbol_group_number < XkbNumKbdGroups)); p += 1)
+                    {
+                        if (*p == '+')
+                        {
+                            /* End of a symbol.  Ignore the symbols "pc" and "inet" and "group". */
+                            *p = '\0';
+                            if ((strcmp(q, "pc") != 0) && (strcmp(q, "inet") != 0) && (strcmp(q, "group") != 0))
+                            {
+                                xkb->symbol_names[symbol_group_number] = g_ascii_strup(q, -1);
+                                symbol_group_number += 1;
+                            }
+                            q = p + 1;
+                        }
+                        else if ((*p == ':') && (p[1] >= '1') && (p[1] < ('1' + XkbNumKbdGroups)) && (p[2] == '+'))
+                        {
+                        /* Construction ":n+" at the end of a symbol.  The digit is a one-based index of the symbol.
+                         * If not present, we will default above to "next index". */
+                            *p = '\0';
+                            symbol_group_number = p[1] - '1';
+                            xkb->symbol_names[symbol_group_number] = g_ascii_strup(q, -1);
+                            symbol_group_number += 1;
+                            p += 2;
+                            q = p + 1;
+                        }
+                        else if ((*p >= 'A') && (*p <= 'Z'))
+                            *p |= 'a' - 'A';
+                        else if ((*p < 'a') || (*p > 'z'))
+                            *p = '\0';
+                    }
+		    
+                    /* Crosscheck the group count determined from the "ctrls" structure,
+                     * that determined from the "groups" vector, and that determined from the "symbols" string.
+                     * The "ctrls" structure is considered less reliable because it has been observed to be incorrect. */
+                    if ((xkb->group_count != symbol_group_number)
+                    || (xkb->group_count != xkb_desc->ctrls->num_groups))
+                    {
+                        g_warning("Group count mismatch, ctrls = %d, groups = %d, symbols = %d\n",
+                            xkb_desc->ctrls->num_groups, xkb->group_count, symbol_group_number);
+
+                        /* Maximize the "groups" and "symbols" value. */
+                        if (xkb->group_count < symbol_group_number)
+                            xkb->group_count = symbol_group_number;
+                    }
+
+                    /* Ensure that all elements within the group count we will actually use are initialized. */
+                    for (i = 0; i < xkb->group_count; i += 1)
+                    {
+                        if (xkb->group_names[i] == NULL)
+                            xkb->group_names[i] = g_strdup("Unknown");
+                        if (xkb->symbol_names[i] == NULL)
+                            xkb->symbol_names[i] = g_strdup("None");
+                    }
+                    XFree(symbol_string);
+                }
+            }
         }
+        XkbFreeKeyboard(xkb_desc, 0, True);
     }
 
     /* Create or recreate hash table.
@@ -231,14 +212,7 @@ static int initialize_keyboard_description(XkbPlugin * xkb)
     if (xkb->group_hash_table != NULL)
         g_hash_table_destroy(xkb->group_hash_table);
     xkb->group_hash_table = g_hash_table_new(g_direct_hash, NULL);
-
-    status = True;
-
-HastaLaVista:
-    if (kbd_desc_ptr != NULL)
-        XkbFreeKeyboard(kbd_desc_ptr, 0, True);
-
-    return status;
+    return TRUE;
 }
 
 /* GDK event filter that receives events from all windows and the Xkb extension. */
@@ -309,12 +283,12 @@ void xkb_mechanism_destructor(XkbPlugin * xkb)
     {
         if (xkb->group_names[i] != NULL)
         {
-            free(xkb->group_names[i]);
+            g_free(xkb->group_names[i]);
             xkb->group_names[i] = NULL;
         }
         if (xkb->symbol_names[i] != NULL)
         {
-            free(xkb->symbol_names[i]);
+            g_free(xkb->symbol_names[i]);
             xkb->symbol_names[i] = NULL;
         }
     }
-- 
1.6.6.1


lxpanel-0.5.5-keyboard-map-changes.patch:
 xkb-plugin.c |   92 ++++++++++++-----------
 xkb.c        |  236 ++++++++++++++++++++++++++++++-----------------------------
 xkb.h        |    8 --
 3 files changed, 173 insertions(+), 163 deletions(-)

--- NEW FILE lxpanel-0.5.5-keyboard-map-changes.patch ---
>From 438d9fdbd3e0be04de933705917d508a02b7c04b Mon Sep 17 00:00:00 2001
From: Marty Jack <martyj at linux.local>
Date: Sat, 20 Feb 2010 16:23:57 -0500
Subject: [PATCH 5/9] Fix failure to react to keyboard map changes initiated outside the plugin
 - Occurred when setxkbmap was run, or when HAL configured the keyboard at X startup
 - Caused by failure to process the NewKeyboard event
 - Caused by dropping events due to faulty code to read them
 - Cosmetic change, the tooltip now the Xkb Group name rather than Xkb Symbol name

---
 src/plugins/xkb/xkb-plugin.c |   92 +++++++++--------
 src/plugins/xkb/xkb.c        |  236 +++++++++++++++++++++--------------------
 src/plugins/xkb/xkb.h        |    7 +-
 3 files changed, 173 insertions(+), 162 deletions(-)

diff --git a/src/plugins/xkb/xkb-plugin.c b/src/plugins/xkb/xkb-plugin.c
index f49a77d..80a14ba 100644
--- a/src/plugins/xkb/xkb-plugin.c
+++ b/src/plugins/xkb/xkb-plugin.c
@@ -1,18 +1,23 @@
-/*
-//====================================================================
-//  xfce4-xkb-plugin - XFCE4 Xkb Layout Indicator panel plugin
-// -------------------------------------------------------------------
-//  Alexander Iliev <sasoiliev at mamul.org>
-//  20-Feb-04
-// -------------------------------------------------------------------
-//  Parts of this code belong to Michael Glickman <wmalms at yahooo.com>
-//  and his program wmxkb.
-//  WARNING: DO NOT BOTHER Michael Glickman WITH QUESTIONS ABOUT THIS
-//           PROGRAM!!! SEND INSTEAD EMAILS TO <sasoiliev at mamul.org>
-//====================================================================
-*/
-
-/* Modified by Hong Jen Yee (PCMan) <pcman.tw at gmail.com> on 2008-04-06 for lxpanel */
+/**
+ * Copyright (c) 2010 LxDE Developers, see the file AUTHORS for details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* Originally derived from xfce4-xkb-plugin, Copyright 2004 Alexander Iliev,
+ * which credits Michael Glickman. */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -49,38 +54,45 @@ void xkb_redraw(XkbPlugin * xkb)
     if (xkb->display_type == IMAGE)
     {
         int size = xkb->plugin->panel->icon_size;
-        char * group_name = (char *) xkb_get_current_group_name_lowercase(xkb);
-        char * filename = g_strdup_printf("%s/%s.png", FLAGSDIR, group_name);
-        GdkPixbuf * unscaled_pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
-        g_free(filename);
-        g_free(group_name);
-
-        if (unscaled_pixbuf != NULL)
+        char * group_name = (char *) xkb_get_current_symbol_name_lowercase(xkb);
+        if (group_name != NULL)
         {
-            /* Loaded successfully. */
-            int width = gdk_pixbuf_get_width(unscaled_pixbuf);
-            int height = gdk_pixbuf_get_height(unscaled_pixbuf);
-            GdkPixbuf * pixbuf = gdk_pixbuf_scale_simple(unscaled_pixbuf, size * width / height, size, GDK_INTERP_BILINEAR);
-            if (pixbuf != NULL)
+            char * filename = g_strdup_printf("%s/%s.png", FLAGSDIR, group_name);
+            GdkPixbuf * unscaled_pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
+            g_free(filename);
+            g_free(group_name);
+
+            if (unscaled_pixbuf != NULL)
             {
-                gtk_image_set_from_pixbuf(GTK_IMAGE(xkb->image), pixbuf);
-                g_object_unref(G_OBJECT(pixbuf));
-                gtk_widget_hide(xkb->label);
-                gtk_widget_show(xkb->image);
-                gtk_widget_set_tooltip_text(xkb->btn, xkb_get_current_group_name(xkb));
-                valid_image = TRUE;
+                /* Loaded successfully. */
+                int width = gdk_pixbuf_get_width(unscaled_pixbuf);
+                int height = gdk_pixbuf_get_height(unscaled_pixbuf);
+                GdkPixbuf * pixbuf = gdk_pixbuf_scale_simple(unscaled_pixbuf, size * width / height, size, GDK_INTERP_BILINEAR);
+                if (pixbuf != NULL)
+                {
+                    gtk_image_set_from_pixbuf(GTK_IMAGE(xkb->image), pixbuf);
+                    g_object_unref(G_OBJECT(pixbuf));
+                    gtk_widget_hide(xkb->label);
+                    gtk_widget_show(xkb->image);
+                    gtk_widget_set_tooltip_text(xkb->btn, xkb_get_current_group_name(xkb));
+                    valid_image = TRUE;
+                }
+                g_object_unref(unscaled_pixbuf);
             }
-            g_object_unref(unscaled_pixbuf);
         }
     }
 
     /* Set the label. */
     if ((xkb->display_type == TEXT) || ( ! valid_image))
     {
-        panel_draw_label_text(xkb->plugin->panel, xkb->label, (char *) xkb_get_current_group_name(xkb), TRUE, TRUE);
-        gtk_widget_hide(xkb->image);
-        gtk_widget_show(xkb->label);
-        gtk_widget_set_tooltip_text(xkb->btn, NULL);
+        char * group_name = (char *) xkb_get_current_symbol_name(xkb);
+        if (group_name != NULL)
+        {
+            panel_draw_label_text(xkb->plugin->panel, xkb->label, (char *) group_name, TRUE, TRUE);
+            gtk_widget_hide(xkb->image);
+            gtk_widget_show(xkb->label);
+            gtk_widget_set_tooltip_text(xkb->btn, xkb_get_current_group_name(xkb));
+        }
     }
 }
 
@@ -196,10 +208,6 @@ static int xkb_constructor(Plugin * plugin, char ** fp)
     /* Initialize the XKB interface. */
     xkb_mechanism_constructor(xkb);
 
-    /* Initialize a channel to listen for XKB events. */
-    GIOChannel * channel = g_io_channel_unix_new(xkb_get_connection_number(xkb));
-    xkb->source_id = g_io_add_watch(channel, G_IO_IN | G_IO_PRI, (GIOFunc) xkb_gio_callback, (gpointer) xkb);
-
     /* Connect signals. */
     g_signal_connect(xkb->btn, "button-press-event", G_CALLBACK(xkb_button_press_event), xkb);
     g_signal_connect(xkb->btn, "scroll-event", G_CALLBACK(xkb_scroll_event), xkb);
diff --git a/src/plugins/xkb/xkb.c b/src/plugins/xkb/xkb.c
index 5bb0c39..898a931 100644
--- a/src/plugins/xkb/xkb.c
+++ b/src/plugins/xkb/xkb.c
@@ -1,18 +1,23 @@
-/*
-// ====================================================================
-//  xfce4-xkb-plugin - XFCE4 Xkb Layout Indicator panel plugin
-// -------------------------------------------------------------------
-//  Alexander Iliev <sasoiliev at mamul.org>
-//  20-Feb-04
-// -------------------------------------------------------------------
-//  Parts of this code belong to Michael Glickman <wmalms at yahooo.com>
-//  and his program wmxkb.
-//  WARNING: DO NOT BOTHER Michael Glickman WITH QUESTIONS ABOUT THIS
-//           PROGRAM!!! SEND INSTEAD EMAILS TO <sasoiliev at mamul.org>
-//====================================================================
-*/
-
-/* Modified by Hong Jen Yee (PCMan) <pcman.tw at gmail.com> on 2008-04-06 for lxpanel */
+/**
+ * Copyright (c) 2010 LxDE Developers, see the file AUTHORS for details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* Originally derived from xfce4-xkb-plugin, Copyright 2004 Alexander Iliev,
+ * which credits Michael Glickman. */
 
 #include "xkb.h"
 
@@ -26,9 +31,13 @@
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <glib.h>
 
+/* The X Keyboard Extension: Library Specification
+ * http://www.xfree86.org/current/XKBlib.pdf */
+
 static void xkb_enter_locale_by_process(XkbPlugin * xkb);
 static void refresh_group_xkb(XkbPlugin * xkb);
-static int do_init_xkb(XkbPlugin * xkb);
+static int initialize_keyboard_description(XkbPlugin * xkb);
+static GdkFilterReturn xkb_event_filter(GdkXEvent * xevent, GdkEvent * event, XkbPlugin * xkb);
 
 /* Insert a process and its layout into the hash table. */
 static void xkb_enter_locale_by_process(XkbPlugin * xkb)
@@ -56,60 +65,65 @@ int xkb_get_group_count(XkbPlugin * xkb)
   return xkb->group_count;
 }
 
+/* Get the current group name. */
+const char * xkb_get_current_group_name(XkbPlugin * xkb) 
+{
+    return xkb->group_names[xkb->current_group_xkb_no];
+}
+
 /* Convert a group number to a symbol name. */
 const char * xkb_get_symbol_name_by_res_no(XkbPlugin * xkb, int n) 
 {
     return xkb->symbol_names[n];
 }
 
-/* Get the current group name. */
-const char * xkb_get_current_group_name(XkbPlugin * xkb) 
+/* Get the current symbol name. */
+const char * xkb_get_current_symbol_name(XkbPlugin * xkb) 
 {
     return xkb_get_symbol_name_by_res_no(xkb, xkb->current_group_xkb_no);
 }
 
-/* Get the current group name converted to lowercase. */
-const char * xkb_get_current_group_name_lowercase(XkbPlugin * xkb) 
+/* Get the current symbol name converted to lowercase. */
+const char * xkb_get_current_symbol_name_lowercase(XkbPlugin * xkb) 
 {
-    const char * tmp = xkb_get_current_group_name(xkb);
-    return g_utf8_strdown(tmp, -1);
+    const char * tmp = xkb_get_current_symbol_name(xkb);
+    return ((tmp != NULL) ? g_utf8_strdown(tmp, -1) : NULL);
 }
 
 /* Refresh current group number from Xkb state. */
 static void refresh_group_xkb(XkbPlugin * xkb) 
 {
     XkbStateRec xkb_state;
-    XkbGetState(xkb->dsp, xkb->device_id, &xkb_state);
+    XkbGetState(GDK_DISPLAY(), XkbUseCoreKbd, &xkb_state);
     xkb->current_group_xkb_no = xkb_state.group;
 }
 
-/* Initialize the Xkb structures. */
-static int do_init_xkb(XkbPlugin * xkb) 
+/* Initialize the keyboard description initially or after a NewKeyboard event. */
+static int initialize_keyboard_description(XkbPlugin * xkb)
 {
-    /* Create hash table. */
-    xkb->group_hash_table = g_hash_table_new(g_direct_hash, NULL);
-
-    /* Initialize the Xkb extension. */
-    int major, minor, opcode;
-    Bool status = XkbQueryExtension(xkb->dsp, &opcode,
-        &xkb->base_event_code, &xkb->base_error_code, &major, &minor);
-
-    /* Use the core keyboard. */
-    xkb->device_id = XkbUseCoreKbd;
+    /* Free the strings. */
+    int i;
+    for (i = 0; i < XkbNumKbdGroups; i += 1)
+    {
+        g_free(xkb->group_names[i]);
+        g_free(xkb->symbol_names[i]);
+        xkb->group_names[i] = NULL;
+        xkb->symbol_names[i] = NULL;
+    }
 
     /* Allocate a keyboard description structure. */
+    int status = False;
     XkbDescRec * kbd_desc_ptr = XkbAllocKeyboard();
     if (kbd_desc_ptr == NULL)
     {
         ERR("Failed to get keyboard description\n");
         goto HastaLaVista;
     }
-    kbd_desc_ptr->dpy = xkb->dsp;
 
     /* Fetch information into the keyboard description. */
-    XkbGetControls(xkb->dsp, XkbAllControlsMask, kbd_desc_ptr);
-    XkbGetNames(xkb->dsp, XkbSymbolsNameMask, kbd_desc_ptr);
-    XkbGetNames(xkb->dsp, XkbGroupNamesMask, kbd_desc_ptr);
+    XkbGetControls(GDK_DISPLAY(), XkbAllControlsMask, kbd_desc_ptr);
+    XkbGetNames(GDK_DISPLAY(), XkbSymbolsNameMask, kbd_desc_ptr);
+    XkbGetNames(GDK_DISPLAY(), XkbGroupNamesMask, kbd_desc_ptr);
 
     if (kbd_desc_ptr->names == NULL)
     {
@@ -137,12 +151,11 @@ static int do_init_xkb(XkbPlugin * xkb)
 
     /* Determine the group names.  Trim off text beginning at a '('. */
     const Atom * tmp_group_source = kbd_desc_ptr->names->groups;
-    int i;
     for (i = 0; i < xkb->group_count; i++)
     {
         if (tmp_group_source[i] != None)
         {
-            char * ptr = XGetAtomName(xkb->dsp, tmp_group_source[i]);
+            char * ptr = XGetAtomName(GDK_DISPLAY(), tmp_group_source[i]);
             xkb->group_names[i] = ptr;
             if ((ptr != NULL) && ((ptr = strchr(ptr, '('))) != NULL)
                 *ptr = '\0';
@@ -153,7 +166,7 @@ static int do_init_xkb(XkbPlugin * xkb)
     Atom sym_name_atom = kbd_desc_ptr->names->symbols;
     char * sym_name;
     if ((sym_name_atom == None)
-    || ((sym_name = XGetAtomName(xkb->dsp, sym_name_atom)) == NULL))
+    || ((sym_name = XGetAtomName(GDK_DISPLAY(), sym_name_atom)) == NULL))
         goto HastaLaVista;
 
     /* Parse and store symbol names. */
@@ -190,83 +203,106 @@ static int do_init_xkb(XkbPlugin * xkb)
     {
         xkb->group_count = 2;
         xkb->symbol_names[1] = xkb->symbol_names[0];
-        xkb->symbol_names[0] = strdup("us");
-        xkb->group_names[0] = strdup("US/ASCII");
-        xkb->group_names[1] = strdup("Japanese");
+        xkb->symbol_names[0] = g_strdup("us");
+        xkb->group_names[0] = g_strdup("US/ASCII");
+        xkb->group_names[1] = g_strdup("Japanese");
     }
     else if (count < xkb->group_count)
     {
         /* Ensure that the names are fully initialized. */
         int j = count, k = xkb->group_count;
         while(--j >= 0) xkb->symbol_names[--k] = xkb->symbol_names[j];
-        while(--k >= 0) xkb->symbol_names[k] = strdup("en_US");
+        while(--k >= 0) xkb->symbol_names[k] = g_strdup("en_US");
     }
 
-    /* Enxure that the names are fully initialized. */
+    /* Ensure that the names are fully initialized. */
     for (i = 0; i < xkb->group_count; i++)
     {
         if (xkb->symbol_names[i] == NULL)
         {
             ERR("\nGroup Symbol %i is undefined, set to 'U/A' !\n", i+1);
-            xkb->symbol_names[i] = strdup("U/A");
+            xkb->symbol_names[i] = g_strdup("U/A");
         }
     }
 
+    /* Create or recreate hash table.
+     * The layout that was associated to the windows may or may not be at the same group number,
+     * and worse, may no longer exist, which there is no meaningful way to deal with. */
+    if (xkb->group_hash_table != NULL)
+        g_hash_table_destroy(xkb->group_hash_table);
+    xkb->group_hash_table = g_hash_table_new(g_direct_hash, NULL);
+
     status = True;
 
 HastaLaVista:
     if (kbd_desc_ptr != NULL)
         XkbFreeKeyboard(kbd_desc_ptr, 0, True);
+
     return status;
 }
 
+/* GDK event filter that receives events from all windows and the Xkb extension. */
+static GdkFilterReturn xkb_event_filter(GdkXEvent * xevent, GdkEvent * event, XkbPlugin * xkb)
+{
+    XEvent * ev = (XEvent *) xevent;
+
+    if (ev->xany.type == xkb->base_event_code + XkbEventCode)
+    {
+        /* Xkb event. */
+        XkbEvent * xkbev = (XkbEvent *) ev;
+        if (xkbev->any.xkb_type == XkbNewKeyboardNotify)
+        {
+            initialize_keyboard_description(xkb);
+            refresh_group_xkb(xkb);
+            xkb_redraw(xkb);
+            xkb_enter_locale_by_process(xkb);
+        }
+        else if (xkbev->any.xkb_type == XkbStateNotify)
+        {
+            if (xkbev->state.group != xkb->current_group_xkb_no)
+            {
+                /* Switch to the new group and redraw the display. */
+                xkb->current_group_xkb_no = xkbev->state.group;
+                refresh_group_xkb(xkb);
+                xkb_redraw(xkb);
+                xkb_enter_locale_by_process(xkb);
+            }
+        }
+    }
+    return GDK_FILTER_CONTINUE;
+}
+
 /* Initialize the Xkb interface. */
 void xkb_mechanism_constructor(XkbPlugin * xkb)
 {
-    /* Enable the Xkb extension on all clients. */
-    XkbIgnoreExtension(False);
-
-    /* Open the display. */
-    int major = XkbMajorVersion;
-    int minor = XkbMinorVersion;
-    char * display_name = "";
-    int event_code;
-    int error_rtrn;
-    int reason_rtrn;
-    xkb->dsp = XkbOpenDisplay(display_name, &event_code, &error_rtrn, &major, &minor, &reason_rtrn);
-
-    switch (reason_rtrn)
+    /* Initialize Xkb extension. */
+    int opcode;
+    int maj = XkbMajorVersion;
+    int min = XkbMinorVersion;
+    if ((XkbLibraryVersion(&maj, &min))
+    && (XkbQueryExtension(GDK_DISPLAY(), &opcode, &xkb->base_event_code, &xkb->base_error_code, &maj, &min)))
     {
-        case XkbOD_BadLibraryVersion:
-            ERR("Bad XKB library version.\n");
-            return;
-        case XkbOD_ConnectionRefused:
-            ERR("Connection to X server refused.\n");
-            return;
-        case XkbOD_BadServerVersion:
-            ERR("Bad X server version.\n");
-            return;
-        case XkbOD_NonXkbServer:
-            ERR("XKB not present.\n");
-            return;
-        case XkbOD_Success:
-            break;
-    }
+        /* Read the keyboard description. */
+        initialize_keyboard_description(xkb);
 
-    /* Initialize our mechanism. */
-    if (do_init_xkb(xkb) != True)
-        return;
+        /* Establish GDK event filter. */
+        gdk_window_add_filter(NULL, (GdkFilterFunc) xkb_event_filter, (gpointer) xkb);
 
-    /* Specify events we will receive. */
-    XkbSelectEventDetails(xkb->dsp, xkb->device_id, XkbStateNotify, XkbAllStateComponentsMask, XkbGroupStateMask);
+        /* Specify events we will receive. */
+        XkbSelectEvents(GDK_DISPLAY(), XkbUseCoreKbd, XkbNewKeyboardNotifyMask, XkbNewKeyboardNotifyMask);
+        XkbSelectEventDetails(GDK_DISPLAY(), XkbUseCoreKbd, XkbStateNotify, XkbAllStateComponentsMask, XkbGroupStateMask);
 
-    /* Get current state. */
-    refresh_group_xkb(xkb);
+        /* Get current state. */
+        refresh_group_xkb(xkb);
+    }
 }
 
 /* Deallocate resources associated with Xkb interface. */
 void xkb_mechanism_destructor(XkbPlugin * xkb) 
 {
+    /* Remove event filter. */
+    gdk_window_remove_filter(NULL, (GdkFilterFunc) xkb_event_filter, xkb);
+
     /* Free group and symbol name memory. */
     int i;
     for (i = 0; i < xkb->group_count; i++)
@@ -283,21 +319,11 @@ void xkb_mechanism_destructor(XkbPlugin * xkb)
         }
     }
 
-    /* Close the display. */
-    XCloseDisplay(xkb->dsp);
-    xkb->dsp = NULL;
-
     /* Destroy the hash table. */
     g_hash_table_destroy(xkb->group_hash_table);
     xkb->group_hash_table = NULL;
 }
 
-/* Return the connection number for the display. */
-int xkb_get_connection_number(XkbPlugin * xkb)
-{
-    return ConnectionNumber(xkb->dsp);
-}
-
 /* Set the layout to the next layout. */
 int xkb_change_group(XkbPlugin * xkb, int increment) 
 {
@@ -307,33 +333,13 @@ int xkb_change_group(XkbPlugin * xkb, int increment)
     if (next_group >= xkb->group_count) next_group = 0;
 
     /* Execute the change. */
-    XkbLockGroup(xkb->dsp, xkb->device_id, next_group);
+    XkbLockGroup(GDK_DISPLAY(), XkbUseCoreKbd, next_group);
     refresh_group_xkb(xkb);
     xkb_redraw(xkb);
     xkb_enter_locale_by_process(xkb);
     return 1;
 }
 
-/* Callback when activity detected on the Xkb channel. */
-gboolean xkb_gio_callback(GIOChannel * source, GIOCondition condition, gpointer data) 
-{
-    XkbPlugin * xkb = (XkbPlugin *) data;
-
-    XkbEvent evnt;
-    XNextEvent(xkb->dsp, &evnt.core);
-    if ((evnt.type == xkb->base_event_code)
-    && (evnt.any.xkb_type == XkbStateNotify)
-    && (evnt.state.group != xkb->current_group_xkb_no))
-    {
-        /* Switch to the new group and redraw the display. */
-        xkb->current_group_xkb_no = evnt.state.group;
-        refresh_group_xkb(xkb);
-        xkb_redraw(xkb);
-        xkb_enter_locale_by_process(xkb);
-    }
-    return TRUE;
-}
-
 /* React to change of focus by switching to the application's layout or the default layout. */
 void xkb_active_window_changed(XkbPlugin * xkb, gint pid)
 {
@@ -345,7 +351,7 @@ void xkb_active_window_changed(XkbPlugin * xkb, gint pid)
 
     if (new_group_xkb_no < xkb->group_count)
     {
-        XkbLockGroup(xkb->dsp, xkb->device_id, new_group_xkb_no);
+        XkbLockGroup(GDK_DISPLAY(), XkbUseCoreKbd, new_group_xkb_no);
         refresh_group_xkb(xkb);
     }
 }
diff --git a/src/plugins/xkb/xkb.h b/src/plugins/xkb/xkb.h
index 9265198..20c7ed3 100644
--- a/src/plugins/xkb/xkb.h
+++ b/src/plugins/xkb/xkb.h
@@ -49,10 +49,8 @@ typedef struct {
     GtkWidget * per_app_default_layout_menu;	/* Combo box of all available layouts */
 
     /* Mechanism. */
-    Display * dsp;				/* Handle to X display */
     int base_event_code;			/* Result of initializing Xkb extension */
     int base_error_code;
-    int device_id;				/* Keyboard device ID (always "core keyboard") */
     int current_group_xkb_no;			/* Current layout */
     int group_count;				/* Count of groups as returned by Xkb */
     char * group_names[XkbNumKbdGroups];	/* Group names as returned by Xkb */
@@ -67,12 +65,11 @@ extern int xkb_get_current_group_xkb_no(XkbPlugin * xkb);
 extern int xkb_get_group_count(XkbPlugin * xkb);
 extern const char * xkb_get_symbol_name_by_res_no(XkbPlugin * xkb, int group_res_no);
 extern const char * xkb_get_current_group_name(XkbPlugin * xkb);
-extern const char * xkb_get_current_group_name_lowercase(XkbPlugin * xkb);
+extern const char * xkb_get_current_symbol_name(XkbPlugin * xkb);
+extern const char * xkb_get_current_symbol_name_lowercase(XkbPlugin * xkb);
 extern void xkb_mechanism_constructor(XkbPlugin * xkb);
 extern void xkb_mechanism_destructor(XkbPlugin * xkb);
-extern int xkb_get_connection_number(XkbPlugin * xkb);
 extern int xkb_change_group(XkbPlugin * xkb, int increment);
-extern gboolean xkb_gio_callback(GIOChannel * source, GIOCondition condition, gpointer data);
 extern void xkb_active_window_changed(XkbPlugin * xkb, GPid pid);
 
 #endif
-- 
1.6.6.1


lxpanel-0.5.5-lxpanelctl-config.patch:
 man/lxpanelctl.xml |   19 +++++++++++++++----
 src/lxpanelctl.c   |    6 +++---
 src/panel.c        |    7 +++++--
 3 files changed, 23 insertions(+), 9 deletions(-)

--- NEW FILE lxpanel-0.5.5-lxpanelctl-config.patch ---
>From 0c5f948f4f55ea63c95cc65d0a6d34e1a3424fc6 Mon Sep 17 00:00:00 2001
From: Marty Jack <martyj at linux.local>
Date: Mon, 22 Feb 2010 08:09:29 -0500
Subject: [PATCH 7/9] Implement lxpanelctl config command (FR1992552).

---
 man/lxpanelctl.xml |   19 +++++++++++++++----
 src/lxpanelctl.c   |    6 +++---
 src/panel.c        |    6 +++++-
 3 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/man/lxpanelctl.xml b/man/lxpanelctl.xml
index a5c439d..ddc0bf0 100644
--- a/man/lxpanelctl.xml
+++ b/man/lxpanelctl.xml
@@ -69,7 +69,7 @@ choice="req"
         </term>
         <listitem
 >          <para
->show system menu</para>
+>Show the system menu.</para>
         </listitem>
       </varlistentry>
       <varlistentry
@@ -79,7 +79,18 @@ choice="req"
         </term>
         <listitem
 >          <para
->show run dialog</para>
+>Show the run dialog.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry
+>        <term
+><command
+>config</command>
+        </term>
+        <listitem
+>          <para
+>Show the panel configuration dialog.  If more than one panel is configured,
+it is undefined which panel configuration dialog will be shown.</para>
         </listitem>
       </varlistentry>
       <varlistentry
@@ -89,7 +100,7 @@ choice="req"
         </term>
         <listitem
 >          <para
->restart lxpanel</para>
+>Restart lxpanel.</para>
         </listitem>
       </varlistentry>
       <varlistentry
@@ -99,7 +110,7 @@ choice="req"
         </term>
         <listitem
 >          <para
->exit lxpanel</para>
+>Exit lxpanel.</para>
         </listitem>
       </varlistentry>
     </variablelist>
diff --git a/src/lxpanelctl.c b/src/lxpanelctl.c
index d8f5ad9..7474a5d 100644
--- a/src/lxpanelctl.c
+++ b/src/lxpanelctl.c
@@ -34,7 +34,7 @@ static const char usage[] =
         "Available commands:\n"
         "menu\tshow system menu\n"
         "run\tshow run dialog\n"
-//       "config\tshow config dialog\n"
+        "config\tshow configuration dialog\n"
         "restart\trestart lxpanel\n"
         "exit\texit lxpanel\n\n";
 
@@ -44,8 +44,8 @@ static int get_cmd( const char* cmd )
         return LXPANEL_CMD_SYS_MENU;
     else if( ! strcmp( cmd, "run") )
         return LXPANEL_CMD_RUN;
-//    else if( ! strcmp( cmd, "config") )
-//        return LXPANEL_CMD_CONFIG;
+    else if( ! strcmp( cmd, "config") )
+        return LXPANEL_CMD_CONFIG;
     else if( ! strcmp( cmd, "restart") )
         return LXPANEL_CMD_RESTART;
     else if( ! strcmp( cmd, "exit") )
diff --git a/src/panel.c b/src/panel.c
index 5859671..db888e6 100644
--- a/src/panel.c
+++ b/src/panel.c
@@ -261,7 +261,11 @@ static void process_client_msg ( XClientMessageEvent* ev )
             break;
 #endif
         case LXPANEL_CMD_CONFIG:
-            //FIXME: configure();
+            {
+            Panel * p = ((all_panels != NULL) ? all_panels->data : NULL);
+            if (p != NULL)
+                panel_configure(p, 0);
+            }
             break;
         case LXPANEL_CMD_RESTART:
             restart();
-- 
1.6.6.1


lxpanel-0.5.5-menu-code-cleanup.patch:
 menu.c |   24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

--- NEW FILE lxpanel-0.5.5-menu-code-cleanup.patch ---
>From b6c8855c97a6c76ec0752e3e33becc34cfa2792a Mon Sep 17 00:00:00 2001
From: Juergen Hoetzel <juergen at archlinux.org>
Date: Fri, 19 Feb 2010 08:46:33 +0100
Subject: [PATCH 3/9] load_menu: code cleanup

---
 src/plugins/menu.c |   23 +++++++++++++----------
 1 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/src/plugins/menu.c b/src/plugins/menu.c
index b36bc20..de576f3 100644
--- a/src/plugins/menu.c
+++ b/src/plugins/menu.c
@@ -425,27 +425,30 @@ static void load_menu(menup* m, MenuCacheDir* dir, GtkWidget* menu, int pos )
     for( l = menu_cache_dir_get_children(dir); l; l = l->next )
     {
         MenuCacheItem* item = MENU_CACHE_ITEM(l->data);
-        if ((menu_cache_item_get_type(item) != MENU_CACHE_TYPE_APP)
-        || (panel_menu_item_evaluate_visibility(item, m->visibility_flags)))
-        {
+	
+        gboolean is_visible = ((menu_cache_item_get_type(item) != MENU_CACHE_TYPE_APP) || 
+			       (panel_menu_item_evaluate_visibility(item, m->visibility_flags)));
+	
+	if (is_visible) 
+	{
             GtkWidget * mi = create_item(item);
             if (mi != NULL)
-            {
                 gtk_menu_shell_insert( (GtkMenuShell*)menu, mi, pos );
                 if( pos >= 0 )
                     ++pos;
-                if (menu_cache_item_get_type(item) == MENU_CACHE_TYPE_DIR)
-                {
+		/* process subentries */
+		if (menu_cache_item_get_type(item) == MENU_CACHE_TYPE_DIR) 
+		{
                     GtkWidget* sub = gtk_menu_new();
                     load_menu( m, MENU_CACHE_DIR(item), sub, -1 );    /* always pass -1 for position */
-                    gtk_menu_item_set_submenu( GTK_MENU_ITEM(mi), sub );
-                }
-            }
-        }
+                    gtk_menu_item_set_submenu( GTK_MENU_ITEM(mi), sub );	    
+		}
+	}
     }
 }
 
 
+
 static gboolean sys_menu_item_has_data( GtkMenuItem* item )
 {
    return (g_object_get_qdata( G_OBJECT(item), SYS_MENU_ITEM_ID ) != NULL);
-- 
1.6.6.1


lxpanel-0.5.5-number-of-visible-items.patch:
 menu.c |   21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

--- NEW FILE lxpanel-0.5.5-number-of-visible-items.patch ---
>From 6a4d4973f1e831aad9fd0cb54585baf7ac3b4932 Mon Sep 17 00:00:00 2001
From: Juergen Hoetzel <juergen at archlinux.org>
Date: Fri, 19 Feb 2010 19:09:05 +0100
Subject: [PATCH 4/9] load_menu: return number of visible items and hide empty submenus

This is used to hide submenus without visible entries (Submenus
containing "OnlyShowIn" entries).
---
 src/plugins/menu.c |   20 +++++++++++++++++---
 1 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/src/plugins/menu.c b/src/plugins/menu.c
index de576f3..5b3ae2f 100644
--- a/src/plugins/menu.c
+++ b/src/plugins/menu.c
@@ -419,9 +419,11 @@ static GtkWidget* create_item( MenuCacheItem* item )
     return mi;
 }
 
-static void load_menu(menup* m, MenuCacheDir* dir, GtkWidget* menu, int pos )
+static int load_menu(menup* m, MenuCacheDir* dir, GtkWidget* menu, int pos )
 {
     GSList * l;
+    /* number of visible entries */
+    gint count = 0;		
     for( l = menu_cache_dir_get_children(dir); l; l = l->next )
     {
         MenuCacheItem* item = MENU_CACHE_ITEM(l->data);
@@ -432,6 +434,7 @@ static void load_menu(menup* m, MenuCacheDir* dir, GtkWidget* menu, int pos )
 	if (is_visible) 
 	{
             GtkWidget * mi = create_item(item);
+	    count++;
             if (mi != NULL)
                 gtk_menu_shell_insert( (GtkMenuShell*)menu, mi, pos );
                 if( pos >= 0 )
@@ -440,11 +443,22 @@ static void load_menu(menup* m, MenuCacheDir* dir, GtkWidget* menu, int pos )
 		if (menu_cache_item_get_type(item) == MENU_CACHE_TYPE_DIR) 
 		{
                     GtkWidget* sub = gtk_menu_new();
-                    load_menu( m, MENU_CACHE_DIR(item), sub, -1 );    /* always pass -1 for position */
-                    gtk_menu_item_set_submenu( GTK_MENU_ITEM(mi), sub );	    
+		    /*  always pass -1 for position */
+		    gint s_count = load_menu( m, MENU_CACHE_DIR(item), sub, -1 );    
+                    if (s_count) 
+			gtk_menu_item_set_submenu( GTK_MENU_ITEM(mi), sub );	    
+		    else 
+		    {
+			/* don't keep empty submenus */
+			gtk_widget_destroy( sub );
+			gtk_widget_destroy( mi );
+			if (pos > 0)
+			    pos--;
+		    }
 		}
 	}
     }
+    return count;
 }
 
 
-- 
1.6.6.1


lxpanel-0.5.5-task-deletion-urgency-timer.patch:
 taskbar.c |    9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

--- NEW FILE lxpanel-0.5.5-task-deletion-urgency-timer.patch ---
>From 0aafb5a5c47213c5072a701f96ae82a910e7de09 Mon Sep 17 00:00:00 2001
From: Marty Jack <martyj at linux.local>
Date: Fri, 19 Mar 2010 22:46:23 -0400
Subject: [PATCH 21/23] Race condition in task deletion, urgency timer could fire after structure deleted
 Fedora bug 554174, 573172

---
 src/plugins/taskbar.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/plugins/taskbar.c b/src/plugins/taskbar.c
index a82286a..d6a1d71 100644
--- a/src/plugins/taskbar.c
+++ b/src/plugins/taskbar.c
@@ -549,15 +549,15 @@ static void task_delete(TaskbarPlugin * tb, Task * tk, gboolean unlink)
     if (tb->focused == tk)
         tb->focused = NULL;
 
+    /* If there is an urgency timeout, remove it. */
+    if (tk->flash_timeout != 0)
+        g_source_remove(tk->flash_timeout);
+
     /* Deallocate structures. */
     icon_grid_remove(tb->icon_grid, tk->button);
     task_free_names(tk);
     task_unlink_class(tk);
 
-    /* If there is an urgency timeout, remove it. */
-    if (tk->flash_timeout != 0)
-        g_source_remove(tk->flash_timeout);
-
     /* If requested, unlink the task from the task list.
      * If not requested, the caller will do this. */
     if (unlink)
-- 
1.6.6.1


lxpanel-0.5.5-update-translations.patch:
 da.po |  541 +++++++++++++++++++++++-------------------------------------------
 fr.po |  232 +++++++++++++---------------
 ru.po |  231 +++++++++++++---------------
 uk.po |  343 ++++++++++++++---------------------------
 4 files changed, 522 insertions(+), 825 deletions(-)

--- NEW FILE lxpanel-0.5.5-update-translations.patch ---
diff -dur lxpanel-0.5.5.orig/po/da.po lxpanel-0.5.5/po/da.po
--- lxpanel-0.5.5.orig/po/da.po	2010-02-06 20:45:38.000000000 +0100
+++ lxpanel-0.5.5/po/da.po	2010-03-20 15:33:05.000000000 +0100
@@ -1,18 +1,18 @@
 # Danish translation for lxpanel.
-# Copyright (C) 2008 THE lxpanel'S COPYRIGHT HOLDER
+# Copyright (C) 2010 THE lxpanel'S COPYRIGHT HOLDER
 # This file is distributed under the same license as the lxpanel package.
-# Mario Blättermann <mario.blaettermann at t-online.de>, 2008.
-# Mario Blättermann <mario.blaettermann at t-online.de>, 2008.
+# Vidar Jon Bauge <vidarjb at gmail.com>, 2009.
+# Joe Hansen <joedalton2 at yahoo.dk>, 2010.
 #
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: lxpanel\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-02-02 01:32+0100\n"
-"PO-Revision-Date: 2009-12-30 10:30+0100\n"
-"Last-Translator: Vidar Jon Bauge <vidarjb at gmail.com>\n"
-"Language-Team: Danish\n"
+"POT-Creation-Date: 2010-02-23 04:06+0000\n"
+"PO-Revision-Date: 2010-02-32 21:06+0100\n"
+"Last-Translator: Joe Hansen <joedalton2 at yahoo.dk>\n"
+"Language-Team: Danish <dansk at dansk-gruppen.dk>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
@@ -22,7 +22,7 @@
 #: ../data/ui/panel-pref.glade.h:2
 #, no-c-format
 msgid "% Percent"
-msgstr "% Procent"
+msgstr "% procent"
 
 #: ../data/ui/panel-pref.glade.h:3
 msgid "<b>Automatic hiding</b>"
@@ -68,13 +68,13 @@
 msgid "Appearance"
 msgstr "Udseende"
 
-#: ../data/ui/panel-pref.glade.h:14 ../src/panel.c:1021
+#: ../data/ui/panel-pref.glade.h:14 ../src/panel.c:1039
 msgid "Bottom"
 msgstr "Bund"
 
 #: ../data/ui/panel-pref.glade.h:15
 msgid "Center"
-msgstr "Center"
+msgstr "Midt"
 
 #: ../data/ui/panel-pref.glade.h:16
 msgid "Custom color"
@@ -96,7 +96,7 @@
 msgid "Geometry"
 msgstr "Ændr størrelse"
 
-#: ../data/ui/panel-pref.glade.h:21 ../src/panel.c:1011 ../src/panel.c:1019
+#: ../data/ui/panel-pref.glade.h:21 ../src/panel.c:1029 ../src/panel.c:1037
 msgid "Height:"
 msgstr "Højde:"
 
@@ -104,7 +104,7 @@
 msgid "Image"
 msgstr "Billede"
 
-#: ../data/ui/panel-pref.glade.h:23 ../src/panel.c:1013
+#: ../data/ui/panel-pref.glade.h:23 ../src/panel.c:1031
 msgid "Left"
 msgstr "Venstre"
 
@@ -118,7 +118,7 @@
 
 #: ../data/ui/panel-pref.glade.h:26
 msgid "Margin:"
-msgstr "Margin:"
+msgstr "Margen:"
 
 #: ../data/ui/panel-pref.glade.h:27
 msgid "Minimize panel when not in use"
@@ -126,7 +126,7 @@
 
 #: ../data/ui/panel-pref.glade.h:28
 msgid "Panel Applets"
-msgstr "Panel appleter"
+msgstr "Panelprogrammer"
 
 #: ../data/ui/panel-pref.glade.h:29
 msgid "Panel Preferences"
@@ -134,13 +134,13 @@
 
 #: ../data/ui/panel-pref.glade.h:30
 msgid "Pixels"
-msgstr "Pixels"
+msgstr "Billedpunkter"
 
 #: ../data/ui/panel-pref.glade.h:31
 msgid "Reserve space, and not covered by maximized windows"
 msgstr "Reserveret plads. Dækkes ikke af maksimerede vinduer"
 
-#: ../data/ui/panel-pref.glade.h:32 ../src/panel.c:1014
+#: ../data/ui/panel-pref.glade.h:32 ../src/panel.c:1032
 msgid "Right"
 msgstr "Højre"
 
@@ -154,7 +154,7 @@
 
 #: ../data/ui/panel-pref.glade.h:35
 msgid "Solid color (with opacity)"
-msgstr "Ensfarvet (Med gennemsigtighed)"
+msgstr "Ensfarvet (med gennemsigtighed)"
 
 #: ../data/ui/panel-pref.glade.h:36
 msgid "System theme"
@@ -162,19 +162,19 @@
 
 #: ../data/ui/panel-pref.glade.h:37
 msgid "Terminal Emulator:"
-msgstr "Terminal emulator:"
+msgstr "Terminalemulator:"
 
-#: ../data/ui/panel-pref.glade.h:38 ../src/panel.c:1020
+#: ../data/ui/panel-pref.glade.h:38 ../src/panel.c:1038
 msgid "Top"
 msgstr "Top"
 
-#: ../data/ui/panel-pref.glade.h:39 ../src/panel.c:1012 ../src/panel.c:1018
+#: ../data/ui/panel-pref.glade.h:39 ../src/panel.c:1030 ../src/panel.c:1036
 msgid "Width:"
 msgstr "Bredde:"
 
 #: ../data/ui/panel-pref.glade.h:40
 msgid "pixels"
-msgstr "px"
+msgstr "billedpunkter"
 
 #: ../data/ui/netstatus.glade.h:2
 #: ../src/plugins/netstatus/gnome-netstatus.glade.h:2
@@ -195,22 +195,22 @@
 #: ../data/ui/netstatus.glade.h:5
 #: ../src/plugins/netstatus/gnome-netstatus.glade.h:5
 msgid "<b>Internet Protocol (IPv4)</b>"
-msgstr "<b>Internet protokol (IPv4)</b>"
+msgstr "<b>Internetprotokol (IPv4)</b>"
 
 #: ../data/ui/netstatus.glade.h:6
 #: ../src/plugins/netstatus/gnome-netstatus.glade.h:6
 msgid "<b>Internet Protocol (IPv6)</b>"
-msgstr "<b>Internet protokol (IPv6)</b>"
+msgstr "<b>Internetprotokol (IPv6)</b>"
 
 #: ../data/ui/netstatus.glade.h:7
 #: ../src/plugins/netstatus/gnome-netstatus.glade.h:7
 msgid "<b>Network Device</b>"
-msgstr "<b>Netværks enhed</b>"
+msgstr "<b>Netværksenhed</b>"
 
 #: ../data/ui/netstatus.glade.h:8
 #: ../src/plugins/netstatus/gnome-netstatus.glade.h:8
 msgid "<b>Signal Strength</b>"
-msgstr "<b>Signal styrke</b>"
+msgstr "<b>Signalstyrke</b>"
 
 #: ../data/ui/netstatus.glade.h:9
 #: ../src/plugins/netstatus/gnome-netstatus.glade.h:9
@@ -226,7 +226,7 @@
 #: ../data/ui/netstatus.glade.h:11
 #: ../src/plugins/netstatus/gnome-netstatus.glade.h:11
 msgid "Con_figure"
-msgstr "Konf_igurér"
+msgstr "Konf_igurer"
 
 #: ../data/ui/netstatus.glade.h:12
 #: ../src/plugins/netstatus/gnome-netstatus.glade.h:12
@@ -261,7 +261,7 @@
 #: ../data/ui/netstatus.glade.h:18
 #: ../src/plugins/netstatus/gnome-netstatus.glade.h:18
 msgid "Subnet Mask:"
-msgstr "Subnet maske:"
+msgstr "Undernetmaske:"
 
 #: ../data/ui/netstatus.glade.h:19
 #: ../src/plugins/netstatus/gnome-netstatus.glade.h:19
@@ -278,19 +278,11 @@
 msgid "_Name:"
 msgstr "_Navn:"
 
-#: ../data/ui/launchbar.glade.h:1 ../src/plugins/launchbar.c:831
+#: ../data/ui/launchbar.glade.h:1 ../src/plugins/launchbar.c:887
 msgid "Application Launch Bar"
-msgstr "Område til start af programmer"
-
-#: ../data/ui/launchbar.glade.h:2
-msgid "Applications"
-msgstr "Programmer"
-
-#: ../data/ui/launchbar.glade.h:3
-msgid "Available Applications"
[...2776 lines suppressed...]
-#: ../src/plugins/volumealsa/volumealsa.c:449
+#: ../src/plugins/volumealsa/volumealsa.c:460
 msgid "Volume Control"
 msgstr "Регулятор Гучності"
 
 #. Create a frame as the child of the viewport.
 #: ../src/plugins/volume/volume-impl.c:109
-#: ../src/plugins/volumealsa/volumealsa.c:358
+#: ../src/plugins/volumealsa/volumealsa.c:369
 msgid "Volume"
 msgstr "Гучність"
 
 #. Create a check button as the child of the vertical box.
-#: ../src/plugins/volumealsa/volumealsa.c:377
+#: ../src/plugins/volumealsa/volumealsa.c:388
 msgid "Mute"
 msgstr "Заглушити"
 
@@ -856,8 +834,7 @@
 msgid "Connection has limited or no connectivity"
 msgstr "Зв’язок обмежений або ж немає з’єднання"
 
-#: ../src/plugins/netstat/netstat.c:307
-#: ../src/plugins/netstat/netstat.c:318
+#: ../src/plugins/netstat/netstat.c:307 ../src/plugins/netstat/netstat.c:318
 #: ../src/plugins/netstat/netstat.c:329
 msgid "IP Address:"
 msgstr "IP адреса:"
@@ -866,38 +843,32 @@
 msgid "Remote IP:"
 msgstr "Віддалене IP:"
 
-#: ../src/plugins/netstat/netstat.c:309
-#: ../src/plugins/netstat/netstat.c:320
+#: ../src/plugins/netstat/netstat.c:309 ../src/plugins/netstat/netstat.c:320
 #: ../src/plugins/netstat/netstat.c:331
 msgid "Netmask:"
 msgstr "Маска мережі:"
 
-#: ../src/plugins/netstat/netstat.c:310
-#: ../src/plugins/netstat/netstat.c:322
+#: ../src/plugins/netstat/netstat.c:310 ../src/plugins/netstat/netstat.c:322
 #: ../src/plugins/netstat/netstat.c:333
 msgid "Activity"
 msgstr "Активність"
 
-#: ../src/plugins/netstat/netstat.c:310
-#: ../src/plugins/netstat/netstat.c:322
+#: ../src/plugins/netstat/netstat.c:310 ../src/plugins/netstat/netstat.c:322
 #: ../src/plugins/netstat/netstat.c:333
 msgid "Sent"
 msgstr "Вислано"
 
-#: ../src/plugins/netstat/netstat.c:310
-#: ../src/plugins/netstat/netstat.c:322
+#: ../src/plugins/netstat/netstat.c:310 ../src/plugins/netstat/netstat.c:322
 #: ../src/plugins/netstat/netstat.c:333
 msgid "Received"
 msgstr "Отримано"
 
-#: ../src/plugins/netstat/netstat.c:311
-#: ../src/plugins/netstat/netstat.c:323
+#: ../src/plugins/netstat/netstat.c:311 ../src/plugins/netstat/netstat.c:323
 #: ../src/plugins/netstat/netstat.c:334
 msgid "bytes"
 msgstr "байт"
 
-#: ../src/plugins/netstat/netstat.c:312
-#: ../src/plugins/netstat/netstat.c:324
+#: ../src/plugins/netstat/netstat.c:312 ../src/plugins/netstat/netstat.c:324
 #: ../src/plugins/netstat/netstat.c:335
 msgid "packets"
 msgstr "пакетів"
@@ -911,8 +882,7 @@
 msgid "Protocol:"
 msgstr "Протокол:"
 
-#: ../src/plugins/netstat/netstat.c:321
-#: ../src/plugins/netstat/netstat.c:332
+#: ../src/plugins/netstat/netstat.c:321 ../src/plugins/netstat/netstat.c:332
 msgid "HW Address:"
 msgstr "Адреса \"заліза\":"
 
@@ -1042,7 +1012,8 @@
 "\n"
 "%s"
 msgstr ""
-"Зв’яжіться з Вашим системним адміністратором для вирішення наступної проблеми:\n"
+"Зв’яжіться з Вашим системним адміністратором для вирішення наступної "
+"проблеми:\n"
 "\n"
 "%s"
 
@@ -1236,8 +1207,12 @@
 #: ../src/plugins/netstatus/netstatus-sysdeps.c:217
 #: ../src/plugins/netstatus/netstatus-sysdeps.c:645
 #, c-format
-msgid "Could not parse interface statistics from '%s'. prx_idx = %d; ptx_idx = %d; brx_idx = %d; btx_idx = %d;"
-msgstr "Не можу обробити статистику пристрою '%s'. prx_idx = %d; ptx_idx = %d; brx_idx = %d; btx_idx = %d;"
+msgid ""
+"Could not parse interface statistics from '%s'. prx_idx = %d; ptx_idx = %d; "
+"brx_idx = %d; btx_idx = %d;"
+msgstr ""
+"Не можу обробити статистику пристрою '%s'. prx_idx = %d; ptx_idx = %d; "
+"brx_idx = %d; btx_idx = %d;"
 
 #: ../src/plugins/netstatus/netstatus-sysdeps.c:314
 msgid "Could not parse /proc/net/wireless. Unknown format."
@@ -1369,91 +1344,3 @@
 #: ../src/plugins/kbled/kbled.c:269
 msgid "Indicators for CapsLock, NumLock, and ScrollLock keys"
 msgstr "Індикатори для клавіш CapsLock, NumLock і ScrollLock"
-
-#~ msgid "Display system temperature, by kesler.daniel at gmail.com"
-#~ msgstr "Моніторинг температури системи, розробка kesler.daniel at gmail.com"
-#~ msgid "Keyboard Led"
-#~ msgstr "Індикатор клавіатури"
-#~ msgid "Left\t"
-#~ msgstr "Зліва\t"
-#~ msgid "Top\t"
-#~ msgstr "Вверху\t"
-#~ msgid "Couldn't find pixmap file: %s"
-#~ msgstr "Не можу знайти pixmap файл: %s"
-#~ msgid "Desktop No / Workspace Name"
-#~ msgstr "Номер стільниці / Назва робочої області"
-#~ msgid ""
-#~ "Allows you to switch the keyboard layout and\n"
-#~ "displays the currently selected layout."
-#~ msgstr ""
-#~ "Дозволяє Вам переключати розкладку клавіатури і\n"
-#~ "показує вибрану розкладку."
-#~ msgid "Other plugins available here"
-#~ msgstr "Інші плагіни доступні тут"
-#~ msgid "Old KDE/GNOME Tray"
-#~ msgstr "Старий лоток KDE/GNOME "
-#~ msgid "Enable Image:"
-#~ msgstr "Дозволити зображення:"
-#~ msgid "Enable Transparency"
-#~ msgstr "Включити прозорість"
-#~ msgid "Tint color:"
-#~ msgstr "Відтінок кольору:"
-#~ msgid " --configure -- launch configuration utility\n"
-#~ msgstr "--configure -- запустити конфігураційну програму\n"
-#~ msgid " -C  -- same as --configure\n"
-#~ msgstr " -C  -- то саме що й  --configure\n"
-#~ msgid "Add Button"
-#~ msgstr "Додати кнопку"
-#~ msgid "Button Properties"
-#~ msgstr "Властивості кнопки"
-#~ msgid "Remove Button"
-#~ msgstr "Видалити кнопку"
-#~ msgid "Buttons"
-#~ msgstr "Кнопки"
-#~ msgid "Accept SkipPager"
-#~ msgstr "Прийняти SkipPager"
-#~ msgid "Show Iconified windows"
-#~ msgstr "Показати мінімалізовані вікна"
-#~ msgid "Show mapped windows"
-#~ msgstr "Показати позначені вікна"
-#~ msgid "Action"
-#~ msgstr "Дія"
-#~ msgid "Provide Menu"
-#~ msgstr "Вставити меню"
-#~ msgid "Kayboard Layout switcher"
-#~ msgstr "Переключатель розкладки клавіатури"
-#~ msgid ""
-#~ "Dynamic\n"
-#~ "Pixels\n"
-#~ "% Percent"
-#~ msgstr ""
-#~ "Динаміка\n"
-#~ "Пікселі\n"
-#~ "% Проценти"
-#~ msgid ""
-#~ "Left\n"
-#~ "Center\n"
-#~ "Right"
-#~ msgstr ""
-#~ "Вліво\n"
-#~ "Центр\n"
-#~ "Вправо"
-#~ msgid ""
-#~ "Left\n"
-#~ "Right\n"
-#~ "Top\n"
-#~ "Bottom"
-#~ msgstr ""
-#~ "Вліво\n"
-#~ "Вправо\n"
-#~ "Вверху\n"
-#~ "Внизу"
-#~ msgid "Where to put the panel?"
-#~ msgstr "Куди помістити цю панель?"
-#~ msgid "Battery: %d%% charged, %s"
-#~ msgstr "Батарея: %d%% заряджено, %s"
-#~ msgid "charging finished"
-#~ msgstr "зарядку завершено"
-#~ msgid "charging"
-#~ msgstr "заряджаю"
-

lxpanel-0.5.5-urgency-notification.patch:
 taskbar.c |   33 +++++++++++++++++----------------
 1 file changed, 17 insertions(+), 16 deletions(-)

--- NEW FILE lxpanel-0.5.5-urgency-notification.patch ---
>From 4468eddd382c06d778132bf7060c7ec579459e2a Mon Sep 17 00:00:00 2001
From: Marty Jack <martyj at linux.local>
Date: Fri, 19 Mar 2010 19:14:50 -0400
Subject: [PATCH 18/23] Fix some issues with urgency notification
 - Was being ignored if coming out of urgency and going back in with grouping
 - Was leaving the button bolded in styled button case
 - Was bolding the button, this was unintended, in styled button case
 Fix two more places with 64-bit clean issue on ALL_DESKTOPS

---
 src/plugins/taskbar.c |   32 +++++++++++++++++---------------
 1 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/src/plugins/taskbar.c b/src/plugins/taskbar.c
index 15139e4..a82286a 100644
--- a/src/plugins/taskbar.c
+++ b/src/plugins/taskbar.c
@@ -163,6 +163,7 @@ static gboolean taskbar_button_press_event(GtkWidget * widget, GdkEventButton *
 static gboolean taskbar_popup_activate_event(GtkWidget * widget, GdkEventButton * event, Task * tk);
 static gboolean taskbar_button_drag_motion_timeout(Task * tk);
 static gboolean taskbar_button_drag_motion(GtkWidget * widget, GdkDragContext * drag_context, gint x, gint y, guint time, Task * tk);
+static void taskbar_button_drag_leave(GtkWidget * widget, GdkDragContext * drag_context, guint time, Task * tk);
 static void taskbar_button_enter(GtkWidget * widget, Task * tk);
 static void taskbar_button_leave(GtkWidget * widget, Task * tk);
 static gboolean taskbar_button_scroll_event(GtkWidget * widget, GdkEventScroll * event, Task * tk);
@@ -276,6 +277,7 @@ static void recompute_group_visibility_for_class(TaskbarPlugin * tb, TaskClass *
         {
             g_source_remove(flashing_task->flash_timeout);
             flashing_task->flash_state = FALSE;
+            flashing_task->flash_timeout = 0;
         }
     }
 }
@@ -294,7 +296,7 @@ static void recompute_group_visibility_on_current_desktop(TaskbarPlugin * tb)
 static void task_draw_label(Task * tk)
 {
     TaskClass * tc = tk->res_class;
-    gboolean bold_style = (((tk->entered_state) && (tk->tb->flat_button)) || tk->flash_state);
+    gboolean bold_style = ((tk->entered_state) && (tk->tb->flat_button));
     if ((tk->tb->grouped_tasks) && (tc != NULL) && (tc->visible_task == tk) && (tc->visible_count > 1))
 	{
         char * label = g_strdup_printf("(%d) %s", tc->visible_count, tc->visible_name);
@@ -931,13 +933,9 @@ static GdkPixbuf * task_update_icon(TaskbarPlugin * tb, Task * tk, Atom source)
 static gboolean flash_window_timeout(Task * tk)
 {
     /* Set state on the button and redraw. */
-    if (tk->tb->flat_button)
-        task_draw_label(tk);
-    else
-    {
+    if ( ! tk->tb->flat_button)
         gtk_widget_set_state(tk->button, tk->flash_state ? GTK_STATE_SELECTED : GTK_STATE_NORMAL);
-        gtk_widget_queue_draw(tk->button);
-    }
+    task_draw_label(tk);
 
     /* Complement the flashing context. */
     tk->flash_state = ! tk->flash_state;
@@ -947,7 +945,11 @@ static gboolean flash_window_timeout(Task * tk)
 /* Set urgency notification. */
 static void task_set_urgency(Task * tk)
 {
-    if (( ! tk->tb->grouped_tasks) || (tk->res_class == NULL))
+    TaskbarPlugin * tb = tk->tb;
+    TaskClass * tc = tk->res_class;
+    if ((tb->grouped_tasks) && (tc != NULL) && (tc->visible_count > 1))
+        recompute_group_visibility_for_class(tk->tb, tk->res_class);
+    else
     {
         /* Set the flashing context and flash the window immediately. */
         tk->flash_state = TRUE;
@@ -957,14 +959,16 @@ static void task_set_urgency(Task * tk)
         if (tk->flash_timeout == 0)
             set_timer_on_task(tk);
     }
-    else
-        recompute_group_visibility_for_class(tk->tb, tk->res_class);
 }
 
 /* Clear urgency notification. */
 static void task_clear_urgency(Task * tk)
 {
-    if (( ! tk->tb->grouped_tasks) || (tk->res_class == NULL))
+    TaskbarPlugin * tb = tk->tb;
+    TaskClass * tc = tk->res_class;
+    if ((tb->grouped_tasks) && (tc != NULL) && (tc->visible_count > 1))
+        recompute_group_visibility_for_class(tk->tb, tk->res_class);
+    else
     {
         /* Remove the timer if one is set. */
         if (tk->flash_timeout != 0)
@@ -978,8 +982,6 @@ static void task_clear_urgency(Task * tk)
         flash_window_timeout(tk);
         tk->flash_state = FALSE;
     }
-    else
-        recompute_group_visibility_for_class(tk->tb, tk->res_class);
 }
 
 /* Do the proper steps to raise a window.
@@ -988,7 +990,7 @@ static void task_clear_urgency(Task * tk)
 static void task_raise_window(Task * tk, guint32 time)
 {
     /* Change desktop if needed. */
-    if ((tk->desktop != -1) && (tk->desktop != tk->tb->current_desktop))
+    if ((tk->desktop != ALL_WORKSPACES) && (tk->desktop != tk->tb->current_desktop))
         Xclimsg(GDK_ROOT_WINDOW(), a_NET_CURRENT_DESKTOP, tk->desktop, 0, 0, 0, 0);
 
     /* Evaluate use_net_active if not yet done. */
@@ -1634,7 +1636,7 @@ static GdkFilterReturn taskbar_event_filter(XEvent * xev, GdkEvent * event, Task
 /* Handler for "activate" event on Raise item of right-click menu for task buttons. */
 static void menu_raise_window(GtkWidget * widget, TaskbarPlugin * tb)
 {
-    if ((tb->menutask->desktop != -1) && (tb->menutask->desktop != tb->current_desktop))
+    if ((tb->menutask->desktop != ALL_WORKSPACES) && (tb->menutask->desktop != tb->current_desktop))
         Xclimsg(GDK_ROOT_WINDOW(), a_NET_CURRENT_DESKTOP, tb->menutask->desktop, 0, 0, 0, 0);
     XMapRaised(GDK_DISPLAY(), tb->menutask->win);
     task_group_menu_destroy(tb);
-- 
1.6.6.1



Index: lxpanel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/lxpanel/devel/lxpanel.spec,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -p -r1.32 -r1.33
--- lxpanel.spec	27 Feb 2010 20:48:04 -0000	1.32
+++ lxpanel.spec	20 Mar 2010 22:19:42 -0000	1.33
@@ -3,7 +3,7 @@
 
 Name:           lxpanel
 Version:        0.5.5
-Release:        2%{?dist}
+Release:        3%{?dist}
 Summary:        A lightweight X11 desktop panel
 
 Group:          User Interface/Desktops
@@ -13,19 +13,43 @@ Source0:        http://downloads.sourcef
 # https://bugzilla.redhat.com/show_bug.cgi?id=564746
 Patch0:         lxpanel-0.5.5-dsofix.patch
 # http://lxde.git.sourceforge.net/git/gitweb.cgi?p=lxde/lxpanel;a=commit;h=b6c8855c97a6c76ec0752e3e33becc34cfa2792a
-Patch3:         lxpanel-0.5.5-load_menu-code-cleanup.patch
+Patch3:         lxpanel-0.5.5-menu-code-cleanup.patch
 # http://lxde.git.sourceforge.net/git/gitweb.cgi?p=lxde/lxpanel;a=commit;h=6a4d4973f1e831aad9fd0cb54585baf7ac3b4932
-Patch4:         lxpanel-0.5.5-load_menu-return-number-of-visible-items-and-hide-em.patch
+Patch4:         lxpanel-0.5.5-number-of-visible-items.patch
 # http://lxde.git.sourceforge.net/git/gitweb.cgi?p=lxde/lxpanel;a=commit;h=438d9fdbd3e0be04de933705917d508a02b7c04b
-Patch5:         lxpanel-0.5.5-Fix-failure-to-react-to-keyboard-map-changes-initiat.patch
+Patch5:         lxpanel-0.5.5-keyboard-map-changes.patch
 # http://lxde.git.sourceforge.net/git/gitweb.cgi?p=lxde/lxpanel;a=commit;h=c7f782401364bd8a8389ffa7a1666d90049113a8
-Patch6:         lxpanel-0.5.5-Fix-failure-to-honor-Terminal-true-in-menu-and-launc.patch
-# http://lxde.git.sourceforge.net/git/gitweb.cgi?p=lxde/lxpanel;a=commit;h=0c5f948f4f55ea63c95cc65d0a6d34e1a3424fc6
-Patch7:         lxpanel-0.5.5-Implement-lxpanelctl-config-command-FR1992552.patch
+Patch6:         lxpanel-0.5.5-Terminal-true.patch
 # http://lxde.git.sourceforge.net/git/gitweb.cgi?p=lxde/lxpanel;a=commit;h=0c5f948f4f55ea63c95cc65d0a6d34e1a3424fc6
+Patch7:         lxpanel-0.5.5-lxpanelctl-config.patch
+# http://lxde.git.sourceforge.net/git/gitweb.cgi?p=lxde/lxpanel;a=commit;h=3855f25de17c1a4b11e63a639ab387efb576271c
+Patch10:        lxpanel-0.5.5-clock-poll-interval.patch
+# http://lxde.git.sourceforge.net/git/gitweb.cgi?p=lxde/lxpanel;a=commit;h=8575ae11809c9d465a0ecba2b1ed79b4e7701f86
+Patch11:        lxpanel-0.5.5-icon-only-case.patch
+# http://lxde.git.sourceforge.net/git/gitweb.cgi?p=lxde/lxpanel;a=commit;h=116746cf09628e3e8968a04b41c0f08aab06cb23
+Patch12:        lxpanel-0.5.5-enum-values.patch
+# http://lxde.git.sourceforge.net/git/gitweb.cgi?p=lxde/lxpanel;a=commit;h=2efc857c9638eb5d2313b7c1551f87c4b33ef3ff
+Patch13:        lxpanel-0.5.5-enum-value.patch
+# http://lxde.git.sourceforge.net/git/gitweb.cgi?p=lxde/lxpanel;a=commit;h=447ea0f5dcafb335348aef764a7d9c45febddc0b
+Patch14:        lxpanel-0.5.5-inconsist-group-count.patch
+# http://lxde.git.sourceforge.net/git/gitweb.cgi?p=lxde/lxpanel;a=commit;h=60c77f707b58b82b009857b6dd17b9fb8effd360
+Patch15:        lxpanel-0.5.5-configuration-not-in-sync.patch
+# http://lxde.git.sourceforge.net/git/gitweb.cgi?p=lxde/lxpanel;a=commit;h=4aae3d92cdce6e212572a7b75749766ef1e1ffcb
+Patch16:        lxpanel-0.5.5-64-bit-clean-regression.patch
+# http://lxde.git.sourceforge.net/git/gitweb.cgi?p=lxde/lxpanel;a=commit;h=4468eddd382c06d778132bf7060c7ec579459e2a
+Patch18:        lxpanel-0.5.5-urgency-notification.patch
+# http://lxde.git.sourceforge.net/git/gitweb.cgi?p=lxde/lxpanel;a=commit;h=0aafb5a5c47213c5072a701f96ae82a910e7de09
+# should fix https://bugzilla.redhat.com/show_bug.cgi?id=554174
+Patch21:        lxpanel-0.5.5-task-deletion-urgency-timer.patch
+# http://lxde.git.sourceforge.net/git/gitweb.cgi?p=lxde/lxpanel;a=commit;h=8bf045c957395c4da6b9e3bbf6833581d9e0b365
+# should fix https://bugzilla.redhat.com/show_bug.cgi?id=575053
+Patch22:        lxpanel-0.5.5-UI-draw-cell-renderer.patch
+# several updates from TX in one patch
+Patch99:        lxpanel-0.5.5-update-translations.patch
+
 # distro specific patches
-Patch10:        lxpanel-0.5.4-default.patch
-Patch11:        lxpanel-0.3.8.1-nm-connection-editor.patch
+Patch100:       lxpanel-0.5.4-default.patch
+Patch101:       lxpanel-0.3.8.1-nm-connection-editor.patch
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
 #BuildRequires:  docbook-utils
@@ -63,10 +87,23 @@ developing applications that use %{name}
 %patch3 -p1 -b .code-cleanup
 %patch4 -p1 -b .visible-items
 %patch5 -p1 -b .keyboard-map
-%patch6 -p1 -b .honor-terminal
+%patch6 -p1 -b .Terminal-true
 %patch7 -p1 -b .lxpanelctl-config
-%patch10 -p1 -b .default
-%patch11 -p1 -b .system-config-network
+%patch10 -p1 -b .clock-poll
+%patch11 -p1 -b .icon-only
+%patch12 -p1 -b .enum-values
+%patch13 -p1 -b .enum-value
+%patch14 -p1 -b .inconsist-group-count
+%patch15 -p1 -b .configuration-not-in-sync
+%patch16 -p1 -b .64-bit-clean
+%patch18 -p1 -b .urgency-notification
+%patch21 -p1 -b .task-deletion
+%patch22 -p1 -b .cell-renderer
+
+%patch99 -p1 -b .old
+
+%patch100 -p1 -b .default
+%patch101 -p1 -b .system-config-network
 
 
 %build
@@ -98,6 +135,12 @@ rm -rf $RPM_BUILD_ROOT
 %{_libdir}/pkgconfig/lxpanel.pc
 
 %changelog
+* Sat Mar 20 2010 Christoph Wickert <cwickert at fedoraproject.org> - 0.5.5-3
+- Fix two race conditions (#554174 and #575053)
+- Hide empty menus
+- Lots of fixes
+- Update translations from Transifex
+
 * Sat Feb 27 2010 Christoph Wickert <cwickert at fedoraproject.org> - 0.5.5-2
 - Rebuild for menu-cache 0.3.2 soname bump
 - Add some more menu code changes from git


--- lxpanel-0.5.5-Fix-failure-to-honor-Terminal-true-in-menu-and-launc.patch DELETED ---


--- lxpanel-0.5.5-Fix-failure-to-react-to-keyboard-map-changes-initiat.patch DELETED ---


--- lxpanel-0.5.5-Implement-lxpanelctl-config-command-FR1992552.patch DELETED ---


--- lxpanel-0.5.5-load_menu-code-cleanup.patch DELETED ---


--- lxpanel-0.5.5-load_menu-return-number-of-visible-items-and-hide-em.patch DELETED ---



More information about the scm-commits mailing list