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

Side by Side Diff: views/focus/accelerator_handler_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, 4 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <gtk/gtk.h> 5 #include <gtk/gtk.h>
6 6
7 #include "base/keyboard_code_conversion_gtk.h" 7 #include "base/keyboard_code_conversion_gtk.h"
8 #include "base/keyboard_codes.h" 8 #include "base/keyboard_codes.h"
9 #include "views/accelerator.h" 9 #include "views/accelerator.h"
10 #include "views/focus/accelerator_handler.h" 10 #include "views/focus/accelerator_handler.h"
11 #include "views/focus/focus_manager.h" 11 #include "views/focus/focus_manager.h"
12 #include "views/widget/widget_gtk.h" 12 #include "views/widget/widget_gtk.h"
13 13
14 namespace views { 14 namespace views {
15 15
16 AcceleratorHandler::AcceleratorHandler() : only_menu_pressed_(false) {} 16 AcceleratorHandler::AcceleratorHandler() {}
17 17
18 bool AcceleratorHandler::Dispatch(GdkEvent* event) { 18 bool AcceleratorHandler::Dispatch(GdkEvent* event) {
19 // When focus changes, we may not see a full key-press / key-release 19 // The logic for handling keyboard accelerators has been moved into
20 // pair, so clear the set of keys we think were pressed. 20 // WidgetGtk::OnKeyEvent handler (views/widget/widget_gtk.cc).
21 if (event->type == GDK_FOCUS_CHANGE) {
22 pressed_hardware_keys_.clear();
23 consumed_vkeys_.clear();
24 only_menu_pressed_ = false;
25 }
26
27 // Skip accelerator handling for non key events.
28 bool skip = event->type != GDK_KEY_PRESS && event->type != GDK_KEY_RELEASE;
29
30 // Skip if there is a grabbed widget and it is not a window. This is because
31 // of the following two reasons:
32 // 1. Widget such as pop up from GtkComboBox is a grabbed widget and use ESC
33 // as its accelerator key to dismiss itself. We will break Gtk's code if
34 // we eat this key. See http://crosbug.com/2355
35 // 2. Modal dialogs in Gtk are grabbed windows and we want to have our
36 // accelerator key processing in this case. See http://crogbug.com/3701
37 if (!skip) {
38 GtkWidget* grabbed_widget = gtk_grab_get_current();
39 skip = grabbed_widget && !GTK_IS_WINDOW(grabbed_widget);
40 }
41
42 if (skip) {
43 // Let Gtk processes the event.
44 gtk_main_do_event(event);
45 return true;
46 }
47
48 GdkEventKey* key_event = reinterpret_cast<GdkEventKey*>(event);
49 // Let's retrieve the focus manager for the GdkWindow.
50 GdkWindow* window = gdk_window_get_toplevel(key_event->window);
51 gpointer ptr;
52 gdk_window_get_user_data(window, &ptr);
53 if (!ptr && !gdk_window_is_visible(window)) {
54 // The window is destroyed while we're handling key events.
55 gtk_main_do_event(event);
56 return true;
57 }
58
59 DCHECK(ptr);
60
61 // The top-level window or window widget is expected to always be associated
62 // with the top-level gtk widget.
63 WidgetGtk* widget =
64 WidgetGtk::GetViewForNative(reinterpret_cast<GtkWidget*>(ptr));
65 if (!widget) {
66 // During dnd we get events for windows we don't control (such as the
67 // window being dragged).
68 gtk_main_do_event(event);
69 return true;
70 }
71 FocusManager* focus_manager = widget->GetFocusManager();
72 if (!focus_manager) {
73 NOTREACHED();
74 return true;
75 }
76
77 KeyEvent view_key_event(key_event);
78 int key_code = view_key_event.GetKeyCode();
79 int hardware_keycode = key_event->hardware_keycode;
80 if (event->type == GDK_KEY_PRESS) {
81 pressed_hardware_keys_.insert(hardware_keycode);
82
83 // If it's the Alt key, don't send it to the focus manager until release
84 // (to handle focusing the menu bar).
85 if (key_code == base::VKEY_MENU && pressed_hardware_keys_.size() == 1) {
86 only_menu_pressed_ = true;
87 return true;
88 }
89
90 if (pressed_hardware_keys_.size() != 1)
91 only_menu_pressed_ = false;
92
93 // FocusManager::OnKeyEvent will return false if this message has been
94 // consumed and should not be propagated further.
95 if (!focus_manager->OnKeyEvent(view_key_event)) {
96 consumed_vkeys_.insert(key_code);
97 return true;
98 }
99 }
100
101 if (event->type == GDK_KEY_RELEASE) {
102 pressed_hardware_keys_.erase(hardware_keycode);
103
104 // Make sure to filter out the key release for a key press consumed
105 // as an accelerator, to avoid calling gtk_main_do_event with an
106 // unpaired key release.
107 if (consumed_vkeys_.find(key_code) != consumed_vkeys_.end()) {
108 consumed_vkeys_.erase(key_code);
109 return true;
110 }
111
112 // Special case: the Alt key can trigger an accelerator on release
113 // rather than on press, but only if no other keys were pressed.
114 if (key_code == base::VKEY_MENU && only_menu_pressed_) {
115 Accelerator accelerator(base::VKEY_MENU, false, false, false);
116 focus_manager->ProcessAccelerator(accelerator);
117 return true;
118 }
119 }
120
121 // Pass the event to gtk if we didn't consume it above.
122 gtk_main_do_event(event); 21 gtk_main_do_event(event);
123 return true; 22 return true;
124 } 23 }
125 24
126 } // namespace views 25 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698