Mir

Merge lp:~alan-griffiths/mir/surface-has-min-size into lp:mir

Proposed by Alan Griffiths
Status: Merged
Approved by: Alan Griffiths
Approved revision: no longer in the source branch.
Merged at revision: 2488
Proposed branch: lp:~alan-griffiths/mir/surface-has-min-size
Merge into: lp:mir
Prerequisite: lp:~alan-griffiths/mir/first-pass-of-surface-spec-modification
Diff against target: 632 lines (+386/-10)
14 files modified
include/client/mir_toolkit/mir_surface.h (+42/-0)
include/common/mir/geometry/dimensions.h (+8/-0)
include/common/mir/geometry/point.h (+6/-0)
include/server/mir/scene/surface_creation_parameters.h (+5/-0)
src/client/mir_surface.cpp (+4/-0)
src/client/mir_surface_api.cpp (+24/-0)
src/client/symbols.map (+4/-0)
src/protobuf/mir_protobuf.proto (+5/-0)
src/server/frontend/session_mediator.cpp (+11/-0)
src/server/shell/basic_window_manager.h (+2/-2)
src/server/shell/canonical_window_manager.cpp (+55/-6)
src/server/shell/canonical_window_manager.h (+6/-1)
tests/acceptance-tests/test_client_library.cpp (+105/-0)
tests/acceptance-tests/test_surface_modifications.cpp (+109/-1)
To merge this branch: bzr merge lp:~alan-griffiths/mir/surface-has-min-size
Reviewer Review Type Date Requested Status
Alberto Aguirre (community) Approve
Kevin DuBois (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Robert Carr (community) Approve
Review via email: mp+256179@code.launchpad.net

Commit message

client API, shell: support for surfaces setting minimum size (and some code towards maximum)

Description of the change

client API, shell: support for surfaces setting minimum size (and some code towards maximum)

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote :

LGTM.

Nits:

+ #define COPY_IF_SET(field)\

Couldn't this be used above in the same method?

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

See bug 1421591. We will eventually need more than min/max dimensions for real apps.

Revision history for this message
Kevin DuBois (kdub) wrote :

lgtm. It be good to validate that the mininum is less than or equal to the maximum if they're both set.

review: Approve
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/client/mir_toolkit/mir_surface.h'
2--- include/client/mir_toolkit/mir_surface.h 2015-04-13 15:38:56 +0000
3+++ include/client/mir_toolkit/mir_surface.h 2015-04-15 11:10:33 +0000
4@@ -239,6 +239,48 @@
5 bool mir_surface_spec_set_height(MirSurfaceSpec* spec, unsigned height);
6
7 /**
8+ * Set the minimum width, in pixels
9+ *
10+ * \param [in] spec Specification to mutate
11+ * \param [in] width Minimum width.
12+ * \return False if minimum width is invalid for a surface of this type
13+ * \note The requested dimensions are a hint only. The server is not guaranteed to create a
14+ * surface of any specific width or height.
15+ */
16+bool mir_surface_spec_set_min_width(MirSurfaceSpec* spec, unsigned min_width);
17+
18+/**
19+ * Set the minimum height, in pixels
20+ *
21+ * \param [in] spec Specification to mutate
22+ * \param [in] height Minimum height.
23+ * \return False if minimum height is invalid for a surface of this type
24+ * \note The requested dimensions are a hint only. The server is not guaranteed to create a
25+ * surface of any specific width or height.
26+ */
27+bool mir_surface_spec_set_min_height(MirSurfaceSpec* spec, unsigned min_height);
28+/**
29+ * Set the maximum width, in pixels
30+ *
31+ * \param [in] spec Specification to mutate
32+ * \param [in] width Maximum width.
33+ * \return False if maximum width is invalid for a surface of this type
34+ * \note The requested dimensions are a hint only. The server is not guaranteed to create a
35+ * surface of any specific width or height.
36+ */
37+bool mir_surface_spec_set_max_width(MirSurfaceSpec* spec, unsigned max_width);
38+
39+/**
40+ * Set the maximum height, in pixels
41+ *
42+ * \param [in] spec Specification to mutate
43+ * \param [in] height Maximum height.
44+ * \return False if maximum height is invalid for a surface of this type
45+ * \note The requested dimensions are a hint only. The server is not guaranteed to create a
46+ * surface of any specific width or height.
47+ */
48+bool mir_surface_spec_set_max_height(MirSurfaceSpec* spec, unsigned max_height);
49+/**
50 * Set the requested pixel format.
51 * \param [in] spec Specification to mutate
52 * \param [in] format Requested pixel format
53
54=== modified file 'include/common/mir/geometry/dimensions.h'
55--- include/common/mir/geometry/dimensions.h 2015-03-31 02:35:42 +0000
56+++ include/common/mir/geometry/dimensions.h 2015-04-15 11:10:33 +0000
57@@ -126,6 +126,10 @@
58 inline Y operator+(Y lhs, DeltaY rhs) { return Y(lhs.as_int() + rhs.as_int()); }
59 inline X operator-(X lhs, DeltaX rhs) { return X(lhs.as_int() - rhs.as_int()); }
60 inline Y operator-(Y lhs, DeltaY rhs) { return Y(lhs.as_int() - rhs.as_int()); }
61+inline X& operator+=(X& lhs, DeltaX rhs) { return lhs = X(lhs.as_int() + rhs.as_int()); }
62+inline Y& operator+=(Y& lhs, DeltaY rhs) { return lhs = Y(lhs.as_int() + rhs.as_int()); }
63+inline X& operator-=(X& lhs, DeltaX rhs) { return lhs = X(lhs.as_int() - rhs.as_int()); }
64+inline Y& operator-=(Y& lhs, DeltaY rhs) { return lhs = Y(lhs.as_int() - rhs.as_int()); }
65
66 // Adding deltas to Width and Height is fine
67 inline Width operator+(Width lhs, DeltaX rhs) { return Width(lhs.as_int() + rhs.as_int()); }
68@@ -137,6 +141,10 @@
69 inline DeltaX operator-(X lhs, X rhs) { return DeltaX(lhs.as_int() - rhs.as_int()); }
70 inline DeltaY operator-(Y lhs, Y rhs) { return DeltaY(lhs.as_int() - rhs.as_int()); }
71
72+//Subtracting Width and Height is fine
73+inline DeltaX operator-(Width lhs, Width rhs) { return DeltaX(lhs.as_int() - rhs.as_int()); }
74+inline DeltaY operator-(Height lhs, Height rhs) { return DeltaY(lhs.as_int() - rhs.as_int()); }
75+
76 // Multiplying by a scalar value is fine
77 template<typename Scalar>
78 inline Width operator*(Scalar scale, Width const& w) { return Width{scale*w.as_int()}; }
79
80=== modified file 'include/common/mir/geometry/point.h'
81--- include/common/mir/geometry/point.h 2015-03-31 02:35:42 +0000
82+++ include/common/mir/geometry/point.h 2015-04-15 11:10:33 +0000
83@@ -56,6 +56,12 @@
84 inline Point operator-(Point lhs, DeltaX rhs) { return{lhs.x - rhs, lhs.y}; }
85 inline Point operator-(Point lhs, DeltaY rhs) { return{lhs.x, lhs.y - rhs}; }
86
87+inline Point& operator+=(Point& lhs, DeltaX rhs) { lhs.x += rhs; return lhs; }
88+inline Point& operator+=(Point& lhs, DeltaY rhs) { lhs.y += rhs; return lhs; }
89+
90+inline Point& operator-=(Point& lhs, DeltaX rhs) { lhs.x -= rhs; return lhs; }
91+inline Point& operator-=(Point& lhs, DeltaY rhs) { lhs.y -= rhs; return lhs; }
92+
93 std::ostream& operator<<(std::ostream& out, Point const& value);
94 }
95 }
96
97=== modified file 'include/server/mir/scene/surface_creation_parameters.h'
98--- include/server/mir/scene/surface_creation_parameters.h 2015-01-23 03:50:26 +0000
99+++ include/server/mir/scene/surface_creation_parameters.h 2015-04-15 11:10:33 +0000
100@@ -89,6 +89,11 @@
101 mir::optional_value<MirEdgeAttachment> edge_attachment;
102
103 std::weak_ptr<Surface> parent;
104+
105+ optional_value<geometry::Width> min_width;
106+ optional_value<geometry::Height> min_height;
107+ optional_value<geometry::Width> max_width;
108+ optional_value<geometry::Height> max_height;
109 };
110
111 bool operator==(const SurfaceCreationParameters& lhs, const SurfaceCreationParameters& rhs);
112
113=== modified file 'src/client/mir_surface.cpp'
114--- src/client/mir_surface.cpp 2015-04-13 15:39:25 +0000
115+++ src/client/mir_surface.cpp 2015-04-15 11:10:33 +0000
116@@ -92,6 +92,10 @@
117 SERIALIZE_OPTION_IF_SET(state, message);
118 SERIALIZE_OPTION_IF_SET(pref_orientation, message);
119 SERIALIZE_OPTION_IF_SET(edge_attachment, message);
120+ SERIALIZE_OPTION_IF_SET(min_width, message);
121+ SERIALIZE_OPTION_IF_SET(min_height, message);
122+ SERIALIZE_OPTION_IF_SET(max_width, message);
123+ SERIALIZE_OPTION_IF_SET(max_height, message);
124
125 if (parent.is_set() && parent.value() != nullptr)
126 message.set_parent_id(parent.value()->id());
127
128=== modified file 'src/client/mir_surface_api.cpp'
129--- src/client/mir_surface_api.cpp 2015-04-14 08:33:18 +0000
130+++ src/client/mir_surface_api.cpp 2015-04-15 11:10:33 +0000
131@@ -175,6 +175,30 @@
132 return true;
133 }
134
135+bool mir_surface_spec_set_min_width(MirSurfaceSpec* spec, unsigned min_width)
136+{
137+ spec->min_width = min_width;
138+ return true;
139+}
140+
141+bool mir_surface_spec_set_min_height(MirSurfaceSpec* spec, unsigned min_height)
142+{
143+ spec->min_height = min_height;
144+ return true;
145+}
146+
147+bool mir_surface_spec_set_max_width(MirSurfaceSpec* spec, unsigned max_width)
148+{
149+ spec->max_width = max_width;
150+ return true;
151+}
152+
153+bool mir_surface_spec_set_max_height(MirSurfaceSpec* spec, unsigned max_height)
154+{
155+ spec->max_height = max_height;
156+ return true;
157+}
158+
159 bool mir_surface_spec_set_pixel_format(MirSurfaceSpec* spec, MirPixelFormat format)
160 {
161 spec->pixel_format = format;
162
163=== modified file 'src/client/symbols.map'
164--- src/client/symbols.map 2015-04-09 16:15:52 +0000
165+++ src/client/symbols.map 2015-04-15 11:10:33 +0000
166@@ -164,6 +164,10 @@
167 mir_surface_event_get_attribute;
168 mir_surface_event_get_attribute_value;
169 mir_surface_set_swapinterval;
170+ mir_surface_spec_set_min_width;
171+ mir_surface_spec_set_min_height;
172+ mir_surface_spec_set_max_width;
173+ mir_surface_spec_set_max_height;
174 mir_surface_swap_buffers;
175 mir_surface_swap_buffers_sync;
176 mir_touch_event_modifiers;
177
178=== modified file 'src/protobuf/mir_protobuf.proto'
179--- src/protobuf/mir_protobuf.proto 2015-04-09 14:29:02 +0000
180+++ src/protobuf/mir_protobuf.proto 2015-04-15 11:10:33 +0000
181@@ -26,6 +26,11 @@
182
183 optional Rectangle aux_rect = 11;
184 optional int32 edge_attachment = 12;
185+
186+ optional int32 min_width = 13;
187+ optional int32 min_height = 14;
188+ optional int32 max_width = 15;
189+ optional int32 max_height = 16;
190 }
191
192 // If and when we break our protocol backward-compatibility, this could be
193
194=== modified file 'src/server/frontend/session_mediator.cpp'
195--- src/server/frontend/session_mediator.cpp 2015-04-09 14:29:02 +0000
196+++ src/server/frontend/session_mediator.cpp 2015-04-15 11:10:33 +0000
197@@ -231,6 +231,17 @@
198 if (request->has_edge_attachment())
199 params.with_edge_attachment(static_cast<MirEdgeAttachment>(request->edge_attachment()));
200
201+ #define COPY_IF_SET(field)\
202+ if (request->has_##field())\
203+ params.field = decltype(params.field.value())(request->field())
204+
205+ COPY_IF_SET(min_width);
206+ COPY_IF_SET(min_height);
207+ COPY_IF_SET(max_width);
208+ COPY_IF_SET(max_height);
209+
210+ #undef COPY_IF_SET
211+
212 auto const surf_id = shell->create_surface(session, params);
213
214 auto surface = session->get_surface(surf_id);
215
216=== modified file 'src/server/shell/basic_window_manager.h'
217--- src/server/shell/basic_window_manager.h 2015-04-09 06:20:31 +0000
218+++ src/server/shell/basic_window_manager.h 2015-04-15 11:10:33 +0000
219@@ -98,7 +98,7 @@
220 ///
221 /// \tparam SessionInfo must be default constructable.
222 ///
223-/// \tparam SurfaceInfo must be constructable from (std::shared_ptr<ms::Session>, std::shared_ptr<ms::Surface>)
224+/// \tparam SurfaceInfo must be constructable from (std::shared_ptr<ms::Session>, std::shared_ptr<ms::Surface>, ms::SurfaceCreationParameters const& params)
225 template<typename WindowManagementPolicy, typename SessionInfo, typename SurfaceInfo>
226 class BasicWindowManager : public WindowManager,
227 private BasicWindowManagerTools<SessionInfo, SurfaceInfo>
228@@ -138,7 +138,7 @@
229 auto const result = build(session, placed_params);
230 auto const surface = session->surface(result);
231 policy.handle_new_surface(session, surface);
232- surface_info.emplace(surface, SurfaceInfo{session, surface});
233+ surface_info.emplace(surface, SurfaceInfo{session, surface, placed_params});
234 return result;
235 }
236
237
238=== modified file 'src/server/shell/canonical_window_manager.cpp'
239--- src/server/shell/canonical_window_manager.cpp 2015-04-10 12:08:18 +0000
240+++ src/server/shell/canonical_window_manager.cpp 2015-04-15 11:10:33 +0000
241@@ -38,11 +38,16 @@
242
243 msh::CanonicalSurfaceInfo::CanonicalSurfaceInfo(
244 std::shared_ptr<scene::Session> const& session,
245- std::shared_ptr<scene::Surface> const& surface) :
246+ std::shared_ptr<scene::Surface> const& surface,
247+ scene::SurfaceCreationParameters const& params) :
248 state{mir_surface_state_restored},
249 restore_rect{surface->top_left(), surface->size()},
250 session{session},
251- parent{surface->parent()}
252+ parent{surface->parent()},
253+ min_width{params.min_width},
254+ min_height{params.min_height},
255+ max_width{params.max_width},
256+ max_height{params.max_height}
257 {
258 }
259
260@@ -87,8 +92,16 @@
261
262 auto width = std::min(display_area.size.width.as_int(), parameters.size.width.as_int());
263 auto height = std::min(display_area.size.height.as_int(), parameters.size.height.as_int());
264- if (!width) width = 1;
265- if (!height) height = 1;
266+
267+ auto const min_width = parameters.min_width.is_set() ?
268+ parameters.min_width.value().as_int() : 1;
269+
270+ auto const min_height = parameters.min_height.is_set() ?
271+ parameters.min_height.value().as_int() : 1;
272+
273+ width = std::max(width, min_width);
274+ height = std::max(height, min_height);
275+
276 parameters.size = Size{width, height};
277
278 bool positioned = false;
279@@ -246,9 +259,23 @@
280 std::shared_ptr<scene::Surface> const& surface,
281 SurfaceSpecification const& modifications)
282 {
283+ auto& surface_info = tools->info_for(surface);
284+
285 if (modifications.name.is_set())
286 surface->rename(modifications.name.value());
287
288+ if (modifications.min_width.is_set())
289+ surface_info.min_width = modifications.min_width;
290+
291+ if (modifications.min_height.is_set())
292+ surface_info.min_height = modifications.min_height;
293+
294+ if (modifications.max_width.is_set())
295+ surface_info.max_width = modifications.max_width;
296+
297+ if (modifications.max_height.is_set())
298+ surface_info.max_height = modifications.max_height;
299+
300 if (modifications.width.is_set() || modifications.height.is_set())
301 {
302 // TODO similar logic is needed in example window management policies
303@@ -566,7 +593,7 @@
304
305 bool msh::CanonicalWindowManagerPolicy::resize(std::shared_ptr<ms::Surface> const& surface, Point cursor, Point old_cursor, Rectangle bounds)
306 {
307- if (!surface || !surface->input_area_contains(cursor))
308+ if (!surface || !surface->input_area_contains(old_cursor))
309 return false;
310
311 auto const top_left = surface->top_left();
312@@ -608,6 +635,28 @@
313 bool const top_resize,
314 Rectangle const& bounds)
315 {
316+ auto const& surface_info = tools->info_for(surface);
317+
318+ if (surface_info.min_width.is_set() && surface_info.min_width.value() > new_size.width)
319+ {
320+ if (left_resize)
321+ {
322+ new_pos.x += surface_info.min_width.value() - new_size.width;
323+ }
324+
325+ new_size.width = surface_info.min_width.value();
326+ }
327+
328+ if (surface_info.min_height.is_set() && surface_info.min_height.value() > new_size.height)
329+ {
330+ if (top_resize)
331+ {
332+ new_pos.y += surface_info.min_height.value() - new_size.height;
333+ }
334+
335+ new_size.height = surface_info.min_height.value();
336+ }
337+
338 if (left_resize)
339 {
340 if (new_pos.x < bounds.top_left.x)
341@@ -638,7 +687,7 @@
342 new_size.height = new_size.height + to_bottom_right.dy;
343 }
344
345- switch (tools->info_for(surface).state)
346+ switch (surface_info.state)
347 {
348 case mir_surface_state_restored:
349 break;
350
351=== modified file 'src/server/shell/canonical_window_manager.h'
352--- src/server/shell/canonical_window_manager.h 2015-04-10 12:08:18 +0000
353+++ src/server/shell/canonical_window_manager.h 2015-04-15 11:10:33 +0000
354@@ -38,13 +38,18 @@
355 {
356 CanonicalSurfaceInfo(
357 std::shared_ptr<scene::Session> const& session,
358- std::shared_ptr<scene::Surface> const& surface);
359+ std::shared_ptr<scene::Surface> const& surface,
360+ scene::SurfaceCreationParameters const& params);
361
362 MirSurfaceState state;
363 geometry::Rectangle restore_rect;
364 std::weak_ptr<scene::Session> session;
365 std::weak_ptr<scene::Surface> parent;
366 std::vector<std::weak_ptr<scene::Surface>> children;
367+ optional_value<geometry::Width> min_width;
368+ optional_value<geometry::Height> min_height;
369+ optional_value<geometry::Width> max_width;
370+ optional_value<geometry::Height> max_height;
371 };
372
373 // standard window management algorithm:
374
375=== modified file 'tests/acceptance-tests/test_client_library.cpp'
376--- tests/acceptance-tests/test_client_library.cpp 2015-04-09 06:20:31 +0000
377+++ tests/acceptance-tests/test_client_library.cpp 2015-04-15 11:10:33 +0000
378@@ -279,6 +279,111 @@
379 mir_connection_release(connection);
380 }
381
382+TEST_F(ClientLibrary, can_set_surface_min_width)
383+{
384+ connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
385+
386+ int const width = 640;
387+ int const height = 480;
388+ auto const format = mir_pixel_format_abgr_8888;
389+ auto const spec =
390+ mir_connection_create_spec_for_normal_surface(connection, width, height, format);
391+
392+ int const min_width = 480;
393+ EXPECT_TRUE(mir_surface_spec_set_min_width(spec, min_width));
394+
395+ surface = mir_surface_create_sync(spec);
396+ mir_surface_spec_release(spec);
397+ mir_surface_release_sync(surface);
398+ mir_connection_release(connection);
399+}
400+
401+TEST_F(ClientLibrary, can_set_surface_min_height)
402+{
403+ connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
404+
405+ int const width = 640;
406+ int const height = 480;
407+ auto const format = mir_pixel_format_abgr_8888;
408+ auto const spec =
409+ mir_connection_create_spec_for_normal_surface(connection, width, height, format);
410+
411+ int const min_height = 480;
412+ EXPECT_TRUE(mir_surface_spec_set_min_height(spec, min_height));
413+
414+ surface = mir_surface_create_sync(spec);
415+ mir_surface_spec_release(spec);
416+ mir_surface_release_sync(surface);
417+ mir_connection_release(connection);
418+}
419+
420+TEST_F(ClientLibrary, can_set_surface_max_width)
421+{
422+ connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
423+
424+ int const width = 640;
425+ int const height = 480;
426+ auto const format = mir_pixel_format_abgr_8888;
427+ auto const spec =
428+ mir_connection_create_spec_for_normal_surface(connection, width, height, format);
429+
430+ int const max_width = 1024;
431+ EXPECT_TRUE(mir_surface_spec_set_max_width(spec, max_width));
432+
433+ surface = mir_surface_create_sync(spec);
434+ mir_surface_spec_release(spec);
435+ mir_surface_release_sync(surface);
436+ mir_connection_release(connection);
437+}
438+
439+TEST_F(ClientLibrary, can_set_surface_max_height)
440+{
441+ connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
442+
443+ int const width = 640;
444+ int const height = 480;
445+ auto const format = mir_pixel_format_abgr_8888;
446+ auto const spec =
447+ mir_connection_create_spec_for_normal_surface(connection, width, height, format);
448+
449+ int const max_height = 1024;
450+ EXPECT_TRUE(mir_surface_spec_set_max_height(spec, max_height));
451+
452+ surface = mir_surface_create_sync(spec);
453+ mir_surface_spec_release(spec);
454+ mir_surface_release_sync(surface);
455+ mir_connection_release(connection);
456+}
457+
458+TEST_F(ClientLibrary, min_size_respected_when_placing_surface)
459+{
460+ connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
461+
462+ int const width = 6400;
463+ int const height = 4800;
464+ auto const format = mir_pixel_format_abgr_8888;
465+ auto const spec =
466+ mir_connection_create_spec_for_normal_surface(connection, width, height, format);
467+
468+ int const min_width = 4800;
469+ int const min_height = 3200;
470+
471+ mir_surface_spec_set_min_width(spec, min_width);
472+ mir_surface_spec_set_min_height(spec, min_height);
473+ surface = mir_surface_create_sync(spec);
474+ mir_surface_spec_release(spec);
475+
476+ auto const buffer_stream = mir_surface_get_buffer_stream(surface);
477+
478+ MirGraphicsRegion graphics_region;
479+ mir_buffer_stream_get_graphics_region(buffer_stream, &graphics_region);
480+ EXPECT_THAT(graphics_region.width, Ge(min_width));
481+ EXPECT_THAT(graphics_region.height, Ge(min_height));
482+
483+ mir_surface_release_sync(surface);
484+ mir_connection_release(connection);
485+}
486+
487 TEST_F(ClientLibrary, receives_surface_dpi_value)
488 {
489 connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
490
491=== modified file 'tests/acceptance-tests/test_surface_modifications.cpp'
492--- tests/acceptance-tests/test_surface_modifications.cpp 2015-04-10 13:38:16 +0000
493+++ tests/acceptance-tests/test_surface_modifications.cpp 2015-04-15 11:10:33 +0000
494@@ -18,13 +18,16 @@
495
496 #include "mir_test_framework/connected_client_with_a_surface.h"
497
498+#include "mir/events/event_builders.h"
499 #include "mir/shell/shell_wrapper.h"
500 #include "mir/scene/session.h"
501 #include "mir/scene/surface.h"
502 #include "mir/scene/null_surface_observer.h"
503
504 #include "mir_test/fake_shared.h"
505+#include "mir_test/signal.h"
506
507+namespace mev = mir::events;
508 namespace mf = mir::frontend;
509 namespace mtf = mir_test_framework;
510 namespace ms = mir::scene;
511@@ -76,11 +79,72 @@
512
513 mtf::ConnectedClientWithASurface::SetUp();
514
515- auto const scene_surface = shell->latest_surface.lock();
516+ shell_surface = shell->latest_surface;
517+ auto const scene_surface = shell_surface.lock();
518 scene_surface->add_observer(mt::fake_shared(surface_observer));
519+
520+ // Swap buffers to ensure surface is visible for event based tests
521+ mir_buffer_stream_swap_buffers_sync(mir_surface_get_buffer_stream(surface));
522+ }
523+
524+ void generate_alt_click_at(Point const& click_position)
525+ {
526+ MirInputDeviceId const device_id{7};
527+ int64_t const timestamp{39};
528+ auto const modifiers = mir_input_event_modifier_alt;
529+ std::vector<MirPointerButton> depressed_buttons{mir_pointer_button_tertiary};
530+
531+ auto const x_axis_value = click_position.x.as_float();
532+ auto const y_axis_value = click_position.y.as_float();
533+ auto const hscroll_value = 0.0;
534+ auto const vscroll_value = 0.0;
535+ auto const action = mir_pointer_action_button_down;
536+
537+ auto const click_event = mev::make_event(device_id, timestamp, modifiers,
538+ action, depressed_buttons, x_axis_value, y_axis_value, hscroll_value, vscroll_value);
539+
540+ server.the_shell()->handle(*click_event);
541+ }
542+
543+ void generate_alt_move_to(Point const& drag_position)
544+ {
545+ MirInputDeviceId const device_id{7};
546+ int64_t const timestamp{39};
547+ auto const modifiers = mir_input_event_modifier_alt;
548+ std::vector<MirPointerButton> depressed_buttons{mir_pointer_button_tertiary};
549+
550+ auto const x_axis_value = drag_position.x.as_float();
551+ auto const y_axis_value = drag_position.y.as_float();
552+ auto const hscroll_value = 0.0;
553+ auto const vscroll_value = 0.0;
554+ auto const action = mir_pointer_action_motion;
555+
556+ auto const drag_event = mev::make_event(device_id, timestamp, modifiers,
557+ action, depressed_buttons, x_axis_value, y_axis_value, hscroll_value, vscroll_value);
558+
559+ server.the_shell()->handle(*drag_event);
560+ }
561+
562+ void ensure_server_has_processed_setup()
563+ {
564+ mt::Signal server_ready;
565+
566+ auto const new_title = __PRETTY_FUNCTION__;
567+
568+ EXPECT_CALL(surface_observer, renamed(StrEq(new_title))).
569+ WillOnce(InvokeWithoutArgs([&]{ server_ready.raise(); }));
570+
571+ auto const spec = mir_connection_create_spec_for_changes(connection);
572+
573+ mir_surface_spec_set_name(spec, new_title);
574+ mir_surface_apply_spec(surface, spec);
575+ mir_surface_spec_release(spec);
576+
577+ server_ready.wait();
578 }
579
580 MockSurfaceObserver surface_observer;
581+ std::weak_ptr<ms::Surface> shell_surface;
582 };
583
584 MATCHER_P(WidthEq, value, "")
585@@ -160,3 +224,47 @@
586 mir_surface_apply_spec(surface, spec);
587 mir_surface_spec_release(spec);
588 }
589+
590+TEST_F(SurfaceModifications, surface_spec_min_width_is_respected)
591+{
592+ auto const min_width = 17;
593+
594+ {
595+ auto const spec = mir_connection_create_spec_for_changes(connection);
596+ mir_surface_spec_set_min_width(spec, min_width);
597+ mir_surface_apply_spec(surface, spec);
598+ mir_surface_spec_release(spec);
599+ }
600+
601+ ensure_server_has_processed_setup();
602+
603+ auto const shell_surface = this->shell_surface.lock();
604+ auto const bottom_right = shell_surface->input_bounds().bottom_right() - Displacement{1,1};
605+
606+ EXPECT_CALL(surface_observer, resized_to(WidthEq(min_width)));
607+
608+ generate_alt_click_at(bottom_right);
609+ generate_alt_move_to(shell_surface->top_left());
610+}
611+
612+TEST_F(SurfaceModifications, surface_spec_min_height_is_respected)
613+{
614+ auto const min_height = 19;
615+
616+ {
617+ auto const spec = mir_connection_create_spec_for_changes(connection);
618+ mir_surface_spec_set_min_height(spec, min_height);
619+ mir_surface_apply_spec(surface, spec);
620+ mir_surface_spec_release(spec);
621+ }
622+
623+ ensure_server_has_processed_setup();
624+
625+ auto const shell_surface = this->shell_surface.lock();
626+ auto const bottom_right = shell_surface->input_bounds().bottom_right() - Displacement{1,1};
627+
628+ EXPECT_CALL(surface_observer, resized_to(HeightEq(min_height)));
629+
630+ generate_alt_click_at(bottom_right);
631+ generate_alt_move_to(shell_surface->top_left());
632+}

Subscribers

People subscribed via source and target branches