Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(924)

Unified Diff: views/widget/widget_gtk.cc

Issue 3046041: [Linux Views] Refactor accelerator handler related code. (Closed) Base URL: http://src.chromium.org/git/chromium.git
Patch Set: Prevent ctrl+alt. Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « views/widget/widget_gtk.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: views/widget/widget_gtk.cc
diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc
index de4ad9a61ada74418ffc4f838df615aadc6bcf15..adad7df800cebadbf071adfeb901b226e3b8303e 100644
--- a/views/widget/widget_gtk.cc
+++ b/views/widget/widget_gtk.cc
@@ -246,7 +246,8 @@ WidgetGtk::WidgetGtk(Type type)
has_focus_(false),
delegate_(NULL),
always_on_top_(false),
- is_double_buffered_(false) {
+ is_double_buffered_(false),
+ should_handle_menu_key_release_(false) {
static bool installed_message_loop_observer = false;
if (!installed_message_loop_observer) {
installed_message_loop_observer = true;
@@ -546,9 +547,9 @@ void WidgetGtk::Init(GtkWidget* parent,
// See views::Views::Focus and views::FocusManager::ClearNativeFocus
// for more details.
g_signal_connect(widget_, "key_press_event",
- G_CALLBACK(&OnKeyPressThunk), this);
+ G_CALLBACK(&OnKeyEventThunk), this);
g_signal_connect(widget_, "key_release_event",
- G_CALLBACK(&OnKeyReleaseThunk), this);
+ G_CALLBACK(&OnKeyEventThunk), this);
// Drag and drop.
gtk_drag_dest_set(window_contents_, static_cast<GtkDestDefaults>(0),
@@ -861,6 +862,38 @@ void WidgetGtk::ClearNativeFocus() {
gtk_window_set_focus(GTK_WINDOW(GetNativeView()), NULL);
}
+bool WidgetGtk::HandleKeyboardEvent(GdkEventKey* event) {
+ if (!focus_manager_)
+ return false;
+
+ KeyEvent key(event);
+ int key_code = key.GetKeyCode();
+ bool handled = false;
+
+ // Always reset |should_handle_menu_key_release_| unless we are handling a
+ // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only
+ // be activated when handling a VKEY_MENU key release event which is preceded
+ // by an unhandled VKEY_MENU key press event.
+ if (key_code != base::VKEY_MENU || event->type != GDK_KEY_RELEASE)
+ should_handle_menu_key_release_ = false;
+
+ if (event->type == GDK_KEY_PRESS) {
+ // VKEY_MENU is triggered by key release event.
+ if (key_code != base::VKEY_MENU)
+ handled = focus_manager_->OnKeyEvent(key);
+ else
+ should_handle_menu_key_release_ = true;
+ } else if (key_code == base::VKEY_MENU && should_handle_menu_key_release_ &&
+ (key.GetFlags() & ~Event::EF_ALT_DOWN) == 0) {
+ // trigger VKEY_MENU when only this key is pressed and released, and both
Jay Civelli 2010/08/04 18:21:00 Nit: Trigger
+ // press and release events are not handled by others.
+ Accelerator accelerator(base::VKEY_MENU, false, false, false);
+ handled = focus_manager_->ProcessAccelerator(accelerator);
+ }
+
+ return handled;
+}
+
////////////////////////////////////////////////////////////////////////////////
// WidgetGtk, protected:
@@ -1088,6 +1121,8 @@ gboolean WidgetGtk::OnFocusIn(GtkWidget* widget, GdkEventFocus* event) {
return false; // This is the second focus-in event in a row, ignore it.
has_focus_ = true;
+ should_handle_menu_key_release_ = false;
+
if (type_ == TYPE_CHILD)
return false;
@@ -1114,14 +1149,41 @@ gboolean WidgetGtk::OnFocusOut(GtkWidget* widget, GdkEventFocus* event) {
return false;
}
-gboolean WidgetGtk::OnKeyPress(GtkWidget* widget, GdkEventKey* event) {
- KeyEvent key_event(event);
- return root_view_->ProcessKeyEvent(key_event);
-}
-
-gboolean WidgetGtk::OnKeyRelease(GtkWidget* widget, GdkEventKey* event) {
- KeyEvent key_event(event);
- return root_view_->ProcessKeyEvent(key_event);
+gboolean WidgetGtk::OnKeyEvent(GtkWidget* widget, GdkEventKey* event) {
+ KeyEvent key(event);
+
+ // Always reset |should_handle_menu_key_release_| unless we are handling a
+ // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only
+ // be activated when handling a VKEY_MENU key release event which is preceded
+ // by an unhandled VKEY_MENU key press event. See also HandleKeyboardEvent().
+ if (key.GetKeyCode() != base::VKEY_MENU || event->type != GDK_KEY_RELEASE)
+ should_handle_menu_key_release_ = false;
+
+ bool handled = false;
+
+ // Dispatch the key event to View hierarchy first.
+ handled = root_view_->ProcessKeyEvent(key);
+
+ // Dispatch the key event to native GtkWidget hierarchy.
+ // To prevent GtkWindow from handling the key event as a keybinding, we need
+ // to bypass GtkWindow's default key event handler and dispatch the event
+ // here.
+ if (!handled && GTK_IS_WINDOW(widget))
+ handled = gtk_window_propagate_key_event(GTK_WINDOW(widget), event);
+
+ // On Linux, in order to handle VKEY_MENU (Alt) accelerator key correctly and
+ // avoid issues like: http://crbug.com/40966 and http://crbug.com/49701, we
+ // should only send the key event to the focus manager if it's not handled by
+ // any View or native GtkWidget.
+ // The flow is different when the focus is in a RenderWidgetHostViewGtk, which
+ // always consumes the key event and send it back to us later by calling
+ // HandleKeyboardEvent() directly, if it's not handled by webkit.
+ if (!handled)
+ handled = HandleKeyboardEvent(event);
+
+ // Always return true for toplevel window to prevents GtkWindow's default key
+ // event handler.
+ return GTK_IS_WINDOW(widget) ? true : handled;
}
gboolean WidgetGtk::OnQueryTooltip(GtkWidget* widget,
« no previous file with comments | « views/widget/widget_gtk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698