[Xfce4-commits] <xfce4-embed-plugin:master> Added configuration dialog and fixed popout window-destruction bugs.

David Schneider noreply at xfce.org
Sun Jan 1 21:44:29 CET 2012


Updating branch refs/heads/master
         to 6af97f8443671aae63781a6b113ff59fd515d838 (commit)
       from d8450df582a8ffe99729dc19ce04ada9d54f5128 (commit)

commit 6af97f8443671aae63781a6b113ff59fd515d838
Author: David Schneider <dnschneid at gmail.com>
Date:   Fri Dec 30 06:01:43 2011 -0500

    Added configuration dialog and fixed popout window-destruction bugs.

 panel-plugin/embed-dialogs.c |  246 ++++++++++++++++++++++++++++++++++++------
 panel-plugin/embed-dialogs.h |    5 +-
 panel-plugin/embed.c         |   39 +++++--
 panel-plugin/embed.h         |   13 ++-
 4 files changed, 256 insertions(+), 47 deletions(-)

diff --git a/panel-plugin/embed-dialogs.c b/panel-plugin/embed-dialogs.c
index 5c86749..edc3ab5 100644
--- a/panel-plugin/embed-dialogs.c
+++ b/panel-plugin/embed-dialogs.c
@@ -31,59 +31,238 @@
 #include "embed-dialogs.h"
 
 /* the website url */
-#define PLUGIN_WEBSITE "http://goodies.xfce.org/projects/panel-plugins/xfce4-embed-plugin"
+#define PLUGIN_WEBSITE \
+  "http://goodies.xfce.org/projects/panel-plugins/xfce4-embed-plugin"
 
 
+#define SETTINGS_PAD_PX 5
+
 
 static void
-embed_configure_response (GtkWidget    *dialog,
-                           gint          response,
-                           EmbedPlugin *embed)
+embed_configure_response (GtkWidget *dialog, gint response, EmbedPlugin *embed)
 {
   gboolean result;
 
-  if (response == GTK_RESPONSE_HELP)
-    {
-      /* show help */
-      result = g_spawn_command_line_async ("exo-open --launch WebBrowser " PLUGIN_WEBSITE, NULL);
+  if (response == GTK_RESPONSE_HELP) {
+    /* show help */
+    result = g_spawn_command_line_async (
+        "exo-open --launch WebBrowser " PLUGIN_WEBSITE, NULL);
+
+    if (G_UNLIKELY (result == FALSE))
+      g_warning (_("Unable to open the following url: %s"), PLUGIN_WEBSITE);
+  } else {
+    /* remove the dialog data from the plugin */
+    g_object_set_data (G_OBJECT (embed->plugin), "dialog", NULL);
+
+    /* unlock the panel menu */
+    xfce_panel_plugin_unblock_menu (embed->plugin);
+
+    /* save the plugin */
+    embed_save (embed->plugin, embed);
+
+    /* destroy the properties dialog */
+    gtk_widget_destroy (dialog);
+
+    /* start a new search if necessary */
+    if (embed->criteria_updated)
+      embed_search_again (embed);
+  }
+}
+
+
+
+static void
+embed_proc_name_changed (GtkEditable *edit, EmbedPlugin *embed)
+{
+  g_free (embed->proc_name);
+  embed->proc_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (edit)));
+  embed->criteria_updated = TRUE;
+}
+
+
+
+static void
+embed_window_class_changed (GtkEditable *edit, EmbedPlugin *embed)
+{
+  g_free (embed->window_class);
+  embed->window_class = g_strdup (gtk_entry_get_text (GTK_ENTRY (edit)));
+  embed->criteria_updated = TRUE;
+}
+
+
+
+static void
+embed_entry_set_good (GtkEntry *edit, gboolean good)
+{
+  if (good) {
+    gtk_entry_set_icon_tooltip_text (edit, GTK_ENTRY_ICON_SECONDARY,
+                                     _("The REGEX is valid"));
+    gtk_entry_set_icon_from_stock (edit, GTK_ENTRY_ICON_SECONDARY,
+                                   GTK_STOCK_YES);
+  } else {
+    gtk_entry_set_icon_tooltip_text (edit, GTK_ENTRY_ICON_SECONDARY,
+                                     _("The REGEX is invalid"));
+    gtk_entry_set_icon_from_stock (edit, GTK_ENTRY_ICON_SECONDARY,
+                                   GTK_STOCK_NO);
+  }
+}
+
+
+
+static void
+embed_window_regex_changed (GtkEditable *edit, EmbedPlugin *embed)
+{
+  const gchar *text;
+  GRegex *regex_comp;
+
+  /* Confirm that the REGEX is okay before saving. */
+  text = gtk_entry_get_text (GTK_ENTRY (edit));
+  regex_comp = g_regex_new (text, G_REGEX_OPTIMIZE, 0, NULL);
+  if (regex_comp) {
+    g_free (embed->window_regex);
+    if (embed->window_regex_comp)
+      g_regex_unref (embed->window_regex_comp);
+    embed->window_regex = g_strdup (text);
+    embed->window_regex_comp = regex_comp;
+    embed->criteria_updated = TRUE;
+    embed_entry_set_good (GTK_ENTRY (edit), TRUE);
+  } else {
+    embed_entry_set_good (GTK_ENTRY (edit), FALSE);
+  }
+}
+
 
-      if (G_UNLIKELY (result == FALSE))
-        g_warning (_("Unable to open the following url: %s"), PLUGIN_WEBSITE);
-    }
-  else
-    {
-      /* remove the dialog data from the plugin */
-      g_object_set_data (G_OBJECT (embed->plugin), "dialog", NULL);
 
-      /* unlock the panel menu */
-      xfce_panel_plugin_unblock_menu (embed->plugin);
+static void
+embed_label_fmt_changed (GtkEditable *edit, EmbedPlugin *embed)
+{
+  g_free (embed->label_fmt);
+  embed->label_fmt = g_strdup (gtk_entry_get_text (GTK_ENTRY (edit)));
+  embed_update_label (embed);
+}
+
 
-      /* save the plugin */
-      embed_save (embed->plugin, embed);
 
-      /* destroy the properties dialog */
-      gtk_widget_destroy (dialog);
-    }
+static void
+embed_min_size_changed (GtkSpinButton *spin, EmbedPlugin *embed)
+{
+  embed->min_size = gtk_spin_button_get_value_as_int (spin);
+  embed_size_changed_simple (embed);
+}
+
+
+
+static void
+embed_expand_toggled (GtkToggleButton *toggle, EmbedPlugin *embed)
+{
+  embed->expand = gtk_toggle_button_get_active (toggle);
+  xfce_panel_plugin_set_expand (embed->plugin, embed->expand);
 }
 
 
 
 void
-embed_configure (XfcePanelPlugin *plugin,
-                  EmbedPlugin    *embed)
+embed_configure (XfcePanelPlugin *plugin, EmbedPlugin *embed)
 {
-  GtkWidget *dialog;
+  GtkWidget *dialog, *content, *hbox, *label, *widget;
+  const gchar *tooltip;
 
   /* block the plugin menu */
   xfce_panel_plugin_block_menu (plugin);
 
+  /* stop searches */
+  embed_stop_search (embed);
+
   /* create the dialog */
-  dialog = xfce_titled_dialog_new_with_buttons (_("Embed Plugin"),
-                                                GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (plugin))),
-                                                GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
-                                                GTK_STOCK_HELP, GTK_RESPONSE_HELP,
-                                                GTK_STOCK_CLOSE, GTK_RESPONSE_OK,
-                                                NULL);
+  dialog = xfce_titled_dialog_new_with_buttons (
+      _("Embed Plugin"),
+      GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (plugin))),
+      GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
+      GTK_STOCK_HELP, GTK_RESPONSE_HELP,
+      GTK_STOCK_CLOSE, GTK_RESPONSE_OK,
+      NULL);
+
+  content = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+#define ADD1(widgetA) \
+    gtk_box_pack_start_defaults (GTK_BOX (content), widgetA)
+#define ADD2(widgetA, widgetB) \
+    hbox = gtk_hbox_new (TRUE, SETTINGS_PAD_PX); \
+    gtk_box_pack_start_defaults (GTK_BOX (hbox), widgetA); \
+    gtk_box_pack_start_defaults (GTK_BOX (hbox), widgetB); \
+    gtk_box_pack_start_defaults (GTK_BOX (content), hbox)
+#define TOOLTIP2(widgetA, widgetB, tooltiptext) \
+    tooltip = tooltiptext; \
+    gtk_widget_set_tooltip_text (widgetA, tooltip); \
+    gtk_widget_set_tooltip_text (widgetB, tooltip);
+#define ENTRY(labeltext, tooltiptext, value, callback) \
+    label = gtk_label_new_with_mnemonic (labeltext); \
+    widget = gtk_entry_new (); \
+    if (value) \
+      gtk_entry_set_text (GTK_ENTRY (widget), value); \
+    g_signal_connect (G_OBJECT (widget), "changed", \
+                      G_CALLBACK (callback), embed); \
+    TOOLTIP2(label, widget, tooltiptext); \
+    gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5f); \
+    gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget); \
+    ADD2(label, widget);
+#define SPIN(labeltext, tooltiptext, value, callback) \
+    label = gtk_label_new_with_mnemonic (labeltext); \
+    widget = gtk_spin_button_new_with_range (0, G_MAXINT, 1); \
+    gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), value); \
+    g_signal_connect (G_OBJECT (widget), "value-changed", \
+                      G_CALLBACK (callback), embed); \
+    TOOLTIP2(label, widget, tooltiptext); \
+    gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5f); \
+    gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget); \
+    ADD2(label, widget);
+
+  /* proc_name */
+  ENTRY(_("Process name"), _("Match the window's application's process name\n"
+                             "Leave blank if it is not a criterion"),
+        embed->proc_name, embed_proc_name_changed);
+
+  /* window_class */
+  ENTRY(_("Window class"), _("Match the window's class\n"
+                             "Leave blank if it is not a criterion"),
+        embed->window_class, embed_window_class_changed);
+
+  /* window_regex */
+  ENTRY(_("Window title"), _("Match the window's title using a REGEX\n"
+                             "Leave blank if it is not a criterion"),
+        embed->window_regex, embed_window_regex_changed);
+  embed_entry_set_good (GTK_ENTRY (widget), TRUE);
+
+  /* label_fmt */
+  ENTRY(_("Label format"), _("Leave blank to hide the label\n"
+        EMBED_LABEL_FMT_TITLE " expands to the embedded window's title"),
+        embed->label_fmt, embed_label_fmt_changed);
+
+  /* poll_delay */
+  /* No UI element. Generally polling is unnecessary, unless you have a very
+   * strange window that you're trying to match that is not uniquely
+   * identifiable when it is mapped. */
+
+  /* min_size */
+  SPIN(_("Minimum _size (px)"), _("Minimum size of the embedded window\n"
+                                  "Set to 0 to keep the original window size"),
+       embed->min_size, embed_min_size_changed);
+
+  /* expand */
+  widget = gtk_check_button_new_with_mnemonic (_("_Expand"));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), embed->expand);
+  g_signal_connect (G_OBJECT (widget), "toggled",
+                    G_CALLBACK (embed_expand_toggled), embed);
+  gtk_widget_set_tooltip_text (widget, _("Use up all available panel space"));
+  ADD1(widget);
+
+#undef ADD1
+#undef ADD2
+#undef TOOLTIP2
+#undef ENTRY
+#undef SPIN
+
+  gtk_widget_show_all (content);
 
   /* center dialog on the screen */
   gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
@@ -95,9 +274,12 @@ embed_configure (XfcePanelPlugin *plugin,
    * is closed, but the dialog is still open */
   g_object_set_data (G_OBJECT (plugin), "dialog", dialog);
 
+  /* criteria have not been updated */
+  embed->criteria_updated = FALSE;
+
   /* connect the reponse signal to the dialog */
   g_signal_connect (G_OBJECT (dialog), "response",
-                    G_CALLBACK(embed_configure_response), embed);
+                    G_CALLBACK (embed_configure_response), embed);
 
   /* show the entire dialog */
   gtk_widget_show (dialog);
diff --git a/panel-plugin/embed-dialogs.h b/panel-plugin/embed-dialogs.h
index c0659f2..98596fd 100644
--- a/panel-plugin/embed-dialogs.h
+++ b/panel-plugin/embed-dialogs.h
@@ -23,11 +23,10 @@
 G_BEGIN_DECLS
 
 void
-embed_configure    (XfcePanelPlugin *plugin,
-                     EmbedPlugin     *embed);
+embed_configure (XfcePanelPlugin *plugin, EmbedPlugin *embed);
 
 void
-embed_about        (XfcePanelPlugin *plugin);
+embed_about (XfcePanelPlugin *plugin);
 
 G_END_DECLS
 
diff --git a/panel-plugin/embed.c b/panel-plugin/embed.c
index 2c13cae..27133a5 100644
--- a/panel-plugin/embed.c
+++ b/panel-plugin/embed.c
@@ -37,7 +37,7 @@
 #define DEFAULT_PROC_NAME    NULL
 #define DEFAULT_WINDOW_REGEX NULL
 #define DEFAULT_WINDOW_CLASS NULL
-#define DEFAULT_LABEL_FMT    NULL
+#define DEFAULT_LABEL_FMT    _("Embed")
 #define DEFAULT_POLL_DELAY   0
 #define DEFAULT_MIN_SIZE     EMBED_MIN_SIZE_MATCH_WINDOW
 #define DEFAULT_EXPAND       TRUE
@@ -48,8 +48,6 @@
 static void
 embed_construct (XfcePanelPlugin *plugin);
 static void
-embed_update_label (EmbedPlugin *embed);
-static void
 embed_popout (GtkMenuItem *popout_menu, EmbedPlugin *embed);
 static void
 embed_destroyed (EmbedPlugin *embed);
@@ -329,7 +327,7 @@ embed_size_changed (XfcePanelPlugin *plugin, gint size, EmbedPlugin *embed)
 
 
 /* Convenience function to call embed_size_changed. */
-static void
+void
 embed_size_changed_simple (EmbedPlugin *embed)
 {
   embed_size_changed (embed->plugin,
@@ -339,7 +337,7 @@ embed_size_changed_simple (EmbedPlugin *embed)
 
 
 /* Updates the text of the label, using the label_fmt. */
-static void
+void
 embed_update_label (EmbedPlugin *embed)
 {
   /* Only show the label if the format is non-empty. */
@@ -414,8 +412,9 @@ embed_search (EmbedPlugin *embed)
 
       /* If it's a match, make a fake socket and embed the window in it. */
       if (match) {
-        /* Destroy the true GtkSocket, as we will not be needing it. */
-        gtk_widget_destroy (embed->socket);
+        /* Destroy the true GtkSocket if it exists, as don't need it. */
+        if (embed->socket)
+          gtk_widget_destroy (embed->socket);
         embed->plug_is_gtkplug = FALSE;
         embed->plug = client_list[i];
         /* Store the old size of the window for both restoring and for deciding
@@ -481,7 +480,7 @@ embed_start_search (GtkWidget *socket, EmbedPlugin *embed)
 
 
 /* Stops the search process, disabling both X11 monitoring and polling. */
-static void
+void
 embed_stop_search (EmbedPlugin *embed)
 {
   /* Set the event mask to 0 to stop receiving X11 events for the root window.
@@ -663,7 +662,10 @@ embed_size_allocate (GtkSocket *socket, GdkRectangle *allocation,
 static void
 embed_add_socket (EmbedPlugin *embed, gboolean update_size)
 {
-  g_assert (embed->socket == NULL);
+  if (embed->socket) {
+    DBG ("socket already exists");
+    return;
+  }
 
   embed->socket = gtk_socket_new ();
 
@@ -734,9 +736,15 @@ embed_popout (GtkMenuItem *popout_menu, EmbedPlugin *embed)
 
   if (!embed->plug_is_gtkplug) {
     /* Since we're not hosting a gtkplug, we should reparent the window so we
-     * don't break the program we were hosting. */
+     * don't break the program we were hosting.
+     * We reparent it both using GDK and using X11: GDK is to ensure that the
+     * destruction of the socket doesn't destroy the plug window. X11 is to
+     * ensure that the window is reparented if the panel plugin is closing.
+     * We do X11 first as it also resizes in one fell swoop. */
     make_window_toplevel (embed->disp, embed->plug,
                           embed->plug_width, embed->plug_height);
+    gdk_window_reparent (embed->plug_window,
+                         gdk_get_default_root_window (), 0, 0);
   }
   /* Don't enable searching for a new window. */
   embed->disable_search = TRUE;
@@ -762,6 +770,17 @@ embed_destroyed (EmbedPlugin *embed)
 
 
 
+/* Pop out whatever is embedded and start a new search.
+ * Called when the window criteria have been updated. */
+void
+embed_search_again (EmbedPlugin *embed)
+{
+  embed_popout (GTK_MENU_ITEM (embed->popout_menu), embed);
+  embed_embed_menu (GTK_MENU_ITEM (embed->embed_menu), embed);
+}
+
+
+
 /* X11 event monitor for the root window. Detects when windows become managed by
  * the window manager so that we can scan for matches. */
 static GdkFilterReturn
diff --git a/panel-plugin/embed.h b/panel-plugin/embed.h
index f5d98c2..d0e3918 100644
--- a/panel-plugin/embed.h
+++ b/panel-plugin/embed.h
@@ -50,6 +50,8 @@ typedef struct
 
     GRegex          *window_regex_comp;
 
+    gboolean         criteria_updated;
+
     /* embed settings */
     gchar           *proc_name;
     gchar           *window_regex;
@@ -68,8 +70,15 @@ EmbedPlugin;
 #define EMBED_LABEL_FMT_TITLE "%t"
 
 void
-embed_save (XfcePanelPlugin *plugin,
-             EmbedPlugin    *embed);
+embed_search_again (EmbedPlugin *embed);
+void
+embed_stop_search (EmbedPlugin *embed);
+void
+embed_update_label (EmbedPlugin *embed);
+void
+embed_size_changed_simple (EmbedPlugin *embed);
+void
+embed_save (XfcePanelPlugin *plugin, EmbedPlugin *embed);
 
 G_END_DECLS
 


More information about the Xfce4-commits mailing list