summaryrefslogtreecommitdiffstats
path: root/views
diff options
context:
space:
mode:
authoroshima@google.com <oshima@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-23 05:01:35 +0000
committeroshima@google.com <oshima@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-23 05:01:35 +0000
commit2bd4b68de2e193aca51caa09edddb8fd0cd3b9cd (patch)
tree46164cc11e0396a66286f29ed4cb99e044583f19 /views
parentd776fbf0f45a3d435449740b1c8973b8866231fa (diff)
downloadchromium_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')
-rw-r--r--views/controls/combobox/native_combobox_views_unittest.cc3
-rw-r--r--views/controls/tabbed_pane/native_tabbed_pane_gtk.cc1
-rw-r--r--views/controls/textfield/native_textfield_views_unittest.cc2
-rw-r--r--views/focus/focus_manager_factory.cc55
-rw-r--r--views/focus/focus_manager_factory.h41
-rw-r--r--views/focus/focus_manager_unittest.cc94
-rw-r--r--views/ime/input_method.h3
-rw-r--r--views/ime/input_method_base.cc4
-rw-r--r--views/ime/input_method_base.h1
-rw-r--r--views/ime/input_method_win.cc31
-rw-r--r--views/ime/input_method_win.h8
-rw-r--r--views/ime/mock_input_method.cc4
-rw-r--r--views/ime/mock_input_method.h1
-rw-r--r--views/views.gyp2
-rw-r--r--views/widget/native_widget_delegate.h7
-rw-r--r--views/widget/native_widget_gtk.cc57
-rw-r--r--views/widget/native_widget_gtk.h9
-rw-r--r--views/widget/native_widget_private.h10
-rw-r--r--views/widget/native_widget_views.cc46
-rw-r--r--views/widget/native_widget_views.h9
-rw-r--r--views/widget/native_widget_win.cc95
-rw-r--r--views/widget/native_widget_win.h12
-rw-r--r--views/widget/widget.cc61
-rw-r--r--views/widget/widget.h36
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_)();