| Index: views/widget/widget_gtk.cc
|
| diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc
|
| index 9f5354319156b6d878acd0392b87c17f8be69dae..00824f503892ad00c94a3b65f58fd2b11304cb44 100644
|
| --- a/views/widget/widget_gtk.cc
|
| +++ b/views/widget/widget_gtk.cc
|
| @@ -25,6 +25,7 @@
|
| #include "ui/gfx/canvas_skia_paint.h"
|
| #include "ui/gfx/path.h"
|
| #include "views/views_delegate.h"
|
| +#include "views/controls/textfield/native_textfield_views.h"
|
| #include "views/focus/view_storage.h"
|
| #include "views/widget/drop_target_gtk.h"
|
| #include "views/widget/gtk_views_fixed.h"
|
| @@ -294,6 +295,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)
|
| @@ -516,6 +520,20 @@ 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.
|
| + // TODO(suzhe): Always enable input method when we start to use
|
| + // RenderWidgetHostViewViews in normal ChromeOS.
|
| +#if !defined(TOUCH_UI)
|
| + if (type_ != TYPE_CHILD && NativeTextfieldViews::IsTextfieldViewsEnabled()) {
|
| +#else
|
| + if (type_ != TYPE_CHILD) {
|
| +#endif
|
| + input_method_.reset(new InputMethodGtk(this));
|
| + input_method_->Init(GetWidget());
|
| + }
|
| +
|
| if (opacity_ != 255)
|
| SetOpacity(opacity_);
|
|
|
| @@ -665,22 +683,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)
|
| @@ -768,6 +785,18 @@ bool WidgetGtk::HasMouseCapture() 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();
|
| @@ -858,6 +887,7 @@ void WidgetGtk::Close() {
|
|
|
| void WidgetGtk::CloseNow() {
|
| if (widget_) {
|
| + input_method_.reset();
|
| gtk_widget_destroy(widget_); // Triggers OnDestroy().
|
| }
|
| }
|
| @@ -1195,6 +1225,10 @@ gboolean WidgetGtk::OnFocusIn(GtkWidget* widget, GdkEventFocus* event) {
|
| if (type_ == TYPE_CHILD)
|
| return false;
|
|
|
| + // Only top-level Widget should have an InputMethod instance.
|
| + if (input_method_.get())
|
| + input_method_->OnFocus();
|
| +
|
| // See description of got_initial_focus_in_ for details on this.
|
| if (!got_initial_focus_in_) {
|
| got_initial_focus_in_ = true;
|
| @@ -1213,6 +1247,10 @@ gboolean WidgetGtk::OnFocusOut(GtkWidget* widget, GdkEventFocus* event) {
|
| if (type_ == TYPE_CHILD)
|
| return false;
|
|
|
| + // Only top-level Widget should have an InputMethod instance.
|
| + if (input_method_.get())
|
| + input_method_->OnBlur();
|
| +
|
| // The top-level window lost focus, store the focused view.
|
| GetFocusManager()->StoreFocusedView();
|
| return false;
|
| @@ -1220,43 +1258,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,
|
| @@ -1334,6 +1342,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.
|
|
|