Index: chrome/browser/gtk/gtk_custom_menu_item.h |
diff --git a/chrome/browser/gtk/gtk_custom_menu_item.h b/chrome/browser/gtk/gtk_custom_menu_item.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a7c152b0d6ccd8a05820e31e8972486e6df493ad |
--- /dev/null |
+++ b/chrome/browser/gtk/gtk_custom_menu_item.h |
@@ -0,0 +1,118 @@ |
+// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef CHROME_BROWSER_GTK_GTK_CUSTOM_MENU_ITEM_H_ |
+#define CHROME_BROWSER_GTK_GTK_CUSTOM_MENU_ITEM_H_ |
+ |
+// GtkCustomMenuItem is a GtkMenuItem subclass that has buttons in it and acts |
+// to support this. GtkCustomMenuItems only render properly when put in a |
+// GtkCustomMenu; there's a lot of collaboration between these two classes |
+// necessary to work around how gtk normally does menus. |
+// |
+// We can't rely on the normal event infrastructure. While a menu is up, the |
+// GtkMenu has a grab on all events. Instead of trying to pump events through |
+// the normal channels, we have the GtkCustomMenu selectively forward mouse |
+// motion through a back channel. The GtkCustomMenu only listens for button |
+// press information so it can block the effects of the click if the cursor |
+// isn't in a button in the menu item. |
+// |
+// A GtkCustomMenuItem doesn't try to take these signals and forward them to |
+// the buttons it owns. The GtkCustomMenu class keeps track of which button is |
+// selected (due to key events and mouse movement) and otherwise acts like a |
+// normal GtkItem. The buttons are only for sizing and rendering; they don't |
+// respond to events. Instead, when the GtkCustomMenuItem is activated by the |
+// GtkMenu, it uses which button was selected as a signal of what to do. |
+// |
+// Users should connect to the "button-pushed" signal to be notified when a |
+// button was pushed. We don't go through the normal "activate" signal because |
+// we need to communicate additional information, namely which button was |
+// activated. |
+ |
+#include <gdk/gdk.h> |
+#include <gtk/gtk.h> |
+ |
+G_BEGIN_DECLS |
+ |
+#define GTK_TYPE_CUSTOM_MENU_ITEM \ |
+ (gtk_custom_menu_item_get_type()) |
+#define GTK_CUSTOM_MENU_ITEM(obj) \ |
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_CUSTOM_MENU_ITEM, \ |
+ GtkCustomMenuItem)) |
+#define GTK_CUSTOM_MENU_ITEM_CLASS(klass) \ |
+ (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_CUSTOM_MENU_ITEM, \ |
+ GtkCustomMenuItemClass)) |
+#define GTK_IS_CUSTOM_MENU_ITEM(obj) \ |
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_CUSTOM_MENU_ITEM)) |
+#define GTK_IS_CUSTOM_MENU_ITEM_CLASS(klass) \ |
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_CUSTOM_MENU_ITEM)) |
+#define GTK_CUSTOM_MENU_ITEM_GET_CLASS(obj) \ |
+ (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_CUSTOM_MENU_ITEM, \ |
+ GtkCustomMenuItemClass)) |
+ |
+typedef struct _GtkCustomMenuItem GtkCustomMenuItem; |
+typedef struct _GtkCustomMenuItemClass GtkCustomMenuItemClass; |
+ |
+struct _GtkCustomMenuItem { |
+ GtkMenuItem menu_item; |
+ |
+ // Container for button widgets. |
+ GtkWidget* hbox; |
+ |
+ // Label on left side of menu item. |
+ GtkWidget* label; |
+ |
+ // Possible button widgets |
+ GList* button_widgets; |
+ |
+ // The widget that currently has highlight. |
+ GtkWidget* currently_selected_button; |
+ |
+ // The widget that was selected *before* |currently_selected_button|. Why do |
+ // we hang on to this? Because the menu system sends us a deselect signal |
+ // right before activating us. We need to listen to deselect since that's |
+ // what we receive when the mouse cursor leaves us entirely. |
+ GtkWidget* previously_selected_button; |
+}; |
+ |
+struct _GtkCustomMenuItemClass { |
+ GtkMenuItemClass parent_class; |
+}; |
+ |
+GType gtk_custom_menu_item_get_type(void) G_GNUC_CONST; |
+GtkWidget* gtk_custom_menu_item_new(const char* title); |
+ |
+// Adds a button to our list of items in the |hbox|. |
+GtkWidget* gtk_custom_menu_item_add_button(GtkCustomMenuItem* menu_item, |
+ int command_id); |
+ |
+// Adds a vertical space in the |hbox|. |
+void gtk_custom_menu_item_add_space(GtkCustomMenuItem* menu_item); |
+ |
+// Receives a motion event from the GtkCustomMenu that contains us. We can't |
+// just subscribe to motion-event or the individual widget enter/leave events |
+// because the top level GtkMenu has an event grab. |
+void gtk_custom_menu_item_receive_motion_event(GtkCustomMenuItem* menu_item, |
+ gdouble x, gdouble y); |
+ |
+// Notification that the menu got a cursor key event. Used to move up/down |
+// within the menu buttons. Returns TRUE to stop the default signal handler |
+// from running. |
+gboolean gtk_custom_menu_item_handle_move(GtkCustomMenuItem* menu_item, |
+ GtkMenuDirectionType direction); |
+ |
+// Because we only get a generic "selected" signal when we've changed, we need |
+// to have a way for the GtkCustomMenu to tell us that we were just |
+// selected. |
+void gtk_custom_menu_item_select_item_by_direction( |
+ GtkCustomMenuItem* menu_item, GtkMenuDirectionType direction); |
+ |
+// Whether we are currently hovering over a clickable region on the menu |
+// item. Used by GtkCustomMenu to determine whether it should discard click |
+// events. |
+gboolean gtk_custom_menu_item_is_in_clickable_region( |
+ GtkCustomMenuItem* menu_item); |
+ |
+G_END_DECLS |
+ |
+#endif // CHROME_BROWSER_GTK_GTK_CUSTOM_MENU_ITEM_H_ |