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

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: Rebase. 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 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 static bool installed_message_loop_observer = false; 285 static bool installed_message_loop_observer = false;
286 if (!installed_message_loop_observer) { 286 if (!installed_message_loop_observer) {
287 installed_message_loop_observer = true; 287 installed_message_loop_observer = true;
288 MessageLoopForUI* loop = MessageLoopForUI::current(); 288 MessageLoopForUI* loop = MessageLoopForUI::current();
289 if (loop) 289 if (loop)
290 loop->AddObserver(DropObserver::GetInstance()); 290 loop->AddObserver(DropObserver::GetInstance());
291 } 291 }
292 } 292 }
293 293
294 WidgetGtk::~WidgetGtk() { 294 WidgetGtk::~WidgetGtk() {
295 // We need to delete the input method before calling DestroyRootView(),
296 // because it'll set focus_manager_ to NULL.
297 input_method_.reset();
295 DestroyRootView(); 298 DestroyRootView();
296 DCHECK(delete_on_destroy_ || widget_ == NULL); 299 DCHECK(delete_on_destroy_ || widget_ == NULL);
297 if (type_ != TYPE_CHILD) 300 if (type_ != TYPE_CHILD)
298 ActiveWindowWatcherX::RemoveObserver(this); 301 ActiveWindowWatcherX::RemoveObserver(this);
299 } 302 }
300 303
301 void WidgetGtk::SetCreateParams(const CreateParams& params) { 304 void WidgetGtk::SetCreateParams(const CreateParams& params) {
302 // Set non-style attributes. 305 // Set non-style attributes.
303 set_delete_on_destroy(params.delete_on_destroy); 306 set_delete_on_destroy(params.delete_on_destroy);
304 307
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 void WidgetGtk::Init(GtkWidget* parent, 500 void WidgetGtk::Init(GtkWidget* parent,
498 const gfx::Rect& bounds) { 501 const gfx::Rect& bounds) {
499 Widget::Init(parent, bounds); 502 Widget::Init(parent, bounds);
500 if (type_ != TYPE_CHILD) 503 if (type_ != TYPE_CHILD)
501 ActiveWindowWatcherX::AddObserver(this); 504 ActiveWindowWatcherX::AddObserver(this);
502 505
503 // Make container here. 506 // Make container here.
504 CreateGtkWidget(parent, bounds); 507 CreateGtkWidget(parent, bounds);
505 delegate_->OnNativeWidgetCreated(); 508 delegate_->OnNativeWidgetCreated();
506 509
510 // Creates input method for toplevel widget after calling
511 // delegate_->OnNativeWidgetCreated(), to make sure that focus manager is
512 // already created at this point.
513 if (type_ != TYPE_CHILD) {
514 input_method_.reset(new InputMethodGtk(this));
515 input_method_->Init(GetWidget());
516 }
oshima 2011/03/24 22:58:47 Looks like we create InputMethodGtk for regular ch
James Su 2011/03/25 05:57:21 Yes. I'll disable this piece of code for ChromeOS.
517
507 if (opacity_ != 255) 518 if (opacity_ != 255)
508 SetOpacity(opacity_); 519 SetOpacity(opacity_);
509 520
510 // Make sure we receive our motion events. 521 // Make sure we receive our motion events.
511 522
512 // In general we register most events on the parent of all widgets. At a 523 // 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 524 // 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 525 // doesn't work at all), and similarly we need mouse release events on the
515 // parent as windows don't get mouse releases. 526 // parent as windows don't get mouse releases.
516 gtk_widget_add_events(window_contents_, 527 gtk_widget_add_events(window_contents_,
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 657
647 void WidgetGtk::ClearNativeFocus() { 658 void WidgetGtk::ClearNativeFocus() {
648 DCHECK(type_ != TYPE_CHILD); 659 DCHECK(type_ != TYPE_CHILD);
649 if (!GetNativeView()) { 660 if (!GetNativeView()) {
650 NOTREACHED(); 661 NOTREACHED();
651 return; 662 return;
652 } 663 }
653 gtk_window_set_focus(GTK_WINDOW(GetNativeView()), NULL); 664 gtk_window_set_focus(GTK_WINDOW(GetNativeView()), NULL);
654 } 665 }
655 666
656 bool WidgetGtk::HandleKeyboardEvent(GdkEventKey* event) { 667 bool WidgetGtk::HandleKeyboardEvent(const KeyEvent& key) {
657 if (!GetFocusManager()) 668 if (!GetFocusManager())
658 return false; 669 return false;
659 670
660 KeyEvent key(reinterpret_cast<NativeEvent>(event)); 671 const int key_code = key.key_code();
661 int key_code = key.key_code();
662 bool handled = false; 672 bool handled = false;
663 673
664 // Always reset |should_handle_menu_key_release_| unless we are handling a 674 // Always reset |should_handle_menu_key_release_| unless we are handling a
665 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only 675 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only
666 // be activated when handling a VKEY_MENU key release event which is preceded 676 // be activated when handling a VKEY_MENU key release event which is preceded
667 // by an un-handled VKEY_MENU key press event. 677 // by an un-handled VKEY_MENU key press event.
668 if (key_code != ui::VKEY_MENU || event->type != GDK_KEY_RELEASE) 678 if (key_code != ui::VKEY_MENU || key.type() != ui::ET_KEY_RELEASED)
669 should_handle_menu_key_release_ = false; 679 should_handle_menu_key_release_ = false;
670 680
671 if (event->type == GDK_KEY_PRESS) { 681 if (key.type() == ui::ET_KEY_PRESSED) {
672 // VKEY_MENU is triggered by key release event. 682 // VKEY_MENU is triggered by key release event.
673 // FocusManager::OnKeyEvent() returns false when the key has been consumed. 683 // FocusManager::OnKeyEvent() returns false when the key has been consumed.
674 if (key_code != ui::VKEY_MENU) 684 if (key_code != ui::VKEY_MENU)
675 handled = !GetFocusManager()->OnKeyEvent(key); 685 handled = !GetFocusManager()->OnKeyEvent(key);
676 else 686 else
677 should_handle_menu_key_release_ = true; 687 should_handle_menu_key_release_ = true;
678 } else if (key_code == ui::VKEY_MENU && should_handle_menu_key_release_ && 688 } else if (key_code == ui::VKEY_MENU && should_handle_menu_key_release_ &&
679 (key.flags() & ~ui::EF_ALT_DOWN) == 0) { 689 (key.flags() & ~ui::EF_ALT_DOWN) == 0) {
680 // Trigger VKEY_MENU when only this key is pressed and released, and both 690 // Trigger VKEY_MENU when only this key is pressed and released, and both
681 // press and release events are not handled by others. 691 // press and release events are not handled by others.
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 if (HasNativeCapture()) 755 if (HasNativeCapture())
746 gtk_grab_remove(window_contents_); 756 gtk_grab_remove(window_contents_);
747 } 757 }
748 758
749 bool WidgetGtk::HasNativeCapture() const { 759 bool WidgetGtk::HasNativeCapture() const {
750 // TODO(beng): Should be able to use gtk_widget_has_grab() here but the 760 // TODO(beng): Should be able to use gtk_widget_has_grab() here but the
751 // trybots don't have Gtk 2.18. 761 // trybots don't have Gtk 2.18.
752 return GTK_WIDGET_HAS_GRAB(window_contents_); 762 return GTK_WIDGET_HAS_GRAB(window_contents_);
753 } 763 }
754 764
765 InputMethod* WidgetGtk::GetInputMethodNative() {
766 return input_method_.get();
767 }
768
769 void WidgetGtk::ReplaceInputMethod(InputMethod* input_method) {
770 input_method_.reset(input_method);
771 if (input_method) {
772 input_method->set_delegate(this);
773 input_method->Init(GetWidget());
774 }
775 }
776
755 gfx::Rect WidgetGtk::GetWindowScreenBounds() const { 777 gfx::Rect WidgetGtk::GetWindowScreenBounds() const {
756 // Client == Window bounds on Gtk. 778 // Client == Window bounds on Gtk.
757 return GetClientAreaScreenBounds(); 779 return GetClientAreaScreenBounds();
758 } 780 }
759 781
760 gfx::Rect WidgetGtk::GetClientAreaScreenBounds() const { 782 gfx::Rect WidgetGtk::GetClientAreaScreenBounds() const {
761 // Due to timing we can get a request for bounds after Close(). 783 // Due to timing we can get a request for bounds after Close().
762 // TODO(beng): Figure out if this is bogus. 784 // TODO(beng): Figure out if this is bogus.
763 if (!widget_) 785 if (!widget_)
764 return gfx::Rect(size_); 786 return gfx::Rect(size_);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 if (close_widget_factory_.empty()) { 862 if (close_widget_factory_.empty()) {
841 // And we delay the close just in case we're on the stack. 863 // And we delay the close just in case we're on the stack.
842 MessageLoop::current()->PostTask(FROM_HERE, 864 MessageLoop::current()->PostTask(FROM_HERE,
843 close_widget_factory_.NewRunnableMethod( 865 close_widget_factory_.NewRunnableMethod(
844 &WidgetGtk::CloseNow)); 866 &WidgetGtk::CloseNow));
845 } 867 }
846 } 868 }
847 869
848 void WidgetGtk::CloseNow() { 870 void WidgetGtk::CloseNow() {
849 if (widget_) { 871 if (widget_) {
872 input_method_.reset();
850 gtk_widget_destroy(widget_); // Triggers OnDestroy(). 873 gtk_widget_destroy(widget_); // Triggers OnDestroy().
851 } 874 }
852 } 875 }
853 876
854 void WidgetGtk::Show() { 877 void WidgetGtk::Show() {
855 if (widget_) { 878 if (widget_) {
856 gtk_widget_show(widget_); 879 gtk_widget_show(widget_);
857 if (widget_->window) 880 if (widget_->window)
858 gdk_window_raise(widget_->window); 881 gdk_window_raise(widget_->window);
859 } 882 }
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
1176 if (type_ == TYPE_CHILD) 1199 if (type_ == TYPE_CHILD)
1177 return false; 1200 return false;
1178 1201
1179 // The top-level window lost focus, store the focused view. 1202 // The top-level window lost focus, store the focused view.
1180 GetFocusManager()->StoreFocusedView(); 1203 GetFocusManager()->StoreFocusedView();
1181 return false; 1204 return false;
1182 } 1205 }
1183 1206
1184 gboolean WidgetGtk::OnKeyEvent(GtkWidget* widget, GdkEventKey* event) { 1207 gboolean WidgetGtk::OnKeyEvent(GtkWidget* widget, GdkEventKey* event) {
1185 KeyEvent key(reinterpret_cast<NativeEvent>(event)); 1208 KeyEvent key(reinterpret_cast<NativeEvent>(event));
1209 if (input_method_.get())
1210 input_method_->DispatchKeyEvent(key);
1211 else
1212 DispatchKeyEventPostIME(key);
1186 1213
1187 // Always reset |should_handle_menu_key_release_| unless we are handling a 1214 // Returns true to prevent GtkWindow's default key event handler.
1188 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only 1215 return true;
1189 // be activated when handling a VKEY_MENU key release event which is preceded
1190 // by an unhandled VKEY_MENU key press event. See also HandleKeyboardEvent().
1191 if (key.key_code() != ui::VKEY_MENU || event->type != GDK_KEY_RELEASE)
1192 should_handle_menu_key_release_ = false;
1193
1194 bool handled = false;
1195
1196 // Dispatch the key event to View hierarchy first.
1197 handled = GetRootView()->ProcessKeyEvent(key);
1198
1199 // Dispatch the key event to native GtkWidget hierarchy.
1200 // To prevent GtkWindow from handling the key event as a keybinding, we need
1201 // to bypass GtkWindow's default key event handler and dispatch the event
1202 // here.
1203 if (!handled && GTK_IS_WINDOW(widget))
1204 handled = gtk_window_propagate_key_event(GTK_WINDOW(widget), event);
1205
1206 // On Linux, in order to handle VKEY_MENU (Alt) accelerator key correctly and
1207 // avoid issues like: http://crbug.com/40966 and http://crbug.com/49701, we
1208 // should only send the key event to the focus manager if it's not handled by
1209 // any View or native GtkWidget.
1210 // The flow is different when the focus is in a RenderWidgetHostViewGtk, which
1211 // always consumes the key event and send it back to us later by calling
1212 // HandleKeyboardEvent() directly, if it's not handled by webkit.
1213 if (!handled)
1214 handled = HandleKeyboardEvent(event);
1215
1216 // Dispatch the key event for bindings processing.
1217 if (!handled && GTK_IS_WINDOW(widget))
1218 handled = gtk_bindings_activate_event(GTK_OBJECT(widget), event);
1219
1220 // Always return true for toplevel window to prevents GtkWindow's default key
1221 // event handler.
1222 return GTK_IS_WINDOW(widget) ? true : handled;
1223 } 1216 }
1224 1217
1225 gboolean WidgetGtk::OnQueryTooltip(GtkWidget* widget, 1218 gboolean WidgetGtk::OnQueryTooltip(GtkWidget* widget,
1226 gint x, 1219 gint x,
1227 gint y, 1220 gint y,
1228 gboolean keyboard_mode, 1221 gboolean keyboard_mode,
1229 GtkTooltip* tooltip) { 1222 GtkTooltip* tooltip) {
1230 return tooltip_manager_->ShowTooltip(x, y, keyboard_mode, tooltip); 1223 return tooltip_manager_->ShowTooltip(x, y, keyboard_mode, tooltip);
1231 } 1224 }
1232 1225
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1292 1285
1293 RootView* WidgetGtk::CreateRootView() { 1286 RootView* WidgetGtk::CreateRootView() {
1294 return new RootView(this); 1287 return new RootView(this);
1295 } 1288 }
1296 1289
1297 gfx::AcceleratedWidget WidgetGtk::GetAcceleratedWidget() { 1290 gfx::AcceleratedWidget WidgetGtk::GetAcceleratedWidget() {
1298 DCHECK(window_contents_ && window_contents_->window); 1291 DCHECK(window_contents_ && window_contents_->window);
1299 return GDK_WINDOW_XID(window_contents_->window); 1292 return GDK_WINDOW_XID(window_contents_->window);
1300 } 1293 }
1301 1294
1295 void WidgetGtk::DispatchKeyEventPostIME(const KeyEvent& key) {
1296 // Always reset |should_handle_menu_key_release_| unless we are handling a
1297 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only
1298 // be activated when handling a VKEY_MENU key release event which is preceded
1299 // by an unhandled VKEY_MENU key press event. See also HandleKeyboardEvent().
1300 if (key.key_code() != ui::VKEY_MENU || key.type() != ui::ET_KEY_RELEASED)
1301 should_handle_menu_key_release_ = false;
1302
1303 bool handled = false;
1304
1305 // Dispatch the key event to View hierarchy first.
1306 handled = GetRootView()->ProcessKeyEvent(key);
1307
1308 if (key.key_code() == ui::VKEY_PROCESSKEY || handled)
1309 return;
1310
1311 // Dispatch the key event to native GtkWidget hierarchy.
1312 // To prevent GtkWindow from handling the key event as a keybinding, we need
1313 // to bypass GtkWindow's default key event handler and dispatch the event
1314 // here.
1315 GdkEventKey* event = reinterpret_cast<GdkEventKey*>(key.native_event());
1316 if (!handled && event && GTK_IS_WINDOW(widget_))
1317 handled = gtk_window_propagate_key_event(GTK_WINDOW(widget_), event);
1318
1319 // On Linux, in order to handle VKEY_MENU (Alt) accelerator key correctly and
1320 // avoid issues like: http://crbug.com/40966 and http://crbug.com/49701, we
1321 // should only send the key event to the focus manager if it's not handled by
1322 // any View or native GtkWidget.
1323 // The flow is different when the focus is in a RenderWidgetHostViewGtk, which
1324 // always consumes the key event and send it back to us later by calling
1325 // HandleKeyboardEvent() directly, if it's not handled by webkit.
1326 if (!handled)
1327 handled = HandleKeyboardEvent(key);
1328
1329 // Dispatch the key event for bindings processing.
1330 if (!handled && event && GTK_IS_WINDOW(widget_))
1331 gtk_bindings_activate_event(GTK_OBJECT(widget_), event);
1332 }
1333
1302 gboolean WidgetGtk::OnWindowPaint(GtkWidget* widget, GdkEventExpose* event) { 1334 gboolean WidgetGtk::OnWindowPaint(GtkWidget* widget, GdkEventExpose* event) {
1303 // Clear the background to be totally transparent. We don't need to 1335 // Clear the background to be totally transparent. We don't need to
1304 // paint the root view here as that is done by OnPaint. 1336 // paint the root view here as that is done by OnPaint.
1305 DCHECK(transparent_); 1337 DCHECK(transparent_);
1306 DrawTransparentBackground(widget, event); 1338 DrawTransparentBackground(widget, event);
1307 return false; 1339 return false;
1308 } 1340 }
1309 1341
1310 bool WidgetGtk::ProcessMousePressed(GdkEventButton* event) { 1342 bool WidgetGtk::ProcessMousePressed(GdkEventButton* event) {
1311 if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS) { 1343 if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS) {
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
1644 1676
1645 NativeWidget* native_widget = GetNativeWidgetForNativeView(native_view); 1677 NativeWidget* native_widget = GetNativeWidgetForNativeView(native_view);
1646 if (native_widget) 1678 if (native_widget)
1647 children->insert(native_widget); 1679 children->insert(native_widget);
1648 gtk_container_foreach(GTK_CONTAINER(native_view), 1680 gtk_container_foreach(GTK_CONTAINER(native_view),
1649 EnumerateChildWidgetsForNativeWidgets, 1681 EnumerateChildWidgetsForNativeWidgets,
1650 reinterpret_cast<gpointer>(children)); 1682 reinterpret_cast<gpointer>(children));
1651 } 1683 }
1652 1684
1653 } // namespace views 1685 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698