summaryrefslogtreecommitdiff
path: root/services
diff options
authorMarco Trevisan (Treviño) <mail@3v1n0.net>2014-01-24 20:00:03 +0100
committerMarco Trevisan (Treviño) <mail@3v1n0.net>2014-01-24 20:00:03 +0100
commita736595e4c8e7adbf655c3096ab1a1ec9a48fb60 (patch)
tree483fc3334dc7cf06238b2812679182be9549007a /services
parent59e2f35230a9ad06116741a56978ac5bbc43e5fb (diff)
PanelService: add ShowEntries method to show a list of entries in a drop-down menu
(bzr r3566.5.262)
Diffstat (limited to 'services')
-rw-r--r--services/panel-main.c20
-rw-r--r--services/panel-service.c130
-rw-r--r--services/panel-service.h6
3 files changed, 147 insertions, 9 deletions
diff --git a/services/panel-main.c b/services/panel-main.c
index a43304e66..590055dab 100644
--- a/services/panel-main.c
+++ b/services/panel-main.c
@@ -55,6 +55,13 @@ static const gchar introspection_xml[] =
" <arg type='u' name='button' direction='in'/>"
" </method>"
""
+ " <method name='ShowEntries'>"
+ " <arg type='as' name='entries_ids' direction='in'/>"
+ " <arg type='u' name='xid' direction='in'/>"
+ " <arg type='i' name='x' direction='in'/>"
+ " <arg type='i' name='y' direction='in'/>"
+ " </method>"
+ ""
" <method name='ShowAppMenu'>"
" <arg type='u' name='xid' direction='in'/>"
" <arg type='i' name='x' direction='in'/>"
@@ -183,6 +190,19 @@ handle_method_call (GDBusConnection *connection,
g_dbus_method_invocation_return_value (invocation, NULL);
g_free (entry_id);
}
+ else if (g_strcmp0 (method_name, "ShowEntries") == 0)
+ {
+ guint32 xid;
+ gchar **entries;
+ gint32 x;
+ gint32 y;
+ g_variant_get (parameters, "(^asuii)", &entries, &xid, &x, &y);
+
+ panel_service_show_entries (service, (const gchar**) entries, xid, x, y);
+
+ g_dbus_method_invocation_return_value (invocation, NULL);
+ g_strfreev (entries);
+ }
else if (g_strcmp0 (method_name, "ShowAppMenu") == 0)
{
guint32 xid;
diff --git a/services/panel-service.c b/services/panel-service.c
index 22bc2a311..3a01f3d75 100644
--- a/services/panel-service.c
+++ b/services/panel-service.c
@@ -62,6 +62,7 @@ struct _PanelServicePrivate
gint32 timeouts[N_TIMEOUT_SLOTS];
+ IndicatorObjectEntry *first_entry;
IndicatorObjectEntry *last_entry;
GtkWidget *menubar;
GtkWidget *offscreen_window;
@@ -1781,7 +1782,6 @@ indicator_entry_compare_func (gpointer* v1, gpointer* v2)
static void
activate_next_prev_menu (PanelService *self,
- IndicatorObject *object,
IndicatorObjectEntry *entry,
GtkMenuDirectionType direction)
{
@@ -1869,7 +1869,7 @@ on_active_menu_move_current (GtkMenu *menu,
PanelService *self)
{
PanelServicePrivate *priv;
- IndicatorObject *object;
+ IndicatorObjectEntry *entry;
g_return_if_fail (PANEL_IS_SERVICE (self));
priv = self->priv;
@@ -1893,21 +1893,21 @@ on_active_menu_move_current (GtkMenu *menu,
{
/* Skip direction due to there being a submenu,
* and we don't want to inhibit going into that */
+ g_list_free (children);
return;
}
}
g_list_free (children);
- }
- /* Find the next/prev indicator */
- object = get_entry_parent_indicator(priv->last_entry);
- if (object == NULL)
+ entry = priv->last_entry;
+ }
+ else
{
- g_warning ("Unable to find IndicatorObject for entry");
- return;
+ entry = (priv->first_entry) ? priv->first_entry : priv->last_entry;
}
- activate_next_prev_menu (self, object, priv->last_entry, direction);
+ /* Find the next/prev indicator */
+ activate_next_prev_menu (self, entry, direction);
}
static void
@@ -2062,6 +2062,118 @@ panel_service_show_entry (PanelService *self,
panel_service_show_entry_common (self, object, entry, xid, x, y, button);
}
+static void
+fake_entry_destroy (GtkWidget *menu, IndicatorObjectEntry *fake_entry)
+{
+ PanelService *self = panel_service_get_default();
+
+ self->priv->first_entry = NULL;
+ g_free (fake_entry);
+}
+
+void
+panel_service_show_entries (PanelService *self,
+ const gchar **entries,
+ guint32 xid,
+ gint32 x,
+ gint32 y)
+{
+ gint i;
+ IndicatorObject *object;
+ IndicatorObjectEntry *entry, *fake_entry, *first_entry, *last_entry;
+ GtkWidget *menu;
+
+ g_return_if_fail (PANEL_IS_SERVICE (self));
+ g_return_if_fail (entries && entries[0]);
+
+ object = NULL;
+ first_entry = NULL;
+ last_entry = NULL;
+ menu = gtk_menu_new ();
+
+ for (i = 0; entries[i]; ++i)
+ {
+ entry = get_indicator_entry_by_id (self, entries[i]);
+
+ if (!entry)
+ continue;
+
+ if (!object)
+ {
+ object = get_entry_parent_indicator (entry);
+
+ if (!object)
+ continue;
+ }
+ else if (object != get_entry_parent_indicator (entry))
+ {
+ g_error ("Impossible build a menu with entries from different indicators!");
+ continue;
+ }
+
+ GtkWidget *menu_item;
+ const char *label = NULL;
+
+ if (GTK_IS_LABEL (entry->label))
+ label = gtk_label_get_label (entry->label);
+
+ if (GTK_IS_IMAGE (entry->image))
+ {
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ if (label)
+ {
+ menu_item = gtk_image_menu_item_new_with_mnemonic (label);
+ }
+ else
+ {
+ menu_item = gtk_image_menu_item_new ();
+ }
+
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), GTK_WIDGET (entry->image));
+ gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menu_item), TRUE);
+ G_GNUC_END_IGNORE_DEPRECATIONS
+ }
+ else if (label)
+ {
+ menu_item = gtk_menu_item_new_with_mnemonic (label);
+ }
+ else
+ {
+ continue;
+ }
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), GTK_WIDGET (entry->menu));
+ g_signal_connect (menu_item, "activate", G_CALLBACK (menuitem_activated), entry);
+ gtk_widget_show (menu_item);
+
+ if (!first_entry)
+ first_entry = entry;
+
+ last_entry = entry;
+ }
+
+ if (!last_entry)
+ {
+ g_warning ("No valid entries to show");
+ gtk_widget_destroy (menu);
+ return;
+ }
+
+ fake_entry = g_new0 (IndicatorObjectEntry, 1);
+ fake_entry->parent_object = object;
+ fake_entry->menu = GTK_MENU (menu);
+
+ g_signal_connect (menu, "deactivate", G_CALLBACK (menu_deactivated), NULL);
+ g_signal_connect (menu, "destroy", G_CALLBACK (fake_entry_destroy), fake_entry);
+ g_signal_connect (menu, "destroy", G_CALLBACK (gtk_widget_destroyed), &self->priv->last_menu);
+
+ panel_service_show_entry_common (self, object, fake_entry, xid, x, y, 1);
+ self->priv->first_entry = first_entry;
+ self->priv->last_entry = last_entry;
+}
+
+
void
panel_service_show_app_menu (PanelService *self, guint32 xid, gint32 x, gint32 y)
{
diff --git a/services/panel-service.h b/services/panel-service.h
index 06d5c35f0..ad8f63383 100644
--- a/services/panel-service.h
+++ b/services/panel-service.h
@@ -101,6 +101,12 @@ void panel_service_show_entry (PanelService *self,
gint32 y,
guint32 button);
+void panel_service_show_entries (PanelService *self,
+ const gchar **entries,
+ guint32 xid,
+ gint32 x,
+ gint32 y);
+
void panel_service_show_app_menu (PanelService *self,
guint32 xid,
gint32 x,