diff options
-rw-r--r-- | gtk/gtkappchooserwidget.c | 94 | ||||
-rw-r--r-- | gtk/gtkappchooserwidget.h | 5 |
2 files changed, 99 insertions, 0 deletions
diff --git a/gtk/gtkappchooserwidget.c b/gtk/gtkappchooserwidget.c index 477fd57399..22c9652a36 100644 --- a/gtk/gtkappchooserwidget.c +++ b/gtk/gtkappchooserwidget.c @@ -85,6 +85,7 @@ enum { enum { SIGNAL_APPLICATION_SELECTED, SIGNAL_APPLICATION_ACTIVATED, + SIGNAL_POPULATE_POPUP, N_SIGNALS }; @@ -136,6 +137,86 @@ refresh_and_emit_app_selected (GtkAppChooserWidget *self, self->priv->selected_app_info); } +static GAppInfo * +get_app_info_for_event (GtkAppChooserWidget *self, + GdkEventButton *event) +{ + GtkTreePath *path = NULL; + GtkTreeIter iter; + GtkTreeModel *model; + GAppInfo *info; + gboolean recommended; + + if (!gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (self->priv->program_list), + event->x, event->y, + &path, + NULL, NULL, NULL)) + return NULL; + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (self->priv->program_list)); + + if (!gtk_tree_model_get_iter (model, &iter, path)) + { + gtk_tree_path_free (path); + return NULL; + } + + /* we only allow interaction with recommended applications */ + gtk_tree_model_get (model, &iter, + COLUMN_APP_INFO, &info, + COLUMN_RECOMMENDED, &recommended, + -1); + + if (!recommended) + g_clear_object (&info); + + return info; +} + +static gboolean +widget_button_press_event_cb (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + GtkAppChooserWidget *self = user_data; + + if (event->button == 3 && event->type == GDK_BUTTON_PRESS) + { + GAppInfo *info; + GtkWidget *menu; + GList *children; + gint n_children; + + info = get_app_info_for_event (self, event); + + if (info == NULL) + return FALSE; + + menu = gtk_menu_new (); + + g_signal_emit (self, signals[SIGNAL_POPULATE_POPUP], 0, + menu, info); + + g_object_unref (info); + + /* see if clients added menu items to this container */ + children = gtk_container_get_children (GTK_CONTAINER (menu)); + n_children = g_list_length (children); + + if (n_children > 0) + { + /* actually popup the menu */ + gtk_menu_attach_to_widget (GTK_MENU (menu), self->priv->program_list, NULL); + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, + event->button, event->time); + } + + g_list_free (children); + } + + return FALSE; +} + static gboolean path_is_heading (GtkTreeView *view, GtkTreePath *path) @@ -972,6 +1053,16 @@ gtk_app_chooser_widget_class_init (GtkAppChooserWidgetClass *klass) G_TYPE_NONE, 1, G_TYPE_APP_INFO); + signals[SIGNAL_POPULATE_POPUP] = + g_signal_new ("populate-popup", + GTK_TYPE_APP_CHOOSER_WIDGET, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GtkAppChooserWidgetClass, populate_popup), + NULL, NULL, + _gtk_marshal_VOID__OBJECT_OBJECT, + G_TYPE_NONE, + 2, GTK_TYPE_MENU, G_TYPE_APP_INFO); + g_type_class_add_private (klass, sizeof (GtkAppChooserWidgetPrivate)); } @@ -1011,6 +1102,9 @@ gtk_app_chooser_widget_init (GtkAppChooserWidget *self) g_signal_connect (self->priv->program_list, "row-activated", G_CALLBACK (program_list_selection_activated), self); + g_signal_connect (self->priv->program_list, "button-press-event", + G_CALLBACK (widget_button_press_event_cb), + self); } static GAppInfo * diff --git a/gtk/gtkappchooserwidget.h b/gtk/gtkappchooserwidget.h index 2bfd00407c..a52b64e096 100644 --- a/gtk/gtkappchooserwidget.h +++ b/gtk/gtkappchooserwidget.h @@ -32,6 +32,7 @@ #define __GTK_APP_CHOOSER_WIDGET_H__ #include <gtk/gtkbox.h> +#include <gtk/gtkmenu.h> #include <gio/gio.h> #define GTK_TYPE_APP_CHOOSER_WIDGET\ @@ -67,6 +68,10 @@ struct _GtkAppChooserWidgetClass { void (* application_activated) (GtkAppChooserWidget *self, GAppInfo *app_info); + void (* populate_popup) (GtkAppChooserWidget *self, + GtkMenu *menu, + GAppInfo *app_info); + /* padding for future class expansion */ gpointer padding[16]; }; |