diff options
author | oshima@google.com <oshima@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-23 05:01:35 +0000 |
---|---|---|
committer | oshima@google.com <oshima@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-23 05:01:35 +0000 |
commit | 2bd4b68de2e193aca51caa09edddb8fd0cd3b9cd (patch) | |
tree | 46164cc11e0396a66286f29ed4cb99e044583f19 /views | |
parent | d776fbf0f45a3d435449740b1c8973b8866231fa (diff) | |
download | chromium_src-2bd4b68de2e193aca51caa09edddb8fd0cd3b9cd.zip chromium_src-2bd4b68de2e193aca51caa09edddb8fd0cd3b9cd.tar.gz chromium_src-2bd4b68de2e193aca51caa09edddb8fd0cd3b9cd.tar.bz2 |
Move input_method to widget
BUG=none
TEST=none. no new functionality. all tests should pass.
Review URL: http://codereview.chromium.org/7371007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@97819 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
24 files changed, 359 insertions, 233 deletions
diff --git a/views/controls/combobox/native_combobox_views_unittest.cc b/views/controls/combobox/native_combobox_views_unittest.cc index 4ebf021..979e0dd 100644 --- a/views/controls/combobox/native_combobox_views_unittest.cc +++ b/views/controls/combobox/native_combobox_views_unittest.cc @@ -114,7 +114,7 @@ class NativeComboboxViewsTest : public ViewsTestBase { ASSERT_TRUE(combobox_view_); input_method_ = new MockInputMethod(); - widget_->native_widget_private()->ReplaceInputMethod(input_method_); + widget_->ReplaceInputMethod(input_method_); // Assumes the Widget is always focused. input_method_->OnFocus(); @@ -164,4 +164,3 @@ TEST_F(NativeComboboxViewsTest, KeyTest) { } } // namespace views - diff --git a/views/controls/tabbed_pane/native_tabbed_pane_gtk.cc b/views/controls/tabbed_pane/native_tabbed_pane_gtk.cc index 7eb01c2..8ffe306 100644 --- a/views/controls/tabbed_pane/native_tabbed_pane_gtk.cc +++ b/views/controls/tabbed_pane/native_tabbed_pane_gtk.cc @@ -169,7 +169,6 @@ void NativeTabbedPaneGtk::DoAddTabAtIndex(int index, } GtkWidget* page = page_container->GetNativeView(); - // increment ref count not to delete on remove below g_object_ref(page); // detach parent from the page so that we can add it to notebook diff --git a/views/controls/textfield/native_textfield_views_unittest.cc b/views/controls/textfield/native_textfield_views_unittest.cc index f6c4e59..40607b0 100644 --- a/views/controls/textfield/native_textfield_views_unittest.cc +++ b/views/controls/textfield/native_textfield_views_unittest.cc @@ -181,7 +181,7 @@ class NativeTextfieldViewsTest : public ViewsTestBase, model_->ClearEditHistory(); input_method_ = new MockInputMethod(); - widget_->native_widget_private()->ReplaceInputMethod(input_method_); + widget_->ReplaceInputMethod(input_method_); // Assumes the Widget is always focused. input_method_->OnFocus(); diff --git a/views/focus/focus_manager_factory.cc b/views/focus/focus_manager_factory.cc new file mode 100644 index 0000000..457f60b --- /dev/null +++ b/views/focus/focus_manager_factory.cc @@ -0,0 +1,55 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "views/focus/focus_manager_factory.h" + +#include "base/compiler_specific.h" +#include "views/focus/focus_manager.h" + +namespace { + +using views::FocusManager; + +class DefaultFocusManagerFactory : public views::FocusManagerFactory { + public: + DefaultFocusManagerFactory() : views::FocusManagerFactory() {} + virtual ~DefaultFocusManagerFactory() {} + + protected: + virtual FocusManager* CreateFocusManager(views::Widget* widget) OVERRIDE { + return new FocusManager(widget); + } + + private: + DISALLOW_COPY_AND_ASSIGN(DefaultFocusManagerFactory); +}; + +views::FocusManagerFactory* focus_manager_factory = NULL; + +} // namespace + +namespace views { + +FocusManagerFactory::FocusManagerFactory() { +} + +FocusManagerFactory::~FocusManagerFactory() { +} + +// static +FocusManager* FocusManagerFactory::Create(Widget* widget) { + if (!focus_manager_factory) + focus_manager_factory = new DefaultFocusManagerFactory(); + return focus_manager_factory->CreateFocusManager(widget); +} + +// static +void FocusManagerFactory::Install(FocusManagerFactory* f) { + if (f == focus_manager_factory) + return; + delete focus_manager_factory; + focus_manager_factory = f ? f : new DefaultFocusManagerFactory(); +} + +} // namespace views diff --git a/views/focus/focus_manager_factory.h b/views/focus/focus_manager_factory.h new file mode 100644 index 0000000..136b254 --- /dev/null +++ b/views/focus/focus_manager_factory.h @@ -0,0 +1,41 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef VIEWS_FOCUS_FOCUS_MANAGER_FACTORY_H_ +#define VIEWS_FOCUS_FOCUS_MANAGER_FACTORY_H_ +#pragma once + +#include "base/basictypes.h" +#include "views/views_export.h" + +namespace views { + +class FocusManager; +class Widget; + +// A factory to create FocusManager. This is used in unit tests +// to inject a custom factory. +class VIEWS_EXPORT FocusManagerFactory { + public: + // Create a FocusManager for the given |widget| using installe Factory. + static FocusManager* Create(Widget* widget); + + // Installs FocusManagerFactory. If |factory| is NULL, it resets + // to the default factory which creates plain FocusManager. + static void Install(FocusManagerFactory* factory); + + protected: + FocusManagerFactory(); + virtual ~FocusManagerFactory(); + + // Create a FocusManager for the given |widget|. + virtual FocusManager* CreateFocusManager(Widget* widget) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(FocusManagerFactory); +}; + +} // namespace views + +#endif // VIEWS_FOCUS_FOCUS_MANAGER_FACTORY_H_ diff --git a/views/focus/focus_manager_unittest.cc b/views/focus/focus_manager_unittest.cc index e6895e8..f31893b 100644 --- a/views/focus/focus_manager_unittest.cc +++ b/views/focus/focus_manager_unittest.cc @@ -26,6 +26,7 @@ #include "views/controls/tabbed_pane/tabbed_pane.h" #include "views/controls/textfield/textfield.h" #include "views/focus/accelerator_handler.h" +#include "views/focus/focus_manager_factory.h" #include "views/widget/root_view.h" #include "views/widget/widget.h" #include "views/widget/widget_delegate.h" @@ -94,7 +95,8 @@ const int kHelpLinkID = count++; const int kThumbnailContainerID = count++; // 45 const int kThumbnailStarID = count++; const int kThumbnailSuperStarID = count++; -} + +} // namespace namespace views { @@ -136,7 +138,7 @@ class FocusManagerTest : public testing::Test, public WidgetDelegate { void FocusNativeView(gfx::NativeView native_view) { #if defined(OS_WIN) - ::SendMessage(native_view, WM_SETFOCUS, NULL, NULL); + ::SendMessage(native_view, WM_SETFOCUS, NULL, NULL); #else gint return_val; GdkEventFocus event; @@ -290,6 +292,8 @@ class BorderView : public NativeViewHost { params.parent = parent->GetWidget()->GetNativeView(); #elif defined(TOOLKIT_USES_GTK) params.parent = native_view(); +#else + NOTREACHED(); #endif widget_->Init(params); widget_->SetFocusTraversableParentView(this); @@ -372,7 +376,8 @@ class FocusTraversalTest : public FocusManagerTest { View* view = GetContentsView()->GetViewByID(id); if (view) return view; - view = style_tab_->GetSelectedTab()->GetViewByID(id); + if (style_tab_) + view = style_tab_->GetSelectedTab()->GetViewByID(id); if (view) return view; view = search_border_view_->GetContentsRootView()->GetViewByID(id); @@ -914,47 +919,32 @@ class TestTabbedPane : public TabbedPane { } }; +#if !defined(TOUCH_UI) +// TODO(oshima): replace TOUCH_UI with PURE_VIEWS + // Tests that NativeControls do set the focus View appropriately on the // FocusManager. TEST_F(FocusManagerTest, FAILS_FocusNativeControls) { - TestNativeButton* button = new TestNativeButton(L"Press me"); - TestCheckbox* checkbox = new TestCheckbox(L"Checkbox"); - TestRadioButton* radio_button = new TestRadioButton(L"RadioButton"); TestTextfield* textfield = new TestTextfield(); - TestCombobox* combobox = new TestCombobox(); TestTabbedPane* tabbed_pane = new TestTabbedPane(); - TestNativeButton* tab_button = new TestNativeButton(L"tab button"); + TestTextfield* textfield2 = new TestTextfield(); - content_view_->AddChildView(button); - content_view_->AddChildView(checkbox); - content_view_->AddChildView(radio_button); content_view_->AddChildView(textfield); - content_view_->AddChildView(combobox); content_view_->AddChildView(tabbed_pane); - tabbed_pane->AddTab(L"Awesome tab", tab_button); - // Simulate the native view getting the native focus (such as by user click). - FocusNativeView(button->TestGetNativeControlView()); - EXPECT_EQ(button, GetFocusManager()->GetFocusedView()); - - FocusNativeView(checkbox->TestGetNativeControlView()); - EXPECT_EQ(checkbox, GetFocusManager()->GetFocusedView()); - - FocusNativeView(radio_button->TestGetNativeControlView()); - EXPECT_EQ(radio_button, GetFocusManager()->GetFocusedView()); + tabbed_pane->AddTab(L"Awesome textfield", textfield2); + // Simulate the native view getting the native focus (such as by user click). FocusNativeView(textfield->TestGetNativeControlView()); EXPECT_EQ(textfield, GetFocusManager()->GetFocusedView()); - FocusNativeView(combobox->TestGetNativeControlView()); - EXPECT_EQ(combobox, GetFocusManager()->GetFocusedView()); - FocusNativeView(tabbed_pane->TestGetNativeControlView()); EXPECT_EQ(tabbed_pane, GetFocusManager()->GetFocusedView()); - FocusNativeView(tab_button->TestGetNativeControlView()); - EXPECT_EQ(tab_button, GetFocusManager()->GetFocusedView()); + FocusNativeView(textfield2->TestGetNativeControlView()); + EXPECT_EQ(textfield2, GetFocusManager()->GetFocusedView()); } +#endif // On linux, we don't store/restore focused view because gtk handles // this (and pure views will be the same). @@ -1038,6 +1028,10 @@ TEST_F(FocusManagerTest, FocusStoreRestore) { } #endif +#if !defined(TOUCH_UI) +// TODO(oshima): There is no tabbed pane in pure views. Replace it +// with different implementation. + TEST_F(FocusManagerTest, ContainsView) { View* view = new View(); scoped_ptr<View> detached_view(new View()); @@ -1058,6 +1052,7 @@ TEST_F(FocusManagerTest, ContainsView) { EXPECT_TRUE(GetFocusManager()->ContainsView(tab_button)); EXPECT_FALSE(GetFocusManager()->ContainsView(detached_view.get())); } +#endif TEST_F(FocusTraversalTest, NormalTraversal) { const int kTraversalIDs[] = { kTopCheckBoxID, kAppleTextfieldID, @@ -1597,6 +1592,7 @@ TEST_F(FocusManagerTest, CreationForNativeRoot) { params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; params.parent = hwnd; params.bounds = gfx::Rect(0, 0, 100, 100); + params.top_level = true; // This is top level in views hierarchy. widget1->Init(params); // Get the focus manager directly from the first window. Should exist @@ -1607,6 +1603,7 @@ TEST_F(FocusManagerTest, CreationForNativeRoot) { // Create another view window parented to the first view window. scoped_ptr<Widget> widget2(new Widget); params.parent = widget1->GetNativeView(); + params.top_level = false; // This is child widget. widget2->Init(params); // Access the shared focus manager directly from the second window. @@ -1654,6 +1651,24 @@ class FocusManagerDtorTest : public FocusManagerTest { } DtorTrackVector* dtor_tracker_; + + private: + DISALLOW_COPY_AND_ASSIGN(FocusManagerDtorTracked); + }; + + class TestFocusManagerFactory : public FocusManagerFactory { + public: + TestFocusManagerFactory(DtorTrackVector* dtor_tracker) + : dtor_tracker_(dtor_tracker) { + } + + FocusManager* CreateFocusManager(Widget* widget) OVERRIDE { + return new FocusManagerDtorTracked(widget, dtor_tracker_); + } + + private: + DtorTrackVector* dtor_tracker_; + DISALLOW_COPY_AND_ASSIGN(TestFocusManagerFactory); }; class NativeButtonDtorTracked : public NativeTextButton { @@ -1672,31 +1687,28 @@ class FocusManagerDtorTest : public FocusManagerTest { class WindowDtorTracked : public Widget { public: - WindowDtorTracked(WidgetDelegate* widget_delegate, - DtorTrackVector* dtor_tracker) + WindowDtorTracked(DtorTrackVector* dtor_tracker) : dtor_tracker_(dtor_tracker) { - tracked_focus_manager_ = new FocusManagerDtorTracked(this, dtor_tracker_); - Widget::InitParams params; - params.delegate = widget_delegate; - params.bounds = gfx::Rect(0, 0, 100, 100); - Init(params); - ReplaceFocusManager(tracked_focus_manager_); } virtual ~WindowDtorTracked() { dtor_tracker_->push_back("WindowDtorTracked"); } - FocusManagerDtorTracked* tracked_focus_manager_; DtorTrackVector* dtor_tracker_; }; - public: virtual void SetUp() { + FocusManagerFactory::Install(new TestFocusManagerFactory(&dtor_tracker_)); // Create WindowDtorTracked that uses FocusManagerDtorTracked. - window_ = new WindowDtorTracked(this, &dtor_tracker_); - ASSERT_TRUE(GetFocusManager() == static_cast<WindowDtorTracked*>( - window_)->tracked_focus_manager_); + window_ = new WindowDtorTracked(&dtor_tracker_); + Widget::InitParams params; + params.delegate = this; + params.bounds = gfx::Rect(0, 0, 100, 100); + window_->Init(params); + + tracked_focus_manager_ = + static_cast<FocusManagerDtorTracked*>(GetFocusManager()); window_->Show(); } @@ -1705,8 +1717,10 @@ class FocusManagerDtorTest : public FocusManagerTest { window_->Close(); message_loop()->RunAllPending(); } + FocusManagerFactory::Install(NULL); } + FocusManager* tracked_focus_manager_; DtorTrackVector dtor_tracker_; }; diff --git a/views/ime/input_method.h b/views/ime/input_method.h index 3b37118..1c7df22 100644 --- a/views/ime/input_method.h +++ b/views/ime/input_method.h @@ -102,6 +102,9 @@ class VIEWS_EXPORT InputMethod { // ui::TEXT_INPUT_TYPE_NONE if there is no focused text input client. virtual ui::TextInputType GetTextInputType() const = 0; + // Returns true if the input method is a mock and not real. + virtual bool IsMock() const = 0; + // TODO(suzhe): Support mouse/touch event. }; diff --git a/views/ime/input_method_base.cc b/views/ime/input_method_base.cc index 89753fb..d494279 100644 --- a/views/ime/input_method_base.cc +++ b/views/ime/input_method_base.cc @@ -75,6 +75,10 @@ ui::TextInputType InputMethodBase::GetTextInputType() const { return client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE; } +bool InputMethodBase::IsMock() const { + return false; +} + void InputMethodBase::FocusWillChange(View* focused_before, View* focused) { DCHECK_EQ(focused_view_, focused_before); FocusedViewWillChange(); diff --git a/views/ime/input_method_base.h b/views/ime/input_method_base.h index 58e4a76..f8e232d 100644 --- a/views/ime/input_method_base.h +++ b/views/ime/input_method_base.h @@ -48,6 +48,7 @@ class VIEWS_EXPORT InputMethodBase : public InputMethod, virtual TextInputClient* GetTextInputClient() const OVERRIDE; virtual ui::TextInputType GetTextInputType() const OVERRIDE; + virtual bool IsMock() const OVERRIDE; // Overridden from FocusChangeListener. Derived classes shouldn't override // this method. Override FocusedViewWillChange() and FocusedViewDidChange() diff --git a/views/ime/input_method_win.cc b/views/ime/input_method_win.cc index f7eb0cc..4ab1a18 100644 --- a/views/ime/input_method_win.cc +++ b/views/ime/input_method_win.cc @@ -99,6 +99,37 @@ bool InputMethodWin::IsActive() { return active_; } +LRESULT InputMethodWin::OnImeMessages( + UINT message, WPARAM w_param, LPARAM l_param, BOOL* handled) { + LRESULT result = 0; + switch (message) { + case WM_IME_SETCONTEXT: + result = OnImeSetContext(message, w_param, l_param, handled); + break; + case WM_IME_STARTCOMPOSITION: + result = OnImeStartComposition(message, w_param, l_param, handled); + break; + case WM_IME_COMPOSITION: + result = OnImeComposition(message, w_param, l_param, handled); + break; + case WM_IME_ENDCOMPOSITION: + result = OnImeEndComposition(message, w_param, l_param, handled); + break; + case WM_CHAR: + case WM_SYSCHAR: + result = OnChar(message, w_param, l_param, handled); + break; + case WM_DEADCHAR: + case WM_SYSDEADCHAR: + result = OnDeadChar(message, w_param, l_param, handled); + break; + default: + NOTREACHED() << "Unknown IME message:" << message; + break; + } + return result; +} + void InputMethodWin::FocusedViewWillChange() { ConfirmCompositionText(); } diff --git a/views/ime/input_method_win.h b/views/ime/input_method_win.h index 84b0ba5..d917508 100644 --- a/views/ime/input_method_win.h +++ b/views/ime/input_method_win.h @@ -37,9 +37,15 @@ class InputMethodWin : public InputMethodBase { virtual base::i18n::TextDirection GetInputTextDirection() OVERRIDE; virtual bool IsActive() OVERRIDE; + // Handles IME messages. + LRESULT OnImeMessages(UINT message, WPARAM wparam, LPARAM lparam, + BOOL* handled); + // Message handlers. The native widget is responsible for forwarding following // messages to the input method. void OnInputLangChange(DWORD character_set, HKL input_language_id); + + private: LRESULT OnImeSetContext( UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled); LRESULT OnImeStartComposition( @@ -55,7 +61,7 @@ class InputMethodWin : public InputMethodBase { LRESULT OnDeadChar( UINT message, WPARAM wparam, LPARAM lparam, BOOL* handled); - private: + // Overridden from InputMethodBase. virtual void FocusedViewWillChange() OVERRIDE; virtual void FocusedViewDidChange() OVERRIDE; diff --git a/views/ime/mock_input_method.cc b/views/ime/mock_input_method.cc index 0d06d19..0889494 100644 --- a/views/ime/mock_input_method.cc +++ b/views/ime/mock_input_method.cc @@ -106,6 +106,10 @@ bool MockInputMethod::IsActive() { return active_; } +bool MockInputMethod::IsMock() const { + return true; +} + void MockInputMethod::FocusedViewWillChange() { TextInputClient* client = GetTextInputClient(); if (client && client->HasCompositionText()) diff --git a/views/ime/mock_input_method.h b/views/ime/mock_input_method.h index b61d4e6..af4e0a5 100644 --- a/views/ime/mock_input_method.h +++ b/views/ime/mock_input_method.h @@ -29,6 +29,7 @@ class VIEWS_EXPORT MockInputMethod : public InputMethodBase { virtual std::string GetInputLocale() OVERRIDE; virtual base::i18n::TextDirection GetInputTextDirection() OVERRIDE; virtual bool IsActive() OVERRIDE; + virtual bool IsMock() const OVERRIDE; bool focus_changed() const { return focus_changed_; } bool text_input_type_changed() const { return text_input_type_changed_; } diff --git a/views/views.gyp b/views/views.gyp index e8fe9f9..7e5ca8a 100644 --- a/views/views.gyp +++ b/views/views.gyp @@ -239,6 +239,8 @@ 'focus/external_focus_tracker.h', 'focus/focus_manager.cc', 'focus/focus_manager.h', + 'focus/focus_manager_factory.cc', + 'focus/focus_manager_factory.h', 'focus/focus_search.cc', 'focus/focus_search.h', 'focus/focus_util_win.cc', diff --git a/views/widget/native_widget_delegate.h b/views/widget/native_widget_delegate.h index bfd0705..95d2aa1 100644 --- a/views/widget/native_widget_delegate.h +++ b/views/widget/native_widget_delegate.h @@ -20,6 +20,8 @@ enum TouchStatus; #endif namespace views { +class InputMethod; + namespace internal { //////////////////////////////////////////////////////////////////////////////// @@ -99,6 +101,11 @@ class VIEWS_EXPORT NativeWidgetDelegate { // Runs the specified native command. Returns true if the command is handled. virtual bool ExecuteCommand(int command_id) = 0; + // Returns the input method of the widget this delegate is associated with. + // Note that this does not use the top level widget, so may return NULL + // if the widget doesn't have input method. + virtual InputMethod* GetInputMethodDirect() = 0; + // virtual Widget* AsWidget() = 0; virtual const Widget* AsWidget() const = 0; diff --git a/views/widget/native_widget_gtk.cc b/views/widget/native_widget_gtk.cc index a57da4a..8081a31 100644 --- a/views/widget/native_widget_gtk.cc +++ b/views/widget/native_widget_gtk.cc @@ -393,7 +393,6 @@ NativeWidgetGtk::NativeWidgetGtk(internal::NativeWidgetDelegate* delegate) NativeWidgetGtk::~NativeWidgetGtk() { // We need to delete the input method before calling DestroyRootView(), // because it'll set focus_manager_ to NULL. - input_method_.reset(); if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) { DCHECK(widget_ == NULL); delete delegate_; @@ -961,33 +960,21 @@ bool NativeWidgetGtk::HasMouseCapture() const { return GTK_WIDGET_HAS_GRAB(window_contents_) || has_pointer_grab_; } -InputMethod* NativeWidgetGtk::GetInputMethodNative() { - if (!input_method_.get()) { - // Create input method when it is requested by a child view. - // TODO(suzhe): Always enable input method when we start to use - // RenderWidgetHostViewViews in normal ChromeOS. - if (!child_ && views::Widget::IsPureViews()) { +InputMethod* NativeWidgetGtk::CreateInputMethod() { + // Create input method when pure views is enabled. + // TODO(suzhe): Always enable input method when we start to use + // RenderWidgetHostViewViews in normal ChromeOS. + if (views::Widget::IsPureViews()) { #if defined(HAVE_IBUS) - input_method_.reset(InputMethodIBus::IsInputMethodIBusEnabled() ? - static_cast<InputMethod*>(new InputMethodIBus(this)) : - static_cast<InputMethod*>(new InputMethodGtk(this))); + return InputMethodIBus::IsInputMethodIBusEnabled() ? + static_cast<InputMethod*>(new InputMethodIBus(this)) : + static_cast<InputMethod*>(new InputMethodGtk(this)); #else - input_method_.reset(new InputMethodGtk(this)); + return new InputMethodGtk(this); #endif - input_method_->Init(GetWidget()); - if (has_focus_) - input_method_->OnFocus(); - } - } - return input_method_.get(); -} - -void NativeWidgetGtk::ReplaceInputMethod(InputMethod* input_method) { - input_method_.reset(input_method); - if (input_method) { - input_method->set_delegate(this); - input_method->Init(GetWidget()); } + // GTK's textfield handles IME. + return NULL; } void NativeWidgetGtk::CenterWindow(const gfx::Size& size) { @@ -1163,7 +1150,6 @@ void NativeWidgetGtk::Close() { void NativeWidgetGtk::CloseNow() { if (widget_) { - input_method_.reset(); gtk_widget_destroy(widget_); // Triggers OnDestroy(). } } @@ -1648,12 +1634,13 @@ gboolean NativeWidgetGtk::OnFocusIn(GtkWidget* widget, GdkEventFocus* event) { should_handle_menu_key_release_ = false; - if (child_) + if (!GetWidget()->is_top_level()) return false; // Only top-level Widget should have an InputMethod instance. - if (input_method_.get()) - input_method_->OnFocus(); + InputMethod* input_method = GetWidget()->GetInputMethodDirect(); + if (input_method) + input_method->OnFocus(); // See description of got_initial_focus_in_ for details on this. if (!got_initial_focus_in_) { @@ -1671,19 +1658,21 @@ gboolean NativeWidgetGtk::OnFocusOut(GtkWidget* widget, GdkEventFocus* event) { return false; // This is the second focus-out event in a row, ignore it. has_focus_ = false; - if (child_) + if (GetWidget()->is_top_level()) return false; // Only top-level Widget should have an InputMethod instance. - if (input_method_.get()) - input_method_->OnBlur(); + InputMethod* input_method = GetWidget()->GetInputMethodDirect(); + if (input_method) + input_method->OnBlur(); return false; } gboolean NativeWidgetGtk::OnEventKey(GtkWidget* widget, GdkEventKey* event) { KeyEvent key(reinterpret_cast<NativeEvent>(event)); - if (input_method_.get()) - input_method_->DispatchKeyEvent(key); + InputMethod* input_method = GetWidget()->GetInputMethodDirect(); + if (input_method) + input_method->DispatchKeyEvent(key); else DispatchKeyEventPostIME(key); @@ -2192,7 +2181,7 @@ NativeWidgetPrivate* NativeWidgetPrivate::GetTopLevelNativeWidget( parent_gtkwidget = gtk_widget_get_parent(parent_gtkwidget); } while (parent_gtkwidget); - return widget; + return widget && widget->GetWidget()->is_top_level() ? widget : NULL; } // static diff --git a/views/widget/native_widget_gtk.h b/views/widget/native_widget_gtk.h index 051e40c..659db5f 100644 --- a/views/widget/native_widget_gtk.h +++ b/views/widget/native_widget_gtk.h @@ -14,7 +14,6 @@ #include "ui/base/x/active_window_watcher_x.h" #include "ui/gfx/size.h" #include "views/focus/focus_manager.h" -#include "views/ime/input_method_delegate.h" #include "views/widget/native_widget_private.h" #include "views/widget/widget.h" @@ -42,8 +41,7 @@ class NativeWidgetDelegate; // Widget implementation for GTK. class VIEWS_EXPORT NativeWidgetGtk : public internal::NativeWidgetPrivate, - public ui::ActiveWindowWatcherX::Observer, - public internal::InputMethodDelegate { + public ui::ActiveWindowWatcherX::Observer { public: explicit NativeWidgetGtk(internal::NativeWidgetDelegate* delegate); virtual ~NativeWidgetGtk(); @@ -166,8 +164,7 @@ class VIEWS_EXPORT NativeWidgetGtk : public internal::NativeWidgetPrivate, virtual void SetMouseCapture() OVERRIDE; virtual void ReleaseMouseCapture() OVERRIDE; virtual bool HasMouseCapture() const OVERRIDE; - virtual InputMethod* GetInputMethodNative() OVERRIDE; - virtual void ReplaceInputMethod(InputMethod* input_method) OVERRIDE; + virtual InputMethod* CreateInputMethod() OVERRIDE; virtual void CenterWindow(const gfx::Size& size) OVERRIDE; virtual void GetWindowBoundsAndMaximizedState(gfx::Rect* bounds, bool* maximized) const OVERRIDE; @@ -434,8 +431,6 @@ class VIEWS_EXPORT NativeWidgetGtk : public internal::NativeWidgetPrivate, // that window manager shows the window only after the window is painted. bool painted_; - scoped_ptr<InputMethod> input_method_; - // The compositor for accelerated drawing. scoped_refptr<ui::Compositor> compositor_; diff --git a/views/widget/native_widget_private.h b/views/widget/native_widget_private.h index 3c31663..df332cf 100644 --- a/views/widget/native_widget_private.h +++ b/views/widget/native_widget_private.h @@ -7,6 +7,7 @@ #pragma once #include "ui/gfx/native_widget_types.h" +#include "views/ime/input_method_delegate.h" #include "views/widget/native_widget.h" namespace gfx { @@ -36,7 +37,8 @@ namespace internal { // NativeWidget implementations. This file should not be included // in code that does not fall into one of these use cases. // -class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget { +class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget, + public internal::InputMethodDelegate { public: virtual ~NativeWidgetPrivate() {} @@ -129,12 +131,8 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget { // Note that all widgets in a widget hierarchy share the same input method. // TODO(suzhe): rename to GetInputMethod() when NativeWidget implementation // class doesn't inherit Widget anymore. - virtual InputMethod* GetInputMethodNative() = 0; + virtual InputMethod* CreateInputMethod() = 0; - // Sets a different InputMethod instance to this native widget. The instance - // must not be initialized, the ownership will be assumed by the native - // widget. It's only for testing purpose. - virtual void ReplaceInputMethod(InputMethod* input_method) = 0; // Centers the window and sizes it to the specified size. virtual void CenterWindow(const gfx::Size& size) = 0; diff --git a/views/widget/native_widget_views.cc b/views/widget/native_widget_views.cc index ebb141e..5fc8721 100644 --- a/views/widget/native_widget_views.cc +++ b/views/widget/native_widget_views.cc @@ -57,26 +57,33 @@ const View* NativeWidgetViews::GetView() const { } void NativeWidgetViews::OnActivate(bool active) { + // TODO(oshima): find out if we should check toplevel here. if (active_ == active) return; active_ = active; delegate_->OnNativeWidgetActivationChanged(active); - InputMethod* input_method = GetInputMethodNative(); + // TODO(oshima): Focus change should be separated from window activation. // This will be fixed when we have WM API. - if (active) { - input_method->OnFocus(); - // See description of got_initial_focus_in_ for details on this. - GetWidget()->GetFocusManager()->RestoreFocusedView(); - } else { - input_method->OnBlur(); - GetWidget()->GetFocusManager()->StoreFocusedView(); + Widget* widget = GetWidget(); + if (widget->is_top_level()) { + InputMethod* input_method = widget->GetInputMethodDirect(); + if (active) { + input_method->OnFocus(); + // See description of got_initial_focus_in_ for details on this. + widget->GetFocusManager()->RestoreFocusedView(); + } else { + input_method->OnBlur(); + widget->GetFocusManager()->StoreFocusedView(); + } } view_->SchedulePaint(); } bool NativeWidgetViews::OnKeyEvent(const KeyEvent& key_event) { - GetInputMethodNative()->DispatchKeyEvent(key_event); + InputMethod* input_method = GetWidget()->GetInputMethodDirect(); + DCHECK(input_method); + input_method->DispatchKeyEvent(key_event); return true; } @@ -227,24 +234,12 @@ bool NativeWidgetViews::HasMouseCapture() const { return WindowManager::Get()->HasMouseCapture(GetWidget()); } -InputMethod* NativeWidgetViews::GetInputMethodNative() { - if (!input_method_.get()) { +InputMethod* NativeWidgetViews::CreateInputMethod() { #if defined(HAVE_IBUS) - input_method_.reset(static_cast<InputMethod*>(new InputMethodIBus(this))); + return new InputMethodIBus(this); #else - // TODO(suzhe|oshima): Figure out what to do on windows. - input_method_.reset(new MockInputMethod(this)); + return new MockInputMethod(this); #endif - input_method_->Init(GetWidget()); - } - return input_method_.get(); -} - -void NativeWidgetViews::ReplaceInputMethod(InputMethod* input_method) { - CHECK(input_method); - input_method_.reset(input_method); - input_method->set_delegate(this); - input_method->Init(GetWidget()); } void NativeWidgetViews::CenterWindow(const gfx::Size& size) { @@ -334,9 +329,6 @@ void NativeWidgetViews::Close() { } void NativeWidgetViews::CloseNow() { - // reset input_method before destroying widget. - input_method_.reset(); - delete view_; view_ = NULL; } diff --git a/views/widget/native_widget_views.h b/views/widget/native_widget_views.h index 1b4ad7d..440600c 100644 --- a/views/widget/native_widget_views.h +++ b/views/widget/native_widget_views.h @@ -10,7 +10,6 @@ #include "base/message_loop.h" #include "ui/gfx/transform.h" -#include "views/ime/input_method_delegate.h" #include "views/widget/native_widget_private.h" namespace views { @@ -27,8 +26,7 @@ class NativeWidgetView; // // A NativeWidget implementation that uses another View as its native widget. // -class VIEWS_EXPORT NativeWidgetViews : public internal::NativeWidgetPrivate, - public internal::InputMethodDelegate { +class VIEWS_EXPORT NativeWidgetViews : public internal::NativeWidgetPrivate { public: explicit NativeWidgetViews(internal::NativeWidgetDelegate* delegate); virtual ~NativeWidgetViews(); @@ -77,8 +75,7 @@ class VIEWS_EXPORT NativeWidgetViews : public internal::NativeWidgetPrivate, virtual void SetMouseCapture() OVERRIDE; virtual void ReleaseMouseCapture() OVERRIDE; virtual bool HasMouseCapture() const OVERRIDE; - virtual InputMethod* GetInputMethodNative() OVERRIDE; - virtual void ReplaceInputMethod(InputMethod* input_method) OVERRIDE; + virtual InputMethod* CreateInputMethod() OVERRIDE; virtual void CenterWindow(const gfx::Size& size) OVERRIDE; virtual void GetWindowBoundsAndMaximizedState(gfx::Rect* bounds, bool* maximized) const OVERRIDE; @@ -164,8 +161,6 @@ class VIEWS_EXPORT NativeWidgetViews : public internal::NativeWidgetPrivate, bool delete_native_view_; - scoped_ptr<InputMethod> input_method_; - std::map<const char*, void*> window_properties_; DISALLOW_COPY_AND_ASSIGN(NativeWidgetViews); diff --git a/views/widget/native_widget_win.cc b/views/widget/native_widget_win.cc index e7f1ebd..16fca92 100644 --- a/views/widget/native_widget_win.cc +++ b/views/widget/native_widget_win.cc @@ -373,7 +373,6 @@ NativeWidgetWin::NativeWidgetWin(internal::NativeWidgetDelegate* delegate) accessibility_view_events_index_(-1), accessibility_view_events_(kMaxAccessibilityViewEvents), previous_cursor_(NULL), - is_input_method_win_(false), fullscreen_(false), force_hidden_count_(0), lock_updates_(false), @@ -386,9 +385,6 @@ NativeWidgetWin::NativeWidgetWin(internal::NativeWidgetDelegate* delegate) } NativeWidgetWin::~NativeWidgetWin() { - // We need to delete the input method before calling DestroyRootView(), - // because it'll set focus_manager_ to NULL. - input_method_.reset(); if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) delete delegate_; else @@ -625,17 +621,8 @@ bool NativeWidgetWin::HasMouseCapture() const { return GetCapture() == hwnd(); } -InputMethod* NativeWidgetWin::GetInputMethodNative() { - return input_method_.get(); -} - -void NativeWidgetWin::ReplaceInputMethod(InputMethod* input_method) { - input_method_.reset(input_method); - if (input_method) { - input_method->set_delegate(this); - input_method->Init(GetWidget()); - } - is_input_method_win_ = false; +InputMethod* NativeWidgetWin::CreateInputMethod() { + return views::Widget::IsPureViews() ? new InputMethodWin(this) : NULL; } void NativeWidgetWin::CenterWindow(const gfx::Size& size) { @@ -841,11 +828,6 @@ void NativeWidgetWin::Close() { } void NativeWidgetWin::CloseNow() { - // Destroys the input method before closing the window so that it can be - // detached from the widget correctly. - input_method_.reset(); - is_input_method_win_ = false; - // We may already have been destroyed if the selection resulted in a tab // switch which will have reactivated the browser window and closed us, so // we need to check to see if we're still a window before trying to destroy @@ -1133,9 +1115,14 @@ LRESULT NativeWidgetWin::OnWndProc(UINT message, WPARAM w_param, MessageLoopForUI::current()->RemoveObserver(this); OnFinalMessage(window); } - if (message == WM_ACTIVATE) + + // Only top level widget should store/restore focus. + if (message == WM_ACTIVATE && GetWidget()->is_top_level()) PostProcessActivateMessage(this, LOWORD(w_param)); if (message == WM_ENABLE && restore_focus_when_enabled_) { + // This path should be executed only for top level as + // restore_focus_when_enabled_ is set in PostProcessActivateMessage. + DCHECK(GetWidget()->is_top_level()); restore_focus_when_enabled_ = false; GetWidget()->GetFocusManager()->RestoreFocusedView(); } @@ -1266,14 +1253,6 @@ LRESULT NativeWidgetWin::OnCreate(CREATESTRUCT* create_struct) { delegate_->OnNativeWidgetCreated(); - // delegate_->OnNativeWidgetCreated() creates the focus manager for top-level - // widget. Only top-level widget should have an input method. - if (delegate_->HasFocusManager() && views::Widget::IsPureViews()) { - input_method_.reset(new InputMethodWin(this)); - input_method_->Init(GetWidget()); - is_input_method_win_ = true; - } - // Get access to a modifiable copy of the system menu. GetSystemMenu(hwnd(), false); return 0; @@ -1388,39 +1367,15 @@ void NativeWidgetWin::OnHScroll(int scroll_type, LRESULT NativeWidgetWin::OnImeMessages(UINT message, WPARAM w_param, LPARAM l_param) { - if (!is_input_method_win_) { + InputMethod* input_method = GetWidget()->GetInputMethodDirect(); + if (!input_method || input_method->IsMock()) { SetMsgHandled(FALSE); return 0; } - InputMethodWin* ime = static_cast<InputMethodWin*>(input_method_.get()); + InputMethodWin* ime_win = static_cast<InputMethodWin*>(input_method); BOOL handled = FALSE; - LRESULT result = 0; - switch (message) { - case WM_IME_SETCONTEXT: - result = ime->OnImeSetContext(message, w_param, l_param, &handled); - break; - case WM_IME_STARTCOMPOSITION: - result = ime->OnImeStartComposition(message, w_param, l_param, &handled); - break; - case WM_IME_COMPOSITION: - result = ime->OnImeComposition(message, w_param, l_param, &handled); - break; - case WM_IME_ENDCOMPOSITION: - result = ime->OnImeEndComposition(message, w_param, l_param, &handled); - break; - case WM_CHAR: - case WM_SYSCHAR: - result = ime->OnChar(message, w_param, l_param, &handled); - break; - case WM_DEADCHAR: - case WM_SYSDEADCHAR: - result = ime->OnDeadChar(message, w_param, l_param, &handled); - break; - default: - NOTREACHED() << "Unknown IME message:" << message; - break; - } + LRESULT result = ime_win->OnImeMessages(message, w_param, l_param, &handled); SetMsgHandled(handled); return result; @@ -1453,8 +1408,10 @@ void NativeWidgetWin::OnInitMenuPopup(HMENU menu, void NativeWidgetWin::OnInputLangChange(DWORD character_set, HKL input_language_id) { - if (is_input_method_win_) { - static_cast<InputMethodWin*>(input_method_.get())->OnInputLangChange( + InputMethod* input_method = GetWidget()->GetInputMethodDirect(); + + if (input_method && !input_method->IsMock()) { + static_cast<InputMethodWin*>(input_method)->OnInputLangChange( character_set, input_language_id); } } @@ -1464,8 +1421,9 @@ LRESULT NativeWidgetWin::OnKeyEvent(UINT message, LPARAM l_param) { MSG msg = { hwnd(), message, w_param, l_param }; KeyEvent key(msg); - if (input_method_.get()) - input_method_->DispatchKeyEvent(key); + InputMethod* input_method = GetWidget()->GetInputMethodDirect(); + if (input_method) + input_method->DispatchKeyEvent(key); else DispatchKeyEventPostIME(key); return 0; @@ -1473,8 +1431,9 @@ LRESULT NativeWidgetWin::OnKeyEvent(UINT message, void NativeWidgetWin::OnKillFocus(HWND focused_window) { delegate_->OnNativeBlur(focused_window); - if (input_method_.get()) - input_method_->OnBlur(); + InputMethod* input_method = GetWidget()->GetInputMethodDirect(); + if (input_method) + input_method->OnBlur(); SetMsgHandled(FALSE); } @@ -1901,8 +1860,9 @@ LRESULT NativeWidgetWin::OnSetCursor(UINT message, void NativeWidgetWin::OnSetFocus(HWND focused_window) { delegate_->OnNativeFocus(focused_window); - if (input_method_.get()) - input_method_->OnFocus(); + InputMethod* input_method = GetWidget()->GetInputMethodDirect(); + if (input_method) + input_method->OnFocus(); SetMsgHandled(FALSE); } @@ -2172,10 +2132,7 @@ void NativeWidgetWin::ExecuteSystemMenuCommand(int command) { // static void NativeWidgetWin::PostProcessActivateMessage(NativeWidgetWin* widget, int activation_state) { - if (!widget->delegate_->HasFocusManager()) { - NOTREACHED(); - return; - } + DCHECK(widget->GetWidget()->is_top_level()); FocusManager* focus_manager = widget->GetWidget()->GetFocusManager(); if (WA_INACTIVE == activation_state) { // We might get activated/inactivated without being enabled, so we need to diff --git a/views/widget/native_widget_win.h b/views/widget/native_widget_win.h index 1525de7..9aef85d 100644 --- a/views/widget/native_widget_win.h +++ b/views/widget/native_widget_win.h @@ -21,7 +21,6 @@ #include "base/win/scoped_comptr.h" #include "ui/base/win/window_impl.h" #include "views/focus/focus_manager.h" -#include "views/ime/input_method_delegate.h" #include "views/layout/layout_manager.h" #include "views/widget/native_widget_private.h" @@ -86,9 +85,8 @@ const int WM_NCUAHDRAWFRAME = 0xAF; // /////////////////////////////////////////////////////////////////////////////// class VIEWS_EXPORT NativeWidgetWin : public ui::WindowImpl, - public internal::NativeWidgetPrivate, public MessageLoopForUI::Observer, - public internal::InputMethodDelegate { + public internal::NativeWidgetPrivate { public: explicit NativeWidgetWin(internal::NativeWidgetDelegate* delegate); virtual ~NativeWidgetWin(); @@ -216,8 +214,7 @@ class VIEWS_EXPORT NativeWidgetWin : public ui::WindowImpl, virtual void SetMouseCapture() OVERRIDE; virtual void ReleaseMouseCapture() OVERRIDE; virtual bool HasMouseCapture() const OVERRIDE; - virtual InputMethod* GetInputMethodNative() OVERRIDE; - virtual void ReplaceInputMethod(InputMethod* input_method) OVERRIDE; + virtual InputMethod* CreateInputMethod() OVERRIDE; virtual void CenterWindow(const gfx::Size& size) OVERRIDE; virtual void GetWindowBoundsAndMaximizedState(gfx::Rect* bounds, bool* maximized) const OVERRIDE; @@ -610,11 +607,6 @@ class VIEWS_EXPORT NativeWidgetWin : public ui::WindowImpl, ViewProps props_; - scoped_ptr<InputMethod> input_method_; - - // Indicates if the |input_method_| is an InputMethodWin instance. - bool is_input_method_win_; - // True if we're in fullscreen mode. bool fullscreen_; diff --git a/views/widget/widget.cc b/views/widget/widget.cc index 691ab97..eb7c0d1 100644 --- a/views/widget/widget.cc +++ b/views/widget/widget.cc @@ -11,6 +11,7 @@ #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/compositor/compositor.h" #include "views/controls/menu/menu_controller.h" +#include "views/focus/focus_manager_factory.h" #include "views/focus/view_storage.h" #include "views/ime/input_method.h" #include "views/views_delegate.h" @@ -104,7 +105,8 @@ Widget::InitParams::InitParams() double_buffer(false), parent(NULL), parent_widget(NULL), - native_widget(NULL) { + native_widget(NULL), + top_level(false) { } Widget::InitParams::InitParams(Type type) @@ -123,7 +125,8 @@ Widget::InitParams::InitParams(Type type) double_buffer(false), parent(NULL), parent_widget(NULL), - native_widget(NULL) { + native_widget(NULL), + top_level(false) { } //////////////////////////////////////////////////////////////////////////////// @@ -149,7 +152,8 @@ Widget::Widget() widget_closed_(false), saved_maximized_state_(false), minimum_size_(100, 100), - focus_on_creation_(true) { + focus_on_creation_(true), + is_top_level_(false) { } Widget::~Widget() { @@ -159,7 +163,6 @@ Widget::~Widget() { } DestroyRootView(); - if (ownership_ == InitParams::WIDGET_OWNS_NATIVE_WIDGET) delete native_widget_; } @@ -275,6 +278,10 @@ bool Widget::IsDebugPaintEnabled() { } void Widget::Init(const InitParams& params) { + is_top_level_ = params.top_level || + (!params.child && + params.type != InitParams::TYPE_CONTROL && + params.type != InitParams::TYPE_TOOLTIP); widget_delegate_ = params.delegate ? params.delegate : new DefaultWidgetDelegate(this); ownership_ = params.ownership; @@ -361,6 +368,12 @@ Widget* Widget::GetTopLevelWidget() { } const Widget* Widget::GetTopLevelWidget() const { + // GetTopLevelNativeWidget doesn't work during destruction because + // property is gone after gobject gets deleted. Short circuit here + // for toplevel so that InputMethod can remove itself from + // focus manager. + if (is_top_level()) + return this; return native_widget_->GetTopLevelWidget(); } @@ -432,7 +445,7 @@ void Widget::Close() { // |FormManager::ViewRemoved()| calls are fouled. We clear focus here // to avoid these redundant steps and to avoid accessing deleted views // that may have been in focus. - if (GetTopLevelWidget() == this && focus_manager_.get()) + if (is_top_level() && focus_manager_.get()) focus_manager_->SetFocusedView(NULL); native_widget_->Close(); @@ -579,16 +592,12 @@ ThemeProvider* Widget::GetThemeProvider() const { FocusManager* Widget::GetFocusManager() { Widget* toplevel_widget = GetTopLevelWidget(); - if (toplevel_widget && toplevel_widget != this) - return toplevel_widget->focus_manager_.get(); - - return focus_manager_.get(); + return toplevel_widget ? toplevel_widget->focus_manager_.get() : NULL; } InputMethod* Widget::GetInputMethod() { Widget* toplevel_widget = GetTopLevelWidget(); - return toplevel_widget ? - toplevel_widget->native_widget_->GetInputMethodNative() : NULL; + return toplevel_widget ? toplevel_widget->GetInputMethodDirect() : NULL; } void Widget::RunShellDrag(View* view, const ui::OSExchangeData& data, @@ -832,11 +841,8 @@ void Widget::OnNativeWidgetVisibilityChanged(bool visible) { } void Widget::OnNativeWidgetCreated() { - if (GetTopLevelWidget() == this) { - // Only the top level Widget in a native widget hierarchy has a focus - // manager. - focus_manager_.reset(new FocusManager(this)); - } + if (is_top_level()) + focus_manager_.reset(FocusManagerFactory::Create(this)); native_widget_->SetAccessibleRole( widget_delegate_->GetAccessibleWindowRole()); @@ -968,6 +974,12 @@ bool Widget::ExecuteCommand(int command_id) { return widget_delegate_->ExecuteWindowsCommand(command_id); } +InputMethod* Widget::GetInputMethodDirect() { + if (!input_method_.get() && is_top_level()) + ReplaceInputMethod(native_widget_->CreateInputMethod()); + return input_method_.get(); +} + Widget* Widget::AsWidget() { return this; } @@ -1006,7 +1018,8 @@ internal::RootView* Widget::CreateRootView() { void Widget::DestroyRootView() { root_view_.reset(); - + // Input method has to be destroyed before focus manager. + input_method_.reset(); // Defer focus manager's destruction. This is for the case when the // focus manager is referenced by a child NativeWidgetGtk (e.g. TabbedPane in // a dialog). When gtk_widget_destroy is called on the parent, the destroy @@ -1019,10 +1032,6 @@ void Widget::DestroyRootView() { MessageLoop::current()->DeleteSoon(FROM_HERE, focus_manager); } -void Widget::ReplaceFocusManager(FocusManager* focus_manager) { - focus_manager_.reset(focus_manager); -} - //////////////////////////////////////////////////////////////////////////////// // Widget, private: @@ -1098,6 +1107,16 @@ bool Widget::GetSavedBounds(gfx::Rect* bounds, bool* maximize) { return false; } +void Widget::ReplaceInputMethod(InputMethod* input_method) { + input_method_.reset(input_method); + // TODO(oshima): Gtk's textfield doesn't need views InputMethod. + // Remove this check once gtk is removed. + if (input_method) { + input_method->set_delegate(native_widget_); + input_method->Init(this); + } +} + namespace internal { //////////////////////////////////////////////////////////////////////////////// diff --git a/views/widget/widget.h b/views/widget/widget.h index 4827eae..a85b619 100644 --- a/views/widget/widget.h +++ b/views/widget/widget.h @@ -8,6 +8,7 @@ #include <stack> +#include "base/gtest_prod_util.h" #include "base/memory/scoped_ptr.h" #include "base/observer_list.h" #include "ui/base/accessibility/accessibility_types.h" @@ -155,6 +156,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // When set, this value is used as the Widget's NativeWidget implementation. // The Widget will not construct a default one. Default is NULL. NativeWidget* native_widget; + bool top_level; }; static InitParams WindowInitParams(); @@ -198,8 +200,11 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, static Widget* GetWidgetForNativeView(gfx::NativeView native_view); static Widget* GetWidgetForNativeWindow(gfx::NativeWindow native_window); - // Retrieves the highest Widget in a native view hierarchy starting at - // |native_view|, which may or may not be a Widget itself. + // Retrieves the top level widget in a native view hierarchy + // starting at |native_view|. Top level widget is a widget with + // TYPE_WINDOW, TYPE_WINDOW_FRAMELESS, POPUP or MENU and has its own + // focus manager. This may be itself if the |native_view| is top level, + // or NULL if there is no toplevel in a native view hierarchy. static Widget* GetTopLevelWidgetForNativeView(gfx::NativeView native_view); // Returns all Widgets in |native_view|'s hierarchy, including itself if @@ -252,8 +257,9 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, void NotifyNativeViewHierarchyChanged(bool attached, gfx::NativeView native_view); - // Returns the top level Widget in a hierarchy. Will return NULL the widget - // is not yet attached to top leve widget's hierarchy. + // Returns the top level widget in a hierarchy (see is_top_level() for + // the definition of top level widget.) Will return NULL if called + // before the widget is attached to the top level widget's hierarchy. Widget* GetTopLevelWidget(); const Widget* GetTopLevelWidget() const; @@ -552,6 +558,12 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // if it exists and the root view otherwise. virtual View* GetChildViewParent(); + // True if the widget is considered top level widget. Top level widget + // is a widget of TYPE_WINDOW, TYPE_WINDOW_FRAMELESS, POPUP or MENU, and + // has a focus manager and input method object associated with it. + // TYPE_CONTROL and TYPE_TOOLTIP is not considered top level. + bool is_top_level() const { return is_top_level_; } + // Overridden from NativeWidgetDelegate: virtual bool IsModal() const OVERRIDE; virtual bool IsDialogBox() const OVERRIDE; @@ -579,6 +591,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, virtual void OnMouseCaptureLost() OVERRIDE; virtual ui::TouchStatus OnTouchEvent(const TouchEvent& event) OVERRIDE; virtual bool ExecuteCommand(int command_id) OVERRIDE; + virtual InputMethod* GetInputMethodDirect() OVERRIDE; virtual Widget* AsWidget() OVERRIDE; virtual const Widget* AsWidget() const OVERRIDE; @@ -601,9 +614,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // TODO(beng): remove once we fold those objects onto this one. void DestroyRootView(); - // Used for testing. - void ReplaceFocusManager(FocusManager* focus_manager); - // TODO(beng): Remove NativeWidgetGtk's dependence on these: // TODO(msw): Make this mouse state member private. // If true, the mouse is currently down. @@ -618,6 +628,8 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, gfx::Point last_mouse_event_position_; private: + friend class NativeTextfieldViewsTest; + friend class NativeComboboxViewsTest; friend class ScopedEvent; // Returns whether capture should be released on mouse release. @@ -634,6 +646,11 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // the delegate wants to use a specified bounds. bool GetSavedBounds(gfx::Rect* bounds, bool* maximize); + // Sets a different InputMethod instance to this widget. The instance + // must not be initialized, the ownership will be assumed by the widget. + // It's only for testing purpose. + void ReplaceInputMethod(InputMethod* input_method); + internal::NativeWidgetPrivate* native_widget_; ObserverList<Observer> observers_; @@ -702,6 +719,11 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, // initial focus for the widget. bool focus_on_creation_; + scoped_ptr<InputMethod> input_method_; + + // See |is_top_leve()| accessor. + bool is_top_level_; + // Factory used to create Compositors. Settable by tests. static ui::Compositor*(*compositor_factory_)(); |