X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=hildon%2Fhildon-app-menu.c;h=e7a769471923adb59bf3d3675d7c1ad416b2cd45;hb=293c5746d90f0f9e5282dce4f99e85cb91777178;hp=e71fdaf623460332877ba166d7bb12cb7ce0d5a0;hpb=30145d2600fdb0a434350f631064cbfbbf9f03eb;p=hildon diff --git a/hildon/hildon-app-menu.c b/hildon/hildon-app-menu.c index e71fdaf..e7a7694 100644 --- a/hildon/hildon-app-menu.c +++ b/hildon/hildon-app-menu.c @@ -106,9 +106,6 @@ #include "hildon-banner.h" #include "hildon-animation-actor.h" -static GdkWindow * -grab_transfer_window_get (GtkWidget *widget); - static void hildon_app_menu_repack_items (HildonAppMenu *menu, gint start_from); @@ -136,10 +133,22 @@ remove_item_from_list (GList **list, gpointer item); static void +emit_menu_changed (HildonAppMenu *menu, + gpointer item); + +static void hildon_app_menu_apply_style (GtkWidget *widget); G_DEFINE_TYPE (HildonAppMenu, hildon_app_menu, GTK_TYPE_WINDOW); +enum +{ + CHANGED, + LAST_SIGNAL +}; + +static guint app_menu_signals[LAST_SIGNAL] = { 0 }; + /** * hildon_app_menu_new: * @@ -197,6 +206,9 @@ hildon_app_menu_insert (HildonAppMenu *menu, /* Remove item from list when it is destroyed */ g_object_weak_ref (G_OBJECT (item), (GWeakNotify) remove_item_from_list, &(priv->buttons)); + g_object_weak_ref (G_OBJECT (item), (GWeakNotify) emit_menu_changed, menu); + + g_signal_emit (menu, app_menu_signals[CHANGED], 0); } /** @@ -304,6 +316,9 @@ hildon_app_menu_add_filter (HildonAppMenu *menu, /* Remove filter from list when it is destroyed */ g_object_weak_ref (G_OBJECT (filter), (GWeakNotify) remove_item_from_list, &(priv->filters)); + g_object_weak_ref (G_OBJECT (filter), (GWeakNotify) emit_menu_changed, menu); + + g_signal_emit (menu, app_menu_signals[CHANGED], 0); } static void @@ -410,6 +425,7 @@ item_visibility_changed (GtkWidget *item, if (! priv->inhibit_repack) hildon_app_menu_repack_items (menu, g_list_index (priv->buttons, item)); + g_signal_emit (menu, app_menu_signals[CHANGED], 0); } static void @@ -421,6 +437,7 @@ filter_visibility_changed (GtkWidget *item, if (! priv->inhibit_repack) hildon_app_menu_repack_filters (menu); + g_signal_emit (menu, app_menu_signals[CHANGED], 0); } static void @@ -431,6 +448,13 @@ remove_item_from_list (GList **list, } static void +emit_menu_changed (HildonAppMenu *menu, + gpointer item) +{ + g_signal_emit (menu, app_menu_signals[CHANGED], 0); +} + +static void hildon_app_menu_show_all (GtkWidget *widget) { HildonAppMenu *menu = HILDON_APP_MENU (widget); @@ -520,66 +544,13 @@ hildon_app_menu_map (GtkWidget *widget) { HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(widget); - if (priv->transfer_window == NULL) - priv->transfer_window = grab_transfer_window_get (widget); - GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->map (widget); - /* Grab pointer and keyboard */ - if (priv->transfer_window != NULL) { - gboolean has_grab = FALSE; - - if (gdk_pointer_grab (priv->transfer_window, TRUE, - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | - GDK_POINTER_MOTION_MASK, NULL, NULL, - GDK_CURRENT_TIME) == GDK_GRAB_SUCCESS) { - if (gdk_keyboard_grab (priv->transfer_window, TRUE, - GDK_CURRENT_TIME) == GDK_GRAB_SUCCESS) { - has_grab = TRUE; - } else { - gdk_display_pointer_ungrab (gtk_widget_get_display (widget), - GDK_CURRENT_TIME); - } - } - - if (has_grab) { - gtk_grab_add (widget); - } else { - gdk_window_destroy (priv->transfer_window); - priv->transfer_window = NULL; - } - } - - /* Make the menu temporary when it's mapped, so it's closed if a - * new window appears */ - gtk_window_set_is_temporary (GTK_WINDOW (widget), TRUE); - if (priv->find_intruder_idle_id == 0) priv->find_intruder_idle_id = gdk_threads_add_idle (hildon_app_menu_find_intruder, widget); } static void -hildon_app_menu_unmap (GtkWidget *widget) -{ - HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(widget); - - /* Remove the grab */ - if (priv->transfer_window != NULL) { - gdk_display_pointer_ungrab (gtk_widget_get_display (widget), - GDK_CURRENT_TIME); - gtk_grab_remove (widget); - - gdk_window_destroy (priv->transfer_window); - priv->transfer_window = NULL; - } - - GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->unmap (widget); - - gtk_window_set_is_temporary (GTK_WINDOW (widget), FALSE); -} - -static void hildon_app_menu_grab_notify (GtkWidget *widget, gboolean was_grabbed) { @@ -658,56 +629,6 @@ hildon_app_menu_key_press (GtkWidget *widget, } static gboolean -hildon_app_menu_button_press (GtkWidget *widget, - GdkEventButton *event) -{ - int x, y; - HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(widget); - - gdk_window_get_position (widget->window, &x, &y); - - /* Whether the button has been pressed outside the widget */ - priv->pressed_outside = (event->x_root < x || event->x_root > x + widget->allocation.width || - event->y_root < y || event->y_root > y + widget->allocation.height); - - if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_press_event) { - return GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_press_event (widget, event); - } else { - return FALSE; - } -} - -static gboolean -hildon_app_menu_button_release (GtkWidget *widget, - GdkEventButton *event) -{ - HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(widget); - - if (priv->pressed_outside) { - int x, y; - gboolean released_outside; - - gdk_window_get_position (widget->window, &x, &y); - - /* Whether the button has been released outside the widget */ - released_outside = (event->x_root < x || event->x_root > x + widget->allocation.width || - event->y_root < y || event->y_root > y + widget->allocation.height); - - if (released_outside) { - gtk_widget_hide (widget); - } - - priv->pressed_outside = FALSE; /* Always reset pressed_outside to FALSE */ - } - - if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_release_event) { - return GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_release_event (widget, event); - } else { - return FALSE; - } -} - -static gboolean hildon_app_menu_delete_event_handler (GtkWidget *widget, GdkEventAny *event) { @@ -716,34 +637,6 @@ hildon_app_menu_delete_event_handler (GtkWidget *widget, return TRUE; } -/* Grab transfer window (based on the one from GtkMenu) */ -static GdkWindow * -grab_transfer_window_get (GtkWidget *widget) -{ - GdkWindow *window; - GdkWindowAttr attributes; - gint attributes_mask; - - attributes.x = 0; - attributes.y = 0; - attributes.width = 10; - attributes.height = 10; - attributes.window_type = GDK_WINDOW_TEMP; - attributes.wclass = GDK_INPUT_ONLY; - attributes.override_redirect = TRUE; - attributes.event_mask = 0; - - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR; - - window = gdk_window_new (gtk_widget_get_root_window (widget), - &attributes, attributes_mask); - gdk_window_set_user_data (window, widget); - - gdk_window_show (window); - - return window; -} - static void hildon_app_menu_size_request (GtkWidget *widget, GtkRequisition *requisition) @@ -797,6 +690,7 @@ static void hildon_app_menu_apply_style (GtkWidget *widget) { GdkScreen *screen; + gint filter_group_width; guint horizontal_spacing, vertical_spacing, filter_vertical_spacing; guint inner_border, external_border; HildonAppMenuPrivate *priv; @@ -806,6 +700,7 @@ hildon_app_menu_apply_style (GtkWidget *widget) gtk_widget_style_get (widget, "horizontal-spacing", &horizontal_spacing, "vertical-spacing", &vertical_spacing, + "filter-group-width", &filter_group_width, "filter-vertical-spacing", &filter_vertical_spacing, "inner-border", &inner_border, "external-border", &external_border, @@ -819,13 +714,20 @@ hildon_app_menu_apply_style (GtkWidget *widget) /* Set inner border */ gtk_container_set_border_width (GTK_CONTAINER (widget), inner_border); + /* Set width of the group of filter buttons */ + gtk_widget_set_size_request (GTK_WIDGET (priv->filters_hbox), filter_group_width, -1); + /* Compute width request */ screen = gtk_widget_get_screen (widget); if (gdk_screen_get_width (screen) < gdk_screen_get_height (screen)) { external_border = 0; } priv->width_request = gdk_screen_get_width (screen) - external_border * 2; - gtk_window_move (GTK_WINDOW (widget), external_border, 0); + + if (widget->window) + gdk_window_move_resize (widget->window, + external_border, 0, 1, 1); + gtk_widget_queue_resize (widget); } @@ -923,6 +825,39 @@ hildon_app_menu_repack_items (HildonAppMenu *menu, } } } + + gtk_widget_queue_draw (GTK_WIDGET (menu)); +} + +/** + * hildon_app_menu_has_visible_children: + * @menu: a #HildonAppMenu + * + * Returns whether this menu has any visible items + * and/or filters. If this is %FALSE, the menu will + * not be popped up. + * + * Returns: whether there are visible items or filters + * + * Since: 2.2 + **/ +gboolean +hildon_app_menu_has_visible_children (HildonAppMenu *menu) +{ + HildonAppMenuPrivate *priv; + GList *i; + gboolean show_menu = FALSE; + + priv = HILDON_APP_MENU_GET_PRIVATE (menu); + + /* Don't show menu if it doesn't contain visible items */ + for (i = priv->buttons; i && !show_menu; i = i->next) + show_menu = GTK_WIDGET_VISIBLE (i->data); + + for (i = priv->filters; i && !show_menu; i = i->next) + show_menu = GTK_WIDGET_VISIBLE (i->data); + + return show_menu; } /** @@ -939,23 +874,10 @@ void hildon_app_menu_popup (HildonAppMenu *menu, GtkWindow *parent_window) { - HildonAppMenuPrivate *priv; - gboolean show_menu = FALSE; - GList *i; - g_return_if_fail (HILDON_IS_APP_MENU (menu)); g_return_if_fail (GTK_IS_WINDOW (parent_window)); - priv = HILDON_APP_MENU_GET_PRIVATE (menu); - - /* Don't show menu if it doesn't contain visible items */ - for (i = priv->buttons; i && !show_menu; i = i->next) - show_menu = GTK_WIDGET_VISIBLE (i->data); - - for (i = priv->filters; i && !show_menu; i = i->next) - show_menu = GTK_WIDGET_VISIBLE (i->data); - - if (show_menu) { + if (hildon_app_menu_has_visible_children (menu)) { hildon_app_menu_set_parent_window (menu, parent_window); gtk_widget_show (GTK_WIDGET (menu)); } @@ -1018,6 +940,7 @@ hildon_app_menu_init (HildonAppMenu *menu) priv->transfer_window = NULL; priv->pressed_outside = FALSE; priv->inhibit_repack = FALSE; + priv->last_pressed_button = NULL; priv->buttons = NULL; priv->filters = NULL; priv->columns = 2; @@ -1089,13 +1012,10 @@ hildon_app_menu_class_init (HildonAppMenuClass *klass) widget_class->show_all = hildon_app_menu_show_all; widget_class->hide_all = hildon_app_menu_hide_all; widget_class->map = hildon_app_menu_map; - widget_class->unmap = hildon_app_menu_unmap; widget_class->realize = hildon_app_menu_realize; widget_class->unrealize = hildon_app_menu_unrealize; widget_class->grab_notify = hildon_app_menu_grab_notify; widget_class->key_press_event = hildon_app_menu_key_press; - widget_class->button_press_event = hildon_app_menu_button_press; - widget_class->button_release_event = hildon_app_menu_button_release; widget_class->style_set = hildon_app_menu_style_set; widget_class->delete_event = hildon_app_menu_delete_event_handler; widget_class->size_request = hildon_app_menu_size_request; @@ -1122,6 +1042,16 @@ hildon_app_menu_class_init (HildonAppMenuClass *klass) gtk_widget_class_install_style_property ( widget_class, + g_param_spec_int ( + "filter-group-width", + "Width of the group of filter buttons", + "Total width of the group of filter buttons, " + "or -1 to use the natural size request.", + -1, G_MAXINT, 444, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property ( + widget_class, g_param_spec_uint ( "filter-vertical-spacing", "Vertical spacing between filters and menu items", @@ -1147,4 +1077,22 @@ hildon_app_menu_class_init (HildonAppMenuClass *klass) "the screen edges (in horizontal mode)", 0, G_MAXUINT, 50, G_PARAM_READABLE)); + + + /** + * HildonAppMenu::changed: + * @widget: the widget that received the signal + * + * The HildonAppMenu::changed signal is emitted whenever an + * item or filter is added or removed from the menu. + * + * Since: 2.2 + */ + app_menu_signals[CHANGED] = + g_signal_new ("changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); }