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

Side by Side 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, 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
« no previous file with comments | « views/widget/widget_gtk.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "views/widget/widget_gtk.h" 5 #include "views/widget/widget_gtk.h"
6 6
7 #include <gdk/gdk.h> 7 #include <gdk/gdk.h>
8 #include <gdk/gdkx.h> 8 #include <gdk/gdkx.h>
9 #include <X11/extensions/shape.h> 9 #include <X11/extensions/shape.h>
10 10
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 ignore_drag_leave_(false), 239 ignore_drag_leave_(false),
240 opacity_(255), 240 opacity_(255),
241 drag_data_(NULL), 241 drag_data_(NULL),
242 in_paint_now_(false), 242 in_paint_now_(false),
243 is_active_(false), 243 is_active_(false),
244 transient_to_parent_(false), 244 transient_to_parent_(false),
245 got_initial_focus_in_(false), 245 got_initial_focus_in_(false),
246 has_focus_(false), 246 has_focus_(false),
247 delegate_(NULL), 247 delegate_(NULL),
248 always_on_top_(false), 248 always_on_top_(false),
249 is_double_buffered_(false) { 249 is_double_buffered_(false),
250 should_handle_menu_key_release_(false) {
250 static bool installed_message_loop_observer = false; 251 static bool installed_message_loop_observer = false;
251 if (!installed_message_loop_observer) { 252 if (!installed_message_loop_observer) {
252 installed_message_loop_observer = true; 253 installed_message_loop_observer = true;
253 MessageLoopForUI* loop = MessageLoopForUI::current(); 254 MessageLoopForUI* loop = MessageLoopForUI::current();
254 if (loop) 255 if (loop)
255 loop->AddObserver(DropObserver::Get()); 256 loop->AddObserver(DropObserver::Get());
256 } 257 }
257 258
258 if (type_ != TYPE_CHILD) 259 if (type_ != TYPE_CHILD)
259 focus_manager_ = new FocusManager(this); 260 focus_manager_ = new FocusManager(this);
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 g_signal_connect(widget_, "show", 540 g_signal_connect(widget_, "show",
540 G_CALLBACK(&OnShowThunk), this); 541 G_CALLBACK(&OnShowThunk), this);
541 g_signal_connect(widget_, "hide", 542 g_signal_connect(widget_, "hide",
542 G_CALLBACK(&OnHideThunk), this); 543 G_CALLBACK(&OnHideThunk), this);
543 544
544 // Views/FocusManager (re)sets the focus to the root window, 545 // Views/FocusManager (re)sets the focus to the root window,
545 // so we need to connect signal handlers to the gtk window. 546 // so we need to connect signal handlers to the gtk window.
546 // See views::Views::Focus and views::FocusManager::ClearNativeFocus 547 // See views::Views::Focus and views::FocusManager::ClearNativeFocus
547 // for more details. 548 // for more details.
548 g_signal_connect(widget_, "key_press_event", 549 g_signal_connect(widget_, "key_press_event",
549 G_CALLBACK(&OnKeyPressThunk), this); 550 G_CALLBACK(&OnKeyEventThunk), this);
550 g_signal_connect(widget_, "key_release_event", 551 g_signal_connect(widget_, "key_release_event",
551 G_CALLBACK(&OnKeyReleaseThunk), this); 552 G_CALLBACK(&OnKeyEventThunk), this);
552 553
553 // Drag and drop. 554 // Drag and drop.
554 gtk_drag_dest_set(window_contents_, static_cast<GtkDestDefaults>(0), 555 gtk_drag_dest_set(window_contents_, static_cast<GtkDestDefaults>(0),
555 NULL, 0, GDK_ACTION_COPY); 556 NULL, 0, GDK_ACTION_COPY);
556 g_signal_connect(window_contents_, "drag_motion", 557 g_signal_connect(window_contents_, "drag_motion",
557 G_CALLBACK(&OnDragMotionThunk), this); 558 G_CALLBACK(&OnDragMotionThunk), this);
558 g_signal_connect(window_contents_, "drag_data_received", 559 g_signal_connect(window_contents_, "drag_data_received",
559 G_CALLBACK(&OnDragDataReceivedThunk), this); 560 G_CALLBACK(&OnDragDataReceivedThunk), this);
560 g_signal_connect(window_contents_, "drag_drop", 561 g_signal_connect(window_contents_, "drag_drop",
561 G_CALLBACK(&OnDragDropThunk), this); 562 G_CALLBACK(&OnDragDropThunk), this);
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
854 855
855 void WidgetGtk::ClearNativeFocus() { 856 void WidgetGtk::ClearNativeFocus() {
856 DCHECK(type_ != TYPE_CHILD); 857 DCHECK(type_ != TYPE_CHILD);
857 if (!GetNativeView()) { 858 if (!GetNativeView()) {
858 NOTREACHED(); 859 NOTREACHED();
859 return; 860 return;
860 } 861 }
861 gtk_window_set_focus(GTK_WINDOW(GetNativeView()), NULL); 862 gtk_window_set_focus(GTK_WINDOW(GetNativeView()), NULL);
862 } 863 }
863 864
865 bool WidgetGtk::HandleKeyboardEvent(GdkEventKey* event) {
866 if (!focus_manager_)
867 return false;
868
869 KeyEvent key(event);
870 int key_code = key.GetKeyCode();
871 bool handled = false;
872
873 // Always reset |should_handle_menu_key_release_| unless we are handling a
874 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only
875 // be activated when handling a VKEY_MENU key release event which is preceded
876 // by an unhandled VKEY_MENU key press event.
877 if (key_code != base::VKEY_MENU || event->type != GDK_KEY_RELEASE)
878 should_handle_menu_key_release_ = false;
879
880 if (event->type == GDK_KEY_PRESS) {
881 // VKEY_MENU is triggered by key release event.
882 if (key_code != base::VKEY_MENU)
883 handled = focus_manager_->OnKeyEvent(key);
884 else
885 should_handle_menu_key_release_ = true;
886 } else if (key_code == base::VKEY_MENU && should_handle_menu_key_release_ &&
887 (key.GetFlags() & ~Event::EF_ALT_DOWN) == 0) {
888 // trigger VKEY_MENU when only this key is pressed and released, and both
Jay Civelli 2010/08/04 18:21:00 Nit: Trigger
889 // press and release events are not handled by others.
890 Accelerator accelerator(base::VKEY_MENU, false, false, false);
891 handled = focus_manager_->ProcessAccelerator(accelerator);
892 }
893
894 return handled;
895 }
896
864 //////////////////////////////////////////////////////////////////////////////// 897 ////////////////////////////////////////////////////////////////////////////////
865 // WidgetGtk, protected: 898 // WidgetGtk, protected:
866 899
867 // static 900 // static
868 int WidgetGtk::GetFlagsForEventButton(const GdkEventButton& event) { 901 int WidgetGtk::GetFlagsForEventButton(const GdkEventButton& event) {
869 int flags = Event::GetFlagsFromGdkState(event.state); 902 int flags = Event::GetFlagsFromGdkState(event.state);
870 switch (event.button) { 903 switch (event.button) {
871 case 1: 904 case 1:
872 flags |= Event::EF_LEFT_BUTTON_DOWN; 905 flags |= Event::EF_LEFT_BUTTON_DOWN;
873 break; 906 break;
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
1081 1114
1082 gboolean WidgetGtk::OnScroll(GtkWidget* widget, GdkEventScroll* event) { 1115 gboolean WidgetGtk::OnScroll(GtkWidget* widget, GdkEventScroll* event) {
1083 return ProcessScroll(event); 1116 return ProcessScroll(event);
1084 } 1117 }
1085 1118
1086 gboolean WidgetGtk::OnFocusIn(GtkWidget* widget, GdkEventFocus* event) { 1119 gboolean WidgetGtk::OnFocusIn(GtkWidget* widget, GdkEventFocus* event) {
1087 if (has_focus_) 1120 if (has_focus_)
1088 return false; // This is the second focus-in event in a row, ignore it. 1121 return false; // This is the second focus-in event in a row, ignore it.
1089 has_focus_ = true; 1122 has_focus_ = true;
1090 1123
1124 should_handle_menu_key_release_ = false;
1125
1091 if (type_ == TYPE_CHILD) 1126 if (type_ == TYPE_CHILD)
1092 return false; 1127 return false;
1093 1128
1094 // See description of got_initial_focus_in_ for details on this. 1129 // See description of got_initial_focus_in_ for details on this.
1095 if (!got_initial_focus_in_) { 1130 if (!got_initial_focus_in_) {
1096 got_initial_focus_in_ = true; 1131 got_initial_focus_in_ = true;
1097 SetInitialFocus(); 1132 SetInitialFocus();
1098 } else { 1133 } else {
1099 focus_manager_->RestoreFocusedView(); 1134 focus_manager_->RestoreFocusedView();
1100 } 1135 }
1101 return false; 1136 return false;
1102 } 1137 }
1103 1138
1104 gboolean WidgetGtk::OnFocusOut(GtkWidget* widget, GdkEventFocus* event) { 1139 gboolean WidgetGtk::OnFocusOut(GtkWidget* widget, GdkEventFocus* event) {
1105 if (!has_focus_) 1140 if (!has_focus_)
1106 return false; // This is the second focus-out event in a row, ignore it. 1141 return false; // This is the second focus-out event in a row, ignore it.
1107 has_focus_ = false; 1142 has_focus_ = false;
1108 1143
1109 if (type_ == TYPE_CHILD) 1144 if (type_ == TYPE_CHILD)
1110 return false; 1145 return false;
1111 1146
1112 // The top-level window lost focus, store the focused view. 1147 // The top-level window lost focus, store the focused view.
1113 focus_manager_->StoreFocusedView(); 1148 focus_manager_->StoreFocusedView();
1114 return false; 1149 return false;
1115 } 1150 }
1116 1151
1117 gboolean WidgetGtk::OnKeyPress(GtkWidget* widget, GdkEventKey* event) { 1152 gboolean WidgetGtk::OnKeyEvent(GtkWidget* widget, GdkEventKey* event) {
1118 KeyEvent key_event(event); 1153 KeyEvent key(event);
1119 return root_view_->ProcessKeyEvent(key_event);
1120 }
1121 1154
1122 gboolean WidgetGtk::OnKeyRelease(GtkWidget* widget, GdkEventKey* event) { 1155 // Always reset |should_handle_menu_key_release_| unless we are handling a
1123 KeyEvent key_event(event); 1156 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only
1124 return root_view_->ProcessKeyEvent(key_event); 1157 // be activated when handling a VKEY_MENU key release event which is preceded
1158 // by an unhandled VKEY_MENU key press event. See also HandleKeyboardEvent().
1159 if (key.GetKeyCode() != base::VKEY_MENU || event->type != GDK_KEY_RELEASE)
1160 should_handle_menu_key_release_ = false;
1161
1162 bool handled = false;
1163
1164 // Dispatch the key event to View hierarchy first.
1165 handled = root_view_->ProcessKeyEvent(key);
1166
1167 // Dispatch the key event to native GtkWidget hierarchy.
1168 // To prevent GtkWindow from handling the key event as a keybinding, we need
1169 // to bypass GtkWindow's default key event handler and dispatch the event
1170 // here.
1171 if (!handled && GTK_IS_WINDOW(widget))
1172 handled = gtk_window_propagate_key_event(GTK_WINDOW(widget), event);
1173
1174 // On Linux, in order to handle VKEY_MENU (Alt) accelerator key correctly and
1175 // avoid issues like: http://crbug.com/40966 and http://crbug.com/49701, we
1176 // should only send the key event to the focus manager if it's not handled by
1177 // any View or native GtkWidget.
1178 // The flow is different when the focus is in a RenderWidgetHostViewGtk, which
1179 // always consumes the key event and send it back to us later by calling
1180 // HandleKeyboardEvent() directly, if it's not handled by webkit.
1181 if (!handled)
1182 handled = HandleKeyboardEvent(event);
1183
1184 // Always return true for toplevel window to prevents GtkWindow's default key
1185 // event handler.
1186 return GTK_IS_WINDOW(widget) ? true : handled;
1125 } 1187 }
1126 1188
1127 gboolean WidgetGtk::OnQueryTooltip(GtkWidget* widget, 1189 gboolean WidgetGtk::OnQueryTooltip(GtkWidget* widget,
1128 gint x, 1190 gint x,
1129 gint y, 1191 gint y,
1130 gboolean keyboard_mode, 1192 gboolean keyboard_mode,
1131 GtkTooltip* tooltip) { 1193 GtkTooltip* tooltip) {
1132 return tooltip_manager_->ShowTooltip(x, y, keyboard_mode, tooltip); 1194 return tooltip_manager_->ShowTooltip(x, y, keyboard_mode, tooltip);
1133 } 1195 }
1134 1196
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after
1548 GtkWindow* window = GTK_WINDOW(element->data); 1610 GtkWindow* window = GTK_WINDOW(element->data);
1549 DCHECK(window); 1611 DCHECK(window);
1550 RootView *root_view = FindRootView(window); 1612 RootView *root_view = FindRootView(window);
1551 if (root_view) 1613 if (root_view)
1552 root_view->NotifyLocaleChanged(); 1614 root_view->NotifyLocaleChanged();
1553 } 1615 }
1554 g_list_free(window_list); 1616 g_list_free(window_list);
1555 } 1617 }
1556 1618
1557 } // namespace views 1619 } // namespace views
OLDNEW
« 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