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

Side by Side Diff: views/widget/widget_gtk.cc

Issue 6675005: Integrate the new input method API for Views into Chromium. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 void WidgetGtk::Init(GtkWidget* parent, 487 void WidgetGtk::Init(GtkWidget* parent,
488 const gfx::Rect& bounds) { 488 const gfx::Rect& bounds) {
489 Widget::Init(parent, bounds); 489 Widget::Init(parent, bounds);
490 if (type_ != TYPE_CHILD) 490 if (type_ != TYPE_CHILD)
491 ActiveWindowWatcherX::AddObserver(this); 491 ActiveWindowWatcherX::AddObserver(this);
492 492
493 // Make container here. 493 // Make container here.
494 CreateGtkWidget(parent, bounds); 494 CreateGtkWidget(parent, bounds);
495 delegate_->OnNativeWidgetCreated(); 495 delegate_->OnNativeWidgetCreated();
496 496
497 // Creates input method for toplevel widget after calling
498 // delegate_->OnNativeWidgetCreated(), to make sure that focus manager is
499 // already created at this point.
500 if (type_ != TYPE_CHILD) {
501 input_method_.reset(new InputMethodGtk(this));
502 input_method_->Init(GetWidget());
503 }
504
497 if (opacity_ != 255) 505 if (opacity_ != 255)
498 SetOpacity(opacity_); 506 SetOpacity(opacity_);
499 507
500 // Make sure we receive our motion events. 508 // Make sure we receive our motion events.
501 509
502 // In general we register most events on the parent of all widgets. At a 510 // In general we register most events on the parent of all widgets. At a
503 // minimum we need painting to happen on the parent (otherwise painting 511 // minimum we need painting to happen on the parent (otherwise painting
504 // doesn't work at all), and similarly we need mouse release events on the 512 // doesn't work at all), and similarly we need mouse release events on the
505 // parent as windows don't get mouse releases. 513 // parent as windows don't get mouse releases.
506 gtk_widget_add_events(window_contents_, 514 gtk_widget_add_events(window_contents_,
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 G_CALLBACK(&OnShowThunk), this); 559 G_CALLBACK(&OnShowThunk), this);
552 g_signal_connect(widget_, "map", 560 g_signal_connect(widget_, "map",
553 G_CALLBACK(&OnMapThunk), this); 561 G_CALLBACK(&OnMapThunk), this);
554 g_signal_connect(widget_, "hide", 562 g_signal_connect(widget_, "hide",
555 G_CALLBACK(&OnHideThunk), this); 563 G_CALLBACK(&OnHideThunk), this);
556 564
557 // Views/FocusManager (re)sets the focus to the root window, 565 // Views/FocusManager (re)sets the focus to the root window,
558 // so we need to connect signal handlers to the gtk window. 566 // so we need to connect signal handlers to the gtk window.
559 // See views::Views::Focus and views::FocusManager::ClearNativeFocus 567 // See views::Views::Focus and views::FocusManager::ClearNativeFocus
560 // for more details. 568 // for more details.
561 g_signal_connect(widget_, "key_press_event", 569 // Child Widget should never get keyboard focus.
562 G_CALLBACK(&OnKeyEventThunk), this); 570 if (type_ != TYPE_CHILD) {
563 g_signal_connect(widget_, "key_release_event", 571 g_signal_connect(widget_, "key_press_event",
564 G_CALLBACK(&OnKeyEventThunk), this); 572 G_CALLBACK(&OnKeyEventThunk), this);
573 g_signal_connect(widget_, "key_release_event",
574 G_CALLBACK(&OnKeyEventThunk), this);
575 }
565 576
566 // Drag and drop. 577 // Drag and drop.
567 gtk_drag_dest_set(window_contents_, static_cast<GtkDestDefaults>(0), 578 gtk_drag_dest_set(window_contents_, static_cast<GtkDestDefaults>(0),
568 NULL, 0, GDK_ACTION_COPY); 579 NULL, 0, GDK_ACTION_COPY);
569 g_signal_connect(window_contents_, "drag_motion", 580 g_signal_connect(window_contents_, "drag_motion",
570 G_CALLBACK(&OnDragMotionThunk), this); 581 G_CALLBACK(&OnDragMotionThunk), this);
571 g_signal_connect(window_contents_, "drag_data_received", 582 g_signal_connect(window_contents_, "drag_data_received",
572 G_CALLBACK(&OnDragDataReceivedThunk), this); 583 G_CALLBACK(&OnDragDataReceivedThunk), this);
573 g_signal_connect(window_contents_, "drag_drop", 584 g_signal_connect(window_contents_, "drag_drop",
574 G_CALLBACK(&OnDragDropThunk), this); 585 G_CALLBACK(&OnDragDropThunk), this);
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 if (HasNativeCapture()) 746 if (HasNativeCapture())
736 gtk_grab_remove(window_contents_); 747 gtk_grab_remove(window_contents_);
737 } 748 }
738 749
739 bool WidgetGtk::HasNativeCapture() const { 750 bool WidgetGtk::HasNativeCapture() const {
740 // TODO(beng): Should be able to use gtk_widget_has_grab() here but the 751 // TODO(beng): Should be able to use gtk_widget_has_grab() here but the
741 // trybots don't have Gtk 2.18. 752 // trybots don't have Gtk 2.18.
742 return GTK_WIDGET_HAS_GRAB(window_contents_); 753 return GTK_WIDGET_HAS_GRAB(window_contents_);
743 } 754 }
744 755
756 InputMethod* WidgetGtk::GetInputMethodNative() {
757 return input_method_.get();
758 }
759
760 void WidgetGtk::ReplaceInputMethod(InputMethod* input_method) {
761 input_method_.reset(input_method);
762 if (input_method) {
763 input_method->set_delegate(this);
764 input_method->Init(GetWidget());
765 }
766 }
767
745 gfx::Rect WidgetGtk::GetWindowScreenBounds() const { 768 gfx::Rect WidgetGtk::GetWindowScreenBounds() const {
746 // Client == Window bounds on Gtk. 769 // Client == Window bounds on Gtk.
747 return GetClientAreaScreenBounds(); 770 return GetClientAreaScreenBounds();
748 } 771 }
749 772
750 gfx::Rect WidgetGtk::GetClientAreaScreenBounds() const { 773 gfx::Rect WidgetGtk::GetClientAreaScreenBounds() const {
751 // Due to timing we can get a request for bounds after Close(). 774 // Due to timing we can get a request for bounds after Close().
752 // TODO(beng): Figure out if this is bogus. 775 // TODO(beng): Figure out if this is bogus.
753 if (!widget_) 776 if (!widget_)
754 return gfx::Rect(size_); 777 return gfx::Rect(size_);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
830 if (close_widget_factory_.empty()) { 853 if (close_widget_factory_.empty()) {
831 // And we delay the close just in case we're on the stack. 854 // And we delay the close just in case we're on the stack.
832 MessageLoop::current()->PostTask(FROM_HERE, 855 MessageLoop::current()->PostTask(FROM_HERE,
833 close_widget_factory_.NewRunnableMethod( 856 close_widget_factory_.NewRunnableMethod(
834 &WidgetGtk::CloseNow)); 857 &WidgetGtk::CloseNow));
835 } 858 }
836 } 859 }
837 860
838 void WidgetGtk::CloseNow() { 861 void WidgetGtk::CloseNow() {
839 if (widget_) { 862 if (widget_) {
863 input_method_.reset();
840 gtk_widget_destroy(widget_); // Triggers OnDestroy(). 864 gtk_widget_destroy(widget_); // Triggers OnDestroy().
841 } 865 }
842 } 866 }
843 867
844 void WidgetGtk::Show() { 868 void WidgetGtk::Show() {
845 if (widget_) { 869 if (widget_) {
846 gtk_widget_show(widget_); 870 gtk_widget_show(widget_);
847 if (widget_->window) 871 if (widget_->window)
848 gdk_window_raise(widget_->window); 872 gdk_window_raise(widget_->window);
849 } 873 }
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
1165 if (type_ == TYPE_CHILD) 1189 if (type_ == TYPE_CHILD)
1166 return false; 1190 return false;
1167 1191
1168 // The top-level window lost focus, store the focused view. 1192 // The top-level window lost focus, store the focused view.
1169 GetFocusManager()->StoreFocusedView(); 1193 GetFocusManager()->StoreFocusedView();
1170 return false; 1194 return false;
1171 } 1195 }
1172 1196
1173 gboolean WidgetGtk::OnKeyEvent(GtkWidget* widget, GdkEventKey* event) { 1197 gboolean WidgetGtk::OnKeyEvent(GtkWidget* widget, GdkEventKey* event) {
1174 KeyEvent key(reinterpret_cast<NativeEvent>(event)); 1198 KeyEvent key(reinterpret_cast<NativeEvent>(event));
1199 if (input_method_.get())
1200 input_method_->DispatchKeyEvent(key);
1201 else
1202 DispatchKeyEventPostIME(key);
sadrul 2011/03/21 19:57:45 return DispatchKeyEventPostIME(key);
James Su 2011/03/21 21:34:07 It's intentionally to always return true to preven
1175 1203
1176 // Always reset |should_handle_menu_key_release_| unless we are handling a 1204 // Returns true to prevent GtkWindow's default key event handler.
1177 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only 1205 return true;
1178 // be activated when handling a VKEY_MENU key release event which is preceded
1179 // by an unhandled VKEY_MENU key press event. See also HandleKeyboardEvent().
1180 if (key.key_code() != ui::VKEY_MENU || event->type != GDK_KEY_RELEASE)
1181 should_handle_menu_key_release_ = false;
1182
1183 bool handled = false;
1184
1185 // Dispatch the key event to View hierarchy first.
1186 handled = GetRootView()->ProcessKeyEvent(key);
1187
1188 // Dispatch the key event to native GtkWidget hierarchy.
1189 // To prevent GtkWindow from handling the key event as a keybinding, we need
1190 // to bypass GtkWindow's default key event handler and dispatch the event
1191 // here.
1192 if (!handled && GTK_IS_WINDOW(widget))
1193 handled = gtk_window_propagate_key_event(GTK_WINDOW(widget), event);
1194
1195 // On Linux, in order to handle VKEY_MENU (Alt) accelerator key correctly and
1196 // avoid issues like: http://crbug.com/40966 and http://crbug.com/49701, we
1197 // should only send the key event to the focus manager if it's not handled by
1198 // any View or native GtkWidget.
1199 // The flow is different when the focus is in a RenderWidgetHostViewGtk, which
1200 // always consumes the key event and send it back to us later by calling
1201 // HandleKeyboardEvent() directly, if it's not handled by webkit.
1202 if (!handled)
1203 handled = HandleKeyboardEvent(event);
1204
1205 // Dispatch the key event for bindings processing.
1206 if (!handled && GTK_IS_WINDOW(widget))
1207 handled = gtk_bindings_activate_event(GTK_OBJECT(widget), event);
1208
1209 // Always return true for toplevel window to prevents GtkWindow's default key
1210 // event handler.
1211 return GTK_IS_WINDOW(widget) ? true : handled;
1212 } 1206 }
1213 1207
1214 gboolean WidgetGtk::OnQueryTooltip(GtkWidget* widget, 1208 gboolean WidgetGtk::OnQueryTooltip(GtkWidget* widget,
1215 gint x, 1209 gint x,
1216 gint y, 1210 gint y,
1217 gboolean keyboard_mode, 1211 gboolean keyboard_mode,
1218 GtkTooltip* tooltip) { 1212 GtkTooltip* tooltip) {
1219 return tooltip_manager_->ShowTooltip(x, y, keyboard_mode, tooltip); 1213 return tooltip_manager_->ShowTooltip(x, y, keyboard_mode, tooltip);
1220 } 1214 }
1221 1215
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1281 1275
1282 RootView* WidgetGtk::CreateRootView() { 1276 RootView* WidgetGtk::CreateRootView() {
1283 return new RootView(this); 1277 return new RootView(this);
1284 } 1278 }
1285 1279
1286 gfx::AcceleratedWidget WidgetGtk::GetAcceleratedWidget() { 1280 gfx::AcceleratedWidget WidgetGtk::GetAcceleratedWidget() {
1287 DCHECK(window_contents_ && window_contents_->window); 1281 DCHECK(window_contents_ && window_contents_->window);
1288 return GDK_WINDOW_XID(window_contents_->window); 1282 return GDK_WINDOW_XID(window_contents_->window);
1289 } 1283 }
1290 1284
1285 void WidgetGtk::DispatchKeyEventPostIME(const KeyEvent& key) {
1286 // Always reset |should_handle_menu_key_release_| unless we are handling a
1287 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only
1288 // be activated when handling a VKEY_MENU key release event which is preceded
1289 // by an unhandled VKEY_MENU key press event. See also HandleKeyboardEvent().
1290 if (key.key_code() != ui::VKEY_MENU || key.type() != ui::ET_KEY_RELEASED)
1291 should_handle_menu_key_release_ = false;
1292
1293 bool handled = false;
1294
1295 // Dispatch the key event to View hierarchy first.
1296 handled = GetRootView()->ProcessKeyEvent(key);
1297
1298 GdkEventKey* event = reinterpret_cast<GdkEventKey*>(key.native_event());
1299 if (key.key_code() == ui::VKEY_PROCESSKEY || handled || !event)
1300 return;
1301
1302 // Dispatch the key event to native GtkWidget hierarchy.
1303 // To prevent GtkWindow from handling the key event as a keybinding, we need
1304 // to bypass GtkWindow's default key event handler and dispatch the event
1305 // here.
1306 if (!handled && GTK_IS_WINDOW(widget_))
1307 handled = gtk_window_propagate_key_event(GTK_WINDOW(widget_), event);
1308
1309 // On Linux, in order to handle VKEY_MENU (Alt) accelerator key correctly and
1310 // avoid issues like: http://crbug.com/40966 and http://crbug.com/49701, we
1311 // should only send the key event to the focus manager if it's not handled by
1312 // any View or native GtkWidget.
1313 // The flow is different when the focus is in a RenderWidgetHostViewGtk, which
1314 // always consumes the key event and send it back to us later by calling
1315 // HandleKeyboardEvent() directly, if it's not handled by webkit.
1316 if (!handled)
1317 handled = HandleKeyboardEvent(event);
1318
1319 // Dispatch the key event for bindings processing.
1320 if (!handled && GTK_IS_WINDOW(widget_))
1321 handled = gtk_bindings_activate_event(GTK_OBJECT(widget_), event);
1322 }
sadrul 2011/03/21 19:57:45 return GTK_IS_WINDOW(widget) ? true : handled;
James Su 2011/03/21 21:34:07 See my comment in OnKeyEvent().
1323
1291 gboolean WidgetGtk::OnWindowPaint(GtkWidget* widget, GdkEventExpose* event) { 1324 gboolean WidgetGtk::OnWindowPaint(GtkWidget* widget, GdkEventExpose* event) {
1292 // Clear the background to be totally transparent. We don't need to 1325 // Clear the background to be totally transparent. We don't need to
1293 // paint the root view here as that is done by OnPaint. 1326 // paint the root view here as that is done by OnPaint.
1294 DCHECK(transparent_); 1327 DCHECK(transparent_);
1295 DrawTransparentBackground(widget, event); 1328 DrawTransparentBackground(widget, event);
1296 return false; 1329 return false;
1297 } 1330 }
1298 1331
1299 bool WidgetGtk::ProcessMousePressed(GdkEventButton* event) { 1332 bool WidgetGtk::ProcessMousePressed(GdkEventButton* event) {
1300 if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS) { 1333 if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS) {
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
1614 1647
1615 NativeWidget* native_widget = GetNativeWidgetForNativeView(native_view); 1648 NativeWidget* native_widget = GetNativeWidgetForNativeView(native_view);
1616 if (native_widget) 1649 if (native_widget)
1617 children->insert(native_widget); 1650 children->insert(native_widget);
1618 gtk_container_foreach(GTK_CONTAINER(native_view), 1651 gtk_container_foreach(GTK_CONTAINER(native_view),
1619 EnumerateChildWidgetsForNativeWidgets, 1652 EnumerateChildWidgetsForNativeWidgets,
1620 reinterpret_cast<gpointer>(children)); 1653 reinterpret_cast<gpointer>(children));
1621 } 1654 }
1622 1655
1623 } // namespace views 1656 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698