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

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: Add some DCHECKs. 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 486 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 void WidgetGtk::Init(GtkWidget* parent, 497 void WidgetGtk::Init(GtkWidget* parent,
498 const gfx::Rect& bounds) { 498 const gfx::Rect& bounds) {
499 Widget::Init(parent, bounds); 499 Widget::Init(parent, bounds);
500 if (type_ != TYPE_CHILD) 500 if (type_ != TYPE_CHILD)
501 ActiveWindowWatcherX::AddObserver(this); 501 ActiveWindowWatcherX::AddObserver(this);
502 502
503 // Make container here. 503 // Make container here.
504 CreateGtkWidget(parent, bounds); 504 CreateGtkWidget(parent, bounds);
505 delegate_->OnNativeWidgetCreated(); 505 delegate_->OnNativeWidgetCreated();
506 506
507 // Creates input method for toplevel widget after calling
508 // delegate_->OnNativeWidgetCreated(), to make sure that focus manager is
509 // already created at this point.
510 if (type_ != TYPE_CHILD) {
511 input_method_.reset(new InputMethodGtk(this));
512 input_method_->Init(GetWidget());
513 }
514
507 if (opacity_ != 255) 515 if (opacity_ != 255)
508 SetOpacity(opacity_); 516 SetOpacity(opacity_);
509 517
510 // Make sure we receive our motion events. 518 // Make sure we receive our motion events.
511 519
512 // In general we register most events on the parent of all widgets. At a 520 // In general we register most events on the parent of all widgets. At a
513 // minimum we need painting to happen on the parent (otherwise painting 521 // minimum we need painting to happen on the parent (otherwise painting
514 // doesn't work at all), and similarly we need mouse release events on the 522 // doesn't work at all), and similarly we need mouse release events on the
515 // parent as windows don't get mouse releases. 523 // parent as windows don't get mouse releases.
516 gtk_widget_add_events(window_contents_, 524 gtk_widget_add_events(window_contents_,
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 G_CALLBACK(&OnShowThunk), this); 569 G_CALLBACK(&OnShowThunk), this);
562 g_signal_connect(widget_, "map", 570 g_signal_connect(widget_, "map",
563 G_CALLBACK(&OnMapThunk), this); 571 G_CALLBACK(&OnMapThunk), this);
564 g_signal_connect(widget_, "hide", 572 g_signal_connect(widget_, "hide",
565 G_CALLBACK(&OnHideThunk), this); 573 G_CALLBACK(&OnHideThunk), this);
566 574
567 // Views/FocusManager (re)sets the focus to the root window, 575 // Views/FocusManager (re)sets the focus to the root window,
568 // so we need to connect signal handlers to the gtk window. 576 // so we need to connect signal handlers to the gtk window.
569 // See views::Views::Focus and views::FocusManager::ClearNativeFocus 577 // See views::Views::Focus and views::FocusManager::ClearNativeFocus
570 // for more details. 578 // for more details.
571 g_signal_connect(widget_, "key_press_event", 579 // Child Widget should never get keyboard focus.
572 G_CALLBACK(&OnKeyEventThunk), this); 580 if (type_ != TYPE_CHILD) {
573 g_signal_connect(widget_, "key_release_event", 581 g_signal_connect(widget_, "key_press_event",
574 G_CALLBACK(&OnKeyEventThunk), this); 582 G_CALLBACK(&OnKeyEventThunk), this);
583 g_signal_connect(widget_, "key_release_event",
584 G_CALLBACK(&OnKeyEventThunk), this);
585 }
oshima 2011/03/22 01:50:39 This may break screen locker. Can you verify?
James Su 2011/03/22 08:41:14 Hmm, according to the code, it'll break screen loc
575 586
576 // Drag and drop. 587 // Drag and drop.
577 gtk_drag_dest_set(window_contents_, static_cast<GtkDestDefaults>(0), 588 gtk_drag_dest_set(window_contents_, static_cast<GtkDestDefaults>(0),
578 NULL, 0, GDK_ACTION_COPY); 589 NULL, 0, GDK_ACTION_COPY);
579 g_signal_connect(window_contents_, "drag_motion", 590 g_signal_connect(window_contents_, "drag_motion",
580 G_CALLBACK(&OnDragMotionThunk), this); 591 G_CALLBACK(&OnDragMotionThunk), this);
581 g_signal_connect(window_contents_, "drag_data_received", 592 g_signal_connect(window_contents_, "drag_data_received",
582 G_CALLBACK(&OnDragDataReceivedThunk), this); 593 G_CALLBACK(&OnDragDataReceivedThunk), this);
583 g_signal_connect(window_contents_, "drag_drop", 594 g_signal_connect(window_contents_, "drag_drop",
584 G_CALLBACK(&OnDragDropThunk), this); 595 G_CALLBACK(&OnDragDropThunk), this);
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 if (HasNativeCapture()) 756 if (HasNativeCapture())
746 gtk_grab_remove(window_contents_); 757 gtk_grab_remove(window_contents_);
747 } 758 }
748 759
749 bool WidgetGtk::HasNativeCapture() const { 760 bool WidgetGtk::HasNativeCapture() const {
750 // TODO(beng): Should be able to use gtk_widget_has_grab() here but the 761 // TODO(beng): Should be able to use gtk_widget_has_grab() here but the
751 // trybots don't have Gtk 2.18. 762 // trybots don't have Gtk 2.18.
752 return GTK_WIDGET_HAS_GRAB(window_contents_); 763 return GTK_WIDGET_HAS_GRAB(window_contents_);
753 } 764 }
754 765
766 InputMethod* WidgetGtk::GetInputMethodNative() {
767 return input_method_.get();
768 }
769
770 void WidgetGtk::ReplaceInputMethod(InputMethod* input_method) {
771 input_method_.reset(input_method);
772 if (input_method) {
773 input_method->set_delegate(this);
774 input_method->Init(GetWidget());
775 }
776 }
777
755 gfx::Rect WidgetGtk::GetWindowScreenBounds() const { 778 gfx::Rect WidgetGtk::GetWindowScreenBounds() const {
756 // Client == Window bounds on Gtk. 779 // Client == Window bounds on Gtk.
757 return GetClientAreaScreenBounds(); 780 return GetClientAreaScreenBounds();
758 } 781 }
759 782
760 gfx::Rect WidgetGtk::GetClientAreaScreenBounds() const { 783 gfx::Rect WidgetGtk::GetClientAreaScreenBounds() const {
761 // Due to timing we can get a request for bounds after Close(). 784 // Due to timing we can get a request for bounds after Close().
762 // TODO(beng): Figure out if this is bogus. 785 // TODO(beng): Figure out if this is bogus.
763 if (!widget_) 786 if (!widget_)
764 return gfx::Rect(size_); 787 return gfx::Rect(size_);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 if (close_widget_factory_.empty()) { 863 if (close_widget_factory_.empty()) {
841 // And we delay the close just in case we're on the stack. 864 // And we delay the close just in case we're on the stack.
842 MessageLoop::current()->PostTask(FROM_HERE, 865 MessageLoop::current()->PostTask(FROM_HERE,
843 close_widget_factory_.NewRunnableMethod( 866 close_widget_factory_.NewRunnableMethod(
844 &WidgetGtk::CloseNow)); 867 &WidgetGtk::CloseNow));
845 } 868 }
846 } 869 }
847 870
848 void WidgetGtk::CloseNow() { 871 void WidgetGtk::CloseNow() {
849 if (widget_) { 872 if (widget_) {
873 input_method_.reset();
850 gtk_widget_destroy(widget_); // Triggers OnDestroy(). 874 gtk_widget_destroy(widget_); // Triggers OnDestroy().
851 } 875 }
852 } 876 }
853 877
854 void WidgetGtk::Show() { 878 void WidgetGtk::Show() {
855 if (widget_) { 879 if (widget_) {
856 gtk_widget_show(widget_); 880 gtk_widget_show(widget_);
857 if (widget_->window) 881 if (widget_->window)
858 gdk_window_raise(widget_->window); 882 gdk_window_raise(widget_->window);
859 } 883 }
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
1174 1198
1175 if (type_ == TYPE_CHILD) 1199 if (type_ == TYPE_CHILD)
1176 return false; 1200 return false;
1177 1201
1178 // The top-level window lost focus, store the focused view. 1202 // The top-level window lost focus, store the focused view.
1179 GetFocusManager()->StoreFocusedView(); 1203 GetFocusManager()->StoreFocusedView();
1180 return false; 1204 return false;
1181 } 1205 }
1182 1206
1183 gboolean WidgetGtk::OnKeyEvent(GtkWidget* widget, GdkEventKey* event) { 1207 gboolean WidgetGtk::OnKeyEvent(GtkWidget* widget, GdkEventKey* event) {
1208 // Only top-level Widget could be focused and receive keyboard events.
1209 DCHECK(GTK_IS_WINDOW(widget_));
1210
1184 KeyEvent key(reinterpret_cast<NativeEvent>(event)); 1211 KeyEvent key(reinterpret_cast<NativeEvent>(event));
1212 if (input_method_.get())
1213 input_method_->DispatchKeyEvent(key);
1214 else
1215 DispatchKeyEventPostIME(key);
1185 1216
1186 // Always reset |should_handle_menu_key_release_| unless we are handling a 1217 // Returns true to prevent GtkWindow's default key event handler.
1187 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only 1218 return true;
1188 // be activated when handling a VKEY_MENU key release event which is preceded
1189 // by an unhandled VKEY_MENU key press event. See also HandleKeyboardEvent().
1190 if (key.key_code() != ui::VKEY_MENU || event->type != GDK_KEY_RELEASE)
1191 should_handle_menu_key_release_ = false;
1192
1193 bool handled = false;
1194
1195 // Dispatch the key event to View hierarchy first.
1196 handled = GetRootView()->ProcessKeyEvent(key);
1197
1198 // Dispatch the key event to native GtkWidget hierarchy.
1199 // To prevent GtkWindow from handling the key event as a keybinding, we need
1200 // to bypass GtkWindow's default key event handler and dispatch the event
1201 // here.
1202 if (!handled && GTK_IS_WINDOW(widget))
1203 handled = gtk_window_propagate_key_event(GTK_WINDOW(widget), event);
1204
1205 // On Linux, in order to handle VKEY_MENU (Alt) accelerator key correctly and
1206 // avoid issues like: http://crbug.com/40966 and http://crbug.com/49701, we
1207 // should only send the key event to the focus manager if it's not handled by
1208 // any View or native GtkWidget.
1209 // The flow is different when the focus is in a RenderWidgetHostViewGtk, which
1210 // always consumes the key event and send it back to us later by calling
1211 // HandleKeyboardEvent() directly, if it's not handled by webkit.
1212 if (!handled)
1213 handled = HandleKeyboardEvent(event);
1214
1215 // Dispatch the key event for bindings processing.
1216 if (!handled && GTK_IS_WINDOW(widget))
1217 handled = gtk_bindings_activate_event(GTK_OBJECT(widget), event);
1218
1219 // Always return true for toplevel window to prevents GtkWindow's default key
1220 // event handler.
1221 return GTK_IS_WINDOW(widget) ? true : handled;
1222 } 1219 }
1223 1220
1224 gboolean WidgetGtk::OnQueryTooltip(GtkWidget* widget, 1221 gboolean WidgetGtk::OnQueryTooltip(GtkWidget* widget,
1225 gint x, 1222 gint x,
1226 gint y, 1223 gint y,
1227 gboolean keyboard_mode, 1224 gboolean keyboard_mode,
1228 GtkTooltip* tooltip) { 1225 GtkTooltip* tooltip) {
1229 return tooltip_manager_->ShowTooltip(x, y, keyboard_mode, tooltip); 1226 return tooltip_manager_->ShowTooltip(x, y, keyboard_mode, tooltip);
1230 } 1227 }
1231 1228
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1291 1288
1292 RootView* WidgetGtk::CreateRootView() { 1289 RootView* WidgetGtk::CreateRootView() {
1293 return new RootView(this); 1290 return new RootView(this);
1294 } 1291 }
1295 1292
1296 gfx::AcceleratedWidget WidgetGtk::GetAcceleratedWidget() { 1293 gfx::AcceleratedWidget WidgetGtk::GetAcceleratedWidget() {
1297 DCHECK(window_contents_ && window_contents_->window); 1294 DCHECK(window_contents_ && window_contents_->window);
1298 return GDK_WINDOW_XID(window_contents_->window); 1295 return GDK_WINDOW_XID(window_contents_->window);
1299 } 1296 }
1300 1297
1298 void WidgetGtk::DispatchKeyEventPostIME(const KeyEvent& key) {
1299 // Only top-level Widget could be focused and receive keyboard events.
1300 DCHECK(GTK_IS_WINDOW(widget_));
1301
1302 // Always reset |should_handle_menu_key_release_| unless we are handling a
1303 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only
1304 // be activated when handling a VKEY_MENU key release event which is preceded
1305 // by an unhandled VKEY_MENU key press event. See also HandleKeyboardEvent().
1306 if (key.key_code() != ui::VKEY_MENU || key.type() != ui::ET_KEY_RELEASED)
1307 should_handle_menu_key_release_ = false;
1308
1309 bool handled = false;
1310
1311 // Dispatch the key event to View hierarchy first.
1312 handled = GetRootView()->ProcessKeyEvent(key);
1313
1314 GdkEventKey* event = reinterpret_cast<GdkEventKey*>(key.native_event());
1315 if (key.key_code() == ui::VKEY_PROCESSKEY || handled || !event)
1316 return;
1317
1318 // Dispatch the key event to native GtkWidget hierarchy.
1319 // To prevent GtkWindow from handling the key event as a keybinding, we need
1320 // to bypass GtkWindow's default key event handler and dispatch the event
1321 // here.
1322 if (!handled && GTK_IS_WINDOW(widget_))
1323 handled = gtk_window_propagate_key_event(GTK_WINDOW(widget_), event);
1324
1325 // On Linux, in order to handle VKEY_MENU (Alt) accelerator key correctly and
1326 // avoid issues like: http://crbug.com/40966 and http://crbug.com/49701, we
1327 // should only send the key event to the focus manager if it's not handled by
1328 // any View or native GtkWidget.
1329 // The flow is different when the focus is in a RenderWidgetHostViewGtk, which
1330 // always consumes the key event and send it back to us later by calling
1331 // HandleKeyboardEvent() directly, if it's not handled by webkit.
1332 if (!handled)
1333 handled = HandleKeyboardEvent(event);
1334
1335 // Dispatch the key event for bindings processing.
1336 if (!handled && GTK_IS_WINDOW(widget_))
1337 gtk_bindings_activate_event(GTK_OBJECT(widget_), event);
1338 }
1339
1301 gboolean WidgetGtk::OnWindowPaint(GtkWidget* widget, GdkEventExpose* event) { 1340 gboolean WidgetGtk::OnWindowPaint(GtkWidget* widget, GdkEventExpose* event) {
1302 // Clear the background to be totally transparent. We don't need to 1341 // Clear the background to be totally transparent. We don't need to
1303 // paint the root view here as that is done by OnPaint. 1342 // paint the root view here as that is done by OnPaint.
1304 DCHECK(transparent_); 1343 DCHECK(transparent_);
1305 DrawTransparentBackground(widget, event); 1344 DrawTransparentBackground(widget, event);
1306 return false; 1345 return false;
1307 } 1346 }
1308 1347
1309 bool WidgetGtk::ProcessMousePressed(GdkEventButton* event) { 1348 bool WidgetGtk::ProcessMousePressed(GdkEventButton* event) {
1310 if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS) { 1349 if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS) {
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
1617 1656
1618 NativeWidget* native_widget = GetNativeWidgetForNativeView(native_view); 1657 NativeWidget* native_widget = GetNativeWidgetForNativeView(native_view);
1619 if (native_widget) 1658 if (native_widget)
1620 children->insert(native_widget); 1659 children->insert(native_widget);
1621 gtk_container_foreach(GTK_CONTAINER(native_view), 1660 gtk_container_foreach(GTK_CONTAINER(native_view),
1622 EnumerateChildWidgetsForNativeWidgets, 1661 EnumerateChildWidgetsForNativeWidgets,
1623 reinterpret_cast<gpointer>(children)); 1662 reinterpret_cast<gpointer>(children));
1624 } 1663 }
1625 1664
1626 } // namespace views 1665 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698