Index: ui/views/widget/widget_interactive_uitest.cc |
diff --git a/ui/views/widget/widget_interactive_uitest.cc b/ui/views/widget/widget_interactive_uitest.cc |
index 9fbb62a42785ce3d54ea36d0c3b690ea460c7a9c..6ae3a6fbd58445c124490ecbbcb32648e29255ec 100644 |
--- a/ui/views/widget/widget_interactive_uitest.cc |
+++ b/ui/views/widget/widget_interactive_uitest.cc |
@@ -9,6 +9,10 @@ |
#include "base/run_loop.h" |
#include "base/strings/stringprintf.h" |
#include "base/strings/utf_string_conversions.h" |
+#include "ui/aura/window.h" |
+#include "ui/aura/window_tree_host.h" |
+#include "ui/base/ime/input_method.h" |
+#include "ui/base/ime/text_input_client.h" |
#include "ui/base/resource/resource_bundle.h" |
#include "ui/base/ui_base_paths.h" |
#include "ui/base/ui_base_switches.h" |
@@ -20,18 +24,20 @@ |
#include "ui/views/controls/textfield/textfield.h" |
#include "ui/views/controls/textfield/textfield_test_api.h" |
#include "ui/views/focus/focus_manager.h" |
+#include "ui/views/ime/input_method.h" |
#include "ui/views/test/focus_manager_test.h" |
#include "ui/views/test/widget_test.h" |
#include "ui/views/touchui/touch_selection_controller_impl.h" |
+#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" |
#include "ui/views/widget/widget.h" |
#include "ui/views/window/dialog_delegate.h" |
#include "ui/wm/public/activation_client.h" |
#if defined(OS_WIN) |
-#include "ui/aura/window.h" |
-#include "ui/aura/window_tree_host.h" |
-#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" |
#include "ui/views/win/hwnd_util.h" |
+#elif defined(USE_X11) |
+#include "ui/base/x/x11_util.h" |
+#include "ui/views/test/x11_property_change_waiter.h" |
#endif |
namespace views { |
@@ -175,6 +181,31 @@ class WidgetActivationWaiter : public WidgetObserver { |
DISALLOW_COPY_AND_ASSIGN(WidgetActivationWaiter); |
}; |
+#if defined(USE_X11) |
+class WidgetActivationWaiterX11 : public X11PropertyChangeWaiter { |
+ public: |
+ explicit WidgetActivationWaiterX11(Widget* widget, bool active) |
+ : X11PropertyChangeWaiter(ui::GetX11RootWindow(), "_NET_ACTIVE_WINDOW"), |
+ window_(widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget()) { |
+ EXPECT_NE(active, widget->IsActive()); |
+ } |
+ |
+ ~WidgetActivationWaiterX11() override {} |
+ |
+ private: |
+ // X11PropertyChangeWaiter: |
+ bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) override { |
+ XID xid = 0; |
+ ui::GetXIDProperty(ui::GetX11RootWindow(), "_NET_ACTIVE_WINDOW", &xid); |
+ return xid != window_; |
+ } |
+ |
+ XID window_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(WidgetActivationWaiterX11); |
+}; |
+#endif |
+ |
ui::WindowShowState GetWidgetShowState(const Widget* widget) { |
// Use IsMaximized/IsMinimized/IsFullScreen instead of GetWindowPlacement |
// because the former is implemented on all platforms but the latter is not. |
@@ -214,6 +245,25 @@ void ShowSync(Widget* widget) { |
waiter.Wait(); |
} |
+#if defined(USE_AURA) |
+void ActivatePlatformWindowSync(Widget* widget) { |
tapted
2015/05/01 01:54:25
Hi There! I'd like to get these tests working on M
tapted
2015/05/01 09:10:17
Looks like ActivateSync() can do the job on Linux.
|
+#if defined(OS_WIN) |
+ ::SetActiveWindow( |
+ widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget()); |
+#elif defined(OS_CHROMEOS) |
+ widget->Activate(); |
+#elif defined(USE_X11) |
+ if (!widget->IsActive()) { |
+ WidgetActivationWaiterX11 waiter(widget, true); |
+ widget->Activate(); |
+ waiter.Wait(); |
+ } |
+#else |
+ ActivateSync(widget); |
+#endif |
+} |
+#endif |
+ |
// Calls ShowInactive() on a Widget, and spins a run loop. The goal is to give |
// the OS a chance to activate a widget. However, for this case, the test |
// doesn't expect that to happen, so there is nothing to wait for. |
@@ -255,6 +305,25 @@ class WidgetTestInteractive : public WidgetTest { |
DCHECK(controller); |
return controller->context_menu_ && controller->context_menu_->visible(); |
} |
+ |
+ scoped_ptr<Widget> CreateWidget() { |
+#if !defined(USE_AURA) |
+ return NULL; |
+#else |
+ scoped_ptr<Widget> widget(new Widget); |
+ Widget::InitParams params = |
+ CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); |
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
+ params.bounds = gfx::Rect(0, 0, 200, 200); |
+#if defined(OS_CHROMEOS) |
+ params.native_widget = NULL; |
+#else |
+ params.native_widget = new DesktopNativeWidgetAura(widget.get()); |
+#endif |
+ widget->Init(params); |
+ return widget.Pass(); |
+#endif |
+ } |
}; |
#if defined(OS_WIN) |
@@ -271,55 +340,41 @@ TEST_F(WidgetTestInteractive, DesktopNativeWidgetAuraActivationAndFocusTest) { |
// Create widget 1 and expect the active window to be its window. |
View* contents_view1 = new View; |
contents_view1->SetFocusable(true); |
- Widget widget1; |
- Widget::InitParams init_params = |
- CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); |
- init_params.bounds = gfx::Rect(0, 0, 200, 200); |
- init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
- init_params.native_widget = new DesktopNativeWidgetAura(&widget1); |
- widget1.Init(init_params); |
- widget1.SetContentsView(contents_view1); |
- widget1.Show(); |
- aura::Window* root_window1= widget1.GetNativeView()->GetRootWindow(); |
+ scoped_ptr<Widget> widget1(CreateWidget()); |
+ widget1->SetContentsView(contents_view1); |
+ widget1->Show(); |
+ aura::Window* root_window1= widget1->GetNativeView()->GetRootWindow(); |
contents_view1->RequestFocus(); |
EXPECT_TRUE(root_window1 != NULL); |
aura::client::ActivationClient* activation_client1 = |
aura::client::GetActivationClient(root_window1); |
EXPECT_TRUE(activation_client1 != NULL); |
- EXPECT_EQ(activation_client1->GetActiveWindow(), widget1.GetNativeView()); |
+ EXPECT_EQ(activation_client1->GetActiveWindow(), widget1->GetNativeView()); |
// Create widget 2 and expect the active window to be its window. |
View* contents_view2 = new View; |
- Widget widget2; |
- Widget::InitParams init_params2 = |
- CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); |
- init_params2.bounds = gfx::Rect(0, 0, 200, 200); |
- init_params2.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
- init_params2.native_widget = new DesktopNativeWidgetAura(&widget2); |
- widget2.Init(init_params2); |
- widget2.SetContentsView(contents_view2); |
- widget2.Show(); |
- aura::Window* root_window2 = widget2.GetNativeView()->GetRootWindow(); |
+ scoped_ptr<Widget> widget2(CreateWidget()); |
+ widget2->SetContentsView(contents_view2); |
+ widget2->Show(); |
+ aura::Window* root_window2 = widget2->GetNativeView()->GetRootWindow(); |
contents_view2->RequestFocus(); |
- ::SetActiveWindow( |
- root_window2->GetHost()->GetAcceleratedWidget()); |
+ ActivatePlatformWindowSync(widget2.get()); |
aura::client::ActivationClient* activation_client2 = |
aura::client::GetActivationClient(root_window2); |
EXPECT_TRUE(activation_client2 != NULL); |
- EXPECT_EQ(activation_client2->GetActiveWindow(), widget2.GetNativeView()); |
+ EXPECT_EQ(activation_client2->GetActiveWindow(), widget2->GetNativeView()); |
EXPECT_EQ(activation_client1->GetActiveWindow(), |
reinterpret_cast<aura::Window*>(NULL)); |
// Now set focus back to widget 1 and expect the active window to be its |
// window. |
contents_view1->RequestFocus(); |
- ::SetActiveWindow( |
- root_window1->GetHost()->GetAcceleratedWidget()); |
+ ActivatePlatformWindowSync(widget1.get()); |
EXPECT_EQ(activation_client2->GetActiveWindow(), |
reinterpret_cast<aura::Window*>(NULL)); |
- EXPECT_EQ(activation_client1->GetActiveWindow(), widget1.GetNativeView()); |
+ EXPECT_EQ(activation_client1->GetActiveWindow(), widget1->GetNativeView()); |
} |
#endif // defined(OS_WIN) |
@@ -871,32 +926,27 @@ TEST_F(WidgetTestInteractive, MAYBE_TouchSelectionQuickMenuIsNotActivated) { |
views_delegate().set_use_desktop_native_widgets(true); |
#endif // !defined(OS_WIN) |
- Widget widget; |
- Widget::InitParams init_params = |
- CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); |
- init_params.bounds = gfx::Rect(0, 0, 200, 200); |
- init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
- widget.Init(init_params); |
+ scoped_ptr<Widget> widget(CreateWidget()); |
Textfield* textfield = new Textfield; |
textfield->SetBounds(0, 0, 200, 20); |
textfield->SetText(base::ASCIIToUTF16("some text")); |
- widget.GetRootView()->AddChildView(textfield); |
+ widget->GetRootView()->AddChildView(textfield); |
- widget.Show(); |
+ widget->Show(); |
textfield->RequestFocus(); |
textfield->SelectAll(true); |
TextfieldTestApi textfield_test_api(textfield); |
RunPendingMessages(); |
- ui::test::EventGenerator generator(widget.GetNativeWindow()); |
+ ui::test::EventGenerator generator(widget->GetNativeWindow()); |
generator.GestureTapAt(gfx::Point(10, 10)); |
ShowQuickMenuImmediately(static_cast<TouchSelectionControllerImpl*>( |
textfield_test_api.touch_selection_controller())); |
EXPECT_TRUE(textfield->HasFocus()); |
- EXPECT_TRUE(widget.IsActive()); |
+ EXPECT_TRUE(widget->IsActive()); |
EXPECT_TRUE(IsQuickMenuVisible(static_cast<TouchSelectionControllerImpl*>( |
textfield_test_api.touch_selection_controller()))); |
} |
@@ -1404,5 +1454,190 @@ TEST_F(WidgetCaptureTest, MouseEventDispatchedToRightWindow) { |
} |
#endif // defined(OS_WIN) |
+#if defined(USE_AURA) |
+// Test input method focus changes affected by top window activaction. |
+TEST_F(WidgetTestInteractive, InputMethodFocus_activation) { |
+ scoped_ptr<Widget> widget(CreateWidget()); |
+ scoped_ptr<Textfield> textfield(new Textfield); |
+ widget->GetRootView()->AddChildView(textfield.get()); |
+ widget->Show(); |
+ textfield->RequestFocus(); |
+ |
+ ActivatePlatformWindowSync(widget.get()); |
+ |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, |
+ widget->GetInputMethod()->GetTextInputType()); |
+ |
+ widget->Deactivate(); |
+ |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
+ widget->GetInputMethod()->GetTextInputType()); |
+} |
+ |
+// Test input method focus changes affected by focus changes within 1 window. |
+TEST_F(WidgetTestInteractive, InputMethodFocus_1_window) { |
+ scoped_ptr<Widget> widget(CreateWidget()); |
+ scoped_ptr<Textfield> textfield1(new Textfield); |
+ scoped_ptr<Textfield> textfield2(new Textfield); |
+ textfield2->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); |
+ widget->GetRootView()->AddChildView(textfield1.get()); |
+ widget->GetRootView()->AddChildView(textfield2.get()); |
+ widget->Show(); |
+ |
+ ActivatePlatformWindowSync(widget.get()); |
+ |
+ textfield1->RequestFocus(); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, |
+ widget->GetInputMethod()->GetTextInputType()); |
+ |
+ textfield2->RequestFocus(); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, |
+ widget->GetInputMethod()->GetTextInputType()); |
+ |
+// Window::Blur doesn't work for CrOS, because it uses NWA instead of DNWA and |
+// involves the AuraTestHelper which setup the input method as DummyInputMethod. |
+// Please refer to CreateWidget method above. |
+#if !defined(OS_CHROMEOS) |
+ aura::Window* window = widget->GetNativeWindow(); |
+ window->Blur(); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
+ widget->GetInputMethod()->GetTextInputType()); |
+ |
+ window->Focus(); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, |
+ widget->GetInputMethod()->GetTextInputType()); |
+ |
+ window->Blur(); |
+ textfield1->RequestFocus(); |
+ window->Focus(); |
+ EXPECT_TRUE(window->HasFocus()); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, |
+ widget->GetInputMethod()->GetTextInputType()); |
+#endif |
+} |
+ |
+// Test input method focus changes affected by focus changes cross 2 windows |
+// which shares the same top window. |
+TEST_F(WidgetTestInteractive, InputMethodFocus_2_windows) { |
+ scoped_ptr<Widget> widget(CreateWidget()); |
+ widget->Show(); |
+ |
+ views::View* parent_root = new View; |
+ scoped_ptr<Widget> parent(new Widget); |
+ Widget::InitParams parent_params(Widget::InitParams::TYPE_WINDOW_FRAMELESS); |
+ parent_params.ownership = |
+ views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
+ parent_params.context = widget->GetNativeWindow(); |
+ parent->Init(parent_params); |
+ parent->SetContentsView(parent_root); |
+ parent->SetBounds(gfx::Rect(100, 100, 100, 100)); |
+ parent->Show(); |
+ |
+ scoped_ptr<Widget> child(new Widget()); |
+ Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL); |
+ child_params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
+ child_params.parent = parent->GetNativeWindow(); |
+ child->Init(child_params); |
+ child->SetBounds(gfx::Rect(0, 0, 50, 50)); |
+ child->Show(); |
+ |
+ scoped_ptr<Textfield> textfield_parent(new Textfield); |
+ scoped_ptr<Textfield> textfield_child(new Textfield); |
+ textfield_parent->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); |
+ parent->GetRootView()->AddChildView(textfield_parent.get()); |
+ child->GetRootView()->AddChildView(textfield_child.get()); |
+ |
+ EXPECT_EQ(parent->GetInputMethod(), child->GetInputMethod()); |
+ |
+ textfield_parent->RequestFocus(); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, |
+ parent->GetInputMethod()->GetTextInputType()); |
+ |
+ textfield_child->RequestFocus(); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, |
+ parent->GetInputMethod()->GetTextInputType()); |
+ |
+// Window::Blur doesn't work for CrOS, because it uses NWA instead of DNWA and |
+// involves the AuraTestHelper which setup the input method as DummyInputMethod. |
+// Please refer to CreateWidget method above. |
+#if !defined(OS_CHROMEOS) |
+ child->GetNativeWindow()->Blur(); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
+ parent->GetInputMethod()->GetTextInputType()); |
+ |
+ child->GetNativeWindow()->Focus(); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, |
+ parent->GetInputMethod()->GetTextInputType()); |
+ |
+ textfield_parent->RequestFocus(); |
+ parent->GetNativeWindow()->Blur(); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
+ parent->GetInputMethod()->GetTextInputType()); |
+ |
+ parent->GetNativeWindow()->Focus(); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, |
+ parent->GetInputMethod()->GetTextInputType()); |
+#endif |
+} |
+ |
+// Test input method focus changes affected by focus changes cross 2 top |
+// windows. |
+TEST_F(WidgetTestInteractive, InputMethodFocus_2_top_windows) { |
+ scoped_ptr<Widget> widget1(CreateWidget()); |
+ scoped_ptr<Widget> widget2(CreateWidget()); |
+ scoped_ptr<Textfield> textfield1(new Textfield); |
+ scoped_ptr<Textfield> textfield2(new Textfield); |
+ textfield2->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); |
+ widget1->GetRootView()->AddChildView(textfield1.get()); |
+ widget2->GetRootView()->AddChildView(textfield2.get()); |
+ widget1->Show(); |
+ widget2->Show(); |
+ |
+ textfield1->RequestFocus(); |
+ textfield2->RequestFocus(); |
+ |
+ ActivatePlatformWindowSync(widget1.get()); |
+ |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, |
+ widget1->GetInputMethod()->GetTextInputType()); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
+ widget2->GetInputMethod()->GetTextInputType()); |
+ |
+ ActivatePlatformWindowSync(widget2.get()); |
+ |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
+ widget1->GetInputMethod()->GetTextInputType()); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, |
+ widget2->GetInputMethod()->GetTextInputType()); |
+} |
+ |
+// Test input method focus changes affected by textfield's state changes. |
+TEST_F(WidgetTestInteractive, InputMethodFocus_textfield) { |
+ scoped_ptr<Widget> widget(CreateWidget()); |
+ scoped_ptr<Textfield> textfield(new Textfield); |
+ widget->GetRootView()->AddChildView(textfield.get()); |
+ widget->Show(); |
+ ActivatePlatformWindowSync(widget.get()); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
+ widget->GetInputMethod()->GetTextInputType()); |
+ |
+ textfield->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
+ widget->GetInputMethod()->GetTextInputType()); |
+ |
+ textfield->RequestFocus(); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, |
+ widget->GetInputMethod()->GetTextInputType()); |
+ |
+ textfield->SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, |
+ widget->GetInputMethod()->GetTextInputType()); |
+ |
+ textfield->SetReadOnly(true); |
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
+ widget->GetInputMethod()->GetTextInputType()); |
+} |
+#endif // defined(USE_AURA) |
+ |
} // namespace test |
} // namespace views |