Mir

Merge lp:~brandontschaefer/mir/client-api-apply-remove-display-config into lp:mir

Proposed by Brandon Schaefer
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
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://trello.com/c/L9LyQ6n6/461-add-client-api-for-mir-connection-apply-display-configuration

Add the two missing functions needed to remove the old display configuration API.

void mir_connection_apply_session_display_config(...)
void mir_connection_remove_session_display_config(...)

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

FAILED: Continuous integration, rev:3872
https://mir-jenkins.ubuntu.com/job/mir-ci/2362/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/3077/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/3144
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/3136
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/3136
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/3136
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/3106/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/3106/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/3106/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/3106
        deb: https://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
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/3106
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/3106/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/3106/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3873
https://mir-jenkins.ubuntu.com/job/mir-ci/2363/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/3078/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/3145
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/3137
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/3137
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/3137
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/3107
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/3107/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/3107
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/3107/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/3107
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/3107/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/3107/console
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/3107/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/3107
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/3107/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/3107
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/3107/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:3873
https://mir-jenkins.ubuntu.com/job/mir-ci/2364/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/3079
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/3146
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/3138
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/3138
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/3138
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/3108
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/3108/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/3108
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/3108/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/3108
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/3108/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/3108
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/3108/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/3108
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/3108/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/3108
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/3108/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
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_get_error_message.
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(std::shared_ptr<Session> const&) = 0;
Not wild on the naming - could this be remove_session_configuration?

336 + else if ("remove_display" == invocation.method_name())
And likewise, "remove_display_configuration" (or some equivalent)?

532 +void ms::MediatingDisplayChanger::remove(
533 + std::shared_ptr<mf::Session> const& session)
534 +{
535 + std::lock_guard<std::mutex> lg{configuration_mutex};
536 + config_map.erase(session);
537 + observer->session_configuration_removed(session);
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_session_display_config from a client that hasn't set a session configuration is a no-op
2) That calling remove_session_display_config from a *focused* client that *has* set a session configuration results in a hardware configuration change
3) That calling remove_session_display_config from an *unfocused* client that *has* set a session configuration results in *no* hardware configuration change
4) That calling remove_session_display_config from an *unfocused* client that *has* set a session configuration results in the base configuration getting applied when the client becomes focused.

review: Needs Fixing
Revision history for this message
Chris Halse Rogers (raof) wrote :

(There are more acceptance tests you could sensibly add, but those are the 4 big ones)

Revision history for this message
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...

review: Needs Fixing
Revision history for this message
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..._display_config_...()
or
   MirDisplayConfiguration
   mir..._display_configuration_...()

For a more clear way forward that gets us closer to this ideal, I have already proposed:
   https://code.launchpad.net/~vanvugt/mir/mir-display-config-header/+merge/311246
which you should probably revisit. Either fix this branch or retract your review of my branch.

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Specifically, according to your own comments we need to rename display_config_ to display_configuration, and here you are proposing the opposite of that, 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://code.launchpad.net/~vanvugt/mir/mir-display-config-header/+merge/311246

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 MirDisplayConfiguration. 6 characters isnt *to* many extra characters to type. 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.

review: Needs Fixing
Revision history for this message
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://code.launchpad.net/~vanvugt/mir/mir-display-config-header/+merge/311246
So that should be revisited.

review: Abstain
Revision history for this message
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 MirDisplayConfiguration*?

In which case, you've missed:

MirBlob* mir_blob_from_display_configuration(MirDisplayConfiguration* configuration);

and

MirDisplayConfiguration* mir_blob_to_display_configuration(MirBlob* blob);

(Yes, I know these have the intended form of the "future" API, but AIUI they have to go before we can eliminate MirDisplayConfiguration* and rename MirDisplayConfig* as planned or confusion will ensue.)

Can you (or other reviewers) clarify?

review: Needs Information
Revision history for this message
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_get_error_message.
> 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(std::shared_ptr<Session> const&) = 0;
> Not wild on the naming - could this be remove_session_configuration?
>
> 336 + else if ("remove_display" == invocation.method_name())
> And likewise, "remove_display_configuration" (or some equivalent)?

All good suggestions.

>
> 532 +void ms::MediatingDisplayChanger::remove(
> 533 + std::shared_ptr<mf::Session> const& session)
> 534 +{
> 535 + std::lock_guard<std::mutex> lg{configuration_mutex};
> 536 + config_map.erase(session);
> 537 + observer->session_configuration_removed(session);
> 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_display_config from a client that hasn't set a
> session configuration is a no-op
> 2) That calling remove_session_display_config from a *focused* client that
> *has* set a session configuration results in a hardware configuration change
> 3) That calling remove_session_display_config from an *unfocused* client that
> *has* set a session configuration results in *no* hardware configuration
> change
> 4) That calling remove_session_display_config from an *unfocused* client that
> *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.

Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

> Specifically, according to your own comments we need to rename display_config_
> to display_configuration, and here you are proposing the opposite of that,
> 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://code.launchpad.net/~vanvugt/mir/mir-display-config-
> header/+merge/311246
>
> 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
> MirDisplayConfiguration. 6 characters isnt *to* many extra characters to type.
> 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_configuration == old API. With the idea that once we get these functions in we then can deprecate the old set of functions then get a branch to rename them all to *_display_configuration.

Though I could still just move to display_configuration vs waiting, figured it would be more uniformed to have a branch that renames everything.

Revision history for this message
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 MirDisplayConfiguration*?

Yes

>
> In which case, you've missed:
>
> MirBlob* mir_blob_from_display_configuration(MirDisplayConfiguration*
> configuration);
>
> and
>
> MirDisplayConfiguration* mir_blob_to_display_configuration(MirBlob* blob);
>

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 MirDisplayConfiguration* and rename
> 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!

Revision history for this message
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 MirDisplayConfiguration*?
>
> Yes
>
> >
> > In which case, you've missed:
> >
> > MirBlob* mir_blob_from_display_configuration(MirDisplayConfiguration*
> > configuration);
> >
> > and
> >
> > MirDisplayConfiguration* mir_blob_to_display_configuration(MirBlob* blob);
> >
>
> 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).

Revision history for this message
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

review: Approve
Revision history for this message
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!

Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3875
https://mir-jenkins.ubuntu.com/job/mir-ci/2408/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/3136/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-0-fetch/3203/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/3195/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/3195/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/3195/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/3165/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/3165/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/3165/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/3165/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/3165/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/3165/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3876
https://mir-jenkins.ubuntu.com/job/mir-ci/2409/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/3137/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/3204
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/3196
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/3196
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/3196
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/3166/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/3166/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/3166/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/3166
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/3166/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/3166
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/3166/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/3166/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3877
https://mir-jenkins.ubuntu.com/job/mir-ci/2410/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/3138/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/3205
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/3197
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/3197
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/3197
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/3167/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/3167/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/3167/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/3167
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/3167/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/3167
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/3167/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/3167/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3878
https://mir-jenkins.ubuntu.com/job/mir-ci/2414/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/3145/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/3212
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/3204
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/3204
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/3204
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/3174
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/3174/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/3174
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/3174/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/3174/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/3174
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/3174/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/3174
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/3174/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/3174
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/3174/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3878
https://mir-jenkins.ubuntu.com/job/mir-ci/2419/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/3150/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/3217
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/3209
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/3209
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/3209
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/3179/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/3179
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/3179/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/3179
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/3179/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/3179/console
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/3179/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/3179
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/3179/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/3179
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/3179/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3878
https://mir-jenkins.ubuntu.com/job/mir-ci/2444/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/3187/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/3254
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/3246
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/3246
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/3246
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/3216/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/3216
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/3216/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/3216
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/3216/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/3216
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/3216/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/3216
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/3216/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/3216
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/3216/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote :

LGTM.

Failure is bug# 1649758.

review: Approve
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

04:21:54 Text conflict in src/client/symbols.map
04:21:54 1 conflicts encountered.

Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:3879
https://mir-jenkins.ubuntu.com/job/mir-ci/2501/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/3259
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/3326
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/3318
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/3318
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/3318
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/3288
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/3288/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/3288
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/3288/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/3288
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/3288/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/3288
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/3288/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/3288
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/3288/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/3288
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/3288/artifact/output/*zip*/output.zip

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

review: Approve (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_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, &times));
783+ EXPECT_CALL(mock_display, configure(mt::DisplayConfigMatches(new_config)))
784+ .Times(1)
785+ .WillOnce(mt::WakeUpWhenZero(&observed_changed, &times));
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, &times));
801+ EXPECT_CALL(mock_display, configure(mt::DisplayConfigMatches(std::cref(stub_display_config))))
802+ .Times(1)
803+ .WillOnce(mt::WakeUpWhenZero(&observed_changed, &times));
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, &times));
829+ EXPECT_CALL(mock_display, configure(mt::DisplayConfigMatches(new_config)))
830+ .Times(1)
831+ .WillOnce(mt::WakeUpWhenZero(&observed_changed, &times));
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, &times));
887+ EXPECT_CALL(mock_display, configure(mt::DisplayConfigMatches(new_config)))
888+ .Times(1)
889+ .WillOnce(mt::WakeUpWhenZero(&observed_changed, &times));
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, &times));
917+ EXPECT_CALL(mock_display, configure(mt::DisplayConfigMatches(new_config)))
918+ .Times(1)
919+ .WillOnce(mt::WakeUpWhenZero(&observed_changed, &times));
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 {}

Subscribers

People subscribed via source and target branches