blob: 261540a58f3c42832f731174c86b0156b6a14741 [file] [log] [blame]
// Copyright 2020 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 "components/exo/wm_helper_chromeos.h"
#include <memory>
#include <vector>
#include "ash/frame_throttler/frame_throttling_controller.h"
#include "ash/shell.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/notreached.h"
#include "components/exo/mock_vsync_timing_observer.h"
#include "components/exo/test/exo_test_base.h"
#include "components/exo/wm_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/drop_target_event.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-forward.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/manager/managed_display_info.h"
#include "ui/display/screen.h"
#include "ui/display/test/display_manager_test_api.h"
#include "ui/gfx/geometry/point_f.h"
namespace exo {
namespace {
using ::ui::mojom::DragOperation;
class MockDragDropObserver : public WMHelper::DragDropObserver {
public:
MockDragDropObserver(DragOperation drop_result) : drop_result_(drop_result) {}
~MockDragDropObserver() override = default;
// WMHelper::DragDropObserver:
void OnDragEntered(const ui::DropTargetEvent& event) override {}
aura::client::DragUpdateInfo OnDragUpdated(
const ui::DropTargetEvent& event) override {
return aura::client::DragUpdateInfo();
}
void OnDragExited() override {}
WMHelper::DragDropObserver::DropCallback GetDropCallback() override {
return base::BindOnce(
[](DragOperation drop_result, DragOperation& output_drag_op) {
output_drag_op = drop_result;
},
drop_result_);
}
private:
DragOperation drop_result_;
};
} // namespace
using WMHelperChromeOSTest = test::ExoTestBase;
TEST_F(WMHelperChromeOSTest, FrameThrottling) {
WMHelperChromeOS* wm_helper_chromeos =
static_cast<WMHelperChromeOS*>(wm_helper());
wm_helper_chromeos->AddFrameThrottlingObserver();
VSyncTimingManager& vsync_timing_manager =
wm_helper_chromeos->GetVSyncTimingManager();
MockVSyncTimingObserver observer;
vsync_timing_manager.AddObserver(&observer);
ash::FrameThrottlingController* ftc =
ash::Shell::Get()->frame_throttling_controller();
// Throttling should be off by default.
EXPECT_EQ(vsync_timing_manager.throttled_interval(), base::TimeDelta());
// Create two arc windows.
std::unique_ptr<aura::Window> arc_window_1 =
CreateAppWindow(gfx::Rect(), ash::AppType::ARC_APP);
std::unique_ptr<aura::Window> arc_window_2 =
CreateAppWindow(gfx::Rect(), ash::AppType::ARC_APP);
// Starting throttling on one of the two arc windows will have no effect on
// vsync time.
EXPECT_CALL(observer, OnUpdateVSyncParameters(testing::_, testing::_))
.Times(0);
ftc->StartThrottling({arc_window_1.get()});
EXPECT_EQ(vsync_timing_manager.throttled_interval(), base::TimeDelta());
// Both windows are to be throttled, vsync timing will be adjusted.
base::TimeDelta throttled_interval = base::Hertz(ftc->throttled_fps());
EXPECT_CALL(observer,
OnUpdateVSyncParameters(testing::_, throttled_interval));
ftc->StartThrottling({arc_window_1.get(), arc_window_2.get()});
EXPECT_EQ(vsync_timing_manager.throttled_interval(), throttled_interval);
EXPECT_CALL(observer,
OnUpdateVSyncParameters(testing::_,
viz::BeginFrameArgs::DefaultInterval()));
ftc->EndThrottling();
EXPECT_EQ(vsync_timing_manager.throttled_interval(), base::TimeDelta());
vsync_timing_manager.RemoveObserver(&observer);
wm_helper_chromeos->RemoveFrameThrottlingObserver();
}
TEST_F(WMHelperChromeOSTest, MultipleDragDropObservers) {
WMHelperChromeOS* wm_helper_chromeos =
static_cast<WMHelperChromeOS*>(wm_helper());
MockDragDropObserver observer_no_drop(DragOperation::kNone);
MockDragDropObserver observer_copy_drop(DragOperation::kCopy);
wm_helper_chromeos->AddDragDropObserver(&observer_no_drop);
ui::DropTargetEvent target_event(ui::OSExchangeData(), gfx::PointF(),
gfx::PointF(), ui::DragDropTypes::DRAG_NONE);
auto drop_cb = wm_helper_chromeos->GetDropCallback(target_event);
DragOperation output_drop_op = DragOperation::kNone;
std::move(drop_cb).Run(std::make_unique<ui::OSExchangeData>(),
output_drop_op);
EXPECT_EQ(output_drop_op, DragOperation::kNone);
wm_helper_chromeos->AddDragDropObserver(&observer_copy_drop);
drop_cb = wm_helper_chromeos->GetDropCallback(target_event);
std::move(drop_cb).Run(std::make_unique<ui::OSExchangeData>(),
output_drop_op);
EXPECT_NE(output_drop_op, DragOperation::kNone);
wm_helper_chromeos->RemoveDragDropObserver(&observer_no_drop);
wm_helper_chromeos->RemoveDragDropObserver(&observer_copy_drop);
}
TEST_F(WMHelperChromeOSTest, DockedModeShouldUseInternalAsDefault) {
UpdateDisplay("1920x1080*2, 600x400");
display::test::DisplayManagerTestApi(display_manager())
.SetFirstDisplayAsInternalDisplay();
auto display_list = display::Screen::GetScreen()->GetAllDisplays();
auto first_info = display_manager()->GetDisplayInfo(display_list[0].id());
auto second_info = display_manager()->GetDisplayInfo(display_list[1].id());
ASSERT_EQ(gfx::Size(1920, 1080), first_info.size_in_pixel());
ASSERT_EQ(first_info.id(), display::Display::InternalDisplayId());
std::vector<display::ManagedDisplayInfo> display_info_list{second_info};
display_manager()->OnNativeDisplaysChanged(display_info_list);
ASSERT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().id(),
second_info.id());
EXPECT_EQ(2.0f, GetDefaultDeviceScaleFactor());
}
} // namespace exo