| // Copyright 2017 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 "ash/system/palette/palette_tray.h" |
| |
| #include <memory> |
| #include <string> |
| |
| #include "ash/assistant/assistant_controller.h" |
| #include "ash/assistant/test/test_assistant_service.h" |
| #include "ash/highlighter/highlighter_controller.h" |
| #include "ash/highlighter/highlighter_controller_test_api.h" |
| #include "ash/public/cpp/ash_pref_names.h" |
| #include "ash/public/cpp/ash_switches.h" |
| #include "ash/public/cpp/stylus_utils.h" |
| #include "ash/public/interfaces/voice_interaction_controller.mojom.h" |
| #include "ash/root_window_controller.h" |
| #include "ash/session/session_controller.h" |
| #include "ash/session/test_session_controller_client.h" |
| #include "ash/shell.h" |
| #include "ash/shell_test_api.h" |
| #include "ash/system/palette/palette_tray_test_api.h" |
| #include "ash/system/palette/palette_utils.h" |
| #include "ash/system/palette/palette_welcome_bubble.h" |
| #include "ash/system/status_area_widget.h" |
| #include "ash/system/status_area_widget_test_helper.h" |
| #include "ash/test/ash_test_base.h" |
| #include "ash/test/ash_test_helper.h" |
| #include "ash/test_shell_delegate.h" |
| #include "ash/voice_interaction/voice_interaction_controller.h" |
| #include "base/command_line.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/run_loop.h" |
| #include "base/test/simple_test_tick_clock.h" |
| #include "chromeos/constants/chromeos_switches.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/session_manager/session_manager_types.h" |
| #include "ui/compositor/scoped_animation_duration_scale_mode.h" |
| #include "ui/display/test/display_manager_test_api.h" |
| #include "ui/events/base_event_utils.h" |
| #include "ui/events/devices/stylus_state.h" |
| #include "ui/events/event.h" |
| #include "ui/events/test/event_generator.h" |
| |
| namespace ash { |
| |
| class PaletteTrayTest : public AshTestBase { |
| public: |
| PaletteTrayTest() = default; |
| ~PaletteTrayTest() override = default; |
| |
| // Performs a tap on the palette tray button. |
| void PerformTap() { |
| ui::GestureEvent tap(0, 0, 0, base::TimeTicks(), |
| ui::GestureEventDetails(ui::ET_GESTURE_TAP)); |
| palette_tray_->PerformAction(tap); |
| } |
| |
| // Fake a stylus ejection. |
| void EjectStylus() { |
| test_api_->OnStylusStateChanged(ui::StylusState::REMOVED); |
| } |
| |
| // Fake a stylus insertion. |
| void InsertStylus() { |
| test_api_->OnStylusStateChanged(ui::StylusState::INSERTED); |
| } |
| |
| // AshTestBase: |
| void SetUp() override { |
| base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| switches::kAshEnablePaletteOnAllDisplays); |
| |
| stylus_utils::SetHasStylusInputForTesting(); |
| |
| AshTestBase::SetUp(); |
| |
| palette_tray_ = |
| StatusAreaWidgetTestHelper::GetStatusAreaWidget()->palette_tray(); |
| test_api_ = std::make_unique<PaletteTrayTestApi>(palette_tray_); |
| } |
| |
| protected: |
| PrefService* active_user_pref_service() { |
| return Shell::Get()->session_controller()->GetActivePrefService(); |
| } |
| |
| PrefService* local_state_pref_service() { |
| return ash_test_helper()->GetLocalStatePrefService(); |
| } |
| |
| PaletteTray* palette_tray_ = nullptr; // not owned |
| |
| std::unique_ptr<PaletteTrayTestApi> test_api_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(PaletteTrayTest); |
| }; |
| |
| // Verify the palette tray button exists and but is not visible initially. |
| TEST_F(PaletteTrayTest, PaletteTrayIsInvisible) { |
| ASSERT_TRUE(palette_tray_); |
| EXPECT_FALSE(palette_tray_->visible()); |
| } |
| |
| // Verify if the has seen stylus pref is not set initially, the palette tray |
| // should become visible after seeing a stylus event. |
| TEST_F(PaletteTrayTest, PaletteTrayVisibleAfterStylusSeen) { |
| ASSERT_FALSE(palette_tray_->visible()); |
| ASSERT_FALSE(local_state_pref_service()->GetBoolean(prefs::kHasSeenStylus)); |
| |
| // Send a stylus event. |
| ui::test::EventGenerator* generator = GetEventGenerator(); |
| generator->EnterPenPointerMode(); |
| generator->PressTouch(); |
| generator->ReleaseTouch(); |
| generator->ExitPenPointerMode(); |
| |
| EXPECT_TRUE(palette_tray_->visible()); |
| } |
| |
| // Verify if the has seen stylus pref is initially set, the palette tray is |
| // visible. |
| TEST_F(PaletteTrayTest, StylusSeenPrefInitiallySet) { |
| ASSERT_FALSE(palette_tray_->visible()); |
| local_state_pref_service()->SetBoolean(prefs::kHasSeenStylus, true); |
| |
| EXPECT_TRUE(palette_tray_->visible()); |
| } |
| |
| // Verify taps on the palette tray button results in expected behaviour. |
| TEST_F(PaletteTrayTest, PaletteTrayWorkflow) { |
| // Verify the palette tray button is not active, and the palette tray bubble |
| // is not shown initially. |
| EXPECT_FALSE(palette_tray_->is_active()); |
| EXPECT_FALSE(test_api_->tray_bubble_wrapper()); |
| |
| // Verify that by tapping the palette tray button, the button will become |
| // active and the palette tray bubble will be open. |
| PerformTap(); |
| EXPECT_TRUE(palette_tray_->is_active()); |
| EXPECT_TRUE(test_api_->tray_bubble_wrapper()); |
| |
| // Verify that activating a mode tool will close the palette tray bubble, but |
| // leave the palette tray button active. |
| test_api_->palette_tool_manager()->ActivateTool(PaletteToolId::LASER_POINTER); |
| EXPECT_TRUE(test_api_->palette_tool_manager()->IsToolActive( |
| PaletteToolId::LASER_POINTER)); |
| EXPECT_TRUE(palette_tray_->is_active()); |
| EXPECT_FALSE(test_api_->tray_bubble_wrapper()); |
| |
| // Verify that tapping the palette tray while a tool is active will deactivate |
| // the tool, and the palette tray button will not be active. |
| PerformTap(); |
| EXPECT_FALSE(palette_tray_->is_active()); |
| EXPECT_FALSE(test_api_->palette_tool_manager()->IsToolActive( |
| PaletteToolId::LASER_POINTER)); |
| |
| // Verify that activating a action tool will close the palette tray bubble and |
| // the palette tray button is will not be active. |
| PerformTap(); |
| ASSERT_TRUE(test_api_->tray_bubble_wrapper()); |
| test_api_->palette_tool_manager()->ActivateTool( |
| PaletteToolId::CAPTURE_SCREEN); |
| EXPECT_FALSE(test_api_->palette_tool_manager()->IsToolActive( |
| PaletteToolId::CAPTURE_SCREEN)); |
| // Wait for the tray bubble widget to close. |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_FALSE(test_api_->tray_bubble_wrapper()); |
| EXPECT_FALSE(palette_tray_->is_active()); |
| } |
| |
| // Verify that the palette tray button and bubble are as expected when modes |
| // that can be deactivated without pressing the palette tray button (such as |
| // capture region) are deactivated. |
| TEST_F(PaletteTrayTest, ModeToolDeactivatedAutomatically) { |
| // Open the palette tray with a tap. |
| PerformTap(); |
| ASSERT_TRUE(palette_tray_->is_active()); |
| ASSERT_TRUE(test_api_->tray_bubble_wrapper()); |
| |
| // Activate and deactivate the laser pointer tool. |
| test_api_->palette_tool_manager()->ActivateTool(PaletteToolId::LASER_POINTER); |
| ASSERT_TRUE(test_api_->palette_tool_manager()->IsToolActive( |
| PaletteToolId::LASER_POINTER)); |
| test_api_->palette_tool_manager()->DeactivateTool( |
| PaletteToolId::LASER_POINTER); |
| |
| // Verify the bubble is hidden and the button is inactive after deactivating |
| // the capture region tool. |
| EXPECT_FALSE(test_api_->tray_bubble_wrapper()); |
| EXPECT_FALSE(palette_tray_->is_active()); |
| } |
| |
| TEST_F(PaletteTrayTest, NoMetalayerToolViewCreated) { |
| EXPECT_FALSE( |
| test_api_->palette_tool_manager()->HasTool(PaletteToolId::METALAYER)); |
| } |
| |
| TEST_F(PaletteTrayTest, EnableStylusPref) { |
| local_state_pref_service()->SetBoolean(prefs::kHasSeenStylus, true); |
| |
| // kEnableStylusTools is true by default |
| ASSERT_TRUE( |
| active_user_pref_service()->GetBoolean(prefs::kEnableStylusTools)); |
| EXPECT_TRUE(palette_tray_->visible()); |
| |
| // Resetting the pref hides the palette tray. |
| active_user_pref_service()->SetBoolean(prefs::kEnableStylusTools, false); |
| EXPECT_FALSE(palette_tray_->visible()); |
| |
| // Setting the pref again shows the palette tray. |
| active_user_pref_service()->SetBoolean(prefs::kEnableStylusTools, true); |
| EXPECT_TRUE(palette_tray_->visible()); |
| } |
| |
| TEST_F(PaletteTrayTest, WelcomeBubbleVisibility) { |
| ASSERT_FALSE(active_user_pref_service()->GetBoolean( |
| prefs::kShownPaletteWelcomeBubble)); |
| EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting()); |
| |
| // Verify that the welcome bubble does not shown up after tapping the screen |
| // with a finger. |
| ui::test::EventGenerator* generator = GetEventGenerator(); |
| generator->PressTouch(); |
| generator->ReleaseTouch(); |
| EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting()); |
| |
| // Verify that the welcome bubble shows up after tapping the screen with a |
| // stylus for the first time. |
| generator->EnterPenPointerMode(); |
| generator->PressTouch(); |
| generator->ReleaseTouch(); |
| EXPECT_TRUE(test_api_->welcome_bubble()->GetBubbleViewForTesting()); |
| } |
| |
| // Base class for tests that rely on Assistant enabled. |
| class PaletteTrayTestWithVoiceInteraction : public PaletteTrayTest { |
| public: |
| PaletteTrayTestWithVoiceInteraction() { |
| feature_list_.InitAndEnableFeature(chromeos::switches::kAssistantFeature); |
| } |
| ~PaletteTrayTestWithVoiceInteraction() override = default; |
| |
| // PaletteTrayTest: |
| void SetUp() override { |
| PaletteTrayTest::SetUp(); |
| |
| // Instantiate EventGenerator now so that its constructor does not overwrite |
| // the simulated clock that is being installed below. |
| GetEventGenerator(); |
| |
| // Tests fail if event time is ever 0. |
| simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(10)); |
| ui::SetEventTickClockForTesting(&simulated_clock_); |
| |
| highlighter_test_api_ = std::make_unique<HighlighterControllerTestApi>( |
| Shell::Get()->highlighter_controller()); |
| |
| Shell::Get()->assistant_controller()->SetAssistant( |
| assistant_.CreateInterfacePtrAndBind()); |
| } |
| |
| void TearDown() override { |
| // This needs to be called first to reset the controller state before the |
| // shell instance gets torn down. |
| highlighter_test_api_.reset(); |
| PaletteTrayTest::TearDown(); |
| } |
| |
| protected: |
| bool metalayer_enabled() const { |
| return test_api_->palette_tool_manager()->IsToolActive( |
| PaletteToolId::METALAYER); |
| } |
| |
| bool highlighter_showing() const { |
| return highlighter_test_api_->IsShowingHighlighter(); |
| } |
| |
| void DragAndAssertMetalayer(const std::string& context, |
| const gfx::Point& origin, |
| int event_flags, |
| bool expected, |
| bool expected_on_press) { |
| SCOPED_TRACE(context); |
| |
| ui::test::EventGenerator* generator = GetEventGenerator(); |
| gfx::Point pos = origin; |
| generator->MoveTouch(pos); |
| generator->set_flags(event_flags); |
| generator->PressTouch(); |
| // If this gesture is supposed to enable the tool, it should have done it by |
| // now. |
| EXPECT_EQ(expected, metalayer_enabled()); |
| // Unlike the tool, the highlighter might become visible only after the |
| // first move, hence a separate parameter to check against. |
| EXPECT_EQ(expected_on_press, highlighter_showing()); |
| pos += gfx::Vector2d(1, 1); |
| generator->MoveTouch(pos); |
| // If this gesture is supposed to show the highlighter, it should have done |
| // it by now. |
| EXPECT_EQ(expected, highlighter_showing()); |
| EXPECT_EQ(expected, metalayer_enabled()); |
| generator->set_flags(ui::EF_NONE); |
| pos += gfx::Vector2d(1, 1); |
| generator->MoveTouch(pos); |
| EXPECT_EQ(expected, highlighter_showing()); |
| EXPECT_EQ(expected, metalayer_enabled()); |
| generator->ReleaseTouch(); |
| } |
| |
| void WaitDragAndAssertMetalayer(const std::string& context, |
| const gfx::Point& origin, |
| int event_flags, |
| bool expected, |
| bool expected_on_press) { |
| const int kStrokeGap = 1000; |
| simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(kStrokeGap)); |
| DragAndAssertMetalayer(context, origin, event_flags, expected, |
| expected_on_press); |
| } |
| |
| std::unique_ptr<HighlighterControllerTestApi> highlighter_test_api_; |
| |
| private: |
| TestAssistantService assistant_; |
| base::SimpleTestTickClock simulated_clock_; |
| base::test::ScopedFeatureList feature_list_; |
| |
| DISALLOW_COPY_AND_ASSIGN(PaletteTrayTestWithVoiceInteraction); |
| }; |
| |
| TEST_F(PaletteTrayTestWithVoiceInteraction, MetalayerToolViewCreated) { |
| EXPECT_TRUE( |
| test_api_->palette_tool_manager()->HasTool(PaletteToolId::METALAYER)); |
| } |
| |
| TEST_F(PaletteTrayTestWithVoiceInteraction, MetalayerToolActivatesHighlighter) { |
| ui::ScopedAnimationDurationScaleMode animation_duration_mode( |
| ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); |
| Shell::Get()->voice_interaction_controller()->NotifyStatusChanged( |
| mojom::VoiceInteractionState::RUNNING); |
| Shell::Get()->voice_interaction_controller()->NotifySettingsEnabled(true); |
| Shell::Get()->voice_interaction_controller()->NotifyContextEnabled(true); |
| Shell::Get()->voice_interaction_controller()->FlushForTesting(); |
| |
| ui::test::EventGenerator* generator = GetEventGenerator(); |
| generator->EnterPenPointerMode(); |
| |
| const gfx::Point origin(1, 1); |
| const gfx::Vector2d step(1, 1); |
| EXPECT_FALSE(palette_utils::PaletteContainsPointInScreen(origin + step)); |
| EXPECT_FALSE( |
| palette_utils::PaletteContainsPointInScreen(origin + step + step)); |
| |
| // Press/drag does not activate the highlighter unless the palette tool is |
| // activated. |
| DragAndAssertMetalayer("tool disabled", origin, ui::EF_NONE, |
| false /* no metalayer */, |
| false /* no highlighter on press */); |
| |
| // Activate the palette tool, still no highlighter. |
| test_api_->palette_tool_manager()->ActivateTool(PaletteToolId::METALAYER); |
| EXPECT_FALSE(highlighter_showing()); |
| |
| // Press/drag over a regular (non-palette) location. This should activate the |
| // highlighter. Note that a diagonal stroke does not create a valid selection. |
| highlighter_test_api_->ResetSelection(); |
| DragAndAssertMetalayer("tool enabled", origin, ui::EF_NONE, |
| true /* metalayer stays enabled after the press */, |
| true /* highlighter shown on press */); |
| // When metalayer is entered normally (not via stylus button), a failed |
| // selection should not exit the mode. |
| EXPECT_FALSE(highlighter_test_api_->HandleSelectionCalled()); |
| EXPECT_TRUE(metalayer_enabled()); |
| |
| // A successfull selection should exit the metalayer mode. |
| SCOPED_TRACE("horizontal stroke"); |
| highlighter_test_api_->ResetSelection(); |
| generator->MoveTouch(gfx::Point(100, 100)); |
| generator->PressTouch(); |
| EXPECT_TRUE(metalayer_enabled()); |
| generator->MoveTouch(gfx::Point(300, 100)); |
| generator->ReleaseTouch(); |
| EXPECT_TRUE(highlighter_test_api_->HandleSelectionCalled()); |
| EXPECT_FALSE(metalayer_enabled()); |
| |
| SCOPED_TRACE("drag over palette"); |
| highlighter_test_api_->DestroyPointerView(); |
| // Press/drag over the palette button. This should not activate the |
| // highlighter, but should disable the palette tool instead. |
| gfx::Point palette_point = palette_tray_->GetBoundsInScreen().CenterPoint(); |
| EXPECT_TRUE(palette_utils::PaletteContainsPointInScreen(palette_point)); |
| generator->MoveTouch(palette_point); |
| generator->PressTouch(); |
| EXPECT_FALSE(highlighter_showing()); |
| palette_point += gfx::Vector2d(1, 1); |
| EXPECT_TRUE(palette_utils::PaletteContainsPointInScreen(palette_point)); |
| generator->MoveTouch(palette_point); |
| EXPECT_FALSE(highlighter_showing()); |
| generator->ReleaseTouch(); |
| EXPECT_FALSE(metalayer_enabled()); |
| |
| // Disabling metalayer support in the delegate should disable the palette |
| // tool. |
| test_api_->palette_tool_manager()->ActivateTool(PaletteToolId::METALAYER); |
| Shell::Get()->voice_interaction_controller()->NotifyContextEnabled(false); |
| Shell::Get()->voice_interaction_controller()->FlushForTesting(); |
| EXPECT_FALSE(metalayer_enabled()); |
| |
| // With the metalayer disabled again, press/drag does not activate the |
| // highlighter. |
| DragAndAssertMetalayer("tool disabled again", origin, ui::EF_NONE, |
| false /* no metalayer */, |
| false /* no highlighter on press */); |
| } |
| |
| TEST_F(PaletteTrayTestWithVoiceInteraction, |
| StylusBarrelButtonActivatesHighlighter) { |
| ui::ScopedAnimationDurationScaleMode animation_duration_mode( |
| ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); |
| Shell::Get()->voice_interaction_controller()->NotifyStatusChanged( |
| mojom::VoiceInteractionState::NOT_READY); |
| Shell::Get()->voice_interaction_controller()->NotifySettingsEnabled(false); |
| Shell::Get()->voice_interaction_controller()->NotifyContextEnabled(false); |
| Shell::Get()->voice_interaction_controller()->FlushForTesting(); |
| |
| ui::test::EventGenerator* generator = GetEventGenerator(); |
| generator->EnterPenPointerMode(); |
| |
| const gfx::Point origin(1, 1); |
| const gfx::Vector2d step(1, 1); |
| |
| EXPECT_FALSE(palette_utils::PaletteContainsPointInScreen(origin)); |
| EXPECT_FALSE(palette_utils::PaletteContainsPointInScreen(origin + step)); |
| EXPECT_FALSE( |
| palette_utils::PaletteContainsPointInScreen(origin + step + step)); |
| |
| // Press and drag while holding down the stylus button, no highlighter unless |
| // the metalayer support is fully enabled and the the framework is ready. |
| WaitDragAndAssertMetalayer("nothing enabled", origin, |
| ui::EF_LEFT_MOUSE_BUTTON, false /* no metalayer */, |
| false /* no highlighter on press */); |
| |
| // Enable one of the two user prefs, should not be sufficient. |
| Shell::Get()->voice_interaction_controller()->NotifyContextEnabled(true); |
| Shell::Get()->voice_interaction_controller()->FlushForTesting(); |
| WaitDragAndAssertMetalayer("one pref enabled", origin, |
| ui::EF_LEFT_MOUSE_BUTTON, false /* no metalayer */, |
| false /* no highlighter on press */); |
| |
| // Enable the other user pref, still not sufficient. |
| Shell::Get()->voice_interaction_controller()->NotifySettingsEnabled(true); |
| Shell::Get()->voice_interaction_controller()->FlushForTesting(); |
| WaitDragAndAssertMetalayer("two prefs enabled", origin, |
| ui::EF_LEFT_MOUSE_BUTTON, false /* no metalayer */, |
| false /* no highlighter on press */); |
| |
| // Once the service is ready, the button should start working. |
| Shell::Get()->voice_interaction_controller()->NotifyStatusChanged( |
| mojom::VoiceInteractionState::RUNNING); |
| Shell::Get()->voice_interaction_controller()->FlushForTesting(); |
| |
| // Press and drag with no button, still no highlighter. |
| WaitDragAndAssertMetalayer("all enabled, no button ", origin, ui::EF_NONE, |
| false /* no metalayer */, |
| false /* no highlighter on press */); |
| |
| // Press/drag with while holding down the stylus button, but over the palette |
| // tray. This should activate neither the palette tool nor the highlighter. |
| gfx::Point palette_point = palette_tray_->GetBoundsInScreen().CenterPoint(); |
| EXPECT_TRUE(palette_utils::PaletteContainsPointInScreen(palette_point)); |
| EXPECT_TRUE( |
| palette_utils::PaletteContainsPointInScreen(palette_point + step)); |
| EXPECT_TRUE( |
| palette_utils::PaletteContainsPointInScreen(palette_point + step + step)); |
| WaitDragAndAssertMetalayer("drag over palette", palette_point, |
| ui::EF_LEFT_MOUSE_BUTTON, false /* no metalayer */, |
| false /* no highlighter on press */); |
| |
| // Perform a regular stroke (no button), followed by a button-down stroke |
| // without a pause. This should not trigger metalayer. |
| DragAndAssertMetalayer("writing, no button", origin, ui::EF_NONE, |
| false /* no metalayer */, |
| false /* no highlighter on press */); |
| DragAndAssertMetalayer("writing, with button ", origin, |
| ui::EF_LEFT_MOUSE_BUTTON, false /* no metalayer */, |
| false /* no highlighter on press */); |
| |
| // Wait, then press/drag while holding down the stylus button over a regular |
| // location. This should activate the palette tool and the highlighter. |
| WaitDragAndAssertMetalayer("with button", origin, ui::EF_LEFT_MOUSE_BUTTON, |
| true /* enables metalayer */, |
| false /* no highlighter on press */); |
| // Metalayer mode entered via the stylus button should not be sticky. |
| EXPECT_FALSE(metalayer_enabled()); |
| |
| // Repeat the previous step without a pause, make sure that the palette tool |
| // is not toggled, and the highlighter is enabled immediately. |
| DragAndAssertMetalayer("with button, again", origin, ui::EF_LEFT_MOUSE_BUTTON, |
| true /* enables metalayer */, |
| true /* highlighter shown on press */); |
| |
| // Same after a pause. |
| WaitDragAndAssertMetalayer( |
| "with button, after a pause", origin, ui::EF_LEFT_MOUSE_BUTTON, |
| true /* enables metalayer */, true /* highlighter shown on press */); |
| |
| // The barrel button should not work on the lock screen. |
| highlighter_test_api_->DestroyPointerView(); |
| GetSessionControllerClient()->RequestLockScreen(); |
| EXPECT_FALSE(test_api_->palette_tool_manager()->IsToolActive( |
| PaletteToolId::METALAYER)); |
| WaitDragAndAssertMetalayer("screen locked", origin, ui::EF_LEFT_MOUSE_BUTTON, |
| false /* no metalayer */, |
| false /* no highlighter on press */); |
| |
| // Unlock the screen, the barrel button should work again. |
| GetSessionControllerClient()->UnlockScreen(); |
| WaitDragAndAssertMetalayer( |
| "screen unlocked", origin, ui::EF_LEFT_MOUSE_BUTTON, |
| true /* enables metalayer */, false /* no highlighter on press */); |
| |
| // Disable the metalayer support. |
| // This should deactivate both the palette tool and the highlighter. |
| Shell::Get()->voice_interaction_controller()->NotifyContextEnabled(false); |
| Shell::Get()->voice_interaction_controller()->FlushForTesting(); |
| EXPECT_FALSE(test_api_->palette_tool_manager()->IsToolActive( |
| PaletteToolId::METALAYER)); |
| |
| highlighter_test_api_->DestroyPointerView(); |
| EXPECT_FALSE(highlighter_showing()); |
| DragAndAssertMetalayer("disabled", origin, ui::EF_LEFT_MOUSE_BUTTON, |
| false /* no metalayer */, |
| false /* no highlighter on press */); |
| } |
| |
| // Base class for tests that need to simulate an internal stylus. |
| class PaletteTrayTestWithInternalStylus : public PaletteTrayTest { |
| public: |
| PaletteTrayTestWithInternalStylus() { |
| base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| switches::kHasInternalStylus); |
| } |
| ~PaletteTrayTestWithInternalStylus() override = default; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(PaletteTrayTestWithInternalStylus); |
| }; |
| |
| // Verify the palette tray button exists and is visible if the device has an |
| // internal stylus. |
| TEST_F(PaletteTrayTestWithInternalStylus, Visible) { |
| ASSERT_TRUE(palette_tray_); |
| EXPECT_TRUE(palette_tray_->visible()); |
| } |
| |
| // Verify that when entering or exiting the lock screen, the behavior of the |
| // palette tray button is as expected. |
| TEST_F(PaletteTrayTestWithInternalStylus, PaletteTrayOnLockScreenBehavior) { |
| ASSERT_TRUE(palette_tray_->visible()); |
| |
| PaletteToolManager* manager = test_api_->palette_tool_manager(); |
| manager->ActivateTool(PaletteToolId::LASER_POINTER); |
| EXPECT_TRUE(manager->IsToolActive(PaletteToolId::LASER_POINTER)); |
| |
| // Verify that when entering the lock screen, the palette tray button is |
| // hidden, and the tool that was active is no longer active. |
| GetSessionControllerClient()->RequestLockScreen(); |
| EXPECT_FALSE(manager->IsToolActive(PaletteToolId::LASER_POINTER)); |
| EXPECT_FALSE(palette_tray_->visible()); |
| |
| // Verify that when logging back in the tray is visible, but the tool that was |
| // active before locking the screen is still inactive. |
| GetSessionControllerClient()->UnlockScreen(); |
| EXPECT_TRUE(palette_tray_->visible()); |
| EXPECT_FALSE(manager->IsToolActive(PaletteToolId::LASER_POINTER)); |
| } |
| |
| // Verify a tool deactivates when the palette bubble is opened while the tool |
| // is active. |
| TEST_F(PaletteTrayTestWithInternalStylus, ToolDeactivatesWhenOpeningBubble) { |
| ASSERT_TRUE(palette_tray_->visible()); |
| |
| palette_tray_->ShowBubble(false /* show_by_click */); |
| EXPECT_TRUE(test_api_->tray_bubble_wrapper()); |
| PaletteToolManager* manager = test_api_->palette_tool_manager(); |
| manager->ActivateTool(PaletteToolId::LASER_POINTER); |
| EXPECT_TRUE(manager->IsToolActive(PaletteToolId::LASER_POINTER)); |
| EXPECT_FALSE(test_api_->tray_bubble_wrapper()); |
| |
| palette_tray_->ShowBubble(false /* show_by_click */); |
| EXPECT_TRUE(test_api_->tray_bubble_wrapper()); |
| EXPECT_FALSE(manager->IsToolActive(PaletteToolId::LASER_POINTER)); |
| } |
| |
| // Verify the palette welcome bubble is shown the first time the stylus is |
| // removed. |
| TEST_F(PaletteTrayTestWithInternalStylus, WelcomeBubbleShownOnEject) { |
| active_user_pref_service()->SetBoolean(prefs::kLaunchPaletteOnEjectEvent, |
| false); |
| ASSERT_FALSE(active_user_pref_service()->GetBoolean( |
| prefs::kShownPaletteWelcomeBubble)); |
| EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting()); |
| |
| EjectStylus(); |
| EXPECT_TRUE(test_api_->welcome_bubble()->GetBubbleViewForTesting()); |
| } |
| |
| // Verify if the pref which tracks if the welcome bubble has been shown before |
| // is true, the welcome bubble is not shown when the stylus is removed. |
| TEST_F(PaletteTrayTestWithInternalStylus, WelcomeBubbleNotShownIfShownBefore) { |
| active_user_pref_service()->SetBoolean(prefs::kLaunchPaletteOnEjectEvent, |
| false); |
| active_user_pref_service()->SetBoolean(prefs::kShownPaletteWelcomeBubble, |
| true); |
| EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting()); |
| |
| EjectStylus(); |
| EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting()); |
| } |
| |
| // Verify that the bubble does not get shown if the auto open palette setting is |
| // true. |
| TEST_F(PaletteTrayTestWithInternalStylus, |
| WelcomeBubbleNotShownIfAutoOpenPaletteTrue) { |
| ASSERT_TRUE(active_user_pref_service()->GetBoolean( |
| prefs::kLaunchPaletteOnEjectEvent)); |
| active_user_pref_service()->SetBoolean(prefs::kShownPaletteWelcomeBubble, |
| false); |
| EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting()); |
| |
| EjectStylus(); |
| EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting()); |
| } |
| |
| // Verify that the bubble does not get shown if a stylus event has been seen by |
| // the tray prior to the first stylus ejection. |
| TEST_F(PaletteTrayTestWithInternalStylus, |
| WelcomeBubbleNotShownIfStylusTouchTray) { |
| ASSERT_FALSE(active_user_pref_service()->GetBoolean( |
| prefs::kShownPaletteWelcomeBubble)); |
| EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting()); |
| |
| ui::test::EventGenerator* generator = GetEventGenerator(); |
| generator->EnterPenPointerMode(); |
| generator->set_current_screen_location( |
| palette_tray_->GetBoundsInScreen().CenterPoint()); |
| generator->PressTouch(); |
| generator->ReleaseTouch(); |
| |
| EXPECT_TRUE(active_user_pref_service()->GetBoolean( |
| prefs::kShownPaletteWelcomeBubble)); |
| EjectStylus(); |
| EXPECT_FALSE(test_api_->welcome_bubble()->GetBubbleViewForTesting()); |
| } |
| |
| // Verify that palette bubble is shown/hidden on stylus eject/insert iff the |
| // auto open palette setting is true. |
| TEST_F(PaletteTrayTestWithInternalStylus, PaletteBubbleShownOnEject) { |
| // kLaunchPaletteOnEjectEvent is true by default |
| ASSERT_TRUE(active_user_pref_service()->GetBoolean( |
| prefs::kLaunchPaletteOnEjectEvent)); |
| |
| // Removing the stylus shows the bubble. |
| EjectStylus(); |
| EXPECT_TRUE(palette_tray_->GetBubbleView()); |
| |
| // Inserting the stylus hides the bubble. |
| InsertStylus(); |
| EXPECT_FALSE(palette_tray_->GetBubbleView()); |
| |
| // Removing the stylus while kLaunchPaletteOnEjectEvent==false does nothing. |
| active_user_pref_service()->SetBoolean(prefs::kLaunchPaletteOnEjectEvent, |
| false); |
| EjectStylus(); |
| EXPECT_FALSE(palette_tray_->GetBubbleView()); |
| InsertStylus(); |
| |
| // Removing the stylus while kEnableStylusTools==false does nothing. |
| active_user_pref_service()->SetBoolean(prefs::kLaunchPaletteOnEjectEvent, |
| true); |
| active_user_pref_service()->SetBoolean(prefs::kEnableStylusTools, false); |
| EjectStylus(); |
| EXPECT_FALSE(palette_tray_->GetBubbleView()); |
| InsertStylus(); |
| |
| // Set both prefs to true, removing should work again. |
| active_user_pref_service()->SetBoolean(prefs::kEnableStylusTools, true); |
| EjectStylus(); |
| EXPECT_TRUE(palette_tray_->GetBubbleView()); |
| |
| // Inserting the stylus should disable a currently selected tool. |
| test_api_->palette_tool_manager()->ActivateTool(PaletteToolId::LASER_POINTER); |
| EXPECT_TRUE(test_api_->palette_tool_manager()->IsToolActive( |
| PaletteToolId::LASER_POINTER)); |
| InsertStylus(); |
| EXPECT_FALSE(test_api_->palette_tool_manager()->IsToolActive( |
| PaletteToolId::LASER_POINTER)); |
| } |
| |
| // Base class for tests that need to simulate an internal stylus, and need to |
| // start without an active session. |
| class PaletteTrayNoSessionTestWithInternalStylus : public NoSessionAshTestBase { |
| public: |
| PaletteTrayNoSessionTestWithInternalStylus() { |
| base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| switches::kHasInternalStylus); |
| stylus_utils::SetHasStylusInputForTesting(); |
| } |
| ~PaletteTrayNoSessionTestWithInternalStylus() override = default; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(PaletteTrayNoSessionTestWithInternalStylus); |
| }; |
| |
| // Verify that the palette tray is created on an external display, but it is not |
| // shown, and the palette tray bubble does not appear when the stylus is |
| // ejected. |
| TEST_F(PaletteTrayNoSessionTestWithInternalStylus, |
| ExternalMonitorBubbleNotShownOnEject) { |
| // Fakes a stylus event with state |state| on all palette trays. |
| auto fake_stylus_event_on_all_trays = [](ui::StylusState state) { |
| Shell::RootWindowControllerList controllers = |
| Shell::GetAllRootWindowControllers(); |
| for (size_t i = 0; i < controllers.size(); ++i) { |
| PaletteTray* tray = controllers[i]->GetStatusAreaWidget()->palette_tray(); |
| PaletteTrayTestApi api(tray); |
| api.OnStylusStateChanged(state); |
| } |
| }; |
| |
| // Add a external display, then sign in. |
| UpdateDisplay("200x200,200x200"); |
| display::test::DisplayManagerTestApi(display_manager()) |
| .SetFirstDisplayAsInternalDisplay(); |
| Shell::RootWindowControllerList controllers = |
| Shell::GetAllRootWindowControllers(); |
| ASSERT_EQ(2u, controllers.size()); |
| SimulateUserLogin("test@test.com"); |
| |
| PaletteTray* main_tray = |
| controllers[0]->GetStatusAreaWidget()->palette_tray(); |
| PaletteTray* external_tray = |
| controllers[1]->GetStatusAreaWidget()->palette_tray(); |
| |
| // The palette tray on the external monitor is not visible. |
| EXPECT_TRUE(main_tray->visible()); |
| EXPECT_FALSE(external_tray->visible()); |
| |
| // Removing the stylus shows the bubble only on the main palette tray. |
| fake_stylus_event_on_all_trays(ui::StylusState::REMOVED); |
| EXPECT_TRUE(main_tray->GetBubbleView()); |
| EXPECT_FALSE(external_tray->GetBubbleView()); |
| |
| // Inserting the stylus hides the bubble on both palette trays. |
| fake_stylus_event_on_all_trays(ui::StylusState::INSERTED); |
| EXPECT_FALSE(main_tray->GetBubbleView()); |
| EXPECT_FALSE(external_tray->GetBubbleView()); |
| } |
| |
| } // namespace ash |