OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef CHROME_BROWSER_UI_GTK_GTK_CUSTOM_MENU_ITEM_H_ |
| 6 #define CHROME_BROWSER_UI_GTK_GTK_CUSTOM_MENU_ITEM_H_ |
| 7 #pragma once |
| 8 |
| 9 // GtkCustomMenuItem is a GtkMenuItem subclass that has buttons in it and acts |
| 10 // to support this. GtkCustomMenuItems only render properly when put in a |
| 11 // GtkCustomMenu; there's a lot of collaboration between these two classes |
| 12 // necessary to work around how gtk normally does menus. |
| 13 // |
| 14 // We can't rely on the normal event infrastructure. While a menu is up, the |
| 15 // GtkMenu has a grab on all events. Instead of trying to pump events through |
| 16 // the normal channels, we have the GtkCustomMenu selectively forward mouse |
| 17 // motion through a back channel. The GtkCustomMenu only listens for button |
| 18 // press information so it can block the effects of the click if the cursor |
| 19 // isn't in a button in the menu item. |
| 20 // |
| 21 // A GtkCustomMenuItem doesn't try to take these signals and forward them to |
| 22 // the buttons it owns. The GtkCustomMenu class keeps track of which button is |
| 23 // selected (due to key events and mouse movement) and otherwise acts like a |
| 24 // normal GtkItem. The buttons are only for sizing and rendering; they don't |
| 25 // respond to events. Instead, when the GtkCustomMenuItem is activated by the |
| 26 // GtkMenu, it uses which button was selected as a signal of what to do. |
| 27 // |
| 28 // Users should connect to the "button-pushed" signal to be notified when a |
| 29 // button was pushed. We don't go through the normal "activate" signal because |
| 30 // we need to communicate additional information, namely which button was |
| 31 // activated. |
| 32 |
| 33 #include <gdk/gdk.h> |
| 34 #include <gtk/gtk.h> |
| 35 |
| 36 G_BEGIN_DECLS |
| 37 |
| 38 #define GTK_TYPE_CUSTOM_MENU_ITEM \ |
| 39 (gtk_custom_menu_item_get_type()) |
| 40 #define GTK_CUSTOM_MENU_ITEM(obj) \ |
| 41 (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_CUSTOM_MENU_ITEM, \ |
| 42 GtkCustomMenuItem)) |
| 43 #define GTK_CUSTOM_MENU_ITEM_CLASS(klass) \ |
| 44 (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_CUSTOM_MENU_ITEM, \ |
| 45 GtkCustomMenuItemClass)) |
| 46 #define GTK_IS_CUSTOM_MENU_ITEM(obj) \ |
| 47 (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_CUSTOM_MENU_ITEM)) |
| 48 #define GTK_IS_CUSTOM_MENU_ITEM_CLASS(klass) \ |
| 49 (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_CUSTOM_MENU_ITEM)) |
| 50 #define GTK_CUSTOM_MENU_ITEM_GET_CLASS(obj) \ |
| 51 (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_CUSTOM_MENU_ITEM, \ |
| 52 GtkCustomMenuItemClass)) |
| 53 |
| 54 typedef struct _GtkCustomMenuItem GtkCustomMenuItem; |
| 55 typedef struct _GtkCustomMenuItemClass GtkCustomMenuItemClass; |
| 56 |
| 57 struct _GtkCustomMenuItem { |
| 58 GtkMenuItem menu_item; |
| 59 |
| 60 // Container for button widgets. |
| 61 GtkWidget* hbox; |
| 62 |
| 63 // Label on left side of menu item. |
| 64 GtkWidget* label; |
| 65 |
| 66 // List of all widgets we added. Used to find the leftmost and rightmost |
| 67 // continuous buttons. |
| 68 GList* all_widgets; |
| 69 |
| 70 // Possible button widgets. Used for keyboard navigation. |
| 71 GList* button_widgets; |
| 72 |
| 73 // The widget that currently has highlight. |
| 74 GtkWidget* currently_selected_button; |
| 75 |
| 76 // The widget that was selected *before* |currently_selected_button|. Why do |
| 77 // we hang on to this? Because the menu system sends us a deselect signal |
| 78 // right before activating us. We need to listen to deselect since that's |
| 79 // what we receive when the mouse cursor leaves us entirely. |
| 80 GtkWidget* previously_selected_button; |
| 81 }; |
| 82 |
| 83 struct _GtkCustomMenuItemClass { |
| 84 GtkMenuItemClass parent_class; |
| 85 }; |
| 86 |
| 87 GType gtk_custom_menu_item_get_type(void) G_GNUC_CONST; |
| 88 GtkWidget* gtk_custom_menu_item_new(const char* title); |
| 89 |
| 90 // Adds a button to our list of items in the |hbox|. |
| 91 GtkWidget* gtk_custom_menu_item_add_button(GtkCustomMenuItem* menu_item, |
| 92 int command_id); |
| 93 |
| 94 // Adds a button to our list of items in the |hbox|, but that isn't part of |
| 95 // |button_widgets| to prevent it from being activatable. |
| 96 GtkWidget* gtk_custom_menu_item_add_button_label(GtkCustomMenuItem* menu_item, |
| 97 int command_id); |
| 98 |
| 99 // Adds a vertical space in the |hbox|. |
| 100 void gtk_custom_menu_item_add_space(GtkCustomMenuItem* menu_item); |
| 101 |
| 102 // Receives a motion event from the GtkCustomMenu that contains us. We can't |
| 103 // just subscribe to motion-event or the individual widget enter/leave events |
| 104 // because the top level GtkMenu has an event grab. |
| 105 void gtk_custom_menu_item_receive_motion_event(GtkCustomMenuItem* menu_item, |
| 106 gdouble x, gdouble y); |
| 107 |
| 108 // Notification that the menu got a cursor key event. Used to move up/down |
| 109 // within the menu buttons. Returns TRUE to stop the default signal handler |
| 110 // from running. |
| 111 gboolean gtk_custom_menu_item_handle_move(GtkCustomMenuItem* menu_item, |
| 112 GtkMenuDirectionType direction); |
| 113 |
| 114 // Because we only get a generic "selected" signal when we've changed, we need |
| 115 // to have a way for the GtkCustomMenu to tell us that we were just |
| 116 // selected. |
| 117 void gtk_custom_menu_item_select_item_by_direction( |
| 118 GtkCustomMenuItem* menu_item, GtkMenuDirectionType direction); |
| 119 |
| 120 // Whether we are currently hovering over a clickable region on the menu |
| 121 // item. Used by GtkCustomMenu to determine whether it should discard click |
| 122 // events. |
| 123 gboolean gtk_custom_menu_item_is_in_clickable_region( |
| 124 GtkCustomMenuItem* menu_item); |
| 125 |
| 126 // If the button is released while the |currently_selected_button| isn't |
| 127 // supposed to dismiss the menu, this signals to our listeners that we want to |
| 128 // run this command if it doesn't dismiss the menu. Returns TRUE if we acted |
| 129 // on this button click (and should prevent the normal GtkMenu machinery from |
| 130 // firing an "activate" signal). |
| 131 gboolean gtk_custom_menu_item_try_no_dismiss_command( |
| 132 GtkCustomMenuItem* menu_item); |
| 133 |
| 134 // Calls |callback| with every button and button-label in the container. |
| 135 void gtk_custom_menu_item_foreach_button(GtkCustomMenuItem* menu_item, |
| 136 GtkCallback callback, |
| 137 gpointer callback_data); |
| 138 |
| 139 G_END_DECLS |
| 140 |
| 141 #endif // CHROME_BROWSER_UI_GTK_GTK_CUSTOM_MENU_ITEM_H_ |
OLD | NEW |