Index: views/widget/widget_gtk.cc |
diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc |
index 5f470c53d751aabe3a816fe52b23fd5d239ca542..4081a48401656e20d6b67f0785d91e497357fd69 100644 |
--- a/views/widget/widget_gtk.cc |
+++ b/views/widget/widget_gtk.cc |
@@ -504,6 +504,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()); |
+ } |
+ |
if (opacity_ != 255) |
SetOpacity(opacity_); |
@@ -568,10 +576,13 @@ void WidgetGtk::Init(GtkWidget* parent, |
// so we need to connect signal handlers to the gtk window. |
// See views::Views::Focus and views::FocusManager::ClearNativeFocus |
// for more details. |
- g_signal_connect(widget_, "key_press_event", |
- G_CALLBACK(&OnKeyEventThunk), this); |
- g_signal_connect(widget_, "key_release_event", |
- G_CALLBACK(&OnKeyEventThunk), this); |
+ // Child Widget should never get keyboard focus. |
+ if (type_ != TYPE_CHILD) { |
+ g_signal_connect(widget_, "key_press_event", |
+ G_CALLBACK(&OnKeyEventThunk), this); |
+ g_signal_connect(widget_, "key_release_event", |
+ G_CALLBACK(&OnKeyEventThunk), this); |
+ } |
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
|
// Drag and drop. |
gtk_drag_dest_set(window_contents_, static_cast<GtkDestDefaults>(0), |
@@ -752,6 +763,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 +870,7 @@ void WidgetGtk::Close() { |
void WidgetGtk::CloseNow() { |
if (widget_) { |
+ input_method_.reset(); |
gtk_widget_destroy(widget_); // Triggers OnDestroy(). |
} |
} |
@@ -1181,44 +1205,17 @@ gboolean WidgetGtk::OnFocusOut(GtkWidget* widget, GdkEventFocus* event) { |
} |
gboolean WidgetGtk::OnKeyEvent(GtkWidget* widget, GdkEventKey* event) { |
- KeyEvent key(reinterpret_cast<NativeEvent>(event)); |
- |
- // 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); |
+ // Only top-level Widget could be focused and receive keyboard events. |
+ DCHECK(GTK_IS_WINDOW(widget_)); |
- // Dispatch the key event for bindings processing. |
- if (!handled && GTK_IS_WINDOW(widget)) |
- handled = gtk_bindings_activate_event(GTK_OBJECT(widget), event); |
+ KeyEvent key(reinterpret_cast<NativeEvent>(event)); |
+ if (input_method_.get()) |
+ input_method_->DispatchKeyEvent(key); |
+ else |
+ DispatchKeyEventPostIME(key); |
- // 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, |
@@ -1298,6 +1295,48 @@ gfx::AcceleratedWidget WidgetGtk::GetAcceleratedWidget() { |
return GDK_WINDOW_XID(window_contents_->window); |
} |
+void WidgetGtk::DispatchKeyEventPostIME(const KeyEvent& key) { |
+ // Only top-level Widget could be focused and receive keyboard events. |
+ DCHECK(GTK_IS_WINDOW(widget_)); |
+ |
+ // 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); |
+ |
+ GdkEventKey* event = reinterpret_cast<GdkEventKey*>(key.native_event()); |
+ if (key.key_code() == ui::VKEY_PROCESSKEY || handled || !event) |
+ 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. |
+ 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_)) |
+ 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. |