Chromium Code Reviews| 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 |