OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |