[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