1 // Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4
5 #include "include/base/cef_callback.h"
6 #include "include/cef_pack_strings.h"
7 #include "include/views/cef_panel.h"
8 #include "include/views/cef_panel_delegate.h"
9 #include "include/views/cef_scroll_view.h"
10 #include "include/wrapper/cef_closure_task.h"
11 #include "tests/ceftests/thread_helper.h"
12 #include "tests/ceftests/views/test_window_delegate.h"
13 #include "tests/gtest/include/gtest/gtest.h"
14
15 #define SCROLL_VIEW_TEST_ASYNC(name) \
16 UI_THREAD_TEST_ASYNC(ViewsScrollViewTest, name)
17
18 namespace {
19
20 const int kScrollViewID = 1;
21 const int kContentPanelID = 2;
22
23 // Make the Panel larger then the Window so scroll bars appear.
24 const int kContentPanelSize = TestWindowDelegate::kWSize + 200;
25
26 class TestScrollViewDelegate : public CefViewDelegate {
27 public:
TestScrollViewDelegate()28 TestScrollViewDelegate() {}
29
GetPreferredSize(CefRefPtr<CefView> view)30 CefSize GetPreferredSize(CefRefPtr<CefView> view) override {
31 EXPECT_EQ(kScrollViewID, view->GetID());
32 got_get_preferred_size_ = true;
33 return CefSize(kContentPanelSize, kContentPanelSize);
34 }
35
36 bool got_get_preferred_size_ = false;
37
38 private:
39 IMPLEMENT_REFCOUNTING(TestScrollViewDelegate);
40 DISALLOW_COPY_AND_ASSIGN(TestScrollViewDelegate);
41 };
42
43 class TestPanelDelegate : public CefPanelDelegate {
44 public:
TestPanelDelegate()45 TestPanelDelegate() {}
46
GetPreferredSize(CefRefPtr<CefView> view)47 CefSize GetPreferredSize(CefRefPtr<CefView> view) override {
48 EXPECT_EQ(kContentPanelID, view->GetID());
49 got_get_preferred_size_ = true;
50 return CefSize(kContentPanelSize, kContentPanelSize);
51 }
52
53 bool got_get_preferred_size_ = false;
54
55 private:
56 IMPLEMENT_REFCOUNTING(TestPanelDelegate);
57 DISALLOW_COPY_AND_ASSIGN(TestPanelDelegate);
58 };
59
RunScrollViewLayout(bool with_delegate,CefRefPtr<CefWindow> window)60 void RunScrollViewLayout(bool with_delegate, CefRefPtr<CefWindow> window) {
61 CefRefPtr<TestScrollViewDelegate> scroll_view_delegate;
62 CefRefPtr<TestPanelDelegate> panel_delegate;
63 if (with_delegate) {
64 scroll_view_delegate = new TestScrollViewDelegate();
65 panel_delegate = new TestPanelDelegate();
66 }
67
68 CefRefPtr<CefScrollView> scroll_view =
69 CefScrollView::CreateScrollView(scroll_view_delegate);
70 EXPECT_TRUE(scroll_view.get());
71 EXPECT_TRUE(scroll_view->AsScrollView().get());
72
73 // Verify default state.
74 EXPECT_FALSE(scroll_view->GetContentView().get());
75 EXPECT_EQ(CefRect(0, 0, 0, 0), scroll_view->GetVisibleContentRect());
76 EXPECT_FALSE(scroll_view->HasHorizontalScrollbar());
77 EXPECT_FALSE(scroll_view->HasVerticalScrollbar());
78
79 scroll_view->SetID(kScrollViewID);
80 scroll_view->SetBackgroundColor(CefColorSetARGB(255, 0, 255, 0));
81
82 CefRefPtr<CefPanel> content_panel = CefPanel::CreatePanel(panel_delegate);
83 content_panel->SetID(kContentPanelID);
84 content_panel->SetBackgroundColor(CefColorSetARGB(255, 255, 0, 0));
85
86 if (!with_delegate) {
87 // Explicitly set the content panel size. Otherwise, it will come from the
88 // delegate.
89 content_panel->SetSize(CefSize(kContentPanelSize, kContentPanelSize));
90 }
91
92 scroll_view->SetContentView(content_panel);
93 EXPECT_TRUE(content_panel->IsSame(scroll_view->GetContentView()));
94
95 window->AddChildView(scroll_view);
96
97 // Force layout.
98 window->Layout();
99
100 EXPECT_TRUE(scroll_view->HasHorizontalScrollbar());
101 EXPECT_TRUE(scroll_view->HasVerticalScrollbar());
102
103 if (with_delegate) {
104 // Layout() of the ScrollView no longer needs to call us for the size,
105 // see https://crrev.com/2701734b44.
106 EXPECT_FALSE(scroll_view_delegate->got_get_preferred_size_);
107 EXPECT_TRUE(panel_delegate->got_get_preferred_size_);
108 }
109
110 window->Show();
111
112 // With default FillLayout the ScrollView should be the size of the Window's
113 // client area.
114 const CefRect& client_bounds = window->GetClientAreaBoundsInScreen();
115 const CefRect& scroll_view_bounds = scroll_view->GetBoundsInScreen();
116 EXPECT_EQ(client_bounds, scroll_view_bounds);
117
118 // Content panel size should be unchanged.
119 const CefSize& content_panel_size = content_panel->GetSize();
120 EXPECT_EQ(CefSize(kContentPanelSize, kContentPanelSize), content_panel_size);
121
122 const int sb_height = scroll_view->GetHorizontalScrollbarHeight();
123 EXPECT_GT(sb_height, 0);
124 const int sb_width = scroll_view->GetVerticalScrollbarWidth();
125 EXPECT_GT(sb_width, 0);
126
127 // Verify visible content panel region.
128 const CefRect& visible_rect = scroll_view->GetVisibleContentRect();
129 EXPECT_EQ(CefRect(0, 0, scroll_view_bounds.width - sb_width,
130 scroll_view_bounds.height - sb_height),
131 visible_rect);
132 }
133
ScrollViewLayout(CefRefPtr<CefWaitableEvent> event,bool with_delegate)134 void ScrollViewLayout(CefRefPtr<CefWaitableEvent> event, bool with_delegate) {
135 auto config = std::make_unique<TestWindowDelegate::Config>();
136 config->on_window_created =
137 base::BindOnce(RunScrollViewLayout, with_delegate);
138 TestWindowDelegate::RunTest(event, std::move(config));
139 }
140
ScrollViewLayoutWithDelegateImpl(CefRefPtr<CefWaitableEvent> event)141 void ScrollViewLayoutWithDelegateImpl(CefRefPtr<CefWaitableEvent> event) {
142 ScrollViewLayout(event, true);
143 }
144
ScrollViewLayoutNoDelegateImpl(CefRefPtr<CefWaitableEvent> event)145 void ScrollViewLayoutNoDelegateImpl(CefRefPtr<CefWaitableEvent> event) {
146 ScrollViewLayout(event, false);
147 }
148
149 } // namespace
150
151 // Test ScrollView layout. This is primarily to exercise exposed CEF APIs and is
152 // not intended to comprehensively test ScrollView-related behavior (which we
153 // presume that Chromium is testing).
154 SCROLL_VIEW_TEST_ASYNC(ScrollViewLayoutWithDelegate)
155 SCROLL_VIEW_TEST_ASYNC(ScrollViewLayoutNoDelegate)
156