Mir

Merge lp:~alan-griffiths/mir/support-gdk_window_move_to_rect into lp:mir

Proposed by Alan Griffiths on 2016-08-31
Status: Merged
Merged at revision: 3685
Proposed branch: lp:~alan-griffiths/mir/support-gdk_window_move_to_rect
Merge into: lp:mir
Diff against target: 588 lines (+366/-12)
13 files modified
include/client/mir_toolkit/mir_surface.h (+33/-1)
include/client/mir_toolkit/version.h (+2/-2)
include/common/mir_toolkit/common.h (+94/-1)
include/server/mir/scene/surface_creation_parameters.h (+6/-1)
include/server/mir/shell/surface_specification.h (+6/-1)
src/client/mir_connection.cpp (+6/-1)
src/client/mir_surface.cpp (+6/-1)
src/client/mir_surface.h (+6/-1)
src/client/mir_surface_api.cpp (+24/-1)
src/client/symbols.map (+1/-0)
src/protobuf/mir_protobuf.proto (+13/-0)
src/server/frontend/session_mediator.cpp (+11/-1)
tests/acceptance-tests/test_custom_window_management.cpp (+158/-1)
To merge this branch: bzr merge lp:~alan-griffiths/mir/support-gdk_window_move_to_rect
Reviewer Review Type Date Requested Status
Mir CI Bot continuous-integration Needs Fixing on 2016-09-06
Chris Halse Rogers Approve on 2016-09-05
Kevin DuBois (community) Approve on 2016-09-01
Gerry Boland vote 2016-08-31 Approve on 2016-09-01
Review via email: mp+304474@code.launchpad.net

Commit Message

Add the API and IPC required to pass the surface placement requests needed to support gdk_window_move_to_rect() to the window manager. It does not include the window manager logic to service the request. (There's an associated window management implementation proposed for MirAL: lp:~alan-griffiths/miral/connect-gdk_window_move_to_rect-inspired-placement-logic-to-Mir-0.25-API/+merge/304481)

To post a comment you must log in.
Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:3685
https://mir-jenkins.ubuntu.com/job/mir-ci/1586/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/1986
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2046
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2037
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2037
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2037
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2012
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2012/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2012
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2012/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2012
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2012/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2012
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2012/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2012
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2012/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2012
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2012/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/1586/rebuild

review: Approve (continuous-integration)
Chris Halse Rogers (raof) wrote :

190 + optional_value<MirPlacementHints> placement_hints;
191 + optional_value<MirPlacementGravity> surface_placement_gravity;
192 + optional_value<MirPlacementGravity> aux_rect_placement_gravity;
193 + optional_value<int> aux_rect_placement_offset_x;
194 + optional_value<int> aux_rect_placement_offset_y;

It seems like these values only ever make sense to be set together? Should this be rolled into a single
optional_value<SurfaceAttachmentParameters>?

Otherwise looks sensible to me. There's presumably a follow-up message where Mir tells the client where the surface was actually placed?

Alan Griffiths (alan-griffiths) wrote :

> 190 + optional_value<MirPlacementHints> placement_hints;
> 191 + optional_value<MirPlacementGravity> surface_placement_gravity;
> 192 + optional_value<MirPlacementGravity> aux_rect_placement_gravity;
> 193 + optional_value<int> aux_rect_placement_offset_x;
> 194 + optional_value<int> aux_rect_placement_offset_y;
>
> It seems like these values only ever make sense to be set together? Should
> this be rolled into a single
> optional_value<SurfaceAttachmentParameters>?

I did think about that, but there's an overlap with...

    optional_value<geometry::Rectangle> aux_rect;
    optional_value<MirEdgeAttachment> edge_attachment;

...which once might also have been said to only make sense together. In the end I decided
that this imposed fewer restrictions on future evolution of the code. It only affects a small part of the system.

> Otherwise looks sensible to me. There's presumably a follow-up message where
> Mir tells the client where the surface was actually placed?

I've intentionally left that out of scope for this MP as we don't currently notify the result of edge attachments and our policy on what placement information to disclose isn't clear to me.

Gerry Boland (gerboland) wrote :

Looks ok to me. API comprehensive enough for GTK's needs.

review: Approve (vote)
Kevin DuBois (kdub) wrote :

I guess the one-way requesting without confirmation or denial of the requests still is something that confuses me a bit in general about the placement/surface_spec api. Notwithstanding that, don't mind a request to place a surface in a certain way.

curiousity (since your testing opinions are typically more well-formed than mine)

+ EXPECT_TRUE(spec.placement_hints.is_set());
+ if (spec.placement_hints.is_set())
+ EXPECT_THAT(spec.placement_hints.value(), Eq(placement_hints));

why not:
ASSERT_TRUE(spec.placement_hints.is_set());
EXPECT_THAT(spec.placement_hints.value(), Eq(placement_hints));

nits/needs fixing:
extra indentation:
+ mir_placement_hints_flip_any = mir_placement_hints_flip_x|mir_placement_hints_flip_y,
+ mir_placement_hints_slide_any = mir_placement_hints_slide_x|mir_placement_hints_slide_y,
+ mir_placement_hints_resize_any = mir_placement_hints_resize_x|mir_placement_hints_resize_y,

+ optional_value<int> aux_rect_placement_offset_x;
+ optional_value<int> aux_rect_placement_offset_y;
why not optional_value<geom::Displacement>?

review: Needs Fixing
Alan Griffiths (alan-griffiths) wrote :

> I guess the one-way requesting without confirmation or denial of the requests
> still is something that confuses me a bit in general about the
> placement/surface_spec api. Notwithstanding that, don't mind a request to
> place a surface in a certain way.
>
> curiousity (since your testing opinions are typically more well-formed than
> mine)
>
> + EXPECT_TRUE(spec.placement_hints.is_set());
> + if (spec.placement_hints.is_set())
> + EXPECT_THAT(spec.placement_hints.value(), Eq(placement_hints));
>
> why not:
> ASSERT_TRUE(spec.placement_hints.is_set());
> EXPECT_THAT(spec.placement_hints.value(), Eq(placement_hints));

Because this callback is happening on the wrong thread, we want a report on any incorrect expectations and to ensure we raise the signal (not wait for a timeout).

> nits/needs fixing:
> extra indentation:
> + mir_placement_hints_flip_any =
> mir_placement_hints_flip_x|mir_placement_hints_flip_y,
> + mir_placement_hints_slide_any =
> mir_placement_hints_slide_x|mir_placement_hints_slide_y,
> + mir_placement_hints_resize_any =
> mir_placement_hints_resize_x|mir_placement_hints_resize_y,

Fixed.

> + optional_value<int> aux_rect_placement_offset_x;
> + optional_value<int> aux_rect_placement_offset_y;
> why not optional_value<geom::Displacement>?

We have more regular code if we match the protobuf structures:

+ COPY_IF_SET(aux_rect_placement_offset_x);
+ COPY_IF_SET(aux_rect_placement_offset_y);
...
+ COPY_IF_SET(aux_rect_placement_offset_x);
+ COPY_IF_SET(aux_rect_placement_offset_y);

The MirAL interface (which is what I want downstreams to use) does wrap this:

+ if (params.aux_rect_placement_offset_x.is_set() && params.aux_rect_placement_offset_y.is_set())
+ aux_rect_placement_offset = Displacement{params.aux_rect_placement_offset_x.value(), params.aux_rect_placement_offset_y.value()};

Alan Griffiths (alan-griffiths) wrote :

> Because this callback is happening on the wrong thread, we want a report on
> any incorrect expectations

I.e. Not just the first.

Kevin DuBois (kdub) wrote :

alright, lgtm then

review: Approve
William Hua (attente) wrote :

Looks good, it isn't clear to me how the positioning feedback will work exactly. Will it be via a configure event? Or is that postponed to another branch?

Alan Griffiths (alan-griffiths) wrote :

> Looks good, it isn't clear to me how the positioning feedback will work
> exactly. Will it be via a configure event? Or is that postponed to another
> branch?

I left position feedback out of this MP because it will cause discussion. I need to do some investigation to determine the minimum information needed, and if there's prior art to follow in Weston.

Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3686
https://mir-jenkins.ubuntu.com/job/mir-ci/1607/
Executed test runs:

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/1607/rebuild

review: Needs Fixing (continuous-integration)
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3688
https://mir-jenkins.ubuntu.com/job/mir-ci/1618/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2026/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2087
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2078
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2078
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2078
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2052/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2052/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2052
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2052/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2052
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2052/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2052
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2052/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2052
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2052/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/1618/rebuild

review: Needs Fixing (continuous-integration)
Alan Griffiths (alan-griffiths) wrote :

10:09:23 11: [ FAILED ] NestedServer.animated_cursor_image_changes_are_forwarded_to_host (6334 ms)

Known flaky test: lp:1523621

Mir CI Bot (mir-ci-bot) wrote :

FAILED: Autolanding.
More details in the following jenkins job:
https://mir-jenkins.ubuntu.com/job/mir-autolanding/564/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2046/console
    None: https://mir-jenkins.ubuntu.com/job/generic-land-mp/603/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2108/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2099/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2099/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2099/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2072/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2072/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2072/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2072/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2072/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2072/console

review: Needs Fixing (continuous-integration)
Chris Halse Rogers (raof) wrote :

I'm good with this.

review: Approve
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Autolanding.
More details in the following jenkins job:
https://mir-jenkins.ubuntu.com/job/mir-autolanding/565/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2047/console
    None: https://mir-jenkins.ubuntu.com/job/generic-land-mp/604/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2109/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2100/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2100/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2100/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2073/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2073/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2073/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2073/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2073/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2073/console

review: Needs Fixing (continuous-integration)

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 2016-07-18 10:21:04 +0000
3+++ include/client/mir_toolkit/mir_surface.h 2016-09-02 09:12:06 +0000
4@@ -1,5 +1,5 @@
5 /*
6- * Copyright © 2012-2014 Canonical Ltd.
7+ * Copyright © 2012-2016 Canonical Ltd.
8 *
9 * This program is free software: you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License version 3,
11@@ -567,6 +567,38 @@
12 void mir_surface_spec_set_pointer_confinement(MirSurfaceSpec* spec, MirPointerConfinementState state);
13
14 /**
15+ * Set the surface placement on the spec.
16+ *
17+ * \param [in] spec the spec to update
18+ * \param [in] rect the destination rectangle to align with
19+ * \param [in] rect_gravity the point on \p rect to align with
20+ * \param [in] surface_gravity the point on the surface to align with
21+ * \param [in] placement_hints positioning hints to use when limited on space
22+ * \param [in] offset_dx horizontal offset to shift w.r.t. \p rect
23+ * \param [in] offset_dy vertical offset to shift w.r.t. \p rect
24+ *
25+ * Moves a surface to \p rect, aligning their reference points.
26+ *
27+ * \p rect is relative to the top-left corner of the parent surface.
28+ * \p rect_gravity and \p surface_gravity determine the points on \p rect and
29+ * the surface to pin together. \p rect's alignment point can be offset by
30+ * \p offset_dx and \p offset_dy, which is equivalent to offsetting the
31+ * position of the surface.
32+ *
33+ * \p placement_hints determine how the window should be positioned in the case
34+ * that the surface would fall off-screen if placed in its ideal position.
35+ * See \ref MirPlacementHints for details.
36+ */
37+void mir_surface_spec_set_placement(
38+ MirSurfaceSpec* spec,
39+ const MirRectangle* rect,
40+ MirPlacementGravity rect_gravity,
41+ MirPlacementGravity surface_gravity,
42+ MirPlacementHints placement_hints,
43+ int offset_dx,
44+ int offset_dy);
45+
46+/**
47 * Set the event handler to be called when events arrive for a surface.
48 * \warning event_handler could be called from another thread. You must do
49 * any locking appropriate to protect your data accessed in the
50
51=== modified file 'include/client/mir_toolkit/version.h'
52--- include/client/mir_toolkit/version.h 2016-05-03 06:55:25 +0000
53+++ include/client/mir_toolkit/version.h 2016-09-02 09:12:06 +0000
54@@ -1,5 +1,5 @@
55 /*
56- * Copyright © 2014 Canonical Ltd.
57+ * Copyright © 2014-2016 Canonical Ltd.
58 *
59 * This program is free software: you can redistribute it and/or modify it
60 * under the terms of the GNU Lesser General Public License version 3,
61@@ -43,7 +43,7 @@
62 *
63 * See also: http://semver.org/
64 */
65-#define MIR_CLIENT_MINOR_VERSION (3)
66+#define MIR_CLIENT_MINOR_VERSION (4)
67
68 /**
69 * MIR_CLIENT_MICRO_VERSION
70
71=== modified file 'include/common/mir_toolkit/common.h'
72--- include/common/mir_toolkit/common.h 2016-08-09 06:44:52 +0000
73+++ include/common/mir_toolkit/common.h 2016-09-02 09:12:06 +0000
74@@ -1,7 +1,7 @@
75 /*
76 * Simple definitions common to client and server.
77 *
78- * Copyright © 2013-2014 Canonical Ltd.
79+ * Copyright © 2013-2016 Canonical Ltd.
80 *
81 * This program is free software: you can redistribute it and/or modify
82 * it under the terms of the GNU Lesser General Public License version 3 as
83@@ -199,6 +199,99 @@
84 mir_edge_attachment_horizontal
85 } MirEdgeAttachment;
86
87+// Inspired by GdkGravity
88+/**
89+ * Reference point for aligning a surface relative to a rectangle.
90+ * Each element (surface and rectangle) has a MirPlacementGravity assigned.
91+ */
92+typedef enum MirPlacementGravity
93+{
94+ /// the reference point is at the center.
95+ mir_placement_gravity_center = 0,
96+
97+ /// the reference point is at the middle of the left edge.
98+ mir_placement_gravity_west = 1 << 0,
99+
100+ /// the reference point is at the middle of the right edge.
101+ mir_placement_gravity_east = 1 << 1,
102+
103+ /// the reference point is in the middle of the top edge.
104+ mir_placement_gravity_north = 1 << 2,
105+
106+ /// the reference point is at the middle of the lower edge.
107+ mir_placement_gravity_south = 1 << 3,
108+
109+ /// the reference point is at the top left corner.
110+ mir_placement_gravity_northwest = mir_placement_gravity_north | mir_placement_gravity_west,
111+
112+ /// the reference point is at the top right corner.
113+ mir_placement_gravity_northeast = mir_placement_gravity_north | mir_placement_gravity_east,
114+
115+ /// the reference point is at the lower left corner.
116+ mir_placement_gravity_southwest = mir_placement_gravity_south | mir_placement_gravity_west,
117+
118+ /// the reference point is at the lower right corner.
119+ mir_placement_gravity_southeast = mir_placement_gravity_south | mir_placement_gravity_east
120+} MirPlacementGravity;
121+
122+// Inspired by GdkAnchorHints
123+/**
124+ * Positioning hints for aligning a window relative to a rectangle.
125+ *
126+ * These hints determine how the window should be positioned in the case that
127+ * the surface would fall off-screen if placed in its ideal position.
128+ *
129+ * For example, \p mir_placement_hints_flip_x will invert the x component of
130+ * \p aux_rect_placement_offset and replace \p mir_placement_gravity_northwest
131+ * with \p mir_placement_gravity_northeast and vice versa if the window extends
132+ * beyond the left or right edges of the monitor.
133+ *
134+ * If \p mir_placement_hints_slide_x is set, the window can be shifted
135+ * horizontally to fit on-screen.
136+ *
137+ * If \p mir_placement_hints_resize_x is set, the window can be shrunken
138+ * horizontally to fit.
139+ *
140+ * If \p mir_placement_hints_antipodes is set then the rect gravity may be
141+ * substituted with the opposite corner (e.g. \p mir_placement_gravity_northeast
142+ * to \p mir_placement_gravity_southwest) in combination with other options.
143+ *
144+ * When multiple flags are set, flipping should take precedence over sliding,
145+ * which should take precedence over resizing.
146+ */
147+typedef enum MirPlacementHints
148+{
149+ /// allow flipping anchors horizontally
150+ mir_placement_hints_flip_x = 1 << 0,
151+
152+ /// allow flipping anchors vertically
153+ mir_placement_hints_flip_y = 1 << 1,
154+
155+ /// allow sliding window horizontally
156+ mir_placement_hints_slide_x = 1 << 2,
157+
158+ /// allow sliding window vertically
159+ mir_placement_hints_slide_y = 1 << 3,
160+
161+ /// allow resizing window horizontally
162+ mir_placement_hints_resize_x = 1 << 4,
163+
164+ /// allow resizing window vertically
165+ mir_placement_hints_resize_y = 1 << 5,
166+
167+ /// allow flipping aux_anchor to opposite corner
168+ mir_placement_hints_antipodes= 1 << 6,
169+
170+ /// allow flipping anchors on both axes
171+ mir_placement_hints_flip_any = mir_placement_hints_flip_x|mir_placement_hints_flip_y,
172+
173+ /// allow sliding window on both axes
174+ mir_placement_hints_slide_any = mir_placement_hints_slide_x|mir_placement_hints_slide_y,
175+
176+ /// allow resizing window on both axes
177+ mir_placement_hints_resize_any = mir_placement_hints_resize_x|mir_placement_hints_resize_y,
178+} MirPlacementHints;
179+
180 /**
181 * Form factor associated with a physical output
182 */
183
184=== modified file 'include/server/mir/scene/surface_creation_parameters.h'
185--- include/server/mir/scene/surface_creation_parameters.h 2016-06-21 21:31:05 +0000
186+++ include/server/mir/scene/surface_creation_parameters.h 2016-09-02 09:12:06 +0000
187@@ -1,5 +1,5 @@
188 /*
189- * Copyright © 2013 Canonical Ltd.
190+ * Copyright © 2013-2016 Canonical Ltd.
191 *
192 * This program is free software: you can redistribute it and/or modify it
193 * under the terms of the GNU General Public License version 3,
194@@ -87,6 +87,11 @@
195 mir::optional_value<frontend::BufferStreamId> content_id;
196 mir::optional_value<geometry::Rectangle> aux_rect;
197 mir::optional_value<MirEdgeAttachment> edge_attachment;
198+ optional_value<MirPlacementHints> placement_hints;
199+ optional_value<MirPlacementGravity> surface_placement_gravity;
200+ optional_value<MirPlacementGravity> aux_rect_placement_gravity;
201+ optional_value<int> aux_rect_placement_offset_x;
202+ optional_value<int> aux_rect_placement_offset_y;
203
204 std::weak_ptr<Surface> parent;
205
206
207=== modified file 'include/server/mir/shell/surface_specification.h'
208--- include/server/mir/shell/surface_specification.h 2016-06-08 13:49:11 +0000
209+++ include/server/mir/shell/surface_specification.h 2016-09-02 09:12:06 +0000
210@@ -1,5 +1,5 @@
211 /*
212- * Copyright © 2015 Canonical Ltd.
213+ * Copyright © 2015-2016 Canonical Ltd.
214 *
215 * This program is free software: you can redistribute it and/or modify it
216 * under the terms of the GNU General Public License version 3,
217@@ -63,6 +63,11 @@
218 optional_value<frontend::SurfaceId> parent_id;
219 optional_value<geometry::Rectangle> aux_rect;
220 optional_value<MirEdgeAttachment> edge_attachment;
221+ optional_value<MirPlacementHints> placement_hints;
222+ optional_value<MirPlacementGravity> surface_placement_gravity;
223+ optional_value<MirPlacementGravity> aux_rect_placement_gravity;
224+ optional_value<int> aux_rect_placement_offset_x;
225+ optional_value<int> aux_rect_placement_offset_y;
226 optional_value<geometry::Width> min_width;
227 optional_value<geometry::Height> min_height;
228 optional_value<geometry::Width> max_width;
229
230=== modified file 'src/client/mir_connection.cpp'
231--- src/client/mir_connection.cpp 2016-08-31 09:41:42 +0000
232+++ src/client/mir_connection.cpp 2016-09-02 09:12:06 +0000
233@@ -1,5 +1,5 @@
234 /*
235- * Copyright © 2012 Canonical Ltd.
236+ * Copyright © 2012-2016 Canonical Ltd.
237 *
238 * This program is free software: you can redistribute it and/or modify it
239 * under the terms of the GNU Lesser General Public License version 3,
240@@ -122,6 +122,11 @@
241 SERIALIZE_OPTION_IF_SET(state);
242 SERIALIZE_OPTION_IF_SET(pref_orientation);
243 SERIALIZE_OPTION_IF_SET(edge_attachment);
244+ SERIALIZE_OPTION_IF_SET(placement_hints);
245+ SERIALIZE_OPTION_IF_SET(surface_placement_gravity);
246+ SERIALIZE_OPTION_IF_SET(aux_rect_placement_gravity);
247+ SERIALIZE_OPTION_IF_SET(aux_rect_placement_offset_x);
248+ SERIALIZE_OPTION_IF_SET(aux_rect_placement_offset_y);
249 SERIALIZE_OPTION_IF_SET(min_width);
250 SERIALIZE_OPTION_IF_SET(min_height);
251 SERIALIZE_OPTION_IF_SET(max_width);
252
253=== modified file 'src/client/mir_surface.cpp'
254--- src/client/mir_surface.cpp 2016-08-24 02:09:08 +0000
255+++ src/client/mir_surface.cpp 2016-09-02 09:12:06 +0000
256@@ -1,5 +1,5 @@
257 /*
258- * Copyright © 2012, 2015 Canonical Ltd.
259+ * Copyright © 2012-2016 Canonical Ltd.
260 *
261 * This program is free software: you can redistribute it and/or modify it
262 * under the terms of the GNU Lesser General Public License version 3,
263@@ -550,6 +550,11 @@
264 // parent_id is a special case (below)
265 // aux_rect is a special case (below)
266 COPY_IF_SET(edge_attachment);
267+ COPY_IF_SET(aux_rect_placement_gravity);
268+ COPY_IF_SET(surface_placement_gravity);
269+ COPY_IF_SET(placement_hints);
270+ COPY_IF_SET(aux_rect_placement_offset_x);
271+ COPY_IF_SET(aux_rect_placement_offset_y);
272 COPY_IF_SET(min_width);
273 COPY_IF_SET(min_height);
274 COPY_IF_SET(max_width);
275
276=== modified file 'src/client/mir_surface.h'
277--- src/client/mir_surface.h 2016-06-09 00:38:26 +0000
278+++ src/client/mir_surface.h 2016-09-02 09:12:06 +0000
279@@ -1,5 +1,5 @@
280 /*
281- * Copyright © 2012, 2015 Canonical Ltd.
282+ * Copyright © 2012-2016 Canonical Ltd.
283 *
284 * This program is free software: you can redistribute it and/or modify it
285 * under the terms of the GNU Lesser General Public License version 3,
286@@ -111,6 +111,11 @@
287 std::shared_ptr<MirPersistentId> parent_id;
288 mir::optional_value<MirRectangle> aux_rect;
289 mir::optional_value<MirEdgeAttachment> edge_attachment;
290+ mir::optional_value<MirPlacementHints> placement_hints;
291+ mir::optional_value<MirPlacementGravity> surface_placement_gravity;
292+ mir::optional_value<MirPlacementGravity> aux_rect_placement_gravity;
293+ mir::optional_value<int> aux_rect_placement_offset_x;
294+ mir::optional_value<int> aux_rect_placement_offset_y;
295
296 mir::optional_value<int> min_width;
297 mir::optional_value<int> min_height;
298
299=== modified file 'src/client/mir_surface_api.cpp'
300--- src/client/mir_surface_api.cpp 2016-07-18 10:11:34 +0000
301+++ src/client/mir_surface_api.cpp 2016-09-02 09:12:06 +0000
302@@ -1,5 +1,5 @@
303 /*
304- * Copyright © 2014 Canonical Ltd.
305+ * Copyright © 2014-2016 Canonical Ltd.
306 *
307 * This program is free software: you can redistribute it and/or modify it
308 * under the terms of the GNU Lesser General Public License version 3,
309@@ -721,6 +721,29 @@
310 MIR_LOG_UNCAUGHT_EXCEPTION(ex);
311 }
312
313+void mir_surface_spec_set_placement(
314+ MirSurfaceSpec* spec,
315+ MirRectangle const* rect,
316+ MirPlacementGravity rect_gravity,
317+ MirPlacementGravity surface_gravity,
318+ MirPlacementHints placement_hints,
319+ int offset_dx,
320+ int offset_dy)
321+try
322+{
323+ spec->aux_rect = *rect;
324+ spec->aux_rect_placement_gravity = rect_gravity;
325+ spec->surface_placement_gravity = surface_gravity;
326+ spec->placement_hints = placement_hints;
327+ spec->aux_rect_placement_offset_x = offset_dx;
328+ spec->aux_rect_placement_offset_y = offset_dy;
329+}
330+catch (std::exception const& ex)
331+{
332+ MIR_LOG_UNCAUGHT_EXCEPTION(ex);
333+}
334+
335+
336 MirWaitHandle* mir_surface_request_persistent_id(MirSurface* surface, mir_surface_id_callback callback, void* context)
337 {
338 mir::require(mir_surface_is_valid(surface));
339
340=== modified file 'src/client/symbols.map'
341--- src/client/symbols.map 2016-08-31 09:41:42 +0000
342+++ src/client/symbols.map 2016-09-02 09:12:06 +0000
343@@ -141,6 +141,7 @@
344 mir_surface_spec_set_name;
345 mir_surface_spec_set_parent;
346 mir_surface_spec_set_pixel_format;
347+ mir_surface_spec_set_placement;
348 mir_surface_spec_set_preferred_orientation;
349 mir_surface_spec_set_state;
350 mir_surface_spec_set_streams;
351
352=== modified file 'src/protobuf/mir_protobuf.proto'
353--- src/protobuf/mir_protobuf.proto 2016-08-09 06:44:52 +0000
354+++ src/protobuf/mir_protobuf.proto 2016-09-02 09:12:06 +0000
355@@ -46,6 +46,12 @@
356 optional int32 shell_chrome = 24;
357 repeated StreamConfiguration stream = 25;
358 optional int32 confine_pointer = 26;
359+
360+ optional int32 placement_hints = 27;
361+ optional int32 surface_placement_gravity = 28;
362+ optional int32 aux_rect_placement_gravity = 29;
363+ optional int32 aux_rect_placement_offset_x = 30;
364+ optional int32 aux_rect_placement_offset_y = 31;
365 }
366
367 message SurfaceAspectRatio
368@@ -86,6 +92,13 @@
369 repeated Rectangle input_shape = 23;
370 optional int32 shell_chrome = 24;
371 optional int32 confine_pointer = 25;
372+
373+ // Intentionally missing 26 to get any further additions in line with SurfaceParameters
374+ optional int32 placement_hints = 27;
375+ optional int32 surface_placement_gravity = 28;
376+ optional int32 aux_rect_placement_gravity = 29;
377+ optional int32 aux_rect_placement_offset_x = 30;
378+ optional int32 aux_rect_placement_offset_y = 31;
379 }
380
381 message StreamConfiguration {
382
383=== modified file 'src/server/frontend/session_mediator.cpp'
384--- src/server/frontend/session_mediator.cpp 2016-08-31 09:41:42 +0000
385+++ src/server/frontend/session_mediator.cpp 2016-09-02 09:12:06 +0000
386@@ -1,5 +1,5 @@
387 /*
388- * Copyright © 2012-2014 Canonical Ltd.
389+ * Copyright © 2012-2016 Canonical Ltd.
390 *
391 * This program is free software: you can redistribute it and/or modify it
392 * under the terms of the GNU General Public License version 3,
393@@ -285,6 +285,11 @@
394 COPY_IF_SET(height_inc);
395 COPY_IF_SET(shell_chrome);
396 COPY_IF_SET(confine_pointer);
397+ COPY_IF_SET(aux_rect_placement_gravity);
398+ COPY_IF_SET(surface_placement_gravity);
399+ COPY_IF_SET(placement_hints);
400+ COPY_IF_SET(aux_rect_placement_offset_x);
401+ COPY_IF_SET(aux_rect_placement_offset_y);
402
403 #undef COPY_IF_SET
404
405@@ -621,6 +626,11 @@
406 COPY_IF_SET(preferred_orientation);
407 COPY_IF_SET(parent_id);
408 // aux_rect is a special case (below)
409+ COPY_IF_SET(aux_rect_placement_gravity);
410+ COPY_IF_SET(surface_placement_gravity);
411+ COPY_IF_SET(placement_hints);
412+ COPY_IF_SET(aux_rect_placement_offset_x);
413+ COPY_IF_SET(aux_rect_placement_offset_y);
414 COPY_IF_SET(edge_attachment);
415 COPY_IF_SET(min_width);
416 COPY_IF_SET(min_height);
417
418=== modified file 'tests/acceptance-tests/test_custom_window_management.cpp'
419--- tests/acceptance-tests/test_custom_window_management.cpp 2016-01-29 08:18:22 +0000
420+++ tests/acceptance-tests/test_custom_window_management.cpp 2016-09-02 09:12:06 +0000
421@@ -1,5 +1,5 @@
422 /*
423- * Copyright © 2015 Canonical Ltd.
424+ * Copyright © 2015-2016 Canonical Ltd.
425 *
426 * This program is free software: you can redistribute it and/or modify it
427 * under the terms of the GNU General Public License version 3,
428@@ -360,3 +360,160 @@
429 mir_surface_release_sync(surface);
430 mir_connection_release(connection);
431 }
432+
433+TEST_F(CustomWindowManagement, when_the_client_places_a_new_surface_the_request_reaches_the_window_manager)
434+{
435+ int const width{800};
436+ int const height{600};
437+ MirPixelFormat const format{mir_pixel_format_bgr_888};
438+ MirRectangle dummy_rect{13, 17, 19, 23};
439+ MirRectangle const aux_rect{20, 20, 50, 50};
440+ auto const rect_gravity = mir_placement_gravity_northeast;
441+ auto const surface_gravity = mir_placement_gravity_northwest;
442+ auto const placement_hints = mir_placement_hints_flip_x;
443+ auto const offset_dx = 2;
444+ auto const offset_dy = 3;
445+
446+ start_server();
447+ auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
448+ auto surface_spec = mir_connection_create_spec_for_normal_surface(connection, width, height, format);
449+ auto parent = mir_surface_create_sync(surface_spec);
450+ mir_surface_spec_release(surface_spec);
451+
452+ surface_spec = mir_connection_create_spec_for_tip(
453+ connection, width, height, format, parent, &dummy_rect, mir_edge_attachment_any);
454+
455+ mir_surface_spec_set_placement(
456+ surface_spec, &aux_rect, rect_gravity, surface_gravity, placement_hints, offset_dx, offset_dy);
457+
458+ mt::Signal received;
459+
460+ auto const check_placement = [&](
461+ std::shared_ptr<ms::Session> const& session,
462+ ms::SurfaceCreationParameters const& params,
463+ std::function<mf::SurfaceId(std::shared_ptr<ms::Session> const& session, ms::SurfaceCreationParameters const& params)> const& build)
464+ {
465+ EXPECT_TRUE(params.aux_rect.is_set());
466+ if (params.aux_rect.is_set())
467+ {
468+ auto const actual_rect = params.aux_rect.value();
469+ EXPECT_THAT(actual_rect.top_left.x, Eq(geom::X{aux_rect.left}));
470+ EXPECT_THAT(actual_rect.top_left.y, Eq(geom::Y{aux_rect.top}));
471+ EXPECT_THAT(actual_rect.size.width, Eq(geom::Width{aux_rect.width}));
472+ EXPECT_THAT(actual_rect.size.height, Eq(geom::Height{aux_rect.height}));
473+ }
474+
475+ EXPECT_TRUE(params.placement_hints.is_set());
476+ if (params.placement_hints.is_set())
477+ EXPECT_THAT(params.placement_hints.value(), Eq(placement_hints));
478+
479+ EXPECT_TRUE(params.surface_placement_gravity.is_set());
480+ if (params.surface_placement_gravity.is_set())
481+ EXPECT_THAT(params.surface_placement_gravity.value(), Eq(surface_gravity));
482+
483+ EXPECT_TRUE(params.aux_rect_placement_gravity.is_set());
484+ if (params.aux_rect_placement_gravity.is_set())
485+ EXPECT_THAT(params.aux_rect_placement_gravity.value(), Eq(rect_gravity));
486+
487+ EXPECT_TRUE(params.aux_rect_placement_offset_x.is_set());
488+ if (params.aux_rect_placement_offset_x.is_set())
489+ EXPECT_THAT(params.aux_rect_placement_offset_x.value(), Eq(offset_dx));
490+
491+ EXPECT_TRUE(params.aux_rect_placement_offset_y.is_set());
492+ if (params.aux_rect_placement_offset_y.is_set())
493+ EXPECT_THAT(params.aux_rect_placement_offset_y.value(), Eq(offset_dy));
494+
495+ received.raise();
496+ return build(session, params);
497+ };
498+
499+ EXPECT_CALL(window_manager, add_surface(_,_,_)).WillOnce(Invoke(check_placement));
500+
501+ auto child = mir_surface_create_sync(surface_spec);
502+ mir_surface_spec_release(surface_spec);
503+
504+ EXPECT_TRUE(received.wait_for(400ms));
505+
506+ mir_surface_release_sync(child);
507+ mir_surface_release_sync(parent);
508+ mir_connection_release(connection);
509+}
510+
511+TEST_F(CustomWindowManagement, when_the_client_places_an_existing_surface_the_request_reaches_the_window_manager)
512+{
513+ int const width{800};
514+ int const height{600};
515+ MirPixelFormat const format{mir_pixel_format_bgr_888};
516+ MirRectangle dummy_rect{13, 17, 19, 23};
517+ MirRectangle const aux_rect{42, 15, 24, 7};
518+ auto const rect_gravity = mir_placement_gravity_north;
519+ auto const surface_gravity = mir_placement_gravity_south;
520+ auto const placement_hints = MirPlacementHints(mir_placement_hints_flip_y|mir_placement_hints_antipodes);
521+ auto const offset_dx = 5;
522+ auto const offset_dy = 7;
523+
524+ start_server();
525+ auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
526+ auto surface_spec = mir_connection_create_spec_for_normal_surface(connection, width, height, format);
527+ auto parent = mir_surface_create_sync(surface_spec);
528+ mir_surface_spec_release(surface_spec);
529+
530+ surface_spec = mir_connection_create_spec_for_menu(
531+ connection, width, height, format, parent, &dummy_rect, mir_edge_attachment_any);
532+ auto child = mir_surface_create_sync(surface_spec);
533+ mir_surface_spec_release(surface_spec);
534+
535+ surface_spec = mir_connection_create_spec_for_changes(connection);
536+ mir_surface_spec_set_placement(
537+ surface_spec, &aux_rect, rect_gravity, surface_gravity, placement_hints, offset_dx, offset_dy);
538+
539+ mt::Signal received;
540+
541+ auto const check_placement = [&](
542+ std::shared_ptr<ms::Session> const&,
543+ std::shared_ptr<ms::Surface> const&,
544+ msh::SurfaceSpecification const& spec)
545+ {
546+ EXPECT_TRUE(spec.aux_rect.is_set());
547+ if (spec.aux_rect.is_set())
548+ {
549+ auto const actual_rect = spec.aux_rect.value();
550+ EXPECT_THAT(actual_rect.top_left.x, Eq(geom::X{aux_rect.left}));
551+ EXPECT_THAT(actual_rect.top_left.y, Eq(geom::Y{aux_rect.top}));
552+ EXPECT_THAT(actual_rect.size.width, Eq(geom::Width{aux_rect.width}));
553+ EXPECT_THAT(actual_rect.size.height, Eq(geom::Height{aux_rect.height}));
554+ }
555+
556+ EXPECT_TRUE(spec.placement_hints.is_set());
557+ if (spec.placement_hints.is_set())
558+ EXPECT_THAT(spec.placement_hints.value(), Eq(placement_hints));
559+
560+ EXPECT_TRUE(spec.surface_placement_gravity.is_set());
561+ if (spec.surface_placement_gravity.is_set())
562+ EXPECT_THAT(spec.surface_placement_gravity.value(), Eq(surface_gravity));
563+
564+ EXPECT_TRUE(spec.aux_rect_placement_gravity.is_set());
565+ if (spec.aux_rect_placement_gravity.is_set())
566+ EXPECT_THAT(spec.aux_rect_placement_gravity.value(), Eq(rect_gravity));
567+
568+ EXPECT_TRUE(spec.aux_rect_placement_offset_x.is_set());
569+ if (spec.aux_rect_placement_offset_x.is_set())
570+ EXPECT_THAT(spec.aux_rect_placement_offset_x.value(), Eq(offset_dx));
571+
572+ EXPECT_TRUE(spec.aux_rect_placement_offset_y.is_set());
573+ if (spec.aux_rect_placement_offset_y.is_set())
574+ EXPECT_THAT(spec.aux_rect_placement_offset_y.value(), Eq(offset_dy));
575+
576+ received.raise();
577+ };
578+
579+ EXPECT_CALL(window_manager, modify_surface(_,_,_)).WillOnce(Invoke(check_placement));
580+ mir_surface_apply_spec(child, surface_spec);
581+ mir_surface_spec_release(surface_spec);
582+
583+ EXPECT_TRUE(received.wait_for(400ms));
584+
585+ mir_surface_release_sync(child);
586+ mir_surface_release_sync(parent);
587+ mir_connection_release(connection);
588+}

Subscribers

People subscribed via source and target branches