Merge lp:~brandontschaefer/mir/client-api-apply-remove-display-config into lp:mir
- client-api-apply-remove-display-config
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Brandon Schaefer |
Approved revision: | no longer in the source branch. |
Merged at revision: | 3900 |
Proposed branch: | lp:~brandontschaefer/mir/client-api-apply-remove-display-config |
Merge into: | lp:mir |
Diff against target: |
1018 lines (+556/-25) 29 files modified
include/client/mir_toolkit/mir_connection.h (+24/-0) include/server/mir/graphics/display_configuration_observer.h (+19/-0) include/test/mir/test/display_config_matchers.h (+5/-0) include/test/mir/test/signal.h (+7/-0) src/client/mir_connection.cpp (+45/-22) src/client/mir_connection.h (+3/-0) src/client/mir_connection_api.cpp (+19/-0) src/client/rpc/mir_display_server.cpp (+7/-0) src/client/rpc/mir_display_server.h (+4/-0) src/client/symbols.map (+2/-0) src/include/common/mir/protobuf/display_server.h (+4/-0) src/include/server/mir/frontend/display_changer.h (+1/-0) src/server/frontend/authorizing_display_changer.cpp (+9/-0) src/server/frontend/authorizing_display_changer.h (+2/-0) src/server/frontend/protobuf_message_processor.cpp (+4/-0) src/server/frontend/session_mediator.cpp (+16/-1) src/server/frontend/session_mediator.h (+4/-0) src/server/graphics/display_configuration_observer_multiplexer.cpp (+13/-0) src/server/graphics/display_configuration_observer_multiplexer.h (+9/-0) src/server/report/logging/display_configuration_report.cpp (+15/-1) src/server/report/logging/display_configuration_report.h (+9/-0) src/server/scene/mediating_display_changer.cpp (+39/-1) src/server/scene/mediating_display_changer.h (+1/-0) tests/acceptance-tests/test_nested_mir.cpp (+2/-0) tests/acceptance-tests/test_new_display_configuration.cpp (+273/-0) tests/include/mir/test/doubles/null_display_changer.h (+3/-0) tests/include/mir/test/doubles/stub_display_server.h (+4/-0) tests/mir_test/display_config_matchers.cpp (+9/-0) tests/unit-tests/scene/test_mediating_display_changer.cpp (+4/-0) |
To merge this branch: | bzr merge lp:~brandontschaefer/mir/client-api-apply-remove-display-config |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Approve | |
Chris Halse Rogers | Approve | ||
Alan Griffiths | Approve | ||
Daniel van Vugt | Abstain | ||
Review via email: mp+312951@code.launchpad.net |
Commit message
Add the two of the missing functions needed to remove the old display configuration API.
Description of the change
https:/
Add the two missing functions needed to remove the old display configuration API.
void mir_connection_
void mir_connection_
Mir CI Bot (mir-ci-bot) wrote : | # |
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3873
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:3873
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Chris Halse Rogers (raof) wrote : | # |
13 + * to get notified about hardware changes, so that the can apply a new config.
Typo, the→they
15 + * \warning This request may be denied. Check that the request succeeded with mir_connection_
You've copy-pasted these warnings. They don't apply; clients get notified via their registered error handler.
252 + mir::protobuf::Void * response,
Nit: Coding style
291 + virtual void remove(
Not wild on the naming - could this be remove_
336 + else if ("remove_display" == invocation.
And likewise, "remove_
532 +void ms::MediatingDi
533 + std::shared_
534 +{
535 + std::lock_
536 + config_
537 + observer-
538 +}
Shouldn't this result in a hardware configuration change if (and only if) the session is currently focused? This will result in the configuration being set to the base config the *next* time the session is focused.
Which leads me into: please add some acceptance tests testing the expected behaviour. Particularly:
1) That calling remove_
2) That calling remove_
3) That calling remove_
4) That calling remove_
Chris Halse Rogers (raof) wrote : | # |
(There are more acceptance tests you could sensibly add, but those are the 4 big ones)
Daniel van Vugt (vanvugt) wrote : | # |
You have just rejected my branch based on the assertion that "_config" should be renamed to "_configuration". So you should probably follow your own advice...
Daniel van Vugt (vanvugt) wrote : | # |
Although I still prefer "config" over "configuration", it should be said.
Regardless, the type name and the function names should match up. Either:
MirDisplayConfig
mir.
or
MirDisplayCo
mir.
For a more clear way forward that gets us closer to this ideal, I have already proposed:
https:/
which you should probably revisit. Either fix this branch or retract your review of my branch.
Daniel van Vugt (vanvugt) wrote : | # |
Specifically, according to your own comments we need to rename display_config_ to display_
If you believe that MirDisplayConfig and _display_config is the way forward then you should retract your review of:
https:/
If not then you should change "config" to "configuration" here. I know we're in limbo right now with the old API hanging around, but we should reject changes like this that make the problem worse, if indeed the team believes that the word "config" is the problem.
Brandon Schaefer (brandontschaefer) wrote on 2016-12-10:
I would like to think we were all doing our jobs. Im still in favour of MirDisplayConfi
Daniel van Vugt (vanvugt) wrote : | # |
On second thoughts, since this is actually the style I want, I shouldn't block it.
However if this lands then it conflicts with the justification for rejecting:
https:/
So that should be revisited.
Alan Griffiths (alan-griffiths) wrote : | # |
*Needs Information*
I'm not entirely sure about the direction here. Surely the "old configuration API" is the set of functions using MirDisplayConfi
In which case, you've missed:
MirBlob* mir_blob_
and
MirDisplayConfi
(Yes, I know these have the intended form of the "future" API, but AIUI they have to go before we can eliminate MirDisplayConfi
Can you (or other reviewers) clarify?
Brandon Schaefer (brandontschaefer) wrote : | # |
> 13 + * to get notified about hardware changes, so that the can apply a
> new config.
> Typo, the→they
>
> 15 + * \warning This request may be denied. Check that the request
> succeeded with mir_connection_
> You've copy-pasted these warnings. They don't apply; clients get notified via
> their registered error handler.
>
> 252 + mir::protobuf::Void * response,
> Nit: Coding style
>
> 291 + virtual void remove(
> Not wild on the naming - could this be remove_
>
> 336 + else if ("remove_display" == invocation.
> And likewise, "remove_
All good suggestions.
>
> 532 +void ms::MediatingDi
> 533 + std::shared_
> 534 +{
> 535 + std::lock_
> 536 + config_
> 537 + observer-
> 538 +}
> Shouldn't this result in a hardware configuration change if (and only if) the
> session is currently focused? This will result in the configuration being set
> to the base config the *next* time the session is focused.
Hmm yes, i would think that sounds like a better behaviour.
>
> Which leads me into: please add some acceptance tests testing the expected
> behaviour. Particularly:
> 1) That calling remove_
> session configuration is a no-op
> 2) That calling remove_
> *has* set a session configuration results in a hardware configuration change
> 3) That calling remove_
> *has* set a session configuration results in *no* hardware configuration
> change
> 4) That calling remove_
> *has* set a session configuration results in the base configuration getting
> applied when the client becomes focused.
Good idea, I was thinking about doing some of these tests but ... wasnt sure.
I also wanted to write some unit test which matched the set session config but theres no accessing point to the config_map[]. Soo I think EXEPCT_CALLS(_) are still fine. Plus these other tests.
Brandon Schaefer (brandontschaefer) wrote : | # |
> Specifically, according to your own comments we need to rename display_config_
> to display_
> actually making the problem worse.
>
> If you believe that MirDisplayConfig and _display_config is the way forward
> then you should retract your review of:
> https:/
> header/
>
> If not then you should change "config" to "configuration" here. I know we're
> in limbo right now with the old API hanging around, but we should reject
> changes like this that make the problem worse, if indeed the team believes
> that the word "config" is the problem.
>
> Brandon Schaefer (brandontschaefer) wrote on 2016-12-10:
> I would like to think we were all doing our jobs. Im still in favour of
> MirDisplayConfi
> Yes it break ABI, yes it'll be a bit more work. We are already planning on
> breaking the ABI. I dont see a reason we should avoid this when a majority of
> us agreed on a name already.
Yes and I still agree with it. I was leaving it how it currently is, *_display_config == new API and
*_display_
Though I could still just move to display_
Brandon Schaefer (brandontschaefer) wrote : | # |
> *Needs Information*
>
> I'm not entirely sure about the direction here. Surely the "old configuration
> API" is the set of functions using MirDisplayConfi
Yes
>
> In which case, you've missed:
>
> MirBlob* mir_blob_
> configuration);
>
> and
>
> MirDisplayConfi
>
Hmm yes, there is no blob for MirDisplayConfig
> (Yes, I know these have the intended form of the "future" API, but AIUI they
> have to go before we can eliminate MirDisplayConfi
> MirDisplayConfig* as planned or confusion will ensue.)
>
> Can you (or other reviewers) clarify?
Ill get this doubled checked as this is the main goal of this branch to be able to deprecate the old display config way!
Alan Griffiths (alan-griffiths) wrote : | # |
> > *Needs Information*
> >
> > I'm not entirely sure about the direction here. Surely the "old
> configuration
> > API" is the set of functions using MirDisplayConfi
>
> Yes
>
> >
> > In which case, you've missed:
> >
> > MirBlob* mir_blob_
> > configuration);
> >
> > and
> >
> > MirDisplayConfi
> >
>
> Hmm yes, there is no blob for MirDisplayConfig
AFAICS the MP is OK except the commit message needs to say "Add two of the missing functions needed to remove the old display configuration API."
Regarding the blobs: don't forget that blobs may have been created by the legacy API - we may need to support loading both versions (if they differ).
Alan Griffiths (alan-griffiths) wrote : | # |
> AFAICS the MP is OK except the commit message needs to say "Add two of the
> missing functions needed to remove the old display configuration API."
Fixed
Brandon Schaefer (brandontschaefer) wrote : | # |
Yup Ill be doing the blob after this branch.
@duflu
I agree, I should just change the name now, theres no point in making any more annoying since they already have a unique name. Thanks!
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3875
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3876
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3877
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3878
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Brandon Schaefer (brandontschaefer) wrote : | # |
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3878
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3878
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Chris Halse Rogers (raof) wrote : | # |
LGTM.
Failure is bug# 1649758.
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
None: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Daniel van Vugt (vanvugt) wrote : | # |
04:21:54 Text conflict in src/client/
04:21:54 1 conflicts encountered.
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:3879
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === modified file 'include/client/mir_toolkit/mir_connection.h' |
2 | --- include/client/mir_toolkit/mir_connection.h 2016-10-12 06:03:15 +0000 |
3 | +++ include/client/mir_toolkit/mir_connection.h 2016-12-23 15:34:22 +0000 |
4 | @@ -202,6 +202,30 @@ |
5 | MirWaitHandle* mir_connection_apply_display_config(MirConnection *connection, MirDisplayConfiguration* display_configuration); |
6 | |
7 | /** |
8 | + * Apply the display configuration for the connection |
9 | + * |
10 | + * The display configuration is applied to this connection only (per-connection |
11 | + * configuration) and is invalidated when a hardware change occurs. Clients should |
12 | + * register a callback with mir_connection_set_display_config_change_callback() |
13 | + * to get notified about hardware changes, so that they can apply a new configuration. |
14 | + * |
15 | + * \param [in] connection The connection |
16 | + * \param [in] display_config The display_config to apply |
17 | + */ |
18 | +void mir_connection_apply_session_display_configuration(MirConnection* connection, MirDisplayConfig const* display_config); |
19 | + |
20 | +/** |
21 | + * Remove the display configuration for the connection |
22 | + * |
23 | + * If a session display configuration is applied to the connection it is removed, and |
24 | + * the base display configuration is used. If there was no previous call to |
25 | + * mir_connection_apply_session_display_config this will do nothing. |
26 | + * |
27 | + * \param [in] connection The connection |
28 | + */ |
29 | +void mir_connection_remove_session_display_configuration(MirConnection* connection); |
30 | + |
31 | +/** |
32 | * Set the base display configuration |
33 | * |
34 | * The base display configuration is the configuration the server applies when |
35 | |
36 | === modified file 'include/server/mir/graphics/display_configuration_observer.h' |
37 | --- include/server/mir/graphics/display_configuration_observer.h 2016-12-09 02:54:31 +0000 |
38 | +++ include/server/mir/graphics/display_configuration_observer.h 2016-12-23 15:34:22 +0000 |
39 | @@ -24,6 +24,10 @@ |
40 | |
41 | namespace mir |
42 | { |
43 | +namespace frontend |
44 | +{ |
45 | +class Session; |
46 | +} |
47 | namespace graphics |
48 | { |
49 | class DisplayConfiguration; |
50 | @@ -58,6 +62,21 @@ |
51 | virtual void base_configuration_updated(std::shared_ptr<DisplayConfiguration const> const& base_config) = 0; |
52 | |
53 | /** |
54 | + * Notification after updating the session display configuration. |
55 | + * |
56 | + * \param [in] session The session that is updating its display configuration. |
57 | + * \param [in] config The configuration that is being applied to the session. |
58 | + */ |
59 | + virtual void session_configuration_applied(std::shared_ptr<frontend::Session> const& session, |
60 | + std::shared_ptr<DisplayConfiguration> const& config) = 0; |
61 | + /** |
62 | + * Notification after removing the session display configuration. |
63 | + * |
64 | + * \param [in] session The session that is removing its display configuration. |
65 | + */ |
66 | + virtual void session_configuration_removed(std::shared_ptr<frontend::Session> const& session) = 0; |
67 | + |
68 | + /** |
69 | * Notification after every failed display configuration attempt. |
70 | * |
71 | * This is called if the graphics platform throws an exception when trying |
72 | |
73 | === modified file 'include/test/mir/test/display_config_matchers.h' |
74 | --- include/test/mir/test/display_config_matchers.h 2016-11-02 05:07:18 +0000 |
75 | +++ include/test/mir/test/display_config_matchers.h 2016-12-23 15:34:22 +0000 |
76 | @@ -111,6 +111,11 @@ |
77 | MirDisplayConfig const* config1, |
78 | MirDisplayConfig const* config2); |
79 | |
80 | +bool compare_display_configurations( |
81 | + testing::MatchResultListener* listener, |
82 | + std::shared_ptr<graphics::DisplayConfiguration> const& config1, |
83 | + MirDisplayConfig const* config2); |
84 | + |
85 | MATCHER_P(DisplayConfigMatches, config, "") |
86 | { |
87 | return compare_display_configurations(result_listener, arg, config); |
88 | |
89 | === modified file 'include/test/mir/test/signal.h' |
90 | --- include/test/mir/test/signal.h 2016-07-18 07:38:38 +0000 |
91 | +++ include/test/mir/test/signal.h 2016-12-23 15:34:22 +0000 |
92 | @@ -69,6 +69,13 @@ |
93 | { |
94 | signal->raise(); |
95 | } |
96 | +ACTION_P2(WakeUpWhenZero, signal, atomic_int) |
97 | +{ |
98 | + if (atomic_int->fetch_sub(1) == 1) |
99 | + { |
100 | + signal->raise(); |
101 | + } |
102 | +} |
103 | |
104 | } |
105 | } |
106 | |
107 | === modified file 'src/client/mir_connection.cpp' |
108 | --- src/client/mir_connection.cpp 2016-12-14 19:53:10 +0000 |
109 | +++ src/client/mir_connection.cpp 2016-12-23 15:34:22 +0000 |
110 | @@ -1054,13 +1054,15 @@ |
111 | |
112 | namespace |
113 | { |
114 | -struct HandleErrorVoid |
115 | +template <class T> |
116 | +struct HandleError |
117 | { |
118 | - std::unique_ptr<mp::Void> result; |
119 | - std::function<void(mp::Void const&)> on_error; |
120 | + std::unique_ptr<T> result; |
121 | + std::function<void(T const&)> on_error; |
122 | }; |
123 | |
124 | -void handle_structured_error(HandleErrorVoid* handler) |
125 | +template <class T> |
126 | +void handle_structured_error(HandleError<T>* handler) |
127 | { |
128 | if (handler->result->has_structured_error()) |
129 | { |
130 | @@ -1068,6 +1070,22 @@ |
131 | } |
132 | delete handler; |
133 | } |
134 | + |
135 | +template <class T> |
136 | +HandleError<T>* create_stored_error_result(std::shared_ptr<mcl::ErrorHandler> const& error_handler) |
137 | +{ |
138 | + auto store_error_result = new HandleError<T>; |
139 | + store_error_result->result = std::make_unique<T>(); |
140 | + store_error_result->on_error = [error_handler](T const& message) |
141 | + { |
142 | + MirError const error{ |
143 | + static_cast<MirErrorDomain>(message.structured_error().domain()), |
144 | + message.structured_error().code()}; |
145 | + (*error_handler)(&error); |
146 | + }; |
147 | + |
148 | + return store_error_result; |
149 | +} |
150 | } |
151 | |
152 | void MirConnection::preview_base_display_configuration( |
153 | @@ -1079,15 +1097,7 @@ |
154 | request.mutable_configuration()->CopyFrom(configuration); |
155 | request.set_timeout(timeout.count()); |
156 | |
157 | - auto store_error_result = new HandleErrorVoid; |
158 | - store_error_result->result = std::make_unique<mp::Void>(); |
159 | - store_error_result->on_error = [this](mp::Void const& message) |
160 | - { |
161 | - MirError const error{ |
162 | - static_cast<MirErrorDomain>(message.structured_error().domain()), |
163 | - message.structured_error().code()}; |
164 | - (*error_handler)(&error); |
165 | - }; |
166 | + auto store_error_result = create_stored_error_result<mp::Void>(error_handler); |
167 | |
168 | server.preview_base_display_configuration( |
169 | &request, |
170 | @@ -1099,15 +1109,7 @@ |
171 | { |
172 | mp::Void request; |
173 | |
174 | - auto store_error_result = new HandleErrorVoid; |
175 | - store_error_result->result = std::make_unique<mp::Void>(); |
176 | - store_error_result->on_error = [this](mp::Void const& message) |
177 | - { |
178 | - MirError const error{ |
179 | - static_cast<MirErrorDomain>(message.structured_error().domain()), |
180 | - message.structured_error().code()}; |
181 | - (*error_handler)(&error); |
182 | - }; |
183 | + auto store_error_result = create_stored_error_result<mp::Void>(error_handler); |
184 | |
185 | server.cancel_base_display_configuration_preview( |
186 | &request, |
187 | @@ -1115,6 +1117,27 @@ |
188 | google::protobuf::NewCallback(&handle_structured_error, store_error_result)); |
189 | } |
190 | |
191 | +void MirConnection::configure_session_display(mp::DisplayConfiguration const& configuration) |
192 | +{ |
193 | + auto store_error_result = create_stored_error_result<mp::DisplayConfiguration>(error_handler); |
194 | + |
195 | + server.configure_display( |
196 | + &configuration, |
197 | + store_error_result->result.get(), |
198 | + google::protobuf::NewCallback(&handle_structured_error, store_error_result)); |
199 | +} |
200 | + |
201 | +void MirConnection::remove_session_display() |
202 | +{ |
203 | + mp::Void request; |
204 | + auto store_error_result = create_stored_error_result<mp::Void>(error_handler); |
205 | + |
206 | + server.remove_session_configuration( |
207 | + &request, |
208 | + store_error_result->result.get(), |
209 | + google::protobuf::NewCallback(&handle_structured_error, store_error_result)); |
210 | +} |
211 | + |
212 | void MirConnection::confirm_base_display_configuration( |
213 | mp::DisplayConfiguration const& configuration) |
214 | { |
215 | |
216 | === modified file 'src/client/mir_connection.h' |
217 | --- src/client/mir_connection.h 2016-12-14 19:53:10 +0000 |
218 | +++ src/client/mir_connection.h 2016-12-23 15:34:22 +0000 |
219 | @@ -187,6 +187,9 @@ |
220 | MirWaitHandle* configure_display(MirDisplayConfiguration* configuration); |
221 | void done_display_configure(); |
222 | |
223 | + void configure_session_display(mir::protobuf::DisplayConfiguration const& configuration); |
224 | + void remove_session_display(); |
225 | + |
226 | MirWaitHandle* set_base_display_configuration(MirDisplayConfiguration const* configuration); |
227 | void preview_base_display_configuration( |
228 | mir::protobuf::DisplayConfiguration const& configuration, |
229 | |
230 | === modified file 'src/client/mir_connection_api.cpp' |
231 | --- src/client/mir_connection_api.cpp 2016-12-13 06:00:32 +0000 |
232 | +++ src/client/mir_connection_api.cpp 2016-12-23 15:34:22 +0000 |
233 | @@ -427,3 +427,22 @@ |
234 | } |
235 | } |
236 | |
237 | +void mir_connection_apply_session_display_configuration(MirConnection* connection, MirDisplayConfig const* display_config) |
238 | +try |
239 | +{ |
240 | + connection->configure_session_display(*display_config); |
241 | +} |
242 | +catch (std::exception const& ex) |
243 | +{ |
244 | + MIR_LOG_UNCAUGHT_EXCEPTION(ex); |
245 | +} |
246 | + |
247 | +void mir_connection_remove_session_display_configuration(MirConnection* connection) |
248 | +try |
249 | +{ |
250 | + connection->remove_session_display(); |
251 | +} |
252 | +catch (std::exception const& ex) |
253 | +{ |
254 | + MIR_LOG_UNCAUGHT_EXCEPTION(ex); |
255 | +} |
256 | |
257 | === modified file 'src/client/rpc/mir_display_server.cpp' |
258 | --- src/client/rpc/mir_display_server.cpp 2016-11-28 16:58:23 +0000 |
259 | +++ src/client/rpc/mir_display_server.cpp 2016-12-23 15:34:22 +0000 |
260 | @@ -84,6 +84,13 @@ |
261 | { |
262 | channel->call_method(std::string(__func__), request, response, done); |
263 | } |
264 | +void mclr::DisplayServer::remove_session_configuration( |
265 | + mir::protobuf::Void const* request, |
266 | + mir::protobuf::Void* response, |
267 | + google::protobuf::Closure* done) |
268 | +{ |
269 | + channel->call_method(std::string(__func__), request, response, done); |
270 | +} |
271 | void mclr::DisplayServer::set_base_display_configuration( |
272 | mir::protobuf::DisplayConfiguration const* request, |
273 | mir::protobuf::Void* response, |
274 | |
275 | === modified file 'src/client/rpc/mir_display_server.h' |
276 | --- src/client/rpc/mir_display_server.h 2016-11-28 16:58:23 +0000 |
277 | +++ src/client/rpc/mir_display_server.h 2016-12-23 15:34:22 +0000 |
278 | @@ -67,6 +67,10 @@ |
279 | mir::protobuf::DisplayConfiguration const* request, |
280 | mir::protobuf::DisplayConfiguration* response, |
281 | google::protobuf::Closure* done) override; |
282 | + void remove_session_configuration( |
283 | + mir::protobuf::Void const* request, |
284 | + mir::protobuf::Void* response, |
285 | + google::protobuf::Closure* done) override; |
286 | void set_base_display_configuration( |
287 | mir::protobuf::DisplayConfiguration const* request, |
288 | mir::protobuf::Void* response, |
289 | |
290 | === modified file 'src/client/symbols.map' |
291 | --- src/client/symbols.map 2016-12-23 04:18:57 +0000 |
292 | +++ src/client/symbols.map 2016-12-23 15:34:22 +0000 |
293 | @@ -500,6 +500,8 @@ |
294 | mir_touchpad_configuration_set_tap_to_click; |
295 | mir_connection_request_extension; |
296 | mir_output_get_model; |
297 | + mir_connection_apply_session_display_configuration; |
298 | + mir_connection_remove_session_display_configuration; |
299 | mir_blob_from_display_config; |
300 | mir_blob_to_display_config; |
301 | } MIR_CLIENT_0.25; |
302 | |
303 | === modified file 'src/include/common/mir/protobuf/display_server.h' |
304 | --- src/include/common/mir/protobuf/display_server.h 2016-11-28 16:58:23 +0000 |
305 | +++ src/include/common/mir/protobuf/display_server.h 2016-12-23 15:34:22 +0000 |
306 | @@ -63,6 +63,10 @@ |
307 | mir::protobuf::DisplayConfiguration const* request, |
308 | mir::protobuf::DisplayConfiguration* response, |
309 | google::protobuf::Closure* done) = 0; |
310 | + virtual void remove_session_configuration( |
311 | + mir::protobuf::Void const* request, |
312 | + mir::protobuf::Void* response, |
313 | + google::protobuf::Closure* done) = 0; |
314 | virtual void set_base_display_configuration( |
315 | mir::protobuf::DisplayConfiguration const* request, |
316 | mir::protobuf::Void* response, |
317 | |
318 | === modified file 'src/include/server/mir/frontend/display_changer.h' |
319 | --- src/include/server/mir/frontend/display_changer.h 2016-10-12 06:03:15 +0000 |
320 | +++ src/include/server/mir/frontend/display_changer.h 2016-12-23 15:34:22 +0000 |
321 | @@ -39,6 +39,7 @@ |
322 | |
323 | virtual std::shared_ptr<graphics::DisplayConfiguration> base_configuration() = 0; |
324 | virtual void configure(std::shared_ptr<Session> const&, std::shared_ptr<graphics::DisplayConfiguration> const&) = 0; |
325 | + virtual void remove_session_configuration(std::shared_ptr<Session> const&) = 0; |
326 | virtual void set_base_configuration(std::shared_ptr<graphics::DisplayConfiguration> const&) = 0; |
327 | virtual void preview_base_configuration( |
328 | std::weak_ptr<Session> const& session, |
329 | |
330 | === modified file 'src/server/frontend/authorizing_display_changer.cpp' |
331 | --- src/server/frontend/authorizing_display_changer.cpp 2016-10-12 06:03:15 +0000 |
332 | +++ src/server/frontend/authorizing_display_changer.cpp 2016-12-23 15:34:22 +0000 |
333 | @@ -69,6 +69,15 @@ |
334 | BOOST_THROW_EXCEPTION(std::runtime_error("not authorized to apply display configurations")); |
335 | } |
336 | |
337 | +void mf::AuthorizingDisplayChanger::remove_session_configuration( |
338 | + std::shared_ptr<mf::Session> const& session) |
339 | +{ |
340 | + if (configure_display_is_allowed) |
341 | + changer->remove_session_configuration(session); |
342 | + else |
343 | + BOOST_THROW_EXCEPTION(std::runtime_error("not authorized to remove display configurations")); |
344 | +} |
345 | + |
346 | void mf::AuthorizingDisplayChanger::set_base_configuration( |
347 | std::shared_ptr<graphics::DisplayConfiguration> const& config) |
348 | { |
349 | |
350 | === modified file 'src/server/frontend/authorizing_display_changer.h' |
351 | --- src/server/frontend/authorizing_display_changer.h 2016-10-12 06:03:15 +0000 |
352 | +++ src/server/frontend/authorizing_display_changer.h 2016-12-23 15:34:22 +0000 |
353 | @@ -49,6 +49,8 @@ |
354 | void configure( |
355 | std::shared_ptr<frontend::Session> const&, |
356 | std::shared_ptr<graphics::DisplayConfiguration> const&) override; |
357 | + void remove_session_configuration( |
358 | + std::shared_ptr<frontend::Session> const&) override; |
359 | void set_base_configuration( |
360 | std::shared_ptr<graphics::DisplayConfiguration> const&) override; |
361 | void preview_base_configuration( |
362 | |
363 | === modified file 'src/server/frontend/protobuf_message_processor.cpp' |
364 | --- src/server/frontend/protobuf_message_processor.cpp 2016-11-28 16:58:23 +0000 |
365 | +++ src/server/frontend/protobuf_message_processor.cpp 2016-12-23 15:34:22 +0000 |
366 | @@ -249,6 +249,10 @@ |
367 | { |
368 | invoke(this, display_server.get(), &DisplayServer::configure_display, invocation); |
369 | } |
370 | + else if ("remove_session_configuration" == invocation.method_name()) |
371 | + { |
372 | + invoke(this, display_server.get(), &DisplayServer::remove_session_configuration, invocation); |
373 | + } |
374 | else if ("set_base_display_configuration" == invocation.method_name()) |
375 | { |
376 | invoke(this, display_server.get(), &DisplayServer::set_base_display_configuration, invocation); |
377 | |
378 | === modified file 'src/server/frontend/session_mediator.cpp' |
379 | --- src/server/frontend/session_mediator.cpp 2016-12-21 03:07:05 +0000 |
380 | +++ src/server/frontend/session_mediator.cpp 2016-12-23 15:34:22 +0000 |
381 | @@ -646,7 +646,7 @@ |
382 | } |
383 | |
384 | void mf::SessionMediator::configure_display( |
385 | - const ::mir::protobuf::DisplayConfiguration* request, |
386 | + ::mir::protobuf::DisplayConfiguration const* request, |
387 | ::mir::protobuf::DisplayConfiguration* response, |
388 | ::google::protobuf::Closure* done) |
389 | { |
390 | @@ -666,6 +666,21 @@ |
391 | done->Run(); |
392 | } |
393 | |
394 | +void mf::SessionMediator::remove_session_configuration( |
395 | + ::mir::protobuf::Void const* /*request*/, |
396 | + ::mir::protobuf::Void* /*response*/, |
397 | + ::google::protobuf::Closure* done) |
398 | +{ |
399 | + auto session = weak_session.lock(); |
400 | + |
401 | + if (session.get() == nullptr) |
402 | + BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session")); |
403 | + |
404 | + display_changer->remove_session_configuration(session); |
405 | + |
406 | + done->Run(); |
407 | +} |
408 | + |
409 | void mf::SessionMediator::set_base_display_configuration( |
410 | mir::protobuf::DisplayConfiguration const* request, |
411 | mir::protobuf::Void* /*response*/, |
412 | |
413 | === modified file 'src/server/frontend/session_mediator.h' |
414 | --- src/server/frontend/session_mediator.h 2016-11-28 16:58:23 +0000 |
415 | +++ src/server/frontend/session_mediator.h 2016-12-23 15:34:22 +0000 |
416 | @@ -144,6 +144,10 @@ |
417 | mir::protobuf::DisplayConfiguration const* request, |
418 | mir::protobuf::DisplayConfiguration* response, |
419 | google::protobuf::Closure* done) override; |
420 | + void remove_session_configuration( |
421 | + mir::protobuf::Void const* request, |
422 | + mir::protobuf::Void* response, |
423 | + google::protobuf::Closure* done) override; |
424 | void set_base_display_configuration( |
425 | mir::protobuf::DisplayConfiguration const* request, |
426 | mir::protobuf::Void* response, |
427 | |
428 | === modified file 'src/server/graphics/display_configuration_observer_multiplexer.cpp' |
429 | --- src/server/graphics/display_configuration_observer_multiplexer.cpp 2016-12-09 02:54:31 +0000 |
430 | +++ src/server/graphics/display_configuration_observer_multiplexer.cpp 2016-12-23 15:34:22 +0000 |
431 | @@ -38,6 +38,19 @@ |
432 | for_each_observer(&mg::DisplayConfigurationObserver::base_configuration_updated, base_config); |
433 | } |
434 | |
435 | +void mg::DisplayConfigurationObserverMultiplexer::session_configuration_applied( |
436 | + std::shared_ptr<frontend::Session> const& session, |
437 | + std::shared_ptr<DisplayConfiguration> const& config) |
438 | +{ |
439 | + for_each_observer(&mg::DisplayConfigurationObserver::session_configuration_applied, session, config); |
440 | +} |
441 | + |
442 | +void mg::DisplayConfigurationObserverMultiplexer::session_configuration_removed( |
443 | + std::shared_ptr<frontend::Session> const& session) |
444 | +{ |
445 | + for_each_observer(&mg::DisplayConfigurationObserver::session_configuration_removed, session); |
446 | +} |
447 | + |
448 | void mg::DisplayConfigurationObserverMultiplexer::configuration_failed( |
449 | std::shared_ptr<mg::DisplayConfiguration const> const& attempted, |
450 | std::exception const& error) |
451 | |
452 | === modified file 'src/server/graphics/display_configuration_observer_multiplexer.h' |
453 | --- src/server/graphics/display_configuration_observer_multiplexer.h 2016-12-09 02:54:31 +0000 |
454 | +++ src/server/graphics/display_configuration_observer_multiplexer.h 2016-12-23 15:34:22 +0000 |
455 | @@ -25,6 +25,10 @@ |
456 | |
457 | namespace mir |
458 | { |
459 | +namespace frontend |
460 | +{ |
461 | +class Session; |
462 | +} |
463 | namespace graphics |
464 | { |
465 | class DisplayConfigurationObserverMultiplexer : public ObserverMultiplexer<DisplayConfigurationObserver> |
466 | @@ -38,6 +42,11 @@ |
467 | |
468 | void base_configuration_updated(std::shared_ptr<DisplayConfiguration const> const& base_config) override; |
469 | |
470 | + void session_configuration_applied(std::shared_ptr<frontend::Session> const& session, |
471 | + std::shared_ptr<DisplayConfiguration> const& config) override; |
472 | + |
473 | + void session_configuration_removed(std::shared_ptr<frontend::Session> const& session) override; |
474 | + |
475 | void configuration_failed( |
476 | std::shared_ptr<DisplayConfiguration const> const& attempted, |
477 | std::exception const& error) override; |
478 | |
479 | === modified file 'src/server/report/logging/display_configuration_report.cpp' |
480 | --- src/server/report/logging/display_configuration_report.cpp 2016-12-14 04:09:02 +0000 |
481 | +++ src/server/report/logging/display_configuration_report.cpp 2016-12-23 15:34:22 +0000 |
482 | @@ -20,11 +20,13 @@ |
483 | #include "mir/graphics/display_configuration.h" |
484 | #include "mir/output_type_names.h" |
485 | #include "mir/logging/logger.h" |
486 | +#include "mir/frontend/session.h" |
487 | #include "mir/graphics/edid.h" |
488 | |
489 | #include <boost/exception/diagnostic_information.hpp> |
490 | #include <cmath> |
491 | |
492 | +namespace mf = mir::frontend; |
493 | namespace mg = mir::graphics; |
494 | namespace ml = mir::logging; |
495 | namespace mrl= mir::report::logging; |
496 | @@ -65,6 +67,18 @@ |
497 | log_configuration(severity, *base_config); |
498 | } |
499 | |
500 | +void mrl::DisplayConfigurationReport::session_configuration_applied(std::shared_ptr<mf::Session> const& session, |
501 | + std::shared_ptr<mg::DisplayConfiguration> const& config) |
502 | +{ |
503 | + logger->log(component, severity, "Session %s applied display configuration", session->name().c_str()); |
504 | + log_configuration(severity, *config); |
505 | +} |
506 | + |
507 | +void mrl::DisplayConfigurationReport::session_configuration_removed(std::shared_ptr<frontend::Session> const& session) |
508 | +{ |
509 | + logger->log(component, severity, "Session %s removed display configuration", session->name().c_str()); |
510 | +} |
511 | + |
512 | void mrl::DisplayConfigurationReport::configuration_failed( |
513 | std::shared_ptr<mg::DisplayConfiguration const> const& attempted, |
514 | std::exception const& error) |
515 | @@ -123,7 +137,7 @@ |
516 | {"on", "in standby", "suspended", "off"}; |
517 | logger->log(component, severity, |
518 | "%sPower is %s", indent, power_mode[out.power_mode]); |
519 | - |
520 | + |
521 | if (out.used) |
522 | { |
523 | if (out.current_mode_index < out.modes.size()) |
524 | |
525 | === modified file 'src/server/report/logging/display_configuration_report.h' |
526 | --- src/server/report/logging/display_configuration_report.h 2016-12-09 02:54:31 +0000 |
527 | +++ src/server/report/logging/display_configuration_report.h 2016-12-23 15:34:22 +0000 |
528 | @@ -27,6 +27,10 @@ |
529 | { |
530 | namespace logging { class Logger; enum class Severity; } |
531 | |
532 | +namespace frontend |
533 | +{ |
534 | +class Session; |
535 | +} |
536 | namespace report |
537 | { |
538 | namespace logging |
539 | @@ -42,6 +46,11 @@ |
540 | |
541 | void base_configuration_updated(std::shared_ptr<graphics::DisplayConfiguration const> const& base_config) override; |
542 | |
543 | + void session_configuration_applied(std::shared_ptr<frontend::Session> const& session, |
544 | + std::shared_ptr<graphics::DisplayConfiguration> const& config) override; |
545 | + |
546 | + void session_configuration_removed(std::shared_ptr<frontend::Session> const& session) override; |
547 | + |
548 | void configuration_failed( |
549 | std::shared_ptr<graphics::DisplayConfiguration const> const& attempted, |
550 | std::exception const& error) override; |
551 | |
552 | === modified file 'src/server/scene/mediating_display_changer.cpp' |
553 | --- src/server/scene/mediating_display_changer.cpp 2016-12-09 02:54:31 +0000 |
554 | +++ src/server/scene/mediating_display_changer.cpp 2016-12-23 15:34:22 +0000 |
555 | @@ -1,5 +1,5 @@ |
556 | /* |
557 | - * Copyright © 2013 Canonical Ltd. |
558 | + * Copyright © 2013-2016 Canonical Ltd. |
559 | * |
560 | * This program is free software: you can redistribute it and/or modify it |
561 | * under the terms of the GNU General Public License version 3, |
562 | @@ -191,6 +191,7 @@ |
563 | { |
564 | std::lock_guard<std::mutex> lg{configuration_mutex}; |
565 | config_map[session] = conf; |
566 | + observer->session_configuration_applied(session, conf); |
567 | |
568 | if (session != focused_session.lock()) |
569 | return; |
570 | @@ -222,6 +223,43 @@ |
571 | }); |
572 | } |
573 | |
574 | +void ms::MediatingDisplayChanger::remove_session_configuration( |
575 | + std::shared_ptr<mf::Session> const& session) |
576 | +{ |
577 | + { |
578 | + std::lock_guard<std::mutex> lg{configuration_mutex}; |
579 | + if (config_map.find(session) != config_map.end()) |
580 | + { |
581 | + config_map.erase(session); |
582 | + observer->session_configuration_removed(session); |
583 | + } |
584 | + |
585 | + if (session != focused_session.lock()) |
586 | + return; |
587 | + } |
588 | + |
589 | + std::weak_ptr<mf::Session> const weak_session{session}; |
590 | + |
591 | + server_action_queue->enqueue( |
592 | + this, |
593 | + [this, weak_session] |
594 | + { |
595 | + if (auto const session = weak_session.lock()) |
596 | + { |
597 | + std::lock_guard<std::mutex> lg{configuration_mutex}; |
598 | + |
599 | + try |
600 | + { |
601 | + apply_base_config(); |
602 | + } |
603 | + catch (std::exception const&) |
604 | + { |
605 | + session->send_error(DisplayConfigurationFailedError{}); |
606 | + } |
607 | + } |
608 | + }); |
609 | +} |
610 | + |
611 | void |
612 | ms::MediatingDisplayChanger::preview_base_configuration( |
613 | std::weak_ptr<frontend::Session> const& session, |
614 | |
615 | === modified file 'src/server/scene/mediating_display_changer.h' |
616 | --- src/server/scene/mediating_display_changer.h 2016-11-15 23:48:01 +0000 |
617 | +++ src/server/scene/mediating_display_changer.h 2016-12-23 15:34:22 +0000 |
618 | @@ -75,6 +75,7 @@ |
619 | std::shared_ptr<graphics::DisplayConfiguration> base_configuration() override; |
620 | void configure(std::shared_ptr<frontend::Session> const& session, |
621 | std::shared_ptr<graphics::DisplayConfiguration> const& conf) override; |
622 | + void remove_session_configuration(std::shared_ptr<frontend::Session> const& session) override; |
623 | void preview_base_configuration( |
624 | std::weak_ptr<frontend::Session> const& session, |
625 | std::shared_ptr<graphics::DisplayConfiguration> const& conf, |
626 | |
627 | === modified file 'tests/acceptance-tests/test_nested_mir.cpp' |
628 | --- tests/acceptance-tests/test_nested_mir.cpp 2016-12-09 02:54:31 +0000 |
629 | +++ tests/acceptance-tests/test_nested_mir.cpp 2016-12-23 15:34:22 +0000 |
630 | @@ -127,6 +127,8 @@ |
631 | { |
632 | MOCK_METHOD1(initial_configuration, void (std::shared_ptr<mg::DisplayConfiguration const> const& configuration)); |
633 | MOCK_METHOD1(configuration_applied, void (std::shared_ptr<mg::DisplayConfiguration const> const& configuration)); |
634 | + MOCK_METHOD2(session_configuration_applied, void (std::shared_ptr<mf::Session> const& session, std::shared_ptr<mg::DisplayConfiguration> const& configuration)); |
635 | + MOCK_METHOD1(session_configuration_removed, void (std::shared_ptr<mf::Session> const& session)); |
636 | MOCK_METHOD1(base_configuration_updated, void (std::shared_ptr<mg::DisplayConfiguration const> const& base_config)); |
637 | MOCK_METHOD2(configuration_failed, void(std::shared_ptr<mg::DisplayConfiguration const> const&, std::exception const&)); |
638 | MOCK_METHOD2(catastrophic_configuration_error, void(std::shared_ptr<mg::DisplayConfiguration const> const&, std::exception const&)); |
639 | |
640 | === modified file 'tests/acceptance-tests/test_new_display_configuration.cpp' |
641 | --- tests/acceptance-tests/test_new_display_configuration.cpp 2016-12-12 05:13:17 +0000 |
642 | +++ tests/acceptance-tests/test_new_display_configuration.cpp 2016-12-23 15:34:22 +0000 |
643 | @@ -41,6 +41,7 @@ |
644 | |
645 | #include <atomic> |
646 | #include <chrono> |
647 | +#include <mutex> |
648 | |
649 | #include <gmock/gmock.h> |
650 | #include <gtest/gtest.h> |
651 | @@ -109,6 +110,11 @@ |
652 | return expectations.back().notifier.get_future(); |
653 | } |
654 | |
655 | + MOCK_METHOD2(session_configuration_applied, void( |
656 | + std::shared_ptr<mf::Session> const&, |
657 | + std::shared_ptr<mg::DisplayConfiguration> const&)); |
658 | + MOCK_METHOD1(session_configuration_removed, void(std::shared_ptr<mf::Session> const&)); |
659 | + |
660 | protected: |
661 | void initial_configuration( |
662 | std::shared_ptr<mg::DisplayConfiguration const> const&) override |
663 | @@ -187,6 +193,7 @@ |
664 | testing::NiceMock<MockDisplay> mock_display; |
665 | std::shared_ptr<NotifyingConfigurationObserver> observer{std::make_shared<NotifyingConfigurationObserver>()}; |
666 | StubAuthorizer stub_authorizer; |
667 | + mir::test::Signal observed_changed; |
668 | }; |
669 | |
670 | TEST_F(DisplayConfigurationTest, display_configuration_reaches_client) |
671 | @@ -259,9 +266,31 @@ |
672 | connection = mir_connect_sync(mir_test_socket.c_str(), __PRETTY_FUNCTION__); |
673 | |
674 | auto const spec = mir_connection_create_spec_for_normal_surface(connection, 100, 100, mir_pixel_format_abgr_8888); |
675 | + mir_surface_spec_set_event_handler(spec, &handle_event, this); |
676 | surface = mir_surface_create_sync(spec); |
677 | mir_surface_spec_release(spec); |
678 | mir_buffer_stream_swap_buffers_sync(mir_surface_get_buffer_stream(surface)); |
679 | + |
680 | + ready_to_accept_events.wait_for(4s); |
681 | + if (!ready_to_accept_events.raised()) |
682 | + BOOST_THROW_EXCEPTION(std::runtime_error("Timeout waiting for surface to become focused and exposed")); |
683 | + } |
684 | + |
685 | + static void handle_event(MirSurface*, MirEvent const* ev, void* context) |
686 | + { |
687 | + auto const client = static_cast<SimpleClient*>(context); |
688 | + auto type = mir_event_get_type(ev); |
689 | + if (type == mir_event_type_surface) |
690 | + { |
691 | + auto surface_event = mir_event_get_surface_event(ev); |
692 | + auto const attrib = mir_surface_event_get_attribute(surface_event); |
693 | + auto const value = mir_surface_event_get_attribute_value(surface_event); |
694 | + |
695 | + std::lock_guard<std::mutex> lk(client->mutex); |
696 | + if (mir_surface_attrib_focus == attrib && |
697 | + mir_surface_focused == value) |
698 | + client->ready_to_accept_events.raise(); |
699 | + } |
700 | } |
701 | |
702 | void disconnect() |
703 | @@ -278,6 +307,9 @@ |
704 | std::string mir_test_socket; |
705 | MirConnection* connection{nullptr}; |
706 | MirSurface* surface{nullptr}; |
707 | + mutable std::mutex mutex; |
708 | + mir::test::Signal ready_to_accept_events; |
709 | + bool focused{false}; |
710 | }; |
711 | |
712 | struct DisplayClient : SimpleClient |
713 | @@ -1743,3 +1775,244 @@ |
714 | |
715 | client.disconnect(); |
716 | } |
717 | + |
718 | +TEST_F(DisplayConfigurationTest, configure_session_display) |
719 | +{ |
720 | + auto configuration = mir_connection_create_display_configuration(connection); |
721 | + |
722 | + EXPECT_CALL(*observer, session_configuration_applied(_, _)) |
723 | + .Times(1) |
724 | + .WillOnce(mt::WakeUp(&observed_changed)); |
725 | + |
726 | + mir_connection_apply_session_display_configuration(connection, configuration); |
727 | + |
728 | + observed_changed.wait_for(10s); |
729 | + |
730 | + mir_display_config_release(configuration); |
731 | +} |
732 | + |
733 | +TEST_F(DisplayConfigurationTest, configure_session_removed_display) |
734 | +{ |
735 | + auto configuration = mir_connection_create_display_configuration(connection); |
736 | + |
737 | + EXPECT_CALL(*observer, session_configuration_applied(_, _)) |
738 | + .Times(1) |
739 | + .WillOnce(mt::WakeUp(&observed_changed)); |
740 | + |
741 | + mir_connection_apply_session_display_configuration(connection, configuration); |
742 | + |
743 | + observed_changed.wait_for(10s); |
744 | + observed_changed.reset(); |
745 | + |
746 | + mir_connection_remove_session_display_configuration(connection); |
747 | + |
748 | + EXPECT_CALL(*observer, session_configuration_removed(_)) |
749 | + .Times(1) |
750 | + .WillOnce(mt::WakeUp(&observed_changed)); |
751 | + |
752 | + observed_changed.wait_for(10s); |
753 | + |
754 | + mir_display_config_release(configuration); |
755 | +} |
756 | + |
757 | +TEST_F(DisplayConfigurationTest, remove_is_noop_when_no_session_configuration_set) |
758 | +{ |
759 | + EXPECT_CALL(*observer, session_configuration_removed(_)) |
760 | + .Times(0); |
761 | + |
762 | + mir_connection_remove_session_display_configuration(connection); |
763 | + |
764 | + std::this_thread::sleep_for(1s); |
765 | +} |
766 | + |
767 | +TEST_F(DisplayConfigurationTest, remove_from_focused_client_causes_hardware_change) |
768 | +{ |
769 | + DisplayClient client{new_connection()}; |
770 | + |
771 | + client.connect(); |
772 | + |
773 | + std::atomic<int> times{2}; |
774 | + auto new_config = mir_connection_create_display_configuration(client.connection); |
775 | + |
776 | + // Apply a configuration to the client, assert it has been configured for the display |
777 | + { |
778 | + mir_output_set_position(mir_display_config_get_mutable_output(new_config, 0), 500, 12000); |
779 | + |
780 | + EXPECT_CALL(*observer, session_configuration_applied(_, mt::DisplayConfigMatches(new_config))) |
781 | + .Times(1) |
782 | + .WillOnce(mt::WakeUpWhenZero(&observed_changed, ×)); |
783 | + EXPECT_CALL(mock_display, configure(mt::DisplayConfigMatches(new_config))) |
784 | + .Times(1) |
785 | + .WillOnce(mt::WakeUpWhenZero(&observed_changed, ×)); |
786 | + |
787 | + mir_connection_apply_session_display_configuration(client.connection, new_config); |
788 | + |
789 | + observed_changed.wait_for(10s); |
790 | + observed_changed.reset(); |
791 | + mir_display_config_release(new_config); |
792 | + } |
793 | + |
794 | + // Remove the configuration, assert we have been re-configured back to the base config |
795 | + { |
796 | + times = 2; |
797 | + |
798 | + EXPECT_CALL(*observer, session_configuration_removed(_)) |
799 | + .Times(1) |
800 | + .WillOnce(mt::WakeUpWhenZero(&observed_changed, ×)); |
801 | + EXPECT_CALL(mock_display, configure(mt::DisplayConfigMatches(std::cref(stub_display_config)))) |
802 | + .Times(1) |
803 | + .WillOnce(mt::WakeUpWhenZero(&observed_changed, ×)); |
804 | + |
805 | + mir_connection_remove_session_display_configuration(client.connection); |
806 | + |
807 | + observed_changed.wait_for(10s); |
808 | + } |
809 | + |
810 | + client.disconnect(); |
811 | +} |
812 | + |
813 | +TEST_F(DisplayConfigurationTest, remove_from_unfocused_client_causes_no_hardware_change) |
814 | +{ |
815 | + DisplayClient client{new_connection()}; |
816 | + |
817 | + client.connect(); |
818 | + |
819 | + auto new_config = mir_connection_create_display_configuration(client.connection); |
820 | + std::atomic<int> times{2}; |
821 | + |
822 | + // Set the first clients display config |
823 | + { |
824 | + mir_output_set_position(mir_display_config_get_mutable_output(new_config, 0), 500, 12000); |
825 | + |
826 | + EXPECT_CALL(*observer, session_configuration_applied(_, mt::DisplayConfigMatches(new_config))) |
827 | + .Times(1) |
828 | + .WillOnce(mt::WakeUpWhenZero(&observed_changed, ×)); |
829 | + EXPECT_CALL(mock_display, configure(mt::DisplayConfigMatches(new_config))) |
830 | + .Times(1) |
831 | + .WillOnce(mt::WakeUpWhenZero(&observed_changed, ×)); |
832 | + |
833 | + mir_connection_apply_session_display_configuration(client.connection, new_config); |
834 | + |
835 | + observed_changed.wait_for(10s); |
836 | + observed_changed.reset(); |
837 | + mir_display_config_release(new_config); |
838 | + } |
839 | + |
840 | + DisplayClient client2{new_connection()}; |
841 | + |
842 | + // Connect and wait for the second client to get setup and config. Which will be the focused session |
843 | + { |
844 | + EXPECT_CALL(mock_display, configure(mt::DisplayConfigMatches(std::cref(stub_display_config)))) |
845 | + .Times(1) |
846 | + .WillOnce(mt::WakeUp(&observed_changed)); |
847 | + |
848 | + client2.connect(); |
849 | + observed_changed.wait_for(10s); |
850 | + observed_changed.reset(); |
851 | + } |
852 | + |
853 | + // Remove the display config from the first config and assert no hardware changes happen |
854 | + { |
855 | + EXPECT_CALL(*observer, session_configuration_removed(_)) |
856 | + .Times(1) |
857 | + .WillOnce(mt::WakeUp(&observed_changed)); |
858 | + EXPECT_CALL(mock_display, configure(_)) |
859 | + .Times(0); |
860 | + |
861 | + mir_connection_remove_session_display_configuration(client.connection); |
862 | + |
863 | + observed_changed.wait_for(10s); |
864 | + std::this_thread::sleep_for(1s); |
865 | + } |
866 | + |
867 | + client2.disconnect(); |
868 | + client.disconnect(); |
869 | +} |
870 | + |
871 | +TEST_F(DisplayConfigurationTest, remove_from_unfocused_client_causes_hardware_change_when_focused) |
872 | +{ |
873 | + DisplayClient client{new_connection()}; |
874 | + |
875 | + client.connect(); |
876 | + |
877 | + auto new_config = mir_connection_create_display_configuration(client.connection); |
878 | + std::atomic<int> times{2}; |
879 | + |
880 | + // Set the first clients display config |
881 | + { |
882 | + mir_output_set_position(mir_display_config_get_mutable_output(new_config, 0), 500, 12000); |
883 | + |
884 | + EXPECT_CALL(*observer, session_configuration_applied(_, mt::DisplayConfigMatches(new_config))) |
885 | + .Times(1) |
886 | + .WillOnce(mt::WakeUpWhenZero(&observed_changed, ×)); |
887 | + EXPECT_CALL(mock_display, configure(mt::DisplayConfigMatches(new_config))) |
888 | + .Times(1) |
889 | + .WillOnce(mt::WakeUpWhenZero(&observed_changed, ×)); |
890 | + |
891 | + mir_connection_apply_session_display_configuration(client.connection, new_config); |
892 | + |
893 | + observed_changed.wait_for(10s); |
894 | + observed_changed.reset(); |
895 | + } |
896 | + |
897 | + DisplayClient client2{new_connection()}; |
898 | + |
899 | + // Connect and wait for the second client to get setup and config. Which will be the focused session |
900 | + { |
901 | + EXPECT_CALL(mock_display, configure(mt::DisplayConfigMatches(std::cref(stub_display_config)))) |
902 | + .Times(1) |
903 | + .WillOnce(mt::WakeUp(&observed_changed)); |
904 | + |
905 | + client2.connect(); |
906 | + observed_changed.wait_for(10s); |
907 | + observed_changed.reset(); |
908 | + } |
909 | + |
910 | + // Apply the new_config to client 2 as well so we can see disconnecting will apply the base config |
911 | + { |
912 | + times = 2; |
913 | + |
914 | + EXPECT_CALL(*observer, session_configuration_applied(_, mt::DisplayConfigMatches(new_config))) |
915 | + .Times(1) |
916 | + .WillOnce(mt::WakeUpWhenZero(&observed_changed, ×)); |
917 | + EXPECT_CALL(mock_display, configure(mt::DisplayConfigMatches(new_config))) |
918 | + .Times(1) |
919 | + .WillOnce(mt::WakeUpWhenZero(&observed_changed, ×)); |
920 | + |
921 | + mir_connection_apply_session_display_configuration(client2.connection, new_config); |
922 | + observed_changed.wait_for(10s); |
923 | + observed_changed.reset(); |
924 | + mir_display_config_release(new_config); |
925 | + } |
926 | + |
927 | + // Remove the display config from the first config and assert no hardware changes happen |
928 | + { |
929 | + |
930 | + EXPECT_CALL(*observer, session_configuration_removed(_)) |
931 | + .Times(1) |
932 | + .WillOnce(mt::WakeUp(&observed_changed)); |
933 | + EXPECT_CALL(mock_display, configure(_)) |
934 | + .Times(0); |
935 | + |
936 | + mir_connection_remove_session_display_configuration(client.connection); |
937 | + |
938 | + observed_changed.wait_for(10s); |
939 | + std::this_thread::sleep_for(1s); |
940 | + observed_changed.reset(); |
941 | + } |
942 | + |
943 | + testing::Mock::VerifyAndClearExpectations(&mock_display); |
944 | + |
945 | + // Disconnect client 2 which makes client 1 regain focus. Assert the base config is configured |
946 | + { |
947 | + EXPECT_CALL(mock_display, configure(mt::DisplayConfigMatches(std::cref(stub_display_config)))) |
948 | + .Times(1) |
949 | + .WillOnce(mt::WakeUp(&observed_changed)); |
950 | + |
951 | + client2.disconnect(); |
952 | + |
953 | + observed_changed.wait_for(10s); |
954 | + } |
955 | + |
956 | + client.disconnect(); |
957 | +} |
958 | |
959 | === modified file 'tests/include/mir/test/doubles/null_display_changer.h' |
960 | --- tests/include/mir/test/doubles/null_display_changer.h 2016-10-12 06:03:15 +0000 |
961 | +++ tests/include/mir/test/doubles/null_display_changer.h 2016-12-23 15:34:22 +0000 |
962 | @@ -39,6 +39,9 @@ |
963 | void configure(std::shared_ptr<frontend::Session> const&, std::shared_ptr<graphics::DisplayConfiguration> const&) override |
964 | { |
965 | } |
966 | + void remove_session_configuration(std::shared_ptr<frontend::Session> const&) override |
967 | + { |
968 | + } |
969 | void set_base_configuration(std::shared_ptr<graphics::DisplayConfiguration> const&) override |
970 | { |
971 | } |
972 | |
973 | === modified file 'tests/include/mir/test/doubles/stub_display_server.h' |
974 | --- tests/include/mir/test/doubles/stub_display_server.h 2016-12-21 03:07:05 +0000 |
975 | +++ tests/include/mir/test/doubles/stub_display_server.h 2016-12-23 15:34:22 +0000 |
976 | @@ -66,6 +66,10 @@ |
977 | mir::protobuf::DisplayConfiguration const* /*request*/, |
978 | mir::protobuf::DisplayConfiguration* /*response*/, |
979 | google::protobuf::Closure* /*done*/) {} |
980 | + void remove_session_configuration( |
981 | + mir::protobuf::Void const* /*request*/, |
982 | + mir::protobuf::Void* /*response*/, |
983 | + google::protobuf::Closure* /*done*/) {} |
984 | void set_base_display_configuration( |
985 | mir::protobuf::DisplayConfiguration const* /*request*/, |
986 | mir::protobuf::Void* /*response*/, |
987 | |
988 | === modified file 'tests/mir_test/display_config_matchers.cpp' |
989 | --- tests/mir_test/display_config_matchers.cpp 2016-12-09 02:54:31 +0000 |
990 | +++ tests/mir_test/display_config_matchers.cpp 2016-12-23 15:34:22 +0000 |
991 | @@ -423,3 +423,12 @@ |
992 | TestDisplayConfiguration translated_config_two{config2}; |
993 | return compare_display_configurations(listener, translated_config_one, translated_config_two); |
994 | } |
995 | + |
996 | +bool mt::compare_display_configurations( |
997 | + testing::MatchResultListener* listener, |
998 | + std::shared_ptr<mg::DisplayConfiguration> const& config1, |
999 | + MirDisplayConfig const* config2) |
1000 | +{ |
1001 | + TestDisplayConfiguration translated_config_two{config2}; |
1002 | + return compare_display_configurations(listener, *config1, translated_config_two); |
1003 | +} |
1004 | |
1005 | === modified file 'tests/unit-tests/scene/test_mediating_display_changer.cpp' |
1006 | --- tests/unit-tests/scene/test_mediating_display_changer.cpp 2016-12-09 02:54:31 +0000 |
1007 | +++ tests/unit-tests/scene/test_mediating_display_changer.cpp 2016-12-23 15:34:22 +0000 |
1008 | @@ -174,6 +174,10 @@ |
1009 | void initial_configuration(std::shared_ptr<mg::DisplayConfiguration const> const&) override {} |
1010 | void configuration_applied(std::shared_ptr<mg::DisplayConfiguration const> const&) override {} |
1011 | void base_configuration_updated(std::shared_ptr<mg::DisplayConfiguration const> const&) override {} |
1012 | + void session_configuration_applied( |
1013 | + std::shared_ptr<mf::Session> const&, |
1014 | + std::shared_ptr<mg::DisplayConfiguration> const&) override {}; |
1015 | + void session_configuration_removed(std::shared_ptr<mf::Session> const&) override {}; |
1016 | void configuration_failed( |
1017 | std::shared_ptr<mg::DisplayConfiguration const> const&, |
1018 | std::exception const&) override {} |
FAILED: Continuous integration, rev:3872 /mir-jenkins. ubuntu. com/job/ mir-ci/ 2362/ /mir-jenkins. ubuntu. com/job/ build-mir/ 3077/console /mir-jenkins. ubuntu. com/job/ build-0- fetch/3144 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 3136 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial+ overlay/ 3136 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= yakkety/ 3136 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= yakkety/ 3106/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 3106/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= yakkety/ 3106/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 3106 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 3106/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 3106 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 3106/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 3106/console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 2362/rebuild
https:/