2
* Copyright © 2014 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: Nick Dedekind <nick.dedekind@canonical.com>
19
#include "mir_toolkit/mir_client_library.h"
20
#include "mir_toolkit/mir_client_library_debug.h"
22
#include "mir/shell/surface_coordinator_wrapper.h"
24
#include "mir/scene/surface.h"
25
#include "mir/scene/surface_creation_parameters.h"
27
#include "mir_test_framework/stubbed_server_configuration.h"
28
#include "mir_test_framework/basic_client_server_fixture.h"
30
#include <gtest/gtest.h>
31
#include <gmock/gmock.h>
33
#include <condition_variable>
37
namespace mtf = mir_test_framework;
38
namespace ms = mir::scene;
39
namespace msh = mir::shell;
41
using namespace testing;
45
struct MockSurfaceCoordinator : msh::SurfaceCoordinatorWrapper
47
MockSurfaceCoordinator(std::shared_ptr<ms::SurfaceCoordinator> const& wrapped) :
48
msh::SurfaceCoordinatorWrapper(wrapped)
52
std::shared_ptr<ms::Surface> add_surface(
53
ms::SurfaceCreationParameters const& params,
54
ms::Session* session) override
56
latest_surface = wrapped->add_surface(params, session);
57
return latest_surface;
60
std::shared_ptr<ms::Surface> latest_surface;
63
struct MyConfig : mtf::StubbedServerConfiguration
65
std::shared_ptr<ms::SurfaceCoordinator> wrap_surface_coordinator(
66
std::shared_ptr<ms::SurfaceCoordinator> const& wrapped) override
68
auto const msc = std::make_shared<MockSurfaceCoordinator>(wrapped);
69
mock_surface_coordinator = msc;
73
std::shared_ptr<MockSurfaceCoordinator> the_mock_surface_coordinator() const
75
return mock_surface_coordinator.lock();
78
std::shared_ptr<ms::Surface> the_latest_surface() const
80
return the_mock_surface_coordinator()->latest_surface;
83
std::weak_ptr<MockSurfaceCoordinator> mock_surface_coordinator;
86
using BasicClientServerFixture = mtf::BasicClientServerFixture<MyConfig>;
88
struct ClientSurfaceEvents : BasicClientServerFixture
90
MirSurfaceParameters const request_params
94
mir_pixel_format_abgr_8888,
95
mir_buffer_usage_hardware,
96
mir_display_output_id_invalid
99
MirSurface* surface{nullptr};
100
MirSurface* other_surface;
102
std::mutex last_event_mutex;
103
std::condition_variable last_event_cv;
104
MirEvent last_event{};
105
MirSurface* last_event_surface = nullptr;
106
MirEventDelegate delegate{&event_callback, this};
108
std::shared_ptr<ms::Surface> scene_surface;
110
static void event_callback(MirSurface* surface, MirEvent const* event, void* ctx)
112
ClientSurfaceEvents* self = static_cast<ClientSurfaceEvents*>(ctx);
113
std::lock_guard<decltype(self->last_event_mutex)> last_event_lock{self->last_event_mutex};
114
self->last_event = *event;
115
self->last_event_surface = surface;
116
self->last_event_cv.notify_one();
119
bool wait_for_event(MirEventType type, std::chrono::milliseconds delay)
121
std::unique_lock<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
122
return last_event_cv.wait_for(last_event_lock, delay,
123
[&] { return !!last_event_surface && last_event.type == type; });
126
void reset_last_event()
128
std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
129
memset(&last_event, 0, sizeof last_event);
130
last_event_surface = nullptr;
133
void SetUp() override
135
BasicClientServerFixture::SetUp();
137
surface = mir_connection_create_surface_sync(connection, &request_params);
138
mir_surface_set_event_handler(surface, &delegate);
140
scene_surface = server_configuration.the_latest_surface();
142
other_surface = mir_connection_create_surface_sync(connection, &request_params);
143
mir_surface_set_event_handler(other_surface, nullptr);
148
void TearDown() override
150
mir_surface_release_sync(other_surface);
151
mir_surface_release_sync(surface);
153
BasicClientServerFixture::TearDown();
158
TEST_F(ClientSurfaceEvents, surface_receives_state_events)
160
int surface_id = mir_debug_surface_id(surface);
163
mir_wait_for(mir_surface_set_state(surface, mir_surface_state_fullscreen));
164
mir_wait_for(mir_surface_set_state(other_surface, mir_surface_state_minimized));
166
std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
168
EXPECT_THAT(last_event_surface, Eq(surface));
169
EXPECT_THAT(last_event.type, Eq(mir_event_type_surface));
170
EXPECT_THAT(last_event.surface.id, Eq(surface_id));
171
EXPECT_THAT(last_event.surface.attrib, Eq(mir_surface_attrib_state));
172
EXPECT_THAT(last_event.surface.value, Eq(mir_surface_state_fullscreen));
176
mir_wait_for(mir_surface_set_state(surface, static_cast<MirSurfaceState>(999)));
178
std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
180
EXPECT_THAT(last_event_surface, Eq(surface));
181
EXPECT_THAT(last_event.type, Eq(mir_event_type_surface));
182
EXPECT_THAT(last_event.surface.id, Eq(surface_id));
183
EXPECT_THAT(last_event.surface.attrib, Eq(mir_surface_attrib_state));
184
EXPECT_THAT(last_event.surface.value, Eq(mir_surface_state_fullscreen));
190
mir_wait_for(mir_surface_set_state(surface, mir_surface_state_minimized));
192
std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
194
EXPECT_THAT(last_event_surface, Eq(surface));
195
EXPECT_THAT(last_event.type, Eq(mir_event_type_surface));
196
EXPECT_THAT(last_event.surface.id, Eq(surface_id));
197
EXPECT_THAT(last_event.surface.attrib, Eq(mir_surface_attrib_state));
198
EXPECT_THAT(last_event.surface.value, Eq(mir_surface_state_minimized));
204
mir_wait_for(mir_surface_set_state(surface, static_cast<MirSurfaceState>(777)));
205
mir_wait_for(mir_surface_set_state(other_surface, mir_surface_state_maximized));
207
std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
209
EXPECT_THAT(last_event_surface, IsNull());
210
EXPECT_THAT(last_event.type, Eq(0));
211
EXPECT_THAT(last_event.surface.id, Eq(0));
212
EXPECT_THAT(last_event.surface.attrib, Eq(0));
213
EXPECT_THAT(last_event.surface.value, Eq(0));
217
struct OrientationEvents : ClientSurfaceEvents, ::testing::WithParamInterface<MirOrientation> {};
219
TEST_P(OrientationEvents, surface_receives_orientation_events)
221
auto const direction = GetParam();
223
scene_surface->set_orientation(direction);
225
EXPECT_TRUE(wait_for_event(mir_event_type_orientation, std::chrono::seconds(1)));
227
std::lock_guard<decltype(last_event_mutex)> last_event_lock{last_event_mutex};
229
EXPECT_THAT(last_event_surface, Eq(surface));
230
EXPECT_THAT(last_event.type, Eq(mir_event_type_orientation));
231
EXPECT_THAT(last_event.orientation.direction, Eq(direction));
234
INSTANTIATE_TEST_CASE_P(ClientSurfaceEvents,
236
Values(mir_orientation_normal, mir_orientation_left, mir_orientation_inverted, mir_orientation_right));