2
* Copyright Ā© 2013 Canonical Ltd.
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License version 3 as
6
* published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Authored by: Kevin DuBois <kevin.dubois@canonical.com>
19
#include "src/server/scene/surface_data.h"
21
#include "mir/geometry/rectangle.h"
23
#include "mir_test/fake_shared.h"
26
#include <gtest/gtest.h>
27
#include <gmock/gmock.h>
29
namespace mc = mir::compositor;
30
namespace mt = mir::test;
31
namespace mi = mir::input;
32
namespace ms = mir::scene;
33
namespace geom = mir::geometry;
40
MOCK_METHOD0(call, void());
43
struct SurfaceDataTest : public testing::Test
47
name = std::string("aa");
48
top_left = geom::Point{geom::X{4}, geom::Y{7}};
49
size = geom::Size{5, 9};
50
rect = geom::Rectangle{top_left, size};
51
null_change_cb = []{};
52
mock_change_cb = std::bind(&MockCallback::call, &mock_callback);
59
testing::NiceMock<MockCallback> mock_callback;
60
std::function<void()> null_change_cb;
61
std::function<void()> mock_change_cb;
66
TEST_F(SurfaceDataTest, basics)
68
ms::SurfaceData data{name, rect, null_change_cb, false};
69
EXPECT_EQ(name, data.name());
70
EXPECT_EQ(rect.size, data.size());
71
EXPECT_EQ(rect.top_left, data.position());
72
EXPECT_FALSE(data.shaped());
75
TEST_F(SurfaceDataTest, update_position)
77
EXPECT_CALL(mock_callback, call())
80
ms::SurfaceData storage{name, rect, mock_change_cb, false};
81
EXPECT_EQ(rect.top_left, storage.position());
83
auto new_top_left = geom::Point{geom::X{6}, geom::Y{10}};
84
storage.move_to(new_top_left);
85
EXPECT_EQ(new_top_left, storage.position());
88
TEST_F(SurfaceDataTest, update_size)
90
geom::Size const new_size{34, 56};
92
EXPECT_CALL(mock_callback, call())
95
ms::SurfaceData storage{name, rect, mock_change_cb, false};
96
EXPECT_EQ(rect.size, storage.size());
97
EXPECT_NE(new_size, storage.size());
99
auto old_transformation = storage.transformation();
101
storage.resize(new_size);
102
EXPECT_EQ(new_size, storage.size());
103
EXPECT_NE(old_transformation, storage.transformation());
106
TEST_F(SurfaceDataTest, test_surface_set_rotation_updates_transform)
108
EXPECT_CALL(mock_callback, call())
111
ms::SurfaceData storage{name, rect, mock_change_cb, false};
112
auto original_transformation = storage.transformation();
114
storage.apply_rotation(60.0f, glm::vec3{0.0f, 0.0f, 1.0f});
115
auto rotated_transformation = storage.transformation();
116
EXPECT_NE(original_transformation, rotated_transformation);
119
TEST_F(SurfaceDataTest, test_surface_transformation_cache_refreshes)
121
using namespace testing;
123
const geom::Size sz{geom::Width{85}, geom::Height{43}};
124
const geom::Rectangle origin{geom::Point{geom::X{77}, geom::Y{88}}, sz};
125
const geom::Rectangle moved_pt{geom::Point{geom::X{55}, geom::Y{66}}, sz};
126
ms::SurfaceData storage{name, origin, null_change_cb, false};
128
glm::mat4 t0 = storage.transformation();
129
storage.move_to(moved_pt.top_left);
130
EXPECT_NE(t0, storage.transformation());
131
storage.move_to(origin.top_left);
132
EXPECT_EQ(t0, storage.transformation());
134
storage.apply_rotation(60.0f, glm::vec3{0.0f, 0.0f, 1.0f});
135
glm::mat4 t1 = storage.transformation();
139
TEST_F(SurfaceDataTest, test_surface_set_alpha_notifies_changes)
141
using namespace testing;
142
EXPECT_CALL(mock_callback, call())
145
ms::SurfaceData surface_state{name, rect, mock_change_cb, false};
148
surface_state.apply_alpha(0.5f);
149
EXPECT_THAT(alpha, FloatEq(surface_state.alpha()));
152
TEST_F(SurfaceDataTest, test_surface_is_opaque_by_default)
154
using namespace testing;
155
ms::SurfaceData surface_state{name, rect, null_change_cb, false};
156
EXPECT_THAT(1.0f, FloatEq(surface_state.alpha()));
157
EXPECT_FALSE(surface_state.shaped());
160
TEST_F(SurfaceDataTest, test_surface_apply_rotation)
162
EXPECT_CALL(mock_callback, call())
165
ms::SurfaceData surface_state{name, rect, mock_change_cb, false};
166
surface_state.apply_rotation(60.0f, glm::vec3{0.0f, 0.0f, 1.0f});
169
TEST_F(SurfaceDataTest, test_surface_should_be_rendered_in)
171
ms::SurfaceData surface_state{name, rect, mock_change_cb, false};
172
geom::Rectangle output_rect{geom::Point{0,0}, geom::Size{100, 100}};
174
//not renderable by default
175
EXPECT_FALSE(surface_state.should_be_rendered_in(rect));
177
surface_state.set_hidden(false);
178
//not renderable if no first frame has been posted by client, regardless of hide state
179
EXPECT_FALSE(surface_state.should_be_rendered_in(output_rect));
180
surface_state.set_hidden(true);
181
EXPECT_FALSE(surface_state.should_be_rendered_in(output_rect));
183
surface_state.frame_posted();
184
EXPECT_FALSE(surface_state.should_be_rendered_in(output_rect));
186
surface_state.set_hidden(false);
187
EXPECT_TRUE(surface_state.should_be_rendered_in(output_rect));
189
// Not renderable if not overlapping with supplied rect
190
geom::Rectangle output_rect1{geom::Point{100,100}, geom::Size{100, 100}};
191
EXPECT_FALSE(surface_state.should_be_rendered_in(output_rect1));
194
TEST_F(SurfaceDataTest, test_surface_hidden_notifies_changes)
196
using namespace testing;
197
EXPECT_CALL(mock_callback, call())
200
ms::SurfaceData surface_state{name, rect, mock_change_cb, false};
201
surface_state.set_hidden(true);
204
TEST_F(SurfaceDataTest, test_surface_frame_posted_notifies_changes)
206
using namespace testing;
207
EXPECT_CALL(mock_callback, call())
210
ms::SurfaceData surface_state{name, rect, mock_change_cb, false};
211
surface_state.frame_posted();
214
// a 1x1 window at (1,1) will get events at (1,1)
215
TEST_F(SurfaceDataTest, default_region_is_surface_rectangle)
218
geom::Size one_by_one{geom::Width{1}, geom::Height{1}};
219
ms::SurfaceData surface_state{name, geom::Rectangle{pt, one_by_one}, mock_change_cb, false};
221
std::vector<geom::Point> contained_pt
223
geom::Point{geom::X{1}, geom::Y{1}}
226
for(auto x = 0; x <= 3; x++)
228
for(auto y = 0; y <= 3; y++)
230
auto test_pt = geom::Point{x, y};
231
auto contains = surface_state.contains(test_pt);
232
if (std::find(contained_pt.begin(), contained_pt.end(), test_pt) != contained_pt.end())
234
EXPECT_TRUE(contains);
238
EXPECT_FALSE(contains);
244
TEST_F(SurfaceDataTest, set_input_region)
246
std::vector<geom::Rectangle> const rectangles = {
247
{{geom::X{0}, geom::Y{0}}, {geom::Width{1}, geom::Height{1}}}, //region0
248
{{geom::X{1}, geom::Y{1}}, {geom::Width{1}, geom::Height{1}}} //region1
251
ms::SurfaceData surface_state{name, rect, mock_change_cb, false};
252
surface_state.set_input_region(rectangles);
254
std::vector<geom::Point> contained_pt
257
geom::Point{geom::X{0}, geom::Y{0}},
259
geom::Point{geom::X{1}, geom::Y{1}},
262
for(auto x = 0; x <= 3; x++)
264
for(auto y = 0; y <= 3; y++)
266
auto test_pt = geom::Point{x, y};
267
auto contains = surface_state.contains(test_pt);
268
if (std::find(contained_pt.begin(), contained_pt.end(), test_pt) != contained_pt.end())
270
EXPECT_TRUE(contains);
274
EXPECT_FALSE(contains);