Chromium Code Reviews| Index: views/widget/widget_gtk.cc |
| diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc |
| index 84f5f35d20333fdb35d433dbc6b17d65e7faf02d..c6ca8a38724e28595886f3b57b63cc8bf2f0997b 100644 |
| --- a/views/widget/widget_gtk.cc |
| +++ b/views/widget/widget_gtk.cc |
| @@ -292,6 +292,9 @@ WidgetGtk::WidgetGtk(Type type) |
| } |
| WidgetGtk::~WidgetGtk() { |
| + // We need to delete the input method before calling DestroyRootView(), |
| + // because it'll set focus_manager_ to NULL. |
| + input_method_.reset(); |
| DestroyRootView(); |
| DCHECK(delete_on_destroy_ || widget_ == NULL); |
| if (type_ != TYPE_CHILD) |
| @@ -504,6 +507,14 @@ void WidgetGtk::Init(GtkWidget* parent, |
| CreateGtkWidget(parent, bounds); |
| delegate_->OnNativeWidgetCreated(); |
| + // Creates input method for toplevel widget after calling |
| + // delegate_->OnNativeWidgetCreated(), to make sure that focus manager is |
| + // already created at this point. |
| + if (type_ != TYPE_CHILD) { |
| + input_method_.reset(new InputMethodGtk(this)); |
| + input_method_->Init(GetWidget()); |
| + } |
|
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.
|
| + |
| if (opacity_ != 255) |
| SetOpacity(opacity_); |
| @@ -653,22 +664,21 @@ void WidgetGtk::ClearNativeFocus() { |
| gtk_window_set_focus(GTK_WINDOW(GetNativeView()), NULL); |
| } |
| -bool WidgetGtk::HandleKeyboardEvent(GdkEventKey* event) { |
| +bool WidgetGtk::HandleKeyboardEvent(const KeyEvent& key) { |
| if (!GetFocusManager()) |
| return false; |
| - KeyEvent key(reinterpret_cast<NativeEvent>(event)); |
| - int key_code = key.key_code(); |
| + const int key_code = key.key_code(); |
| bool handled = false; |
| // Always reset |should_handle_menu_key_release_| unless we are handling a |
| // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only |
| // be activated when handling a VKEY_MENU key release event which is preceded |
| // by an un-handled VKEY_MENU key press event. |
| - if (key_code != ui::VKEY_MENU || event->type != GDK_KEY_RELEASE) |
| + if (key_code != ui::VKEY_MENU || key.type() != ui::ET_KEY_RELEASED) |
| should_handle_menu_key_release_ = false; |
| - if (event->type == GDK_KEY_PRESS) { |
| + if (key.type() == ui::ET_KEY_PRESSED) { |
| // VKEY_MENU is triggered by key release event. |
| // FocusManager::OnKeyEvent() returns false when the key has been consumed. |
| if (key_code != ui::VKEY_MENU) |
| @@ -752,6 +762,18 @@ bool WidgetGtk::HasNativeCapture() const { |
| return GTK_WIDGET_HAS_GRAB(window_contents_); |
| } |
| +InputMethod* WidgetGtk::GetInputMethodNative() { |
| + return input_method_.get(); |
| +} |
| + |
| +void WidgetGtk::ReplaceInputMethod(InputMethod* input_method) { |
| + input_method_.reset(input_method); |
| + if (input_method) { |
| + input_method->set_delegate(this); |
| + input_method->Init(GetWidget()); |
| + } |
| +} |
| + |
| gfx::Rect WidgetGtk::GetWindowScreenBounds() const { |
| // Client == Window bounds on Gtk. |
| return GetClientAreaScreenBounds(); |
| @@ -847,6 +869,7 @@ void WidgetGtk::Close() { |
| void WidgetGtk::CloseNow() { |
| if (widget_) { |
| + input_method_.reset(); |
| gtk_widget_destroy(widget_); // Triggers OnDestroy(). |
| } |
| } |
| @@ -1183,43 +1206,13 @@ gboolean WidgetGtk::OnFocusOut(GtkWidget* widget, GdkEventFocus* event) { |
| gboolean WidgetGtk::OnKeyEvent(GtkWidget* widget, GdkEventKey* event) { |
| KeyEvent key(reinterpret_cast<NativeEvent>(event)); |
| + if (input_method_.get()) |
| + input_method_->DispatchKeyEvent(key); |
| + else |
| + DispatchKeyEventPostIME(key); |
| - // Always reset |should_handle_menu_key_release_| unless we are handling a |
| - // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only |
| - // be activated when handling a VKEY_MENU key release event which is preceded |
| - // by an unhandled VKEY_MENU key press event. See also HandleKeyboardEvent(). |
| - if (key.key_code() != ui::VKEY_MENU || event->type != GDK_KEY_RELEASE) |
| - should_handle_menu_key_release_ = false; |
| - |
| - bool handled = false; |
| - |
| - // Dispatch the key event to View hierarchy first. |
| - handled = GetRootView()->ProcessKeyEvent(key); |
| - |
| - // Dispatch the key event to native GtkWidget hierarchy. |
| - // To prevent GtkWindow from handling the key event as a keybinding, we need |
| - // to bypass GtkWindow's default key event handler and dispatch the event |
| - // here. |
| - if (!handled && GTK_IS_WINDOW(widget)) |
| - handled = gtk_window_propagate_key_event(GTK_WINDOW(widget), event); |
| - |
| - // On Linux, in order to handle VKEY_MENU (Alt) accelerator key correctly and |
| - // avoid issues like: http://crbug.com/40966 and http://crbug.com/49701, we |
| - // should only send the key event to the focus manager if it's not handled by |
| - // any View or native GtkWidget. |
| - // The flow is different when the focus is in a RenderWidgetHostViewGtk, which |
| - // always consumes the key event and send it back to us later by calling |
| - // HandleKeyboardEvent() directly, if it's not handled by webkit. |
| - if (!handled) |
| - handled = HandleKeyboardEvent(event); |
| - |
| - // Dispatch the key event for bindings processing. |
| - if (!handled && GTK_IS_WINDOW(widget)) |
| - handled = gtk_bindings_activate_event(GTK_OBJECT(widget), event); |
| - |
| - // Always return true for toplevel window to prevents GtkWindow's default key |
| - // event handler. |
| - return GTK_IS_WINDOW(widget) ? true : handled; |
| + // Returns true to prevent GtkWindow's default key event handler. |
| + return true; |
| } |
| gboolean WidgetGtk::OnQueryTooltip(GtkWidget* widget, |
| @@ -1299,6 +1292,45 @@ gfx::AcceleratedWidget WidgetGtk::GetAcceleratedWidget() { |
| return GDK_WINDOW_XID(window_contents_->window); |
| } |
| +void WidgetGtk::DispatchKeyEventPostIME(const KeyEvent& key) { |
| + // Always reset |should_handle_menu_key_release_| unless we are handling a |
| + // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only |
| + // be activated when handling a VKEY_MENU key release event which is preceded |
| + // by an unhandled VKEY_MENU key press event. See also HandleKeyboardEvent(). |
| + if (key.key_code() != ui::VKEY_MENU || key.type() != ui::ET_KEY_RELEASED) |
| + should_handle_menu_key_release_ = false; |
| + |
| + bool handled = false; |
| + |
| + // Dispatch the key event to View hierarchy first. |
| + handled = GetRootView()->ProcessKeyEvent(key); |
| + |
| + if (key.key_code() == ui::VKEY_PROCESSKEY || handled) |
| + return; |
| + |
| + // Dispatch the key event to native GtkWidget hierarchy. |
| + // To prevent GtkWindow from handling the key event as a keybinding, we need |
| + // to bypass GtkWindow's default key event handler and dispatch the event |
| + // here. |
| + GdkEventKey* event = reinterpret_cast<GdkEventKey*>(key.native_event()); |
| + if (!handled && event && GTK_IS_WINDOW(widget_)) |
| + handled = gtk_window_propagate_key_event(GTK_WINDOW(widget_), event); |
| + |
| + // On Linux, in order to handle VKEY_MENU (Alt) accelerator key correctly and |
| + // avoid issues like: http://crbug.com/40966 and http://crbug.com/49701, we |
| + // should only send the key event to the focus manager if it's not handled by |
| + // any View or native GtkWidget. |
| + // The flow is different when the focus is in a RenderWidgetHostViewGtk, which |
| + // always consumes the key event and send it back to us later by calling |
| + // HandleKeyboardEvent() directly, if it's not handled by webkit. |
| + if (!handled) |
| + handled = HandleKeyboardEvent(key); |
| + |
| + // Dispatch the key event for bindings processing. |
| + if (!handled && event && GTK_IS_WINDOW(widget_)) |
| + gtk_bindings_activate_event(GTK_OBJECT(widget_), event); |
| +} |
| + |
| gboolean WidgetGtk::OnWindowPaint(GtkWidget* widget, GdkEventExpose* event) { |
| // Clear the background to be totally transparent. We don't need to |
| // paint the root view here as that is done by OnPaint. |