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. |