[Xfce4-commits] <xfce4-appfinder:andrzejr/plugin> Factored out a popup class for overloading some widget event methods.
Andrzej
noreply at xfce.org
Sat Feb 18 12:58:01 CET 2012
Updating branch refs/heads/andrzejr/plugin
to 2cdb9c500f77e3321ffd519087a8daff3b9ab3de (commit)
from cde7eeb485cbdf85727007e295f46a3940eb9117 (commit)
commit 2cdb9c500f77e3321ffd519087a8daff3b9ab3de
Author: Andrzej <ndrwrdck at gmail.com>
Date: Sat Feb 18 20:55:49 2012 +0900
Factored out a popup class for overloading some widget event methods.
Added pointer and keyboard grabbing (so that the popup closes when user
clicks outside of it).
GtkSocket doesn't seem to work with gdk_pointer_grab - the widget doesn't
receive any events. For comparison, a "local" button embedded in the window
works just fine.
If this cannot be resolved it is a "dead end" for the plugin in this form.
panel-plugin/Makefile.am | 2 +
panel-plugin/appfinder-plugin.c | 236 +++++----------------
panel-plugin/appfinder-plugin.h | 1 +
panel-plugin/appfinder-popup.c | 455 +++++++++++++++++++++++++++++++++++++++
panel-plugin/appfinder-popup.h | 45 ++++
5 files changed, 556 insertions(+), 183 deletions(-)
diff --git a/panel-plugin/Makefile.am b/panel-plugin/Makefile.am
index fafd742..fae2800 100644
--- a/panel-plugin/Makefile.am
+++ b/panel-plugin/Makefile.am
@@ -9,6 +9,8 @@ plugin_LTLIBRARIES = \
libappfinder.la
libappfinder_la_SOURCES = \
+ appfinder-popup.c \
+ appfinder-popup.h \
appfinder-plugin.c \
appfinder-plugin.h
diff --git a/panel-plugin/appfinder-plugin.c b/panel-plugin/appfinder-plugin.c
index 39b67ce..53fbbe8 100644
--- a/panel-plugin/appfinder-plugin.c
+++ b/panel-plugin/appfinder-plugin.c
@@ -29,6 +29,7 @@
#include <dbus/dbus-glib.h>
+#include "appfinder-popup.h"
#include "appfinder-plugin.h"
/* I18N: default tooltip of the appfinder */
@@ -36,13 +37,6 @@
#define DEFAULT_ICON_NAME "gtk-find"
#define DEFAULT_ICON_SIZE (16)
-#define APPFINDER_DBUS_SERVICE "org.xfce.Appfinder"
-#define APPFINDER_DBUS_INTERFACE APPFINDER_DBUS_SERVICE
-#define APPFINDER_DBUS_PATH "/org/xfce/Appfinder"
-#define APPFINDER_DBUS_METHOD_OPEN "OpenWindow"
-#define APPFINDER_DBUS_METHOD_OPEN_WIDGET "OpenWidget"
-#define APPFINDER_DBUS_METHOD_QUIT "Quit"
-
struct _XfceAppfinderPluginClass
{
XfcePanelPluginClass __parent__;
@@ -56,15 +50,7 @@ struct _XfceAppfinderPlugin
GtkWidget *box;
GtkWidget *icon;
GtkWidget *label;
- GtkWidget *appfinder_window;
- GtkWidget *appfinder_socket;
-
- gboolean visible;
-
- gint busy;
- gint handler;
-
- DBusGProxy *proxy;
+ GtkWidget *popup;
guint show_button_title : 1;
gchar *button_title;
@@ -100,6 +86,9 @@ static gboolean xfce_appfinder_plugin_remote_event (XfcePanelPlugin
static gboolean xfce_appfinder_plugin_button_pressed (GtkWidget *widget,
GdkEventButton *event,
XfceAppfinderPlugin *plugin);
+static void xfce_appfinder_plugin_visibility_changed (XfceAppfinderPopup *popup,
+ gboolean visible,
+ gpointer data);
@@ -163,12 +152,7 @@ xfce_appfinder_plugin_init (XfceAppfinderPlugin *plugin)
{
plugin->show_button_title = TRUE;
- plugin->visible = FALSE;
- plugin->busy = 0;
- plugin->handler = 0;
- plugin->proxy = NULL;
- plugin->appfinder_window = NULL;
- plugin->appfinder_socket = NULL;
+ plugin->popup = NULL;
plugin->button = xfce_panel_create_toggle_button ();
xfce_panel_plugin_add_action_widget (XFCE_PANEL_PLUGIN (plugin), plugin->button);
@@ -300,167 +284,46 @@ xfce_appfinder_plugin_construct (XfcePanelPlugin *panel_plugin)
-static void
-xfce_appfinder_plugin_destroy_window (XfceAppfinderPlugin *plugin,
- GtkWidget *socket)
-{
- appfinder_return_if_fail (XFCE_IS_APPFINDER_PLUGIN (plugin));
-
- plugin->busy += 1;
-
- if (plugin->appfinder_socket != NULL)
- {
- g_signal_handler_disconnect(socket, plugin->handler);
- gtk_widget_destroy (plugin->appfinder_socket);
- plugin->appfinder_socket = NULL;
- }
- if (plugin->appfinder_window != NULL)
- {
- gtk_widget_destroy (plugin->appfinder_window);
- plugin->appfinder_window = NULL;
- }
-
- plugin->visible = FALSE;
- if (plugin->button != NULL)
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (plugin->button), FALSE);
-
- APPFINDER_DEBUG ("destroyed window");
-
- plugin->busy -= 1;
-}
-
-
-
-static void
-xfce_appfinder_plugin_create_window (XfceAppfinderPlugin *plugin)
-{
- GtkWidget *window;
- GtkWidget *socket;
- GtkWidget *vbox;
-
- appfinder_return_if_fail (XFCE_IS_APPFINDER_PLUGIN (plugin));
-
- window = plugin->appfinder_window =
- g_object_new (GTK_TYPE_WINDOW,
- "type", GTK_WINDOW_POPUP,
- //"child", socket,
- NULL);
-
- gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
- gtk_window_set_mnemonic_modifier (GTK_WINDOW (window), 0);
- gtk_window_set_accept_focus (GTK_WINDOW (window), TRUE);
-
- vbox = gtk_vbox_new (FALSE, 10);
- gtk_container_add (GTK_CONTAINER (window), vbox);
- gtk_container_set_border_width (GTK_CONTAINER (vbox), 7);
- gtk_widget_show (vbox);
-
- socket = plugin->appfinder_socket = gtk_socket_new ();
- gtk_box_pack_start (GTK_BOX (vbox), socket, TRUE, TRUE, 0);
- gtk_widget_show (socket);
-
- plugin->handler = g_signal_connect_swapped
- (G_OBJECT (socket), "destroy",
- G_CALLBACK (xfce_appfinder_plugin_destroy_window), plugin);
-
- APPFINDER_DEBUG ("contructed window");
-}
-
-
-
static gboolean
-xfce_appfinder_plugin_activate_dbus (DBusGProxy *proxy,
- GdkNativeWindow id,
- GError **error)
+xfce_appfinder_plugin_toggle (XfceAppfinderPlugin *plugin,
+ gboolean visible)
{
- DBusGConnection *connection;
- gboolean retval = FALSE;
+ gboolean retval;
+ GtkWidget *parent_toplevel;
+ gint x, y;
- /* connect to DBUS service and cache the proxy */
- if (proxy == NULL)
- {
- connection = dbus_g_bus_get (DBUS_BUS_SESSION, error);
- if (connection == NULL)
- return retval;
-
- proxy = dbus_g_proxy_new_for_name (connection,
- APPFINDER_DBUS_SERVICE,
- APPFINDER_DBUS_PATH,
- APPFINDER_DBUS_INTERFACE);
- }
+ appfinder_return_val_if_fail (XFCE_IS_APPFINDER_PLUGIN (plugin), FALSE);
- if (G_LIKELY (proxy != NULL))
+ if (visible && plugin->popup == NULL)
{
- retval = dbus_g_proxy_call (proxy, APPFINDER_DBUS_METHOD_OPEN_WIDGET, error,
- G_TYPE_UINT, id,
- G_TYPE_INVALID,
- G_TYPE_INVALID);
-
- g_object_unref (G_OBJECT (proxy));
+ plugin->popup = g_object_new (XFCE_TYPE_APPFINDER_POPUP,
+ "type", GTK_WINDOW_POPUP,
+ NULL);
+ parent_toplevel = gtk_widget_get_toplevel (GTK_WIDGET (plugin));
+ if (GTK_IS_WINDOW (parent_toplevel))
+ gtk_window_set_transient_for (GTK_WINDOW (plugin->popup),
+ GTK_WINDOW (parent_toplevel));
+ g_signal_connect (G_OBJECT(plugin->popup), "popup-visibility-changed",
+ G_CALLBACK(xfce_appfinder_plugin_visibility_changed), plugin->button);
}
- return retval;
-}
-
-
-
-static void
-xfce_appfinder_plugin_widget_toggle (XfceAppfinderPlugin *plugin,
- gboolean visible)
-{
- GError *error = NULL;
- gboolean succeeded;
- gint x, y;
-
- appfinder_return_if_fail (XFCE_IS_APPFINDER_PLUGIN (plugin));
-
- if (plugin->busy > 0 || plugin->visible == visible)
- return;
-
- plugin->busy += 1;
-
- plugin->visible = visible;
-
- if (plugin->button != NULL)
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (plugin->button), visible);
-
if (visible)
{
- if (plugin->appfinder_window == NULL)
- xfce_appfinder_plugin_create_window (plugin);
- gtk_widget_set_size_request (plugin->appfinder_window, 600, 400);
-
+ retval = xfce_appfinder_popup_popup (XFCE_APPFINDER_POPUP (plugin->popup));
xfce_panel_plugin_position_widget
- (XFCE_PANEL_PLUGIN (plugin), plugin->appfinder_window, NULL, &x, &y);
- gtk_window_move (GTK_WINDOW (plugin->appfinder_window), x, y);
-
- succeeded = xfce_appfinder_plugin_activate_dbus
- (plugin->proxy,
- gtk_socket_get_id (GTK_SOCKET (plugin->appfinder_socket)),
- &error);
-
- if (!succeeded)
- {
- xfce_dialog_show_error (NULL, error,
- _("Failed to open Appfinder widget"));
- g_error_free (error);
- xfce_appfinder_plugin_destroy_window (plugin, plugin->appfinder_socket);
- plugin->busy -= 1;
- return;
- }
-
- if (visible)
- gtk_widget_set_visible (plugin->appfinder_window, visible);
+ (XFCE_PANEL_PLUGIN (plugin), plugin->popup, NULL, &x, &y);
+ gtk_window_move (GTK_WINDOW (plugin->popup), x, y);
}
else
{
- xfce_appfinder_plugin_destroy_window (plugin, plugin->appfinder_socket);
+ retval = xfce_appfinder_popup_popdown (XFCE_APPFINDER_POPUP (plugin->popup));
}
- plugin->busy -= 1;
-
+ return retval;
}
+
+
static gboolean
xfce_appfinder_plugin_button_pressed (GtkWidget *button,
GdkEventButton *event,
@@ -475,9 +338,12 @@ xfce_appfinder_plugin_button_pressed (GtkWidget *button,
//&& !PANEL_HAS_FLAG (event->state, GDK_CONTROL_MASK)))
return FALSE;
- APPFINDER_DEBUG ("button pressed %d", plugin->busy);
+ APPFINDER_DEBUG ("button pressed");
- xfce_appfinder_plugin_widget_toggle (plugin, !plugin->visible);
+ xfce_appfinder_plugin_toggle
+ (plugin,
+ plugin->popup == NULL ||
+ !xfce_appfinder_popup_is_visible (XFCE_APPFINDER_POPUP (plugin->popup)));
return TRUE;
}
@@ -584,19 +450,9 @@ xfce_appfinder_plugin_remote_event (XfcePanelPlugin *panel_plugin,
APPFINDER_DEBUG ("remote event %s", name);
- if (exo_str_is_equal (name, "popup")
- && GTK_WIDGET_VISIBLE (panel_plugin)
- && !plugin->visible)
- //&& panel_utils_grab_available ())
- {
- /* show the widget at the button */
- xfce_appfinder_plugin_widget_toggle (plugin, TRUE);
-
- /* don't popup another widget */
- return TRUE;
- }
-
- return FALSE;
+ return (exo_str_is_equal (name, "popup")
+ && GTK_WIDGET_VISIBLE (panel_plugin)
+ && xfce_appfinder_plugin_toggle (plugin, TRUE));
}
@@ -607,9 +463,23 @@ xfce_appfinder_plugin_free_data (XfcePanelPlugin *panel_plugin)
XfceAppfinderPlugin *plugin = XFCE_APPFINDER_PLUGIN (panel_plugin);
appfinder_return_if_fail (XFCE_IS_APPFINDER_PLUGIN (panel_plugin));
- if (plugin->visible)
- xfce_appfinder_plugin_destroy_window (plugin, plugin->appfinder_socket);
+
+ if (plugin->popup != NULL)
+ gtk_widget_destroy (plugin->popup);
g_free (plugin->button_title);
g_free (plugin->button_icon);
}
+
+
+static void
+xfce_appfinder_plugin_visibility_changed (XfceAppfinderPopup *popup,
+ gboolean visible,
+ gpointer data)
+{
+ GtkToggleButton *button = GTK_TOGGLE_BUTTON (data);
+
+ appfinder_return_if_fail (XFCE_IS_APPFINDER_POPUP (popup));
+
+ gtk_toggle_button_set_active (button, visible);
+}
diff --git a/panel-plugin/appfinder-plugin.h b/panel-plugin/appfinder-plugin.h
index 0c020fe..4c2f821 100644
--- a/panel-plugin/appfinder-plugin.h
+++ b/panel-plugin/appfinder-plugin.h
@@ -20,6 +20,7 @@
#define __XFCE_APPFINDER_PLUGIN_H__
#include <gtk/gtk.h>
+#include <libxfce4panel/libxfce4panel.h>
G_BEGIN_DECLS
diff --git a/panel-plugin/appfinder-popup.c b/panel-plugin/appfinder-popup.c
new file mode 100644
index 0000000..85a0486
--- /dev/null
+++ b/panel-plugin/appfinder-popup.c
@@ -0,0 +1,455 @@
+/*
+ * Copyright (C) 2012 Andrzej <ndrwrdck at gmail.com>
+ *
+ * This library 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 library 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 Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <exo/exo.h>
+#include <libxfce4ui/libxfce4ui.h>
+
+//#include <xfconf/xfconf.h>
+
+#include <dbus/dbus-glib.h>
+
+#include "appfinder-popup.h"
+#include "appfinder-plugin.h"
+
+#define APPFINDER_DBUS_SERVICE "org.xfce.Appfinder"
+#define APPFINDER_DBUS_INTERFACE APPFINDER_DBUS_SERVICE
+#define APPFINDER_DBUS_PATH "/org/xfce/Appfinder"
+#define APPFINDER_DBUS_METHOD_OPEN "OpenWindow"
+#define APPFINDER_DBUS_METHOD_OPEN_WIDGET "OpenWidget"
+#define APPFINDER_DBUS_METHOD_QUIT "Quit"
+
+
+static void xfce_appfinder_popup_socket_destroyed (XfceAppfinderPopup *popup,
+ GtkWidget *socket);
+static void xfce_appfinder_popup_proxy_destroyed (XfceAppfinderPopup *popup,
+ DBusGProxy *proxy);
+static gboolean xfce_appfinder_popup_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gboolean xfce_appfinder_popup_button_release (GtkWidget *widget,
+ GdkEventButton *event);
+static gboolean xfce_appfinder_popup_key_press (GtkWidget *widget,
+ GdkEventKey *event);
+
+
+struct _XfceAppfinderPopupClass
+{
+ GtkWindowClass __parent__;
+};
+
+struct _XfceAppfinderPopup
+{
+ GtkWindow __parent__;
+
+ GtkWidget *vbox;
+ GtkWidget *socket;
+
+ gboolean visible;
+
+ gint busy;
+ gint handler;
+
+ DBusGProxy *proxy;
+
+ GdkGrabStatus grab_pointer;
+ GdkGrabStatus grab_keyboard;
+
+ gboolean ignore;
+};
+
+enum
+{
+ POPUP_VISIBILITY_CHANGED,
+ LAST_SIGNAL
+};
+
+
+
+static guint appfinder_popup_signals[LAST_SIGNAL];
+
+
+
+G_DEFINE_TYPE (XfceAppfinderPopup, xfce_appfinder_popup, GTK_TYPE_WINDOW)
+
+
+
+static void
+xfce_appfinder_popup_class_init (XfceAppfinderPopupClass *klass)
+{
+ GObjectClass *gobject_class;
+ GtkWidgetClass *widget_class;
+ //GtkWindowClass *window_class;
+
+ widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->button_press_event = xfce_appfinder_popup_button_press;
+ widget_class->button_release_event = xfce_appfinder_popup_button_release;
+ widget_class->key_press_event = xfce_appfinder_popup_key_press;
+ //widget_class->focus = xfce_appfinder_popup_focus;
+
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ appfinder_popup_signals[POPUP_VISIBILITY_CHANGED] =
+ g_signal_new (g_intern_static_string ("popup-visibility-changed"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
+}
+
+
+
+static void
+xfce_appfinder_popup_init (XfceAppfinderPopup *popup)
+{
+ popup->visible = FALSE;
+ popup->busy = 0;
+ popup->handler = 0;
+ popup->proxy = NULL;
+ popup->socket = NULL;
+ popup->grab_pointer = GDK_GRAB_FROZEN;
+ popup->grab_keyboard = GDK_GRAB_FROZEN;
+ popup->ignore = FALSE;
+
+ //g_object_set (G_OBJECT (popup), "type", GTK_WINDOW_POPUP, NULL);
+
+ gtk_window_set_resizable (GTK_WINDOW (popup), FALSE);
+ gtk_window_set_mnemonic_modifier (GTK_WINDOW (popup), 0);
+ gtk_window_set_accept_focus (GTK_WINDOW (popup), TRUE);
+ gtk_widget_set_can_focus (GTK_WIDGET (popup), TRUE);
+ gtk_widget_set_size_request (GTK_WIDGET (popup), 600, 400);
+
+ popup->vbox = gtk_vbox_new (FALSE, 10);
+ gtk_container_add (GTK_CONTAINER (popup), popup->vbox);
+ gtk_container_set_border_width (GTK_CONTAINER (popup->vbox), 7);
+ gtk_widget_show (popup->vbox);
+
+ {
+ GtkWidget *button;
+ button = xfce_panel_create_toggle_button ();
+ gtk_box_pack_start (GTK_BOX (popup->vbox), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+ }
+}
+
+
+
+static gboolean
+xfce_appfinder_popup_activate_dbus (XfceAppfinderPopup *popup,
+ GdkNativeWindow id,
+ GError **error)
+{
+ DBusGConnection *connection;
+ gboolean retval = FALSE;
+
+ /* connect to DBUS service and cache the proxy */
+ if (popup->proxy == NULL)
+ {
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, error);
+ if (connection == NULL)
+ return retval;
+
+ popup->proxy = dbus_g_proxy_new_for_name (connection,
+ APPFINDER_DBUS_SERVICE,
+ APPFINDER_DBUS_PATH,
+ APPFINDER_DBUS_INTERFACE);
+
+ /* clear cached proxy reference when connection is lost */
+ g_signal_connect_swapped
+ (G_OBJECT (popup->proxy), "destroy",
+ G_CALLBACK (xfce_appfinder_popup_proxy_destroyed), popup);
+
+ }
+
+ if (G_LIKELY (popup->proxy != NULL))
+ {
+ retval = dbus_g_proxy_call (popup->proxy, APPFINDER_DBUS_METHOD_OPEN_WIDGET, error,
+ G_TYPE_UINT, id,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ }
+
+ return retval;
+}
+
+
+
+static void
+xfce_appfinder_popup_grab_remove (XfceAppfinderPopup *popup)
+{
+ if (popup->grab_pointer == GDK_GRAB_SUCCESS)
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+ if (popup->grab_keyboard == GDK_GRAB_SUCCESS)
+ gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+}
+
+
+
+static gboolean
+xfce_appfinder_popup_grab (XfceAppfinderPopup *popup, gboolean keep)
+{
+ GdkWindow *window;
+ gboolean grab_succeed = FALSE;
+ guint i;
+ GdkEventMask pointer_mask = GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
+ | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK
+ | GDK_POINTER_MOTION_MASK;
+
+ window = GTK_WIDGET (popup->socket)->window;
+
+ /* don't try to get the grab for longer then 1/4 second */
+ for (i = 0; i < (G_USEC_PER_SEC / 100 / 4); i++)
+ {
+ popup->grab_keyboard = gdk_keyboard_grab (window, TRUE, GDK_CURRENT_TIME);
+ if (popup->grab_keyboard == GDK_GRAB_SUCCESS)
+ {
+ popup->grab_pointer = gdk_pointer_grab (window, TRUE, pointer_mask,
+ NULL, NULL, GDK_CURRENT_TIME);
+ if (popup->grab_pointer == GDK_GRAB_SUCCESS)
+ {
+ grab_succeed = TRUE;
+ break;
+ }
+ }
+
+ g_usleep (100);
+ }
+
+ /* release the grab */
+ if (!keep)
+ xfce_appfinder_popup_grab_remove (popup);
+
+ if (!grab_succeed)
+ {
+ xfce_appfinder_popup_grab_remove (popup);
+ g_printerr (PACKAGE_NAME ": Unable to get keyboard and mouse "
+ "grab. Popup failed.\n");
+ }
+
+ return grab_succeed;
+}
+
+
+
+
+gboolean
+xfce_appfinder_popup_is_visible (XfceAppfinderPopup *popup)
+{
+ appfinder_return_val_if_fail (XFCE_IS_APPFINDER_POPUP (popup), FALSE);
+
+ return popup->visible;
+}
+
+
+
+gboolean
+xfce_appfinder_popup_popdown (XfceAppfinderPopup *popup)
+{
+ appfinder_return_val_if_fail (XFCE_IS_APPFINDER_POPUP (popup), FALSE);
+
+ if (!popup->visible || popup->busy > 0)
+ return FALSE;
+
+ popup->busy += 1;
+
+ xfce_appfinder_popup_grab_remove (popup);
+
+ if (popup->socket != NULL)
+ {
+ g_signal_handler_disconnect(popup->socket, popup->handler);
+ gtk_widget_destroy (popup->socket);
+ popup->socket = NULL;
+ }
+ //gtk_window_set_transient_for (GTK_WINDOW (popup), NULL);
+ gtk_widget_hide (GTK_WIDGET (popup));
+
+ popup->visible = FALSE;
+ g_signal_emit (G_OBJECT (popup), appfinder_popup_signals[POPUP_VISIBILITY_CHANGED], 0,
+ FALSE);
+
+ APPFINDER_DEBUG ("popdown");
+
+ popup->busy -= 1;
+
+ return TRUE;
+}
+
+
+
+gboolean
+xfce_appfinder_popup_popup (XfceAppfinderPopup *popup)
+{
+ GError *error = NULL;
+
+ appfinder_return_val_if_fail (XFCE_IS_APPFINDER_POPUP (popup), FALSE);
+
+ if (popup->visible || popup->busy > 0)
+ return FALSE;
+
+ popup->busy += 1;
+ popup->ignore = TRUE;
+
+ popup->socket = gtk_socket_new ();
+ gtk_box_pack_start (GTK_BOX (popup->vbox), popup->socket, TRUE, TRUE, 0);
+
+ popup->handler = g_signal_connect_swapped
+ (G_OBJECT (popup->socket), "destroy",
+ G_CALLBACK (xfce_appfinder_popup_socket_destroyed), popup);
+
+ if (!xfce_appfinder_popup_activate_dbus
+ (popup,
+ gtk_socket_get_id (GTK_SOCKET (popup->socket)),
+ &error))
+ {
+ xfce_dialog_show_error (NULL, error,
+ _("Failed to open Appfinder widget"));
+ g_error_free (error);
+ xfce_appfinder_popup_popdown (popup);
+ popup->busy -= 1;
+ return FALSE;
+ }
+
+ gtk_widget_show (popup->socket);
+ gtk_widget_show (GTK_WIDGET (popup));
+
+ xfce_appfinder_popup_grab (popup, TRUE);
+
+ popup->visible = TRUE;
+ g_signal_emit (G_OBJECT (popup), appfinder_popup_signals[POPUP_VISIBILITY_CHANGED], 0,
+ TRUE);
+
+ popup->busy -= 1;
+
+ APPFINDER_DEBUG ("popup");
+
+ return TRUE;
+}
+
+
+
+static void
+xfce_appfinder_popup_socket_destroyed (XfceAppfinderPopup *popup,
+ GtkWidget *socket)
+{
+ appfinder_return_if_fail (XFCE_IS_APPFINDER_POPUP (popup));
+ appfinder_return_if_fail (GTK_IS_SOCKET (socket));
+
+ xfce_appfinder_popup_popdown (popup);
+}
+
+
+
+static void
+xfce_appfinder_popup_proxy_destroyed (XfceAppfinderPopup *popup,
+ DBusGProxy *proxy)
+{
+ appfinder_return_if_fail (XFCE_IS_APPFINDER_POPUP (popup));
+ appfinder_return_if_fail (DBUS_IS_G_PROXY (proxy));
+
+ g_object_unref (G_OBJECT (popup->proxy));
+ popup->proxy = NULL;
+}
+
+
+
+static gboolean
+xfce_appfinder_popup_pointer_in_popup (GtkWidget *widget,
+ gdouble x_root,
+ gdouble y_root)
+{
+ if (gtk_widget_get_mapped (widget))
+ {
+ gint window_x, window_y;
+
+ gdk_window_get_position (widget->window, &window_x, &window_y);
+
+ if (x_root >= window_x && x_root < window_x + widget->allocation.width &&
+ y_root >= window_y && y_root < window_y + widget->allocation.height)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+static gboolean
+xfce_appfinder_popup_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ XfceAppfinderPopup *popup = XFCE_APPFINDER_POPUP (widget);
+
+ APPFINDER_DEBUG ("press %d, %g %g\n", event->type, event->x_root, event->y_root);
+
+ if (event->type != GDK_BUTTON_PRESS)
+ return FALSE;
+
+ if (!xfce_appfinder_popup_pointer_in_popup (widget, event->x_root, event->y_root))
+ {
+ xfce_appfinder_popup_popdown (popup);
+ return TRUE;
+ }
+
+ return GTK_WIDGET_CLASS (xfce_appfinder_popup_parent_class)->button_press_event (widget, event);
+}
+
+
+
+static gboolean
+xfce_appfinder_popup_button_release (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ XfceAppfinderPopup *popup = XFCE_APPFINDER_POPUP (widget);
+
+ APPFINDER_DEBUG ("release %d, %g %g\n", event->type, event->x_root, event->y_root);
+
+ if (event->type != GDK_BUTTON_RELEASE || popup->ignore)
+ {
+ /* ignore the first release event (coming from the button?) */
+ popup->ignore = FALSE;
+ return FALSE;
+ }
+
+ return GTK_WIDGET_CLASS (xfce_appfinder_popup_parent_class)->button_release_event (widget, event);
+}
+
+
+
+
+static gboolean
+xfce_appfinder_popup_key_press (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ //XfceAppfinderPopup *popup = XFCE_APPFINDER_POPUP (widget);
+
+ APPFINDER_DEBUG ("press %d, %s\n", event->type, event->string);
+
+ if (event->type != GDK_KEY_PRESS)
+ return FALSE;
+
+ return GTK_WIDGET_CLASS (xfce_appfinder_popup_parent_class)->key_press_event (widget, event);
+
+}
+
+
+
+
diff --git a/panel-plugin/appfinder-popup.h b/panel-plugin/appfinder-popup.h
new file mode 100644
index 0000000..34ba072
--- /dev/null
+++ b/panel-plugin/appfinder-popup.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 Andrzej <ndrwrdck at gmail.com>
+ *
+ * This library 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 library 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 Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __XFCE_APPFINDER_POPUP_H__
+#define __XFCE_APPFINDER_POPUP_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _XfceAppfinderPopupClass XfceAppfinderPopupClass;
+typedef struct _XfceAppfinderPopup XfceAppfinderPopup;
+
+#define XFCE_TYPE_APPFINDER_POPUP (xfce_appfinder_popup_get_type ())
+#define XFCE_APPFINDER_POPUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_APPFINDER_POPUP, XfceAppfinderPopup))
+#define XFCE_APPFINDER_POPUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_APPFINDER_POPUP, XfceAppfinderPopupClass))
+#define XFCE_IS_APPFINDER_POPUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_APPFINDER_POPUP))
+#define XFCE_IS_APPFINDER_POPUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_APPFINDER_POPUP))
+#define XFCE_APPFINDER_POPUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_APPFINDER_POPUP, XfceAppfinderPopupClass))
+
+GType xfce_appfinder_popup_get_type (void) G_GNUC_CONST;
+
+gboolean xfce_appfinder_popup_popdown (XfceAppfinderPopup *popup);
+gboolean xfce_appfinder_popup_popup (XfceAppfinderPopup *popup);
+gboolean xfce_appfinder_popup_is_visible (XfceAppfinderPopup *popup);
+
+
+G_END_DECLS
+
+#endif /* !__XFCE_APPFINDER_POPUP_H__ */
More information about the Xfce4-commits
mailing list