blob: 3ecc10ce74af946585003ea627ba65c0e7cccfec [file] [log] [blame]
// 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