Mir

Merge lp:~robertcarr/mir/client-focus-notifications into lp:~mir-team/mir/trunk

Proposed by Robert Carr
Status: Superseded
Proposed branch: lp:~robertcarr/mir/client-focus-notifications
Merge into: lp:~mir-team/mir/trunk
Prerequisite: lp:~mir-team/mir/connect-display-request-merge-trunk
Diff against target: 4839 lines (+960/-1609) (has conflicts)
85 files modified
examples/demo-inprocess-surface-client/inprocess_egl_client.cpp (+4/-5)
examples/demo-inprocess-surface-client/inprocess_egl_client.h (+0/-5)
examples/demo-shell/demo_shell.cpp (+1/-1)
examples/demo-shell/window_manager.cpp (+3/-3)
examples/demo-shell/window_manager.h (+3/-3)
include/platform/mir/graphics/display_configuration.h (+0/-31)
include/server/mir/default_server_configuration.h (+2/-0)
include/server/mir/frontend/display_changer.h (+0/-7)
include/server/mir/frontend/message_processor_report.h (+4/-0)
include/server/mir/frontend/null_message_processor_report.h (+2/-0)
include/server/mir/frontend/session.h (+0/-1)
include/server/mir/frontend/shell.h (+3/-5)
include/server/mir/logging/message_processor_report.h (+2/-0)
include/server/mir/lttng/message_processor_report.h (+1/-0)
include/server/mir/shell/default_focus_mechanism.h (+6/-21)
include/server/mir/shell/focus_controller.h (+44/-0)
include/server/mir/shell/focus_setter.h (+3/-9)
include/server/mir/shell/mediating_display_changer.h (+0/-41)
include/server/mir/shell/session_manager.h (+18/-9)
include/server/mir/shell/unauthorized_display_changer.h (+1/-4)
include/shared/mir_toolkit/client_types.h (+1/-30)
include/shared/mir_toolkit/common.h (+15/-2)
include/test/mir_test/event_matchers.h (+14/-0)
include/test/mir_test_doubles/mock_display_changer.h (+1/-3)
include/test/mir_test_doubles/mock_drm.h (+2/-4)
include/test/mir_test_doubles/mock_focus_setter.h (+1/-5)
include/test/mir_test_doubles/mock_shell.h (+1/-3)
include/test/mir_test_doubles/null_display_changer.h (+3/-7)
include/test/mir_test_doubles/stub_display_configuration.h (+2/-14)
include/test/mir_test_doubles/stub_session.h (+5/-1)
include/test/mir_test_doubles/stub_shell.h (+7/-15)
include/test/mir_test_framework/input_testing_server_configuration.h (+2/-3)
src/client/display_configuration.cpp (+4/-31)
src/client/display_configuration.h (+0/-1)
src/client/mir_connection.cpp (+4/-1)
src/client/mir_surface.cpp (+3/-4)
src/client/mir_surface.h (+1/-1)
src/platform/graphics/default_display_configuration_policy.cpp (+2/-4)
src/platform/graphics/display_configuration.cpp (+2/-55)
src/server/default_server_configuration.cpp (+9/-16)
src/server/frontend/null_message_processor_report.cpp (+4/-0)
src/server/frontend/protobuf_buffer_packer.cpp (+0/-16)
src/server/frontend/session_mediator.cpp (+47/-52)
src/server/graphics/android/android_display.cpp (+3/-9)
src/server/graphics/gbm/drm_mode_resources.cpp (+0/-15)
src/server/graphics/gbm/drm_mode_resources.h (+0/-4)
src/server/graphics/gbm/real_kms_display_configuration.cpp (+5/-23)
src/server/graphics/gbm/real_kms_display_configuration.h (+2/-1)
src/server/logging/message_processor_report.cpp (+6/-3)
src/server/lttng/message_processor_report.cpp (+5/-0)
src/server/shell/default_focus_mechanism.cpp (+20/-69)
src/server/shell/mediating_display_changer.cpp (+0/-64)
src/server/shell/session_manager.cpp (+72/-31)
src/server/shell/surface.cpp (+5/-2)
src/server/shell/unauthorized_display_changer.cpp (+1/-10)
src/shared/protobuf/mir_protobuf.proto (+0/-8)
tests/acceptance-tests/CMakeLists.txt (+1/-0)
tests/acceptance-tests/test_client_focus_notification.cpp (+231/-0)
tests/acceptance-tests/test_client_input.cpp (+4/-6)
tests/acceptance-tests/test_focus_selection.cpp (+22/-19)
tests/acceptance-tests/test_shell_control_of_surface_configuration.cpp (+7/-0)
tests/integration-tests/CMakeLists.txt (+0/-1)
tests/integration-tests/shell/CMakeLists.txt (+1/-1)
tests/integration-tests/test_display_info.cpp (+12/-106)
tests/integration-tests/test_server_client_types.cpp (+0/-46)
tests/mir_test/display_config_matchers.cpp (+18/-88)
tests/mir_test_doubles/mock_drm.cpp (+5/-12)
tests/mir_test_framework/input_testing_server_options.cpp (+38/-53)
tests/mir_test_framework/testing_server_options.cpp (+1/-2)
tests/unit-tests/client/test_client_display_conf.cpp (+0/-9)
tests/unit-tests/client/test_mir_connection.cpp (+1/-1)
tests/unit-tests/frontend/test_session_mediator.cpp (+2/-56)
tests/unit-tests/graphics/gbm/test_gbm_cursor.cpp (+1/-5)
tests/unit-tests/graphics/gbm/test_gbm_display_configuration.cpp (+13/-83)
tests/unit-tests/graphics/gbm/test_gbm_display_multi_monitor.cpp (+11/-11)
tests/unit-tests/graphics/gbm/test_overlapping_output_grouping.cpp (+1/-4)
tests/unit-tests/graphics/gbm/test_real_kms_output.cpp (+3/-6)
tests/unit-tests/graphics/test_default_display_configuration_policy.cpp (+5/-12)
tests/unit-tests/graphics/test_display_configuration.cpp (+8/-53)
tests/unit-tests/shell/CMakeLists.txt (+0/-1)
tests/unit-tests/shell/test_default_focus_mechanism.cpp (+72/-116)
tests/unit-tests/shell/test_mediating_display_changer.cpp (+0/-179)
tests/unit-tests/shell/test_session_manager.cpp (+121/-76)
tests/unit-tests/shell/test_surface.cpp (+34/-0)
tests/unit-tests/shell/test_unauthorized_display_changer.cpp (+2/-11)
Text conflict in include/shared/mir_toolkit/common.h
To merge this branch: bzr merge lp:~robertcarr/mir/client-focus-notifications
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Alan Griffiths Pending
Alexandros Frantzis Pending
Chris Halse Rogers Pending
Daniel van Vugt Pending
Review via email: mp+179801@code.launchpad.net

This proposal supersedes a proposal from 2013-05-30.

This proposal has been superseded by a proposal from 2013-08-13.

Commit message

Implement client notification of focus (received/lost) in terms of a Mir surface attribute.

Description of the change

This branch is a new version of client-focus-notifications based on ~mir-team/mir/connect-display-request-merge-trunk which enables removal of the cloggable event sink (notice how focus is now set in handle_surface_created, executed after the surface frontend processing has completed).

I've elected to still use surface attributes for focus, for two reasons:
1. I can't think of anything else to use
2. mir_surface_get_state(mir_surface_attrib_focus...seems to make sense as client API.

I think perhaps though, the default_focus_mechanism should handle the response of surface->configure with surface_attrib_focus. This way the shell can use the surface configurator to interfere and say, actually this surface may not take focus. I'm happy to include it in this MP if it's a popular idea or propose a followup for discussion after.

To post a comment you must log in.
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

There are a few open questions:

Should focus be modeled as a Surface attribute?
Is there any reason for the Surface to keep track of if it has focus.

Revision history for this message
kevin gunn (kgunn72) wrote : Posted in a previous version of this proposal

> There are a few open questions:
>
> Should focus be modeled as a Surface attribute?
> Is there any reason for the Surface to keep track of if it has focus.

makes sense to me it would be a surface attribute. as to why it might want to keep track....optimizations if there is no focus? and possibly, other client requests that won't work/don't make sense if focused or not.

just curious...is this some convention ?
mir_surface_focus_arraysize_
didn't understand why it was in the surf attrib for focusstate

in general...might be my lack of understanding. there are some mutex/surface locks in the proposed code....but i don't see unlocks (do those happen automagically as the code goes out of scope?)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal

> just curious...is this some convention ?
> mir_surface_focus_arraysize_
> didn't understand why it was in the surf attrib for focusstate

Yes, it is a sentinel element for the array, and its value is equal to the array size.

> in general...might be my lack of understanding. there are some mutex/surface
> locks in the proposed code....but i don't see unlocks (do those happen
> automagically as the code goes out of scope?)

std::unique_lock<> and std::lock_guard<> are scoped locks. They lock the associated mutex when created, and unlock it when going out of scope.

Revision history for this message
Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal

202 + std::unique_lock<std::mutex> lg(lock);
207 + std::unique_lock<std::mutex> lg(lock);

Are these locks necessary? Can a SessionMediator service two requests (in this case, two create_surface requests) concurrently? If it can, then the locks, as they are, have the following problem:

(t1) clog
(t2) clog
(t1) unclog, oops, any events for the surface created in (t2) will be sent to the client, too

214 + void handle_event(MirEvent const& ev)
215 + {
216 + if (clogged)

Taking into account the previous point (assuming the mediator can't service two requests from the same connection concurrently) and since this access to clogged is not protected, I suggest that we make clogged atomic<bool> and get rid of the locks.

315 + notify_change(attrib, value);
316 + break;

Indented one level deeper than required.

374 +namespace
375 +{
376 +
377 + struct ClientConfigCommon : TestingClientConfiguration
378 + {
379 + ClientConfigCommon() :
380 + connection(0),
381 + surface(0)
382 + {
383 + }
...

No need for indentation in namespace block.

415 + surface = NULL;

nullptr

505 +TEST_F(BespokeDisplayServerTestFixture, two_surfaces_are_notified_of_gaining_and_losing_focus)
552 + // We need some synchronization to ensure client two does not connect before client one.

Doesn't waiting for ready_for_second_client semaphore take care of that (it triggers only after the first client has received a surface created event, which means it has already connected)?

However, the test is still fragile. If the second client hasn't managed to connect and create a surface in the 5 seconds the first test has to finish, e.g., because of super high system load, then all_events_received.wait_for_at_most_seconds(5) in the first client will expire and the test will fail.

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

CloggableEventSink looks horribly broken:

There is no synchronization around "216 + if (clogged)" - which means it could be in different states in different threads.

"clogged" could change between "if (clogged)" being evaluated and the next statement.

There is nothing to prevent multiple calls to clog() - perhaps clogged should be an atomic counter?

I assume that clog() and unclog() are intended to be paired operations - but the calls I see don't deal with exceptions being thrown (please use RAII for paired operations).

What is the motivation for CloggableEventSink? Is this the right place for synchronization?

review: Needs Fixing
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

Hi all! Thanks for review...I think I have improved it some but still not found the final solution.

Starting with Alf's comments:

>> Are these locks necessary? Can a SessionMediator service two requests (in this case, two create_surface
>> requests) concurrently

As it stands the SessionMediator can not service two requests concurrently (the SocketSession only reads a new request after processing the last one). These locks are necessary however, as handle_event may be called from any thread (i.e. the shell configuring a surface from any thread), to prevent a data race on the event buffer.

I would propose we make explicit that the SessionMediator can not service two requests with locking.

>> SNIP

Indentation and nullptr and such fixed.

>> Doesn't waiting for ready_for_second_client semaphore take care of that (it triggers only after
>> the first client has received a surface created event, which means it has already connected)?

Yes sorry I moved the wait without moving the comment making this misleading. This is in fact the point of ready_for_second_client.

>> However, the test is still fragile. If the second client hasn't managed to connect and create a surface in
>> the 5 seconds the first test has to finish, e.g., because of super high system load, then
>> all_events_received.wait_for_at_most_seconds(5) in the first client will expire and the test will fail.

The test will always be fragile or have the possibility to lock indefinitely. I think 5 seconds is perhaps to short though (things have taken longer than this in valgrind on jenkins in the past) so I've bumped the timeouts to 60 seconds. We could consider a standard set of timeout values.

Alan:

>>
>> There is no synchronization around "216 + if (clogged)" - which means it could be in different states in >> different threads.
>>

This is just in error of course. Fixed.

>>
>> What is the motivation for CloggableEventSink? Is this the right place for synchronization?
>>

The motivation is that sending a surface configuration event (i.e. one generated before shell::SessionManager::create_surface returns) before replying to the create_surface request leaves client session in a situation which it can't know how to rectify. I think the SessionMediator acts to arbitrate communication between the Session and the IPC layer, and so this is in fact the right place for synchronization.

>>
>> There is nothing to prevent multiple calls to clog() - perhaps clogged should be an atomic counter?
>> I assume that clog() and unclog() are intended to be paired operations - but the calls I see don't deal
>> with exceptions being thrown (please use RAII for paired operations).
>>

I'll update the API to be safer at the beginning of next week after some feedback from the team on the high level approach.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

Events should be removed from buffered_events once handled. (Consider also: what should happen if handle_event() throws.)

review: Needs Fixing
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

Fixed the failure to clear buffered_events (whoops!)

There is something strange going on with the acceptance tests under valgrind (intermittent failure to complete, client never receives the event). I'll stew on it (and the whole branch) overnight and revisit tomorrow.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

The valgrind-induced race-triggered test-failure was due to the test client code, see the comment and change at l555 (vs the previous location of mir_surface_set_event_handler).

I think EventDelegate should be moved to the surface_create arguments. As it stands now mir_surface_create_sync should be considered dangerous.

Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

In the process of debugging message_processor_report grew a sent_event method, as did the logging implementation (not sure how to print MirEvent from lttng...). Note the diff to add a single print line amounts to 141 lines...a bit unsatisfying imo.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Nice to see the attribute logic being reused, but I don't think focus is an attribute of a Surface in the traditional sense. But it's kind of OK too because you're only doing notifications here.

I would like to say focus should never be an attribute because that increases the risk and confusion of potentially having multiple focused surfaces. And internally at least the attribute system is one for getting/setting simple values. But being able to set focus per surface would be dangerous.

This risk is mitigated by the absence of a mir_surface_set_focus. It's only a bit wrong internally then [1]. And I agree you need focus to be an attribute to get notifications for it. So I'm glad you're using the attribute notifications as I intended.

I'm not sure though.

If anything I'll just say that "focused" should be the attribute (boolean 0 or 1) instead of focus. And even if you disagree with renaming then please reorder the enum MirSurfaceFocusState so it's usable as a boolean.

[1] The "bit wrong internally" comment is really about this:
437 + case mir_surface_attrib_focus:
438 + notify_change(attrib, value);
439 + break;
You've implemented a stub setter for focus in msh::Surface::configure which doesn't set anything. In fact instead of notify_change and returning the default value 0 (which is wrong BTW) it should be throwing an exception on any attempt to set ("configure") focus. There must be a nicer way to do it, without modifying msh::Surface::configure (hence letting it throw on any attempt to configure focus).

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

198 + virtual ~IPCSemaphore();

Prefer a non-virtual, noexcept destructor

~~~~

549 + client->handler->handle_event(ev);

If "ev" were given the more meaningful name the sheer repetitiveness would be even more apparent:

    client->handler->handle_event(event);

You can see it here too:

948 + event_sink->handle_event(any_event);

s/handle_event/handle/ would be an improvement.

~~~~

98 + std::weak_ptr<Surface> focus_surface;

What is the purpose of this? The name isn't clear, and the usage is entirely at member function scope (so why use a member variable).

review: Needs Fixing
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

Thanks both!

Alan: Comments addressed. Name improved to be clear at l98

Daniel: I've flipped the enum values...good point. As for the use of configure...I'm not sure of a better way to do this until a bigger focus refactoring happens. This is "next on my list"

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Again with:
437 + case mir_surface_attrib_focus:
438 + notify_change(attrib, value);
439 + break;

It would be easy to write reasonable test cases that now fail. Similar to:
tests/unit-tests/shell/test_surface.cpp: TEST_F(ShellSurface, states)

Because calling:
    surf.configure(mir_surface_attrib_focus, X) != X
and fails to throw an exception too.

review: Needs Fixing
Revision history for this message
Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal

> As for the use of configure...I'm not sure of a better way to do this until a bigger focus refactoring happens. This is "next on my list".

If you have in mind a better way to achieve this, perhaps we should treat this MP as a spike, drop it, and move on to a refactoring that will allow implementing a better solution?

review: Abstain
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

I assume that clog() and unclog() are intended to be paired operations - but the calls I see don't deal with exceptions being thrown (please use RAII for paired operations).

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

I really don't like RAII because it's too implicit and hidden from the reader. That said, you kind of need it for exception safety. But I would recommend against ever using exceptions too :)

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> I really don't like RAII because it's too implicit and hidden from the reader.
> That said, you kind of need it for exception safety. But I would recommend
> against ever using exceptions too :)

You'd recommend against using C++ then?

RAAI and exceptions have been idiomatic C++ for two decades now.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Well, for many people not using C++ or RAII has been idomatic for almost four decades ;)
</troll>

Revision history for this message
Olli Ries (ories) wrote : Posted in a previous version of this proposal

you guys... ;)

On Mon, Jun 10, 2013 at 2:28 AM, Daniel van Vugt <
<email address hidden>> wrote:

> Well, for many people not using C++ or RAII has been idomatic for almost
> four decades ;)
> </troll>
> --
>
> https://code.launchpad.net/~robertcarr/mir/client-focus-notifications/+merge/166440
> Your team Mir development team is subscribed to branch lp:mir.
>

Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

This is non-critical so I am putting it on hold for a few days so I can focus on the Unity stack.

Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

It returns! With RAII on the event sink. I encountered some intermittent failures (both related, and somewhat unrelated but exposed):

MirConnection::released -> We don't want to remove the surface from valid surfaces until here because we may still be receiving configuration events until the surface is actually released on the server side.

input_testing_server_options: It's not enough to say we are ready for input when the input_registrar returns, because the shell may have not yet granted keyboard focus (fixes 1196744)

MirSurface::release_surface: There was a deadlock going on here:

22:42 < racarr> Client calls mir_surface_release it gets to MirSurface::release_surface which acquires the recursive lock on the MirSurface
22:42 < racarr> then calls MirConnection::release_surface
22:42 < racarr> which trys to acquire the connection lock, but blocks because an RPC thread is
22:42 < racarr> has called MirConnection::handle_event
22:42 < racarr> holding the lock
22:43 < racarr> but the RPC thread while executing MirConnection::handle_event tries to call
22:43 < racarr> MirSurface::handle_event
22:43 < racarr> but the Surface is already locked from the
22:43 < racarr> original client thread

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

352 + class Impediment
353 + {
354 + public:
355 + ~Impediment()
356 + {
357 + remove_callback();
358 + }
359 + protected:
360 + friend class CloggableEventSink;
361 + Impediment(std::function<void()> const& remove) :
362 + remove_callback(remove)
363 + {
364 + }
365 + private:
366 + std::function<void()> const remove_callback;
367 + };
368 +
369 + std::unique_ptr<Impediment> clog()
370 + {
371 + std::unique_lock<std::mutex> lg(lock);
372 + clogged = true;
373 +
374 + return std::unique_ptr<Impediment>(new Impediment(
375 + std::bind(std::mem_fn(&CloggableEventSink::unclog), this)));
376 + }

This approach seems complicated to me. C.f.

template<class Cloggee>
class Clogger
{
public:
    Clogger(Cloggee& cloggee) : cloggee{cloggee} { cloggee.clog(); }
    ~Clogger() { cloggee.unclog(); }
private:
    Cloggee& cloggee;
    Clogger(Clogger const&) = delete;
    Clogger& operator=(Clogger const&) = delete;
};

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

438 === modified file 'src/server/frontend/socket_session.cpp'
445 + // TODO: It might make sense to use a pool for these.
446 + std::vector<char> whole_message;
...
451 === modified file 'src/server/frontend/socket_session.h'
458 - std::vector<char> whole_message;

This shouldn't be needed.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

1321 msh::SingleVisibilityFocusMechanism focus_mechanism(mt::fake_shared(model),
1322 - std::make_shared<mtd::StubInputTargeter>());
1323 + std::make_shared<mtd::StubInputTargeter>());

Changes layout from one of our common styles to one we don't use.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

I'm tempted to suggest -Wno-mismatched-tags to quiet clang's curious insistence that struct X is not a synonym for class X.

I've commented on a couple of oddities above - my biggest concern being that if we really need to move "whole_message" that there is an existing race condition (and that should be fixed instead of hacking around it).

Overall, the MP looks reasonable, but is a bit big for me to feel confident I understand it all.

review: Needs Information
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

Fixed clang compile.

I don't think the whole_message bit is required, that was introduced by me in an early iteration to attempt to fix a race that ended up being in the SessionMediator as I recall. It's been removed.

Fixed whitespace around 1321.

I'm not sure I like the Clogger class, the way it is now makes it clear how to call clog.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

I still think that clog()/unclog() are dubious.

What should happen if clog() is called in two threads and then unclog() is called in the first?

Why are you creating a unique_ptr at all? Surely, as you don't want to follow the model used in std (e.g. unique_lock), all that you need to return is a move-only type that calls unclog() in the destructor?

~~~~

234 +protected

line noise

review: Needs Fixing
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

Improved the clogging API and added exceptions for some exceptional conditions.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

352 + ~CloggableEventSink()
353 + {
354 + std::unique_lock<std::mutex> lg(lock);
355 +
356 + if (clogged == true)
357 + BOOST_THROW_EXCEPTION(std::logic_error("EventSink destroyed while clogged leading to lost events"));
358 + }

See "C++ Coding Standards" Guideline 51 (this isn't the guideline I consider wrong).

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

606 +};
607 +struct MockEventObserver
608 +{
609 + MOCK_METHOD1(see, void(MirEvent const*));
610 +};
611 +struct EventObservingClient : ClientConfigCommon

A bit of whitespace between classes aids readability

Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

Added some whitespace.

Removed the dtor. I thought it might be ok to throw in this case as it likely indicates a programmer error which should never happen.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

On 15/07/13 17:34, Robert Carr wrote:
> Removed the dtor. I thought it might be ok to throw in this case as it likely indicates a programmer error which should never happen.

Better to abort?

--
Alan Griffiths +44 (0)798 9938 758
Octopull Ltd http://www.octopull.co.uk/

Revision history for this message
Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal

219 +#include <initializer_list>
220 +#include <string>

Are these needed?

> 234 +protected
>
> line noise

+1. Just a nit, but there is no reason to add a protected block just for the deleted CopyAssign operations; we can put them under private.

> See "C++ Coding Standards" Guideline 51 (this isn't the guideline I consider wrong).

This also applies to

401 + ~Clog()
402 + {
403 + sink.unclog();
404 + }

since sink.unclog() can throw.

Revision history for this message
Alexandros Frantzis (afrantzis) : Posted in a previous version of this proposal
review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> On 15/07/13 17:34, Robert Carr wrote:
> > Removed the dtor. I thought it might be ok to throw in this case as it
> likely indicates a programmer error which should never happen.

It is low cost to detect and leads to undefined behavior: just put an assert here.

review: Needs Fixing
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

assert(asserts_present_in_revision_755)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

...Merged trunk!

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

Last jenkins failure was just intermittent jenkins infrastructure issue. I would like this to land one day because it conflicts a lot.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Looks like my review is way out of date now. So no comment.

review: Abstain
Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

I think lp:~kdub/mir/prepare-for-display-notifications will help with this... EventSink now is a bit more decoupled and the interface can be developed against without messing with ProtobufSocketCommunicator at all.

Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

Is there a specific portion of the change that people don't want to land?

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

My previous objection is addressed, and I don't have the headspace right now.

recursive mutexes are usually a sign of design issues, but this MP doesn't introduced a new problem.

review: Abstain
Revision history for this message
Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal

Looks good overall. One question:

486 + if (current_focus)
487 + current_focus->configure(mir_surface_attrib_focus, mir_surface_unfocused);
488 + surface->configure(mir_surface_attrib_focus, mir_surface_focused);.

Is there a way for the currently focused surface to get the focus again, and receive a confusing [unfocused,focused] sequence of events? We don't seem to guard against this, at least not at this level.

review: Approve
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

NB this needs to be re-sync'ed with trunk before top-approving.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

Merged trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> > just curious...is this some convention ?
> > mir_surface_focus_arraysize_
> > didn't understand why it was in the surf attrib for focusstate
>
> Yes, it is a sentinel element for the array, and its value is equal to the
> array size.

Just curious - was there an array when this was written? (There isn't now, and it seems unlikely there ever was.)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

The merge conflicts were not entirely trivial so maybe someone wants to give it a once over?

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

1. Conflicts...
Text conflict in include/server/mir/shell/default_focus_mechanism.h
Text conflict in src/server/shell/default_focus_mechanism.cpp
Text conflict in tests/unit-tests/shell/test_default_focus_mechanism.cpp
3 conflicts encountered.

2. I think the past tense "sent_event" doesn't feel right, and is a confusing function name despite being similar to those above it. Maybe "on_event_sent".

3. As already mentioned, I still don't think MirSurfaceFocusState should exist at all. Making "focus" an attribute of a surface leads to dangerous and impossible situations:
  (a) Many surfaces focused simultaneously; and
  (b) surf.configure(mir_surface_attrib_focus, X) != X

4. IPCSemaphore: Everyone knows semaphores as having "wait" and "signal" operations. I'd prefer those to the verbose method names you have. But it's not important.

5. Focus/blur should be an event on the connection, not the surface. This would resolve the ambiguities mentioned in 3.

Sorry to keep touching on the same things (3, 5), but I did first raise these concerns 2 months ago. At the time you seem to have agreed saying:
  "I'm not sure of a better way to do this until a bigger focus refactoring happens. This is "next on my list"
I think we should avoid a temporary solution that adds attributes which ultimately we agree should not exist.

review: Needs Fixing
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

I don't understand what you mean by point 5. We need to deliver focus based on surface, i.e. you have multiple terminal windows open from the same session and they need to know whether or not to blink the cursor.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

(5) is really an extension of (3). Given that (3) I don't think focus should be a per-surface attribute then one would conclude (5) that the "currently focused surface" should be stored in a single location, single variable. This makes it an attribute of some other class, like maybe the session.

Revision history for this message
Chris Halse Rogers (raof) wrote : Posted in a previous version of this proposal

High level - I concur with Daniel: having focus being a surface attribute seems dangerous. Current focus is... session local? Hm.

Focus is a per-keyboardish attribute, so it's not strictly speaking unique in a compositor session, but it's pretty close to.

===

Why are we calling the guard value of the enums *_arraysize_? That seems somewhat misleading.

===

Perhaps Clog should take a shared_ptr<CloggableEventSink> rather than a reference? It needs to keep the event sink live while the Clog is live. This is not a problem in the current code, though.

<bikeshed>I'd find "Plug" a more natural name for the Clog class; you stick a plug in your sink to clog it ☺ </bikeshed>

====

I was going to say that lttng::MPR::sent_event should be event_sent to match exception_handled above, but it turns out that above *that* is received_invocation/completed_invocation.

I think event_sent (and invocation_{received,completed}) makes more sense, but there's no consistency there at the moment.

===

812 + ~ProxyShell() noexcept(true) = default;

I *think* the default destructor is noexcept, so the noexcept(true) there is redundant?

===

949 + static int const semaphore_enable_process_shared = 1;

Why is this static? You don't need to track the value of this across entries to IPCSemaphore(), and I presume the compiler will entirely optimise it out.

===

1171 + ~MockEventSink() … {} could be ~MockEventSink() = default; ?

review: Needs Fixing
Revision history for this message
Chris Halse Rogers (raof) wrote : Posted in a previous version of this proposal

On second thoughts, maybe it's ok?

We're not storing the focus state in a surface attribute, we're storing it in the FocusStrategy and projecting that to the client as a surface state.

It's possible that there's a nicer way of projecting that data, but maybe this isn't too bad.

review: Abstain
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:766
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~robertcarr/mir/client-focus-notifications/+merge/179801/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mir-ci/1286/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-android-saucy-i386-build/1716
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-clang-saucy-amd64-build/1601
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-saucy-amd64-ci/524/console

Click here to trigger a rebuild:
http://s-jenkins:8080/job/mir-ci/1286/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:767
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~robertcarr/mir/client-focus-notifications/+merge/179801/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mir-ci/1289/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-android-saucy-i386-build/1719
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-clang-saucy-amd64-build/1604
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-saucy-amd64-ci/527/console

Click here to trigger a rebuild:
http://s-jenkins:8080/job/mir-ci/1289/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:768
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~robertcarr/mir/client-focus-notifications/+merge/179801/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mir-ci/1290/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-android-saucy-i386-build/1720/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-clang-saucy-amd64-build/1605/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-saucy-amd64-ci/528/console

Click here to trigger a rebuild:
http://s-jenkins:8080/job/mir-ci/1290/rebuild

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

BTW, "enum_max_" is not accurate. It goes one past the max value, used to size fixed arrays. Hence "arraysize_".

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'examples/demo-inprocess-surface-client/inprocess_egl_client.cpp'
2--- examples/demo-inprocess-surface-client/inprocess_egl_client.cpp 2013-08-13 22:17:09 +0000
3+++ examples/demo-inprocess-surface-client/inprocess_egl_client.cpp 2013-08-09 08:50:40 +0000
4@@ -65,10 +65,9 @@
5 me::InprocessEGLClient::~InprocessEGLClient()
6 {
7 terminate = true;
8- //TODO: this is messy, need a better interface for internal clients to interact with shell
9- if ( auto ses = std::dynamic_pointer_cast<msh::Session>(session))
10- ses->force_requests_to_complete();
11-
12+ auto session = session_manager->focussed_application().lock();
13+ if (session)
14+ session->force_requests_to_complete();
15 client_thread.join();
16 }
17
18@@ -81,7 +80,7 @@
19 .of_size(surface_size)
20 .of_buffer_usage(mg::BufferUsage::hardware)
21 .of_pixel_format(geom::PixelFormat::argb_8888);
22- session = session_manager->open_session("Inprocess client",
23+ auto session = session_manager->open_session("Inprocess client",
24 std::shared_ptr<mf::EventSink>());
25 // TODO: Why do we get an ID? ~racarr
26 auto surface = session->get_surface(session_manager->create_surface_for(session, params));
27
28=== modified file 'examples/demo-inprocess-surface-client/inprocess_egl_client.h'
29--- examples/demo-inprocess-surface-client/inprocess_egl_client.h 2013-08-13 22:17:09 +0000
30+++ examples/demo-inprocess-surface-client/inprocess_egl_client.h 2013-08-08 02:34:31 +0000
31@@ -39,10 +39,6 @@
32 {
33 class Platform;
34 }
35-namespace frontend
36-{
37-class Session;
38-}
39 namespace shell
40 {
41 class SessionManager;
42@@ -67,7 +63,6 @@
43 private:
44 std::shared_ptr<graphics::Platform> const graphics_platform;
45 std::shared_ptr<shell::SessionManager> const session_manager;
46- std::shared_ptr<frontend::Session> session;
47
48 std::thread client_thread;
49
50
51=== modified file 'examples/demo-shell/demo_shell.cpp'
52--- examples/demo-shell/demo_shell.cpp 2013-08-13 22:17:09 +0000
53+++ examples/demo-shell/demo_shell.cpp 2013-08-07 07:18:03 +0000
54@@ -96,7 +96,7 @@
55 {
56 // We use this strange two stage initialization to avoid a circular dependency between the EventFilters
57 // and the SessionStore
58- wm->set_focus_controller(config.the_shell_focus_setter());
59+ wm->set_focus_controller(config.the_focus_controller());
60 wm->set_session_manager(config.the_session_manager());
61 });
62 return 0;
63
64=== modified file 'examples/demo-shell/window_manager.cpp'
65--- examples/demo-shell/window_manager.cpp 2013-08-13 22:17:09 +0000
66+++ examples/demo-shell/window_manager.cpp 2013-07-10 17:06:37 +0000
67@@ -18,7 +18,7 @@
68
69 #include "window_manager.h"
70
71-#include "mir/shell/focus_setter.h"
72+#include "mir/shell/focus_controller.h"
73 #include "mir/shell/session_manager.h"
74 #include "mir/shell/session.h"
75 #include "mir/shell/surface.h"
76@@ -41,7 +41,7 @@
77 {
78 }
79
80-void me::WindowManager::set_focus_controller(std::shared_ptr<msh::FocusSetter> const& controller)
81+void me::WindowManager::set_focus_controller(std::shared_ptr<msh::FocusController> const& controller)
82 {
83 focus_controller = controller;
84 }
85@@ -92,7 +92,7 @@
86 MirMotionAction action = static_cast<MirMotionAction>(event.motion.action & ~0xff00);
87
88 std::shared_ptr<msh::Session> app =
89- focus_controller->focused_session().lock();
90+ session_manager->focussed_application().lock();
91
92 int fingers = static_cast<int>(event.motion.pointer_count);
93
94
95=== modified file 'examples/demo-shell/window_manager.h'
96--- examples/demo-shell/window_manager.h 2013-08-13 22:17:09 +0000
97+++ examples/demo-shell/window_manager.h 2013-06-10 11:26:51 +0000
98@@ -28,7 +28,7 @@
99 {
100 namespace shell
101 {
102-class FocusSetter;
103+class FocusController;
104 class SessionManager;
105 }
106 namespace examples
107@@ -40,7 +40,7 @@
108 WindowManager();
109 ~WindowManager() = default;
110
111- void set_focus_controller(std::shared_ptr<shell::FocusSetter> const& focus_controller);
112+ void set_focus_controller(std::shared_ptr<shell::FocusController> const& focus_controller);
113 void set_session_manager(std::shared_ptr<shell::SessionManager> const& sm);
114
115 bool handle(MirEvent const& event) override;
116@@ -50,7 +50,7 @@
117 WindowManager& operator=(const WindowManager&) = delete;
118
119 private:
120- std::shared_ptr<shell::FocusSetter> focus_controller;
121+ std::shared_ptr<shell::FocusController> focus_controller;
122 std::shared_ptr<shell::SessionManager> session_manager;
123 geometry::Displacement relative_click; // Click location in window space
124 geometry::Point click; // Click location in screen space
125
126=== modified file 'include/platform/mir/graphics/display_configuration.h'
127--- include/platform/mir/graphics/display_configuration.h 2013-08-12 08:58:59 +0000
128+++ include/platform/mir/graphics/display_configuration.h 2013-08-13 22:17:10 +0000
129@@ -42,29 +42,6 @@
130 struct DisplayConfigurationCard
131 {
132 DisplayConfigurationCardId id;
133- size_t max_simultaneous_outputs;
134-};
135-
136-/**
137- * The type of a display output.
138- */
139-enum class DisplayConfigurationOutputType
140-{
141- unknown,
142- vga,
143- dvii,
144- dvid,
145- dvia,
146- composite,
147- svideo,
148- lvds,
149- component,
150- ninepindin,
151- displayport,
152- hdmia,
153- hdmib,
154- tv,
155- edp
156 };
157
158 /**
159@@ -85,14 +62,10 @@
160 DisplayConfigurationOutputId id;
161 /** The id of the card the output is connected to. */
162 DisplayConfigurationCardId card_id;
163- /** The type of the output. */
164- DisplayConfigurationOutputType type;
165 /** The pixel formats supported by the output */
166 std::vector<geometry::PixelFormat> pixel_formats;
167 /** The modes supported by the output. */
168 std::vector<DisplayConfigurationMode> modes;
169- /** The index in the 'modes' vector of the preferred output mode. */
170- size_t preferred_mode_index;
171 /** The physical size of the output. */
172 geometry::Size physical_size_mm;
173 /** Whether the output is connected. */
174@@ -107,10 +80,6 @@
175 size_t current_format_index;
176 };
177
178-std::ostream& operator<<(std::ostream& out, DisplayConfigurationCard const& val);
179-bool operator==(DisplayConfigurationCard const& val1, DisplayConfigurationCard const& val2);
180-bool operator!=(DisplayConfigurationCard const& val1, DisplayConfigurationCard const& val2);
181-
182 std::ostream& operator<<(std::ostream& out, DisplayConfigurationMode const& val);
183 bool operator==(DisplayConfigurationMode const& val1, DisplayConfigurationMode const& val2);
184 bool operator!=(DisplayConfigurationMode const& val1, DisplayConfigurationMode const& val2);
185
186=== modified file 'include/server/mir/default_server_configuration.h'
187--- include/server/mir/default_server_configuration.h 2013-08-13 22:17:09 +0000
188+++ include/server/mir/default_server_configuration.h 2013-08-13 13:54:24 +0000
189@@ -161,6 +161,8 @@
190 virtual std::shared_ptr<frontend::DisplayChanger> the_frontend_display_changer();
191 /** @} */
192
193+ virtual std::shared_ptr<shell::FocusController> the_focus_controller();
194+
195 /** @name shell configuration - customization
196 * configurable interfaces for modifying shell
197 * @{ */
198
199=== modified file 'include/server/mir/frontend/display_changer.h'
200--- include/server/mir/frontend/display_changer.h 2013-08-13 22:17:09 +0000
201+++ include/server/mir/frontend/display_changer.h 2013-08-12 17:20:29 +0000
202@@ -37,14 +37,7 @@
203 virtual ~DisplayChanger() = default;
204
205 virtual std::shared_ptr<graphics::DisplayConfiguration> active_configuration() = 0;
206-<<<<<<< TREE
207 virtual void configure(std::weak_ptr<Session> const&, std::shared_ptr<graphics::DisplayConfiguration> const&) = 0;
208-=======
209- virtual void store_configuration_for(
210- std::weak_ptr<frontend::Session> const&, std::shared_ptr<graphics::DisplayConfiguration> const&) = 0;
211- virtual void apply_configuration_of(std::weak_ptr<frontend::Session> const&) = 0;
212- virtual void remove_configuration_for(std::weak_ptr<frontend::Session> const&) = 0;
213->>>>>>> MERGE-SOURCE
214
215 protected:
216 DisplayChanger() = default;
217
218=== modified file 'include/server/mir/frontend/message_processor_report.h'
219--- include/server/mir/frontend/message_processor_report.h 2013-04-24 05:22:20 +0000
220+++ include/server/mir/frontend/message_processor_report.h 2013-08-13 22:17:10 +0000
221@@ -20,6 +20,8 @@
222 #ifndef MIR_FRONTEND_MESSAGE_PROCESSOR_REPORT_H_
223 #define MIR_FRONTEND_MESSAGE_PROCESSOR_REPORT_H_
224
225+#include "mir_toolkit/event.h"
226+
227 #include <string>
228
229 namespace mir
230@@ -42,6 +44,8 @@
231 virtual void exception_handled(void const* mediator, int id, std::exception const& error) = 0;
232
233 virtual void exception_handled(void const* mediator, std::exception const& error) = 0;
234+
235+ virtual void sent_event(void const* mediator, MirSurfaceEvent const& ev) = 0;
236
237 private:
238 MessageProcessorReport(MessageProcessorReport const&) = delete;
239
240=== modified file 'include/server/mir/frontend/null_message_processor_report.h'
241--- include/server/mir/frontend/null_message_processor_report.h 2013-04-24 05:22:20 +0000
242+++ include/server/mir/frontend/null_message_processor_report.h 2013-08-13 22:17:10 +0000
243@@ -36,6 +36,8 @@
244 void exception_handled(void const*, int, std::exception const&);
245
246 void exception_handled(void const*, std::exception const&);
247+
248+ void sent_event(void const*, MirSurfaceEvent const& e);
249 };
250 }
251 }
252
253=== modified file 'include/server/mir/frontend/session.h'
254--- include/server/mir/frontend/session.h 2013-08-13 22:17:09 +0000
255+++ include/server/mir/frontend/session.h 2013-08-08 19:40:41 +0000
256@@ -21,7 +21,6 @@
257
258 #include "mir_toolkit/common.h"
259 #include "mir/frontend/surface_id.h"
260-#include "mir/shell/surface_creation_parameters.h"
261
262 #include <mutex>
263 #include <atomic>
264
265=== modified file 'include/server/mir/frontend/shell.h'
266--- include/server/mir/frontend/shell.h 2013-08-13 22:17:09 +0000
267+++ include/server/mir/frontend/shell.h 2013-08-13 22:17:10 +0000
268@@ -42,13 +42,11 @@
269 std::string const& name, std::shared_ptr<EventSink> const& sink) = 0;
270 virtual void close_session(std::shared_ptr<Session> const& session) = 0;
271
272- virtual void handle_display_configuration(std::shared_ptr<Session> const& session) = 0;
273+ virtual SurfaceId create_surface_for(std::shared_ptr<Session> const& session,
274+ shell::SurfaceCreationParameters const& params) = 0;
275+
276 virtual void handle_surface_created(std::shared_ptr<Session> const& session) = 0;
277
278- //TODO: remove, object needed to handle calling appropriate shell notifications for internal clients
279- virtual SurfaceId create_surface_for(std::shared_ptr<Session> const& session,
280- shell::SurfaceCreationParameters const& params) = 0;
281-
282 protected:
283 Shell() = default;
284 Shell(const Shell&) = delete;
285
286=== modified file 'include/server/mir/logging/message_processor_report.h'
287--- include/server/mir/logging/message_processor_report.h 2013-04-24 05:22:20 +0000
288+++ include/server/mir/logging/message_processor_report.h 2013-08-13 22:17:10 +0000
289@@ -68,6 +68,8 @@
290
291 void exception_handled(void const* mediator, std::exception const& error);
292
293+ void sent_event(void const* mediator, MirSurfaceEvent const& event);
294+
295 ~MessageProcessorReport() noexcept(true);
296
297 private:
298
299=== modified file 'include/server/mir/lttng/message_processor_report.h'
300--- include/server/mir/lttng/message_processor_report.h 2013-06-03 12:15:44 +0000
301+++ include/server/mir/lttng/message_processor_report.h 2013-08-13 22:17:10 +0000
302@@ -35,6 +35,7 @@
303 void unknown_method(void const* mediator, int id, std::string const& method);
304 void exception_handled(void const* mediator, int id, std::exception const& error);
305 void exception_handled(void const* mediator, std::exception const& error);
306+ void sent_event(void const* mediator, MirSurfaceEvent const& event);
307
308 private:
309 ServerTracepointProvider tp_provider;
310
311=== modified file 'include/server/mir/shell/default_focus_mechanism.h'
312--- include/server/mir/shell/default_focus_mechanism.h 2013-08-13 22:17:09 +0000
313+++ include/server/mir/shell/default_focus_mechanism.h 2013-08-13 22:17:10 +0000
314@@ -27,44 +27,29 @@
315
316 namespace shell
317 {
318+class Surface;
319 class InputTargeter;
320 class SurfaceController;
321-class SessionListener;
322-class FocusSequence;
323
324 class DefaultFocusMechanism : public FocusSetter
325 {
326 public:
327- explicit DefaultFocusMechanism(std::shared_ptr<FocusSequence> const& sequence,
328- std::shared_ptr<InputTargeter> const& input_targeter,
329- std::shared_ptr<SurfaceController> const& surface_controller,
330- std::shared_ptr<SessionListener> const& session_listener);
331+ explicit DefaultFocusMechanism(std::shared_ptr<InputTargeter> const& input_targeter,
332+ std::shared_ptr<SurfaceController> const& surface_controller);
333 virtual ~DefaultFocusMechanism() = default;
334
335- void surface_created_for(std::shared_ptr<Session> const& session);
336- void session_opened(std::shared_ptr<Session> const& session);
337- void session_closed(std::shared_ptr<Session> const& session);
338- std::weak_ptr<Session> focused_session() const;
339-
340- //TODO: this is only used in example code
341- void focus_next();
342+ void set_focus_to(std::shared_ptr<shell::Session> const& new_focus);
343
344 protected:
345- void focus_next_locked();
346-
347 DefaultFocusMechanism(const DefaultFocusMechanism&) = delete;
348 DefaultFocusMechanism& operator=(const DefaultFocusMechanism&) = delete;
349
350 private:
351- void set_focus(std::shared_ptr<Session> const& session);
352-
353- std::shared_ptr<FocusSequence> const sequence;
354- std::shared_ptr<SessionListener> const session_listener;
355 std::shared_ptr<InputTargeter> const input_targeter;
356 std::shared_ptr<SurfaceController> const surface_controller;
357
358- std::mutex mutable mutex;
359- std::shared_ptr<Session> focus_session;
360+ // TODO: Protect with mutex
361+ std::weak_ptr<Surface> currently_focused_surface;
362 };
363
364 }
365
366=== added file 'include/server/mir/shell/focus_controller.h'
367--- include/server/mir/shell/focus_controller.h 1970-01-01 00:00:00 +0000
368+++ include/server/mir/shell/focus_controller.h 2013-04-17 21:33:51 +0000
369@@ -0,0 +1,44 @@
370+/*
371+ * Copyright © 2013 Canonical Ltd.
372+ *
373+ * This program is free software: you can redistribute it and/or modify it
374+ * under the terms of the GNU General Public License version 3,
375+ * as published by the Free Software Foundation.
376+ *
377+ * This program is distributed in the hope that it will be useful,
378+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
379+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
380+ * GNU General Public License for more details.
381+ *
382+ * You should have received a copy of the GNU General Public License
383+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
384+ *
385+ * Authored by: Robert Carr <robert.carr@canonical.com>
386+ */
387+
388+#ifndef MIR_SHELL_FOCUS_CONTROLLER_H_
389+#define MIR_SHELL_FOCUS_CONTROLLER_H_
390+
391+namespace mir
392+{
393+
394+namespace shell
395+{
396+
397+class FocusController
398+{
399+public:
400+ virtual ~FocusController() {}
401+
402+ virtual void focus_next() = 0;
403+
404+protected:
405+ FocusController() = default;
406+ FocusController(FocusController const&) = delete;
407+ FocusController& operator=(FocusController const&) = delete;
408+};
409+
410+}
411+} // namespace mir
412+
413+#endif // MIR_SHELL_FOCUS_CONTROLLER_H_
414
415=== modified file 'include/server/mir/shell/focus_setter.h'
416--- include/server/mir/shell/focus_setter.h 2013-08-13 22:17:09 +0000
417+++ include/server/mir/shell/focus_setter.h 2013-04-24 05:22:20 +0000
418@@ -28,20 +28,14 @@
419 {
420 class Session;
421
422-/// Interface used by the Shell to customize behavior based around focus
423+/// Interface used by the Shell to propagate changes in the focus model to interested views
424+/// e.g. Input, or Surfaces.
425 class FocusSetter
426 {
427 public:
428 virtual ~FocusSetter() {}
429
430- virtual void surface_created_for(std::shared_ptr<Session> const& session) = 0;
431- virtual void session_opened(std::shared_ptr<Session> const& session) = 0;
432- virtual void session_closed(std::shared_ptr<Session> const& session) = 0;
433-
434- //TODO: this is only used in example code
435- virtual void focus_next() = 0;
436-
437- virtual std::weak_ptr<Session> focused_session() const = 0;
438+ virtual void set_focus_to(std::shared_ptr<shell::Session> const& new_focus) = 0;
439
440 protected:
441 FocusSetter() = default;
442
443=== modified file 'include/server/mir/shell/mediating_display_changer.h'
444--- include/server/mir/shell/mediating_display_changer.h 2013-08-13 22:17:09 +0000
445+++ include/server/mir/shell/mediating_display_changer.h 2013-08-13 13:54:24 +0000
446@@ -19,15 +19,10 @@
447 #ifndef MIR_SHELL_MEDIATING_DISPLAY_CHANGER_H_
448 #define MIR_SHELL_MEDIATING_DISPLAY_CHANGER_H_
449
450-<<<<<<< TREE
451 #include "mir/frontend/display_changer.h"
452 #include "mir/display_changer.h"
453
454 #include <mutex>
455-=======
456-#include "mir/shell/display_changer.h"
457-#include <unordered_map>
458->>>>>>> MERGE-SOURCE
459
460 namespace mir
461 {
462@@ -37,41 +32,24 @@
463 class Display;
464 class DisplayConfigurationPolicy;
465 }
466-<<<<<<< TREE
467 namespace compositor { class Compositor; }
468 namespace input { class InputManager; }
469
470-=======
471-
472-namespace compositor
473-{
474-class Compositor;
475-}
476-
477->>>>>>> MERGE-SOURCE
478 namespace shell
479 {
480-class FocusSetter;
481
482 class MediatingDisplayChanger : public frontend::DisplayChanger,
483 public mir::DisplayChanger
484 {
485 public:
486-<<<<<<< TREE
487 MediatingDisplayChanger(
488 std::shared_ptr<graphics::Display> const& display,
489 std::shared_ptr<compositor::Compositor> const& compositor,
490 std::shared_ptr<input::InputManager> const& input_manager,
491 std::shared_ptr<graphics::DisplayConfigurationPolicy> const& display_configuration_policy);
492-=======
493- explicit MediatingDisplayChanger(
494- std::shared_ptr<graphics::Display> const& display,
495- std::shared_ptr<compositor::Compositor> const& compositor);
496->>>>>>> MERGE-SOURCE
497
498 /* From mir::frontend::DisplayChanger */
499 std::shared_ptr<graphics::DisplayConfiguration> active_configuration();
500-<<<<<<< TREE
501 void configure(std::weak_ptr<frontend::Session> const& session,
502 std::shared_ptr<graphics::DisplayConfiguration> const& conf);
503
504@@ -79,35 +57,16 @@
505 void configure_for_hardware_change(
506 std::shared_ptr<graphics::DisplayConfiguration> const& conf,
507 SystemStateHandling pause_resume_system);
508-=======
509-
510- void store_configuration_for(std::weak_ptr<frontend::Session> const&, std::shared_ptr<graphics::DisplayConfiguration> const&);
511- void apply_configuration_of(std::weak_ptr<frontend::Session> const&);
512- void remove_configuration_for(std::weak_ptr<frontend::Session> const&);
513->>>>>>> MERGE-SOURCE
514
515 private:
516-<<<<<<< TREE
517 void apply_config(std::shared_ptr<graphics::DisplayConfiguration> const& conf,
518 SystemStateHandling pause_resume_system);
519
520-=======
521- void apply_config(std::shared_ptr<graphics::DisplayConfiguration> const&);
522-
523-
524- std::unordered_map<frontend::Session*, std::shared_ptr<graphics::DisplayConfiguration> > config_map;
525->>>>>>> MERGE-SOURCE
526 std::shared_ptr<graphics::Display> const display;
527-<<<<<<< TREE
528 std::shared_ptr<compositor::Compositor> const compositor;
529 std::shared_ptr<input::InputManager> const input_manager;
530 std::shared_ptr<graphics::DisplayConfigurationPolicy> const display_configuration_policy;
531 std::mutex configuration_mutex;
532-=======
533- std::shared_ptr<compositor::Compositor> const compositor;
534- std::shared_ptr<graphics::DisplayConfiguration> const base_config;
535- std::shared_ptr<graphics::DisplayConfiguration> active_config;
536->>>>>>> MERGE-SOURCE
537 };
538
539 }
540
541=== modified file 'include/server/mir/shell/session_manager.h'
542--- include/server/mir/shell/session_manager.h 2013-08-13 22:17:09 +0000
543+++ include/server/mir/shell/session_manager.h 2013-08-13 22:17:10 +0000
544@@ -21,6 +21,7 @@
545
546 #include "mir/frontend/surface_id.h"
547 #include "mir/frontend/shell.h"
548+#include "mir/shell/focus_controller.h"
549
550 #include <mutex>
551 #include <memory>
552@@ -38,34 +39,37 @@
553 {
554 class SurfaceFactory;
555 class SessionContainer;
556+class FocusSequence;
557 class FocusSetter;
558 class Session;
559 class InputRegistrar;
560 class SnapshotStrategy;
561 class SessionListener;
562 struct SurfaceCreationParameters;
563-class DisplayChanger;
564
565-class SessionManager : public frontend::Shell
566+class SessionManager : public frontend::Shell, public shell::FocusController
567 {
568 public:
569 explicit SessionManager(std::shared_ptr<SurfaceFactory> const& surface_factory,
570 std::shared_ptr<SessionContainer> const& app_container,
571+ std::shared_ptr<FocusSequence> const& focus_sequence,
572 std::shared_ptr<FocusSetter> const& focus_setter,
573 std::shared_ptr<SnapshotStrategy> const& snapshot_strategy,
574- std::shared_ptr<SessionListener> const& session_listener,
575- std::shared_ptr<DisplayChanger> const& display_changer);
576+ std::shared_ptr<SessionListener> const& session_listener);
577 virtual ~SessionManager();
578
579 virtual std::shared_ptr<frontend::Session> open_session(
580 std::string const& name, std::shared_ptr<frontend::EventSink> const& sink);
581 virtual void close_session(std::shared_ptr<frontend::Session> const& session);
582
583- virtual void handle_display_configuration(std::shared_ptr<frontend::Session> const& session);
584- virtual void handle_surface_created(std::shared_ptr<frontend::Session> const& session);
585+ frontend::SurfaceId create_surface_for(std::shared_ptr<frontend::Session> const& session,
586+ SurfaceCreationParameters const& params);
587
588- virtual frontend::SurfaceId create_surface_for(std::shared_ptr<frontend::Session> const& session,
589- shell::SurfaceCreationParameters const& params);
590+ void focus_next();
591+ std::weak_ptr<Session> focussed_application() const;
592+ void set_focus_to(std::shared_ptr<Session> const& focus);
593+
594+ void handle_surface_created(std::shared_ptr<frontend::Session> const& session);
595
596 protected:
597 SessionManager(const SessionManager&) = delete;
598@@ -74,10 +78,15 @@
599 private:
600 std::shared_ptr<SurfaceFactory> const surface_factory;
601 std::shared_ptr<SessionContainer> const app_container;
602+ std::shared_ptr<FocusSequence> const focus_sequence;
603 std::shared_ptr<FocusSetter> const focus_setter;
604 std::shared_ptr<SnapshotStrategy> const snapshot_strategy;
605 std::shared_ptr<SessionListener> const session_listener;
606- std::shared_ptr<DisplayChanger> const display_changer;
607+
608+ std::mutex mutex;
609+ std::weak_ptr<Session> focus_application;
610+
611+ void set_focus_to_locked(std::unique_lock<std::mutex> const& lock, std::shared_ptr<Session> const& next_focus);
612 };
613
614 }
615
616=== modified file 'include/server/mir/shell/unauthorized_display_changer.h'
617--- include/server/mir/shell/unauthorized_display_changer.h 2013-08-13 22:17:09 +0000
618+++ include/server/mir/shell/unauthorized_display_changer.h 2013-08-12 17:20:29 +0000
619@@ -32,10 +32,7 @@
620 explicit UnauthorizedDisplayChanger(std::shared_ptr<frontend::DisplayChanger> const& changer);
621
622 std::shared_ptr<graphics::DisplayConfiguration> active_configuration();
623- void store_configuration_for(
624- std::weak_ptr<frontend::Session> const&, std::shared_ptr<graphics::DisplayConfiguration> const&);
625- void apply_configuration_of(std::weak_ptr<frontend::Session> const&);
626- void remove_configuration_for(std::weak_ptr<frontend::Session> const&);
627+ void configure(std::weak_ptr<frontend::Session> const&, std::shared_ptr<graphics::DisplayConfiguration> const&);
628
629 private:
630 std::shared_ptr<frontend::DisplayChanger> const changer;
631
632=== modified file 'include/shared/mir_toolkit/client_types.h'
633--- include/shared/mir_toolkit/client_types.h 2013-08-12 08:58:59 +0000
634+++ include/shared/mir_toolkit/client_types.h 2013-08-13 22:17:10 +0000
635@@ -176,34 +176,9 @@
636 } MirDisplayInfo;
637
638 /**
639- * MirDisplayConfiguration provides details of the graphics environment.
640+ * MirDisplayOutput provides details of the graphics environment.
641 */
642
643-typedef struct MirDisplayCard
644-{
645- uint32_t card_id;
646- uint32_t max_simultaneous_outputs;
647-} MirDisplayCard;
648-
649-typedef enum MirDisplayOutputType
650-{
651- mir_display_output_type_unknown,
652- mir_display_output_type_vga,
653- mir_display_output_type_dvii,
654- mir_display_output_type_dvid,
655- mir_display_output_type_dvia,
656- mir_display_output_type_composite,
657- mir_display_output_type_svideo,
658- mir_display_output_type_lvds,
659- mir_display_output_type_component,
660- mir_display_output_type_ninepindin,
661- mir_display_output_type_displayport,
662- mir_display_output_type_hdmia,
663- mir_display_output_type_hdmib,
664- mir_display_output_type_tv,
665- mir_display_output_type_edp
666-} MirDisplayOutputType;
667-
668 typedef struct MirDisplayMode
669 {
670 uint32_t vertical_resolution;
671@@ -215,7 +190,6 @@
672 {
673 uint32_t num_modes;
674 MirDisplayMode* modes;
675- uint32_t preferred_mode;
676 uint32_t current_mode;
677
678 uint32_t num_output_formats;
679@@ -224,7 +198,6 @@
680
681 uint32_t card_id;
682 uint32_t output_id;
683- MirDisplayOutputType type;
684
685 int32_t position_x;
686 int32_t position_y;
687@@ -239,8 +212,6 @@
688 {
689 uint32_t num_displays;
690 MirDisplayOutput* displays;
691- uint32_t num_cards;
692- MirDisplayCard *cards;
693 } MirDisplayConfiguration;
694
695 /**
696
697=== modified file 'include/shared/mir_toolkit/common.h'
698--- include/shared/mir_toolkit/common.h 2013-07-09 10:51:59 +0000
699+++ include/shared/mir_toolkit/common.h 2013-08-13 22:17:10 +0000
700@@ -36,7 +36,8 @@
701 mir_surface_attrib_type,
702 mir_surface_attrib_state,
703 mir_surface_attrib_swapinterval,
704- mir_surface_attrib_arraysize_
705+ mir_surface_attrib_focus,
706+ mir_surface_attrib_enum_max_
707 } MirSurfaceAttrib;
708
709 typedef enum MirSurfaceType
710@@ -47,8 +48,12 @@
711 mir_surface_type_overlay,
712 mir_surface_type_freestyle,
713 mir_surface_type_popover,
714+<<<<<<< TREE
715 mir_surface_type_inputmethod,
716 mir_surface_type_arraysize_
717+=======
718+ mir_surface_type_enum_max_
719+>>>>>>> MERGE-SOURCE
720 } MirSurfaceType;
721
722 typedef enum MirSurfaceState
723@@ -62,8 +67,16 @@
724 Omitted for now, since it's functionally a subset of vertmaximized and
725 differs only in the X coordinate. */
726 mir_surface_state_fullscreen,
727- mir_surface_state_arraysize_
728+ mir_surface_state_enum_max_
729 } MirSurfaceState;
730+
731+typedef enum MirSurfaceFocusState
732+{
733+ mir_surface_unfocused = 0,
734+ mir_surface_focused,
735+ mir_surface_focus_enum_max_
736+} MirSurfaceFocusState;
737+
738 /**@}*/
739
740 #endif
741
742=== modified file 'include/test/mir_test/event_matchers.h'
743--- include/test/mir_test/event_matchers.h 2013-04-26 16:31:48 +0000
744+++ include/test/mir_test/event_matchers.h 2013-08-13 22:17:10 +0000
745@@ -19,6 +19,8 @@
746 #ifndef MIR_TEST_EVENT_MATCHERS_H_
747 #define MIR_TEST_EVENT_MATCHERS_H_
748
749+#include "mir_toolkit/event.h"
750+
751 #include <androidfw/Input.h>
752
753 #include <gmock/gmock.h>
754@@ -64,6 +66,18 @@
755 return (coords->x == dx) && (coords->y == dy);
756 }
757
758+MATCHER_P2(SurfaceEvent, attrib, value, "")
759+{
760+ if (arg.type != mir_event_type_surface)
761+ return false;
762+ auto surface_ev = arg.surface;
763+ if (surface_ev.attrib != attrib)
764+ return false;
765+ if (surface_ev.value != value)
766+ return false;
767+ return true;
768+}
769+
770 }
771 } // namespace mir
772
773
774=== modified file 'include/test/mir_test_doubles/mock_display_changer.h'
775--- include/test/mir_test_doubles/mock_display_changer.h 2013-08-13 22:17:09 +0000
776+++ include/test/mir_test_doubles/mock_display_changer.h 2013-08-12 17:20:29 +0000
777@@ -33,10 +33,8 @@
778 {
779 public:
780 MOCK_METHOD0(active_configuration, std::shared_ptr<graphics::DisplayConfiguration>());
781- MOCK_METHOD2(store_configuration_for,
782+ MOCK_METHOD2(configure,
783 void(std::weak_ptr<frontend::Session> const&, std::shared_ptr<graphics::DisplayConfiguration> const&));
784- MOCK_METHOD1(remove_configuration_for, void(std::weak_ptr<frontend::Session> const&));
785- MOCK_METHOD1(apply_configuration_of, void(std::weak_ptr<frontend::Session> const&));
786 };
787
788 }
789
790=== modified file 'include/test/mir_test_doubles/mock_drm.h'
791--- include/test/mir_test_doubles/mock_drm.h 2013-08-12 08:58:58 +0000
792+++ include/test/mir_test_doubles/mock_drm.h 2013-08-13 22:17:10 +0000
793@@ -48,7 +48,7 @@
794
795 void add_crtc(uint32_t id, drmModeModeInfo mode);
796 void add_encoder(uint32_t encoder_id, uint32_t crtc_id, uint32_t possible_crtcs_mask);
797- void add_connector(uint32_t connector_id, uint32_t type, drmModeConnection connection,
798+ void add_connector(uint32_t connector_id, drmModeConnection connection,
799 uint32_t encoder_id, std::vector<drmModeModeInfo>& modes,
800 std::vector<uint32_t>& possible_encoder_ids,
801 geometry::Size const& physical_size);
802@@ -60,10 +60,8 @@
803 drmModeEncoder* find_encoder(uint32_t id);
804 drmModeConnector* find_connector(uint32_t id);
805
806- enum ModePreference {NormalMode, PreferredMode};
807 static drmModeModeInfo create_mode(uint16_t hdisplay, uint16_t vdisplay,
808- uint32_t clock, uint16_t htotal, uint16_t vtotal,
809- ModePreference preferred);
810+ uint32_t clock, uint16_t htotal, uint16_t vtotal);
811
812 private:
813 int pipe_fds[2];
814
815=== modified file 'include/test/mir_test_doubles/mock_focus_setter.h'
816--- include/test/mir_test_doubles/mock_focus_setter.h 2013-08-13 22:17:09 +0000
817+++ include/test/mir_test_doubles/mock_focus_setter.h 2013-04-24 05:22:20 +0000
818@@ -32,11 +32,7 @@
819
820 struct MockFocusSetter : public shell::FocusSetter
821 {
822- MOCK_METHOD1(session_opened, void(std::shared_ptr<shell::Session> const&));
823- MOCK_METHOD1(session_closed, void(std::shared_ptr<shell::Session> const&));
824- MOCK_METHOD1(surface_created_for, void(std::shared_ptr<shell::Session> const&));
825- MOCK_CONST_METHOD0(focused_session, std::weak_ptr<shell::Session>());
826- MOCK_METHOD0(focus_next, void());
827+ MOCK_METHOD1(set_focus_to, void(std::shared_ptr<shell::Session> const&));
828 };
829
830 }
831
832=== modified file 'include/test/mir_test_doubles/mock_shell.h'
833--- include/test/mir_test_doubles/mock_shell.h 2013-08-13 22:17:09 +0000
834+++ include/test/mir_test_doubles/mock_shell.h 2013-08-13 22:17:10 +0000
835@@ -38,10 +38,8 @@
836 std::string const&, std::shared_ptr<frontend::EventSink> const&));
837 MOCK_METHOD1(close_session, void(std::shared_ptr<frontend::Session> const&));
838
839- MOCK_METHOD1(handle_display_configuration, void(std::shared_ptr<frontend::Session> const&));
840- MOCK_METHOD1(handle_surface_created, void(std::shared_ptr<frontend::Session> const&));
841-
842 MOCK_METHOD2(create_surface_for, frontend::SurfaceId(std::shared_ptr<frontend::Session> const&, shell::SurfaceCreationParameters const&));
843+ MOCK_METHOD1(handle_surface_created, void(std::shared_ptr<frontend::Session> const&));
844 };
845
846 }
847
848=== modified file 'include/test/mir_test_doubles/null_display_changer.h'
849--- include/test/mir_test_doubles/null_display_changer.h 2013-08-13 22:17:09 +0000
850+++ include/test/mir_test_doubles/null_display_changer.h 2013-08-12 17:20:29 +0000
851@@ -36,13 +36,9 @@
852 {
853 return std::make_shared<NullDisplayConfig>();
854 }
855- virtual void store_configuration_for(
856- std::weak_ptr<frontend::Session> const&, std::shared_ptr<graphics::DisplayConfiguration> const&)
857- {}
858- virtual void apply_configuration_of(std::weak_ptr<frontend::Session> const&)
859- {}
860- virtual void remove_configuration_for(std::weak_ptr<frontend::Session> const&)
861- {}
862+ virtual void configure(std::weak_ptr<frontend::Session> const&, std::shared_ptr<graphics::DisplayConfiguration> const&)
863+ {
864+ }
865 };
866 }
867 }
868
869=== modified file 'include/test/mir_test_doubles/stub_display_configuration.h'
870--- include/test/mir_test_doubles/stub_display_configuration.h 2013-08-12 08:58:59 +0000
871+++ include/test/mir_test_doubles/stub_display_configuration.h 2013-08-13 22:17:10 +0000
872@@ -62,8 +62,7 @@
873 graphics::DisplayConfigurationOutput output{
874 graphics::DisplayConfigurationOutputId{static_cast<int>(i)},
875 graphics::DisplayConfigurationCardId{static_cast<int>(i)},
876- graphics::DisplayConfigurationOutputType::vga,
877- pfs, modes, i,
878+ pfs, modes,
879 physical_size,
880 ((i % 2) == 0),
881 ((i % 2) == 1),
882@@ -72,21 +71,11 @@
883 };
884
885 outputs.push_back(output);
886-
887- graphics::DisplayConfigurationCard card{
888- graphics::DisplayConfigurationCardId{static_cast<int>(i)},
889- i + 1
890- };
891-
892- cards.push_back(card);
893 }
894-
895 };
896
897- void for_each_card(std::function<void(graphics::DisplayConfigurationCard const&)> f) const
898+ void for_each_card(std::function<void(graphics::DisplayConfigurationCard const&)>) const
899 {
900- for (auto const& card : cards)
901- f(card);
902 }
903
904 void for_each_output(std::function<void(graphics::DisplayConfigurationOutput const&)> f) const
905@@ -101,7 +90,6 @@
906 {
907 }
908
909- std::vector<graphics::DisplayConfigurationCard> cards;
910 std::vector<graphics::DisplayConfigurationOutput> outputs;
911 };
912
913
914=== modified file 'include/test/mir_test_doubles/stub_session.h'
915--- include/test/mir_test_doubles/stub_session.h 2013-08-13 22:17:09 +0000
916+++ include/test/mir_test_doubles/stub_session.h 2013-08-08 22:16:06 +0000
917@@ -32,7 +32,7 @@
918 {
919 frontend::SurfaceId create_surface(shell::SurfaceCreationParameters const& /* params */)
920 {
921- return frontend::SurfaceId{1};
922+ return frontend::SurfaceId{0};
923 }
924 void destroy_surface(frontend::SurfaceId /* surface */)
925 {
926@@ -58,6 +58,10 @@
927 {
928 return 0;
929 }
930+ void set_event_sink(std::shared_ptr<frontend::EventSink> const&)
931+ {
932+ }
933+
934 void send_display_config(graphics::DisplayConfiguration const&)
935 {
936 }
937
938=== modified file 'include/test/mir_test_doubles/stub_shell.h'
939--- include/test/mir_test_doubles/stub_shell.h 2013-08-13 22:17:09 +0000
940+++ include/test/mir_test_doubles/stub_shell.h 2013-08-13 22:17:10 +0000
941@@ -35,24 +35,16 @@
942 {
943 return std::make_shared<StubSession>();
944 }
945-
946 void close_session(std::shared_ptr<frontend::Session> const& /* session */) override
947 {
948 }
949-
950- virtual void handle_display_configuration(std::shared_ptr<frontend::Session> const&)
951- {
952- }
953-
954- virtual void handle_surface_created(std::shared_ptr<frontend::Session> const&)
955- {
956- }
957-
958- virtual frontend::SurfaceId create_surface_for(
959- std::shared_ptr<frontend::Session> const& /* session */,
960- shell::SurfaceCreationParameters const& /* params */)
961- {
962- return frontend::SurfaceId{4};
963+ frontend::SurfaceId create_surface_for(std::shared_ptr<frontend::Session> const& /* session */,
964+ shell::SurfaceCreationParameters const& /* params */) override
965+ {
966+ return frontend::SurfaceId{0};
967+ }
968+ void handle_surface_created(std::shared_ptr<frontend::Session> const& /* session */) override
969+ {
970 }
971 };
972
973
974=== modified file 'include/test/mir_test_framework/input_testing_server_configuration.h'
975--- include/test/mir_test_framework/input_testing_server_configuration.h 2013-07-24 05:22:03 +0000
976+++ include/test/mir_test_framework/input_testing_server_configuration.h 2013-08-13 22:17:10 +0000
977@@ -63,14 +63,13 @@
978 void on_exit();
979
980 std::shared_ptr<mir::input::InputConfiguration> the_input_configuration() override;
981- std::shared_ptr<mir::surfaces::InputRegistrar> the_input_registrar() override;
982+ std::shared_ptr<mir::frontend::Shell> the_frontend_shell() override;
983
984 protected:
985 virtual void inject_input() = 0;
986 mir::input::android::FakeEventHub* fake_event_hub;
987
988 void wait_until_client_appears(std::string const& surface_name);
989- void wait_until_client_vanishes(std::string const& surface_name);
990
991 private:
992 std::mutex lifecycle_lock;
993@@ -81,7 +80,7 @@
994 std::thread input_injection_thread;
995
996 std::shared_ptr<mir::test::doubles::FakeEventHubInputConfiguration> input_configuration;
997- std::shared_ptr<mir::surfaces::InputRegistrar> input_registrar;
998+ std::shared_ptr<mir::frontend::Shell> frontend_shell;
999 };
1000
1001 }
1002
1003=== modified file 'src/client/display_configuration.cpp'
1004--- src/client/display_configuration.cpp 2013-08-12 08:58:59 +0000
1005+++ src/client/display_configuration.cpp 2013-08-13 22:17:10 +0000
1006@@ -59,17 +59,10 @@
1007 namespace
1008 {
1009
1010-void fill_display_card(MirDisplayCard& card, mp::DisplayCard const& msg)
1011-{
1012- card.card_id = msg.card_id();
1013- card.max_simultaneous_outputs = msg.max_simultaneous_outputs();
1014-}
1015-
1016 void fill_display_output(MirDisplayOutput& output, mp::DisplayOutput const& msg)
1017 {
1018 output.card_id = msg.card_id();
1019 output.output_id = msg.output_id();
1020- output.type = static_cast<MirDisplayOutputType>(msg.type());
1021
1022 for (auto i = 0u; i < output.num_modes; i++)
1023 {
1024@@ -78,7 +71,6 @@
1025 output.modes[i].vertical_resolution = mode.vertical_resolution();
1026 output.modes[i].refresh_rate = mode.refresh_rate();
1027 }
1028- output.preferred_mode = msg.preferred_mode();
1029 output.current_mode = msg.current_mode();
1030
1031 for (auto i = 0u; i < output.num_output_formats; i++)
1032@@ -109,16 +101,6 @@
1033 void mcl::DisplayConfiguration::set_configuration(mp::DisplayConfiguration const& msg)
1034 {
1035 std::unique_lock<std::mutex> lk(guard);
1036-
1037- cards.clear();
1038- for (auto i = 0; i < msg.display_card_size(); i++)
1039- {
1040- auto const& msg_card = msg.display_card(i);
1041- MirDisplayCard card;
1042- fill_display_card(card, msg_card);
1043- cards.push_back(card);
1044- }
1045-
1046 outputs.clear();
1047 for (auto i = 0; i < msg.display_output_size(); i++)
1048 {
1049@@ -141,22 +123,14 @@
1050 {
1051 std::unique_lock<std::mutex> lk(guard);
1052 auto new_config = new MirDisplayConfiguration;
1053-
1054- /* Cards */
1055- new_config->num_cards = cards.size();
1056- new_config->cards = new MirDisplayCard[new_config->num_cards];
1057-
1058- for (auto i = 0u; i < cards.size(); i++)
1059- new_config->cards[i] = cards[i];
1060-
1061- /* Outputs */
1062 new_config->num_displays = outputs.size();
1063 new_config->displays = new MirDisplayOutput[new_config->num_displays];
1064
1065- for (auto i = 0u; i < outputs.size(); i++)
1066+ auto i=0u;
1067+ for (auto const& out : outputs)
1068 {
1069- auto new_info = &new_config->displays[i];
1070- MirDisplayOutput* output = outputs[i].get();
1071+ auto new_info = &new_config->displays[i++];
1072+ MirDisplayOutput* output = out.get();
1073 std::memcpy(new_info, output, sizeof(MirDisplayOutput));
1074
1075 new_info->output_formats = new MirPixelFormat[new_info->num_output_formats];
1076@@ -167,7 +141,6 @@
1077 auto mode_size = sizeof(MirDisplayMode)* new_info->num_modes;
1078 std::memcpy(new_info->modes, output->modes, mode_size);
1079 }
1080-
1081 return new_config;
1082 }
1083
1084
1085=== modified file 'src/client/display_configuration.h'
1086--- src/client/display_configuration.h 2013-08-12 08:58:59 +0000
1087+++ src/client/display_configuration.h 2013-08-13 22:17:10 +0000
1088@@ -56,7 +56,6 @@
1089
1090 private:
1091 std::mutex mutable guard;
1092- std::vector<MirDisplayCard> cards;
1093 std::vector<std::shared_ptr<DisplayOutput>> outputs;
1094 std::function<void()> notify_change;
1095 };
1096
1097=== modified file 'src/client/mir_connection.cpp'
1098--- src/client/mir_connection.cpp 2013-08-09 09:32:07 +0000
1099+++ src/client/mir_connection.cpp 2013-08-13 22:17:10 +0000
1100@@ -118,6 +118,10 @@
1101
1102 void MirConnection::released(SurfaceRelease data)
1103 {
1104+ {
1105+ std::lock_guard<std::recursive_mutex> lock(mutex);
1106+ surface_map->erase(data.surface->id());
1107+ }
1108 data.callback(data.surface, data.context);
1109 data.handle->result_received();
1110 delete data.surface;
1111@@ -133,7 +137,6 @@
1112 auto new_wait_handle = new MirWaitHandle;
1113
1114 SurfaceRelease surf_release{surface, new_wait_handle, callback, context};
1115- surface_map->erase(surface->id());
1116
1117 mir::protobuf::SurfaceId message;
1118 message.set_value(surface->id());
1119
1120=== modified file 'src/client/mir_surface.cpp'
1121--- src/client/mir_surface.cpp 2013-06-28 09:25:09 +0000
1122+++ src/client/mir_surface.cpp 2013-08-13 22:17:10 +0000
1123@@ -54,7 +54,7 @@
1124
1125 server.create_surface(0, &message, &surface, gp::NewCallback(this, &MirSurface::created, callback, context));
1126
1127- for (int i = 0; i < mir_surface_attrib_arraysize_; i++)
1128+ for (int i = 0; i < mir_surface_attrib_enum_max_; i++)
1129 attrib_cache[i] = -1;
1130 attrib_cache[mir_surface_attrib_type] = mir_surface_type_normal;
1131 attrib_cache[mir_surface_attrib_state] = mir_surface_state_unknown;
1132@@ -221,8 +221,6 @@
1133 mir_surface_callback callback,
1134 void * context)
1135 {
1136- std::lock_guard<std::recursive_mutex> lock(mutex);
1137-
1138 return connection->release_surface(this, callback, context);
1139 }
1140
1141@@ -307,6 +305,7 @@
1142 {
1143 case mir_surface_attrib_type:
1144 case mir_surface_attrib_state:
1145+ case mir_surface_attrib_focus:
1146 case mir_surface_attrib_swapinterval:
1147 if (configure_result.has_ivalue())
1148 attrib_cache[a] = configure_result.ivalue();
1149@@ -362,7 +361,7 @@
1150 if (e.type == mir_event_type_surface)
1151 {
1152 MirSurfaceAttrib a = e.surface.attrib;
1153- if (a < mir_surface_attrib_arraysize_)
1154+ if (a < mir_surface_attrib_enum_max_)
1155 attrib_cache[a] = e.surface.value;
1156 }
1157
1158
1159=== modified file 'src/client/mir_surface.h'
1160--- src/client/mir_surface.h 2013-06-28 11:10:25 +0000
1161+++ src/client/mir_surface.h 2013-08-13 22:17:10 +0000
1162@@ -122,7 +122,7 @@
1163 mir::protobuf::SurfaceSetting configure_result;
1164
1165 // Cache of latest SurfaceSettings returned from the server
1166- int attrib_cache[mir_surface_attrib_arraysize_];
1167+ int attrib_cache[mir_surface_attrib_enum_max_];
1168
1169 std::function<void(MirEvent const*)> handle_event_callback;
1170 std::shared_ptr<mir::input::receiver::InputReceiverThread> input_thread;
1171
1172=== modified file 'src/platform/graphics/default_display_configuration_policy.cpp'
1173--- src/platform/graphics/default_display_configuration_policy.cpp 2013-08-12 08:58:58 +0000
1174+++ src/platform/graphics/default_display_configuration_policy.cpp 2013-08-13 22:17:10 +0000
1175@@ -24,15 +24,13 @@
1176
1177 void mg::DefaultDisplayConfigurationPolicy::apply_to(DisplayConfiguration& conf)
1178 {
1179+ size_t const preferred_mode_index{0};
1180+
1181 conf.for_each_output(
1182 [&conf](DisplayConfigurationOutput const& conf_output)
1183 {
1184 if (conf_output.connected && conf_output.modes.size() > 0)
1185 {
1186- size_t preferred_mode_index{conf_output.preferred_mode_index};
1187- if (preferred_mode_index > conf_output.modes.size())
1188- preferred_mode_index = 0;
1189-
1190 conf.configure_output(conf_output.id, true, geom::Point(),
1191 preferred_mode_index);
1192 }
1193
1194=== modified file 'src/platform/graphics/display_configuration.cpp'
1195--- src/platform/graphics/display_configuration.cpp 2013-08-12 11:55:54 +0000
1196+++ src/platform/graphics/display_configuration.cpp 2013-08-13 22:17:10 +0000
1197@@ -47,41 +47,6 @@
1198 std::streamsize const precision;
1199 };
1200
1201-char const* output_type_to_string(mg::DisplayConfigurationOutputType type)
1202-{
1203- static char const* type_names[] =
1204- {
1205- "unknown",
1206- "vga",
1207- "dvii",
1208- "dvid",
1209- "dvia",
1210- "composite",
1211- "lvds",
1212- "component",
1213- "9pindin",
1214- "displayport",
1215- "hdmia",
1216- "hdmib",
1217- "tv",
1218- "edp"
1219- };
1220-
1221- auto index = static_cast<ssize_t>(type);
1222- static auto const size = std::distance(std::begin(type_names), std::end(type_names));
1223- if (index >= size || index < 0)
1224- return "invalid";
1225-
1226- return type_names[index];
1227-}
1228-
1229-}
1230-
1231-std::ostream& mg::operator<<(std::ostream& out, mg::DisplayConfigurationCard const& val)
1232-{
1233- return out << "{ id: " << val.id
1234- << " max_simultaneous_outputs: " << val.max_simultaneous_outputs << " }"
1235- << std::endl;
1236 }
1237
1238 std::ostream& mg::operator<<(std::ostream& out, mg::DisplayConfigurationMode const& val)
1239@@ -96,9 +61,7 @@
1240
1241 std::ostream& mg::operator<<(std::ostream& out, mg::DisplayConfigurationOutput const& val)
1242 {
1243- out << "{ id: " << val.id << ", card_id: " << val.card_id
1244- << " type: " << output_type_to_string(val.type)
1245- << " modes: [";
1246+ out << "{ id: " << val.id << ", card_id: " << val.card_id << " modes: [";
1247
1248 for (size_t i = 0; i < val.modes.size(); ++i)
1249 {
1250@@ -107,8 +70,7 @@
1251 out << ", ";
1252 }
1253
1254- out << "], preferred_mode: " << val.preferred_mode_index;
1255- out << " physical_size_mm: " << val.physical_size_mm.width << "x" << val.physical_size_mm.height;
1256+ out << "], physical_size_mm: " << val.physical_size_mm.width << "x" << val.physical_size_mm.height;
1257 out << ", connected: " << (val.connected ? "true" : "false");
1258 out << ", used: " << (val.used ? "true" : "false");
1259 out << ", top_left: " << val.top_left;
1260@@ -123,19 +85,6 @@
1261 return out;
1262 }
1263
1264-bool mg::operator==(mg::DisplayConfigurationCard const& val1,
1265- mg::DisplayConfigurationCard const& val2)
1266-{
1267- return (val1.id == val2.id) &&
1268- (val1.max_simultaneous_outputs == val2.max_simultaneous_outputs);
1269-}
1270-
1271-bool mg::operator!=(mg::DisplayConfigurationCard const& val1,
1272- mg::DisplayConfigurationCard const& val2)
1273-{
1274- return !(val1 == val2);
1275-}
1276-
1277 bool mg::operator==(mg::DisplayConfigurationMode const& val1,
1278 mg::DisplayConfigurationMode const& val2)
1279 {
1280@@ -154,9 +103,7 @@
1281 {
1282 bool equal{(val1.id == val2.id) &&
1283 (val1.card_id == val2.card_id) &&
1284- (val1.type == val2.type) &&
1285 (val1.physical_size_mm == val2.physical_size_mm) &&
1286- (val1.preferred_mode_index == val2.preferred_mode_index) &&
1287 (val1.connected == val2.connected) &&
1288 (val1.used == val2.used) &&
1289 (val1.top_left == val2.top_left) &&
1290
1291=== modified file 'src/server/default_server_configuration.cpp'
1292--- src/server/default_server_configuration.cpp 2013-08-13 22:17:09 +0000
1293+++ src/server/default_server_configuration.cpp 2013-08-13 13:54:24 +0000
1294@@ -362,7 +362,6 @@
1295 });
1296 }
1297
1298-<<<<<<< TREE
1299 std::shared_ptr<msh::MediatingDisplayChanger>
1300 mir::DefaultServerConfiguration::the_mediating_display_changer()
1301 {
1302@@ -388,14 +387,6 @@
1303 mir::DefaultServerConfiguration::the_display_changer()
1304 {
1305 return the_mediating_display_changer();
1306-=======
1307-std::shared_ptr<msh::DisplayChanger>
1308-mir::DefaultServerConfiguration::the_shell_display_changer()
1309-{
1310- return shell_display_changer([this]()
1311- { return std::make_shared<msh::MediatingDisplayChanger>(
1312- the_display(), the_compositor());});
1313->>>>>>> MERGE-SOURCE
1314 }
1315
1316 std::shared_ptr<msh::SessionContainer>
1317@@ -411,11 +402,7 @@
1318 return shell_focus_setter(
1319 [this]
1320 {
1321- return std::make_shared<msh::DefaultFocusMechanism>(
1322- the_shell_focus_sequence(),
1323- the_input_targeter(),
1324- the_surface_controller(),
1325- the_shell_session_listener());
1326+ return std::make_shared<msh::DefaultFocusMechanism>(the_input_targeter(), the_surface_controller());
1327 });
1328 }
1329
1330@@ -460,10 +447,10 @@
1331 return std::make_shared<msh::SessionManager>(
1332 the_shell_surface_factory(),
1333 the_shell_session_container(),
1334+ the_shell_focus_sequence(),
1335 the_shell_focus_setter(),
1336 the_shell_snapshot_strategy(),
1337- the_shell_session_listener(),
1338- the_shell_display_changer());
1339+ the_shell_session_listener());
1340 });
1341 }
1342
1343@@ -505,6 +492,12 @@
1344 });
1345 }
1346
1347+std::shared_ptr<msh::FocusController>
1348+mir::DefaultServerConfiguration::the_focus_controller()
1349+{
1350+ return the_session_manager();
1351+}
1352+
1353 std::shared_ptr<mi::CompositeEventFilter>
1354 mir::DefaultServerConfiguration::the_composite_event_filter()
1355 {
1356
1357=== modified file 'src/server/frontend/null_message_processor_report.cpp'
1358--- src/server/frontend/null_message_processor_report.cpp 2013-04-24 05:22:20 +0000
1359+++ src/server/frontend/null_message_processor_report.cpp 2013-08-13 22:17:10 +0000
1360@@ -39,3 +39,7 @@
1361 void mf::NullMessageProcessorReport::exception_handled(void const*, std::exception const&)
1362 {
1363 }
1364+
1365+void mf::NullMessageProcessorReport::sent_event(void const*, MirSurfaceEvent const&)
1366+{
1367+}
1368
1369=== modified file 'src/server/frontend/protobuf_buffer_packer.cpp'
1370--- src/server/frontend/protobuf_buffer_packer.cpp 2013-08-12 08:58:59 +0000
1371+++ src/server/frontend/protobuf_buffer_packer.cpp 2013-08-13 22:17:10 +0000
1372@@ -28,19 +28,11 @@
1373 namespace
1374 {
1375
1376-void pack_protobuf_display_card(mp::DisplayCard& protobuf_card,
1377- mg::DisplayConfigurationCard const& display_card)
1378-{
1379- protobuf_card.set_card_id(display_card.id.as_value());
1380- protobuf_card.set_max_simultaneous_outputs(display_card.max_simultaneous_outputs);
1381-}
1382-
1383 void pack_protobuf_display_output(mp::DisplayOutput& protobuf_output,
1384 mg::DisplayConfigurationOutput const& display_output)
1385 {
1386 protobuf_output.set_output_id(display_output.id.as_value());
1387 protobuf_output.set_card_id(display_output.card_id.as_value());
1388- protobuf_output.set_type(static_cast<uint32_t>(display_output.type));
1389
1390 for (auto const& pf : display_output.pixel_formats)
1391 {
1392@@ -54,7 +46,6 @@
1393 protobuf_output_mode->set_vertical_resolution(mode.size.height.as_uint32_t());
1394 protobuf_output_mode->set_refresh_rate(mode.vrefresh_hz);
1395 }
1396- protobuf_output.set_preferred_mode(display_output.preferred_mode_index);
1397
1398 protobuf_output.set_physical_width_mm(display_output.physical_size_mm.width.as_uint32_t());
1399 protobuf_output.set_physical_height_mm(display_output.physical_size_mm.height.as_uint32_t());
1400@@ -72,13 +63,6 @@
1401 void mfd::pack_protobuf_display_configuration(mp::DisplayConfiguration& protobuf_config,
1402 mg::DisplayConfiguration const& display_config)
1403 {
1404- display_config.for_each_card(
1405- [&protobuf_config](mg::DisplayConfigurationCard const& card)
1406- {
1407- auto protobuf_card = protobuf_config.add_display_card();
1408- pack_protobuf_display_card(*protobuf_card, card);
1409- });
1410-
1411 display_config.for_each_output(
1412 [&protobuf_config](mg::DisplayConfigurationOutput const& output)
1413 {
1414
1415=== modified file 'src/server/frontend/session_mediator.cpp'
1416--- src/server/frontend/session_mediator.cpp 2013-08-13 22:17:09 +0000
1417+++ src/server/frontend/session_mediator.cpp 2013-08-13 22:17:10 +0000
1418@@ -35,17 +35,22 @@
1419 #include "mir/graphics/display_configuration.h"
1420 #include "mir/graphics/platform_ipc_package.h"
1421 #include "mir/frontend/client_constants.h"
1422+#include "mir/frontend/event_sink.h"
1423+
1424 #include "mir/geometry/rectangles.h"
1425 #include "client_buffer_tracker.h"
1426 #include "protobuf_buffer_packer.h"
1427
1428 #include <boost/throw_exception.hpp>
1429
1430+#include <mutex>
1431+#include <functional>
1432+
1433 namespace msh = mir::shell;
1434 namespace mf = mir::frontend;
1435-namespace mfd = mir::frontend::detail;
1436+namespace mfd=mir::frontend::detail;
1437+namespace mg = mir::graphics;
1438 namespace geom = mir::geometry;
1439-namespace mg = mir::graphics;
1440
1441 mf::SessionMediator::SessionMediator(
1442 std::shared_ptr<frontend::Shell> const& shell,
1443@@ -71,7 +76,6 @@
1444 if (session)
1445 {
1446 report->session_error(session->name(), __PRETTY_FUNCTION__, "connection dropped without disconnect");
1447- display_changer->remove_configuration_for(session);
1448 shell->close_session(session);
1449 }
1450 }
1451@@ -113,50 +117,44 @@
1452 mir::protobuf::Surface* response,
1453 google::protobuf::Closure* done)
1454 {
1455- {
1456- std::unique_lock<std::mutex> lock(session_mutex);
1457-
1458- if (session.get() == nullptr)
1459- BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
1460-
1461- report->session_create_surface_called(session->name());
1462-
1463- auto const id = session->create_surface(
1464- msh::SurfaceCreationParameters()
1465- .of_name(request->surface_name())
1466- .of_size(request->width(), request->height())
1467- .of_buffer_usage(static_cast<graphics::BufferUsage>(request->buffer_usage()))
1468- .of_pixel_format(static_cast<geometry::PixelFormat>(request->pixel_format()))
1469- );
1470-
1471- {
1472- auto surface = session->get_surface(id);
1473- response->mutable_id()->set_value(id.as_value());
1474- response->set_width(surface->size().width.as_uint32_t());
1475- response->set_height(surface->size().height.as_uint32_t());
1476- response->set_pixel_format((int)surface->pixel_format());
1477- response->set_buffer_usage(request->buffer_usage());
1478-
1479- if (surface->supports_input())
1480- response->add_fd(surface->client_input_fd());
1481-
1482- client_buffer_resource = surface->advance_client_buffer();
1483- auto const& id = client_buffer_resource->id();
1484-
1485- auto buffer = response->mutable_buffer();
1486- buffer->set_buffer_id(id.as_uint32_t());
1487-
1488- if (!client_tracker->client_has(id))
1489- {
1490- auto packer = std::make_shared<mfd::ProtobufBufferPacker>(buffer);
1491- graphics_platform->fill_ipc_package(packer, client_buffer_resource);
1492- }
1493- client_tracker->add(id);
1494- }
1495- }
1496-
1497- done->Run();
1498- shell->handle_surface_created(session);
1499+ std::unique_lock<std::mutex> lock(session_mutex);
1500+
1501+ if (session.get() == nullptr)
1502+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
1503+
1504+ report->session_create_surface_called(session->name());
1505+
1506+ auto const id = session->create_surface(
1507+ msh::SurfaceCreationParameters()
1508+ .of_name(request->surface_name())
1509+ .of_size(request->width(), request->height())
1510+ .of_buffer_usage(static_cast<graphics::BufferUsage>(request->buffer_usage()))
1511+ .of_pixel_format(static_cast<geometry::PixelFormat>(request->pixel_format()))
1512+ );
1513+ {
1514+ auto surface = session->get_surface(id);
1515+ response->mutable_id()->set_value(id.as_value());
1516+ response->set_width(surface->size().width.as_uint32_t());
1517+ response->set_height(surface->size().height.as_uint32_t());
1518+ response->set_pixel_format((int)surface->pixel_format());
1519+ response->set_buffer_usage(request->buffer_usage());
1520+ if (surface->supports_input())
1521+ response->add_fd(surface->client_input_fd());
1522+ client_buffer_resource = surface->advance_client_buffer();
1523+ auto const& id = client_buffer_resource->id();
1524+ auto buffer = response->mutable_buffer();
1525+ buffer->set_buffer_id(id.as_uint32_t());
1526+ if (!client_tracker->client_has(id))
1527+ {
1528+ auto packer = std::make_shared<mfd::ProtobufBufferPacker>(buffer);
1529+ graphics_platform->fill_ipc_package(packer, client_buffer_resource);
1530+ }
1531+ client_tracker->add(id);
1532+ }
1533+
1534+ // TODO: We rely on done->Run() sending messages synchronously.
1535+ done->Run();
1536+ shell->handle_surface_created(session);
1537 }
1538
1539 void mf::SessionMediator::next_buffer(
1540@@ -210,6 +208,7 @@
1541 session->destroy_surface(id);
1542 }
1543
1544+ // TODO: We rely on this sending responses synchronously.
1545 done->Run();
1546 }
1547
1548@@ -227,7 +226,6 @@
1549
1550 report->session_disconnect_called(session->name());
1551
1552- display_changer->remove_configuration_for(session);
1553 shell->close_session(session);
1554 session.reset();
1555 }
1556@@ -283,10 +281,7 @@
1557 output.current_mode());
1558 }
1559
1560- display_changer->store_configuration_for(session, config);
1561-
1562- shell->handle_display_configuration(session);
1563+ display_changer->configure(session, config);
1564 }
1565 done->Run();
1566-
1567 }
1568
1569=== modified file 'src/server/graphics/android/android_display.cpp'
1570--- src/server/graphics/android/android_display.cpp 2013-08-12 08:58:59 +0000
1571+++ src/server/graphics/android/android_display.cpp 2013-08-13 22:17:10 +0000
1572@@ -56,22 +56,17 @@
1573 AndroidDisplayConfiguration(geom::Size const& display_size)
1574 : configuration{mg::DisplayConfigurationOutputId{0},
1575 mg::DisplayConfigurationCardId{0},
1576- mg::DisplayConfigurationOutputType::lvds,
1577 {geom::PixelFormat::abgr_8888},
1578 {mg::DisplayConfigurationMode{display_size,0.0f}},
1579- 0,
1580 geom::Size{0,0},
1581 true,
1582 true,
1583 geom::Point{0,0},
1584- 0, 0},
1585- card{mg::DisplayConfigurationCardId{0}, 1}
1586+ 0, 0}
1587 {
1588 }
1589-
1590- void for_each_card(std::function<void(mg::DisplayConfigurationCard const&)> f) const
1591+ void for_each_card(std::function<void(mg::DisplayConfigurationCard const&)>) const
1592 {
1593- f(card);
1594 }
1595
1596 void for_each_output(std::function<void(mg::DisplayConfigurationOutput const&)> f) const
1597@@ -85,8 +80,7 @@
1598 }
1599
1600 private:
1601- mg::DisplayConfigurationOutput const configuration;
1602- mg::DisplayConfigurationCard const card;
1603+ mg::DisplayConfigurationOutput configuration;
1604 };
1605
1606 EGLDisplay create_and_initialize_display()
1607
1608=== modified file 'src/server/graphics/gbm/drm_mode_resources.cpp'
1609--- src/server/graphics/gbm/drm_mode_resources.cpp 2013-08-12 08:58:59 +0000
1610+++ src/server/graphics/gbm/drm_mode_resources.cpp 2013-08-13 22:17:10 +0000
1611@@ -95,21 +95,6 @@
1612 }
1613 }
1614
1615-size_t mgg::DRMModeResources::num_connectors()
1616-{
1617- return resources->count_connectors;
1618-}
1619-
1620-size_t mgg::DRMModeResources::num_encoders()
1621-{
1622- return resources->count_encoders;
1623-}
1624-
1625-size_t mgg::DRMModeResources::num_crtcs()
1626-{
1627- return resources->count_crtcs;
1628-}
1629-
1630 mgg::DRMModeConnectorUPtr mgg::DRMModeResources::connector(uint32_t id) const
1631 {
1632 auto connector_raw = drmModeGetConnector(drm_fd, id);
1633
1634=== modified file 'src/server/graphics/gbm/drm_mode_resources.h'
1635--- src/server/graphics/gbm/drm_mode_resources.h 2013-08-12 08:58:59 +0000
1636+++ src/server/graphics/gbm/drm_mode_resources.h 2013-08-13 22:17:10 +0000
1637@@ -46,10 +46,6 @@
1638 void for_each_encoder(std::function<void(DRMModeEncoderUPtr)> const& f) const;
1639 void for_each_crtc(std::function<void(DRMModeCrtcUPtr)> const& f) const;
1640
1641- size_t num_connectors();
1642- size_t num_encoders();
1643- size_t num_crtcs();
1644-
1645 DRMModeConnectorUPtr connector(uint32_t id) const;
1646 DRMModeEncoderUPtr encoder(uint32_t id) const;
1647 DRMModeCrtcUPtr crtc(uint32_t id) const;
1648
1649=== modified file 'src/server/graphics/gbm/real_kms_display_configuration.cpp'
1650--- src/server/graphics/gbm/real_kms_display_configuration.cpp 2013-08-12 08:58:59 +0000
1651+++ src/server/graphics/gbm/real_kms_display_configuration.cpp 2013-08-13 22:17:10 +0000
1652@@ -59,12 +59,6 @@
1653 return round(vrefresh_hz * 10.0) / 10.0;
1654 }
1655
1656-mg::DisplayConfigurationOutputType
1657-kms_connector_type_to_output_type(uint32_t connector_type)
1658-{
1659- return static_cast<mg::DisplayConfigurationOutputType>(connector_type);
1660-}
1661-
1662 }
1663
1664 mgg::RealKMSDisplayConfiguration::RealKMSDisplayConfiguration(int drm_fd)
1665@@ -75,8 +69,7 @@
1666
1667 mgg::RealKMSDisplayConfiguration::RealKMSDisplayConfiguration(
1668 RealKMSDisplayConfiguration const& conf)
1669- : KMSDisplayConfiguration(), drm_fd{conf.drm_fd},
1670- card(conf.card), outputs{conf.outputs}
1671+ : KMSDisplayConfiguration(), drm_fd{conf.drm_fd}, outputs{conf.outputs}
1672 {
1673 }
1674
1675@@ -86,7 +79,6 @@
1676 if (&conf != this)
1677 {
1678 drm_fd = conf.drm_fd;
1679- card = conf.card;
1680 outputs = conf.outputs;
1681 }
1682
1683@@ -96,6 +88,7 @@
1684 void mgg::RealKMSDisplayConfiguration::for_each_card(
1685 std::function<void(DisplayConfigurationCard const&)> f) const
1686 {
1687+ DisplayConfigurationCard const card{DisplayConfigurationCardId{0}};
1688 f(card);
1689 }
1690
1691@@ -161,9 +154,6 @@
1692 {
1693 DRMModeResources resources{drm_fd};
1694
1695- size_t max_outputs = std::min(resources.num_crtcs(), resources.num_connectors());
1696- card = {mg::DisplayConfigurationCardId{0}, max_outputs};
1697-
1698 resources.for_each_connector([&](DRMModeConnectorUPtr connector)
1699 {
1700 add_or_update_output(resources, *connector);
1701@@ -176,12 +166,9 @@
1702 {
1703 DisplayConfigurationOutputId id{static_cast<int>(connector.connector_id)};
1704 DisplayConfigurationCardId card_id{0};
1705- DisplayConfigurationOutputType const type{
1706- kms_connector_type_to_output_type(connector.connector_type)};
1707 geom::Size physical_size{connector.mmWidth, connector.mmHeight};
1708 bool connected{connector.connection == DRM_MODE_CONNECTED};
1709 size_t current_mode_index{std::numeric_limits<size_t>::max()};
1710- size_t preferred_mode_index{std::numeric_limits<size_t>::max()};
1711 std::vector<DisplayConfigurationMode> modes;
1712 std::vector<geom::PixelFormat> formats {geom::PixelFormat::argb_8888,
1713 geom::PixelFormat::xrgb_8888};
1714@@ -197,7 +184,7 @@
1715 current_mode_info = crtc->mode;
1716 }
1717
1718- /* Add all the available modes and find the current and preferred one */
1719+ /* Add all the available modes and find the current one */
1720 for (int m = 0; m < connector.count_modes; m++)
1721 {
1722 drmModeModeInfo& mode_info = connector.modes[m];
1723@@ -210,9 +197,6 @@
1724
1725 if (kms_modes_are_equal(mode_info, current_mode_info))
1726 current_mode_index = m;
1727-
1728- if ((mode_info.type & DRM_MODE_TYPE_PREFERRED) == DRM_MODE_TYPE_PREFERRED)
1729- preferred_mode_index = m;
1730 }
1731
1732 /* Add or update the output */
1733@@ -220,16 +204,14 @@
1734
1735 if (iter == outputs.end())
1736 {
1737- outputs.push_back({id, card_id, type, formats, modes, preferred_mode_index,
1738- physical_size, connected, false, geom::Point(),
1739- current_mode_index, 0u});
1740+ outputs.push_back({id, card_id, formats, modes, physical_size,
1741+ connected, false, geom::Point(), current_mode_index, 0u});
1742 }
1743 else
1744 {
1745 auto& output = *iter;
1746
1747 output.modes = modes;
1748- output.preferred_mode_index = preferred_mode_index;
1749 output.physical_size_mm = physical_size;
1750 output.connected = connected;
1751 output.current_mode_index = current_mode_index;
1752
1753=== modified file 'src/server/graphics/gbm/real_kms_display_configuration.h'
1754--- src/server/graphics/gbm/real_kms_display_configuration.h 2013-08-12 08:58:59 +0000
1755+++ src/server/graphics/gbm/real_kms_display_configuration.h 2013-08-13 22:17:10 +0000
1756@@ -30,6 +30,8 @@
1757 namespace gbm
1758 {
1759
1760+class DRMModeResources;
1761+
1762 class RealKMSDisplayConfiguration : public KMSDisplayConfiguration
1763 {
1764 public:
1765@@ -52,7 +54,6 @@
1766 std::vector<DisplayConfigurationOutput>::const_iterator find_output_with_id(DisplayConfigurationOutputId id) const;
1767
1768 int drm_fd;
1769- DisplayConfigurationCard card;
1770 std::vector<DisplayConfigurationOutput> outputs;
1771 };
1772
1773
1774=== modified file 'src/server/logging/message_processor_report.cpp'
1775--- src/server/logging/message_processor_report.cpp 2013-04-24 05:22:20 +0000
1776+++ src/server/logging/message_processor_report.cpp 2013-08-13 22:17:10 +0000
1777@@ -162,6 +162,9 @@
1778 mediators.erase(mediator);
1779 }
1780
1781-
1782-
1783-
1784+void ml::MessageProcessorReport::sent_event(void const* mediator, MirSurfaceEvent const& event)
1785+{
1786+ std::ostringstream out;
1787+ out << "mediator=" << mediator << ", sent event, surface id=" << event.id;
1788+ log->log<Logger::debug>(out.str(), component);
1789+}
1790
1791=== modified file 'src/server/lttng/message_processor_report.cpp'
1792--- src/server/lttng/message_processor_report.cpp 2013-06-03 12:15:44 +0000
1793+++ src/server/lttng/message_processor_report.cpp 2013-08-13 22:17:10 +0000
1794@@ -49,3 +49,8 @@
1795 void const* /*mediator*/, std::exception const& /*error*/)
1796 {
1797 }
1798+
1799+void mir::lttng::MessageProcessorReport::sent_event(
1800+ void const* /*mediator*/, MirSurfaceEvent const&)
1801+{
1802+}
1803
1804=== modified file 'src/server/shell/default_focus_mechanism.cpp'
1805--- src/server/shell/default_focus_mechanism.cpp 2013-08-13 22:17:09 +0000
1806+++ src/server/shell/default_focus_mechanism.cpp 2013-08-13 22:17:10 +0000
1807@@ -22,89 +22,40 @@
1808 #include "mir/shell/session.h"
1809 #include "mir/shell/surface.h"
1810 #include "mir/shell/surface_controller.h"
1811-#include "mir/shell/session_listener.h"
1812-#include "mir/shell/focus_sequence.h"
1813
1814 namespace mf = mir::frontend;
1815 namespace msh = mir::shell;
1816
1817-msh::DefaultFocusMechanism::DefaultFocusMechanism(std::shared_ptr<msh::FocusSequence> const& sequence,
1818- std::shared_ptr<msh::InputTargeter> const& input_targeter,
1819- std::shared_ptr<msh::SurfaceController> const& surface_controller,
1820- std::shared_ptr<msh::SessionListener> const& session_listener)
1821- : sequence(sequence),
1822- session_listener(session_listener),
1823- input_targeter(input_targeter),
1824- surface_controller(surface_controller),
1825- focus_session(nullptr)
1826-{
1827+msh::DefaultFocusMechanism::DefaultFocusMechanism(std::shared_ptr<msh::InputTargeter> const& input_targeter,
1828+ std::shared_ptr<msh::SurfaceController> const& surface_controller)
1829+ : input_targeter(input_targeter),
1830+ surface_controller(surface_controller)
1831+{
1832 }
1833
1834-void msh::DefaultFocusMechanism::set_focus(std::shared_ptr<msh::Session> const& session)
1835+void msh::DefaultFocusMechanism::set_focus_to(std::shared_ptr<Session> const& focus_session)
1836 {
1837- focus_session = session;
1838-
1839+ // TODO: This path should be encapsulated in a seperate clear_focus message
1840+ if (!focus_session)
1841+ {
1842+ input_targeter->focus_cleared();
1843+ return;
1844+ }
1845+
1846 auto surface = focus_session->default_surface();
1847 if (surface)
1848 {
1849+ auto current_focus = currently_focused_surface.lock();
1850+ if (current_focus)
1851+ current_focus->configure(mir_surface_attrib_focus, mir_surface_unfocused);
1852+ surface->configure(mir_surface_attrib_focus, mir_surface_focused);
1853+ currently_focused_surface = surface;
1854+
1855 surface->raise(surface_controller);
1856 surface->take_input_focus(input_targeter);
1857- session_listener->focused(focus_session);
1858 }
1859 else
1860 {
1861 input_targeter->focus_cleared();
1862- session_listener->unfocused();
1863- }
1864-}
1865-
1866-void msh::DefaultFocusMechanism::surface_created_for(std::shared_ptr<Session> const& session)
1867-{
1868- std::unique_lock<std::mutex> lock(mutex);
1869-
1870- //just set focus when a new surface is created
1871- set_focus(session);
1872-}
1873-void msh::DefaultFocusMechanism::session_opened(std::shared_ptr<Session> const& session)
1874-{
1875- std::unique_lock<std::mutex> lock(mutex);
1876-
1877- //just set focus to new session for now
1878- set_focus(session);
1879-}
1880-
1881-void msh::DefaultFocusMechanism::session_closed(std::shared_ptr<Session> const& session)
1882-{
1883- std::unique_lock<std::mutex> lock(mutex);
1884-
1885- //cycle through to next focus only if the currently-focused app is being closed
1886- if (focus_session == session)
1887- {
1888- focus_next_locked();
1889- }
1890-}
1891-
1892-void msh::DefaultFocusMechanism::focus_next_locked()
1893-{
1894- try
1895- {
1896- auto b = sequence->successor_of(focus_session);
1897- set_focus(b);
1898- } catch (std::logic_error)
1899- {
1900- input_targeter->focus_cleared();
1901- session_listener->unfocused();
1902- }
1903-}
1904-
1905-void msh::DefaultFocusMechanism::focus_next()
1906-{
1907- std::unique_lock<std::mutex> lock(mutex);
1908- focus_next_locked();
1909-}
1910-
1911-std::weak_ptr<msh::Session> msh::DefaultFocusMechanism::focused_session() const
1912-{
1913- std::unique_lock<std::mutex> lock(mutex);
1914- return focus_session;
1915+ }
1916 }
1917
1918=== modified file 'src/server/shell/mediating_display_changer.cpp'
1919--- src/server/shell/mediating_display_changer.cpp 2013-08-13 22:17:09 +0000
1920+++ src/server/shell/mediating_display_changer.cpp 2013-08-12 17:20:29 +0000
1921@@ -17,9 +17,6 @@
1922 */
1923
1924 #include "mir/shell/mediating_display_changer.h"
1925-#include "mir/shell/focus_setter.h"
1926-#include "mir/shell/session.h"
1927-#include "mir/compositor/compositor.h"
1928 #include "mir/graphics/display.h"
1929 #include "mir/compositor/compositor.h"
1930 #include "mir/input/input_manager.h"
1931@@ -28,7 +25,6 @@
1932 namespace mf = mir::frontend;
1933 namespace msh = mir::shell;
1934 namespace mg = mir::graphics;
1935-<<<<<<< TREE
1936 namespace mc = mir::compositor;
1937 namespace mi = mir::input;
1938
1939@@ -115,64 +111,4 @@
1940 {
1941 display->configure(*conf);
1942 }
1943-=======
1944-namespace mc = mir::compositor;
1945-
1946-msh::MediatingDisplayChanger::MediatingDisplayChanger(
1947- std::shared_ptr<mg::Display> const& display,
1948- std::shared_ptr<mc::Compositor> const& compositor)
1949- : display(display),
1950- compositor(compositor),
1951- base_config(display->configuration()),
1952- active_config(base_config)
1953-{
1954-}
1955-
1956-std::shared_ptr<mg::DisplayConfiguration> msh::MediatingDisplayChanger::active_configuration()
1957-{
1958- return active_config;
1959-}
1960-
1961-void msh::MediatingDisplayChanger::apply_config(
1962- std::shared_ptr<mg::DisplayConfiguration> const& requested_configuration)
1963-{
1964- compositor->stop();
1965- display->configure(*requested_configuration);
1966- active_config = requested_configuration;
1967- compositor->start();
1968-}
1969-
1970-void msh::MediatingDisplayChanger::store_configuration_for(
1971- std::weak_ptr<mf::Session> const& app,
1972- std::shared_ptr<mg::DisplayConfiguration> const& requested_configuration)
1973-{
1974- auto requesting_application = app.lock();
1975- config_map[requesting_application.get()] = requested_configuration;
1976-}
1977-
1978-void msh::MediatingDisplayChanger::apply_configuration_of(std::weak_ptr<mf::Session> const& app)
1979-{
1980- auto it = config_map.find(app.lock().get());
1981- if (it == config_map.end())
1982- {
1983- apply_config(base_config);
1984- }
1985- else
1986- {
1987- apply_config(it->second);
1988- }
1989-}
1990-
1991-void msh::MediatingDisplayChanger::remove_configuration_for(std::weak_ptr<mf::Session> const& app)
1992-{
1993- auto it = config_map.find(app.lock().get());
1994- if (it != config_map.end())
1995- {
1996- if (it->second == active_config)
1997- {
1998- apply_config(base_config);
1999- }
2000- config_map.erase(it);
2001- }
2002->>>>>>> MERGE-SOURCE
2003 }
2004
2005=== modified file 'src/server/shell/session_manager.cpp'
2006--- src/server/shell/session_manager.cpp 2013-08-13 22:17:09 +0000
2007+++ src/server/shell/session_manager.cpp 2013-08-13 22:17:10 +0000
2008@@ -18,7 +18,6 @@
2009
2010 #include "mir/shell/session_manager.h"
2011 #include "mir/shell/application_session.h"
2012-#include "mir/shell/display_changer.h"
2013 #include "mir/shell/session_container.h"
2014 #include "mir/shell/surface_factory.h"
2015 #include "mir/shell/focus_sequence.h"
2016@@ -36,18 +35,19 @@
2017
2018 msh::SessionManager::SessionManager(std::shared_ptr<msh::SurfaceFactory> const& surface_factory,
2019 std::shared_ptr<msh::SessionContainer> const& container,
2020+ std::shared_ptr<msh::FocusSequence> const& sequence,
2021 std::shared_ptr<msh::FocusSetter> const& focus_setter,
2022 std::shared_ptr<msh::SnapshotStrategy> const& snapshot_strategy,
2023- std::shared_ptr<msh::SessionListener> const& session_listener,
2024- std::shared_ptr<msh::DisplayChanger> const& display_changer) :
2025+ std::shared_ptr<msh::SessionListener> const& session_listener) :
2026 surface_factory(surface_factory),
2027 app_container(container),
2028+ focus_sequence(sequence),
2029 focus_setter(focus_setter),
2030 snapshot_strategy(snapshot_strategy),
2031- session_listener(session_listener),
2032- display_changer(display_changer)
2033+ session_listener(session_listener)
2034 {
2035 assert(surface_factory);
2036+ assert(sequence);
2037 assert(container);
2038 assert(focus_setter);
2039 assert(session_listener);
2040@@ -76,51 +76,92 @@
2041 std::shared_ptr<mf::Session> msh::SessionManager::open_session(std::string const& name,
2042 std::shared_ptr<mf::EventSink> const& sender)
2043 {
2044- auto new_session = std::make_shared<msh::ApplicationSession>(
2045+ std::shared_ptr<msh::Session> new_session =
2046+ std::make_shared<msh::ApplicationSession>(
2047 surface_factory, name, snapshot_strategy, session_listener, sender);
2048
2049 app_container->insert_session(new_session);
2050+
2051 session_listener->starting(new_session);
2052- focus_setter->session_opened(new_session);
2053+
2054+ set_focus_to(new_session);
2055
2056 return new_session;
2057 }
2058
2059+inline void msh::SessionManager::set_focus_to_locked(std::unique_lock<std::mutex> const&, std::shared_ptr<Session> const& shell_session)
2060+{
2061+ auto old_focus = focus_application.lock();
2062+
2063+ focus_application = shell_session;
2064+
2065+ focus_setter->set_focus_to(shell_session);
2066+ if (shell_session)
2067+ {
2068+ session_listener->focused(shell_session);
2069+ }
2070+ else
2071+ {
2072+ session_listener->unfocused();
2073+ }
2074+}
2075+
2076+void msh::SessionManager::set_focus_to(std::shared_ptr<Session> const& shell_session)
2077+{
2078+ std::unique_lock<std::mutex> lg(mutex);
2079+ set_focus_to_locked(lg, shell_session);
2080+}
2081
2082 void msh::SessionManager::close_session(std::shared_ptr<mf::Session> const& session)
2083 {
2084 auto shell_session = std::dynamic_pointer_cast<Session>(session);
2085
2086+ session_listener->stopping(shell_session);
2087+
2088 app_container->remove_session(shell_session);
2089
2090- session_listener->stopping(shell_session);
2091-
2092- focus_setter->session_closed(shell_session);
2093-}
2094-
2095-void msh::SessionManager::handle_display_configuration(std::shared_ptr<mf::Session> const& session)
2096-{
2097- auto shell_session = std::dynamic_pointer_cast<Session>(session);
2098- if (focus_setter->focused_session().lock() == session)
2099- {
2100- display_changer->apply_configuration_of(session);
2101- }
2102-}
2103-
2104-void msh::SessionManager::handle_surface_created(std::shared_ptr<mf::Session> const& session)
2105-{
2106- auto shell_session = std::dynamic_pointer_cast<Session>(session);
2107- focus_setter->surface_created_for(shell_session);
2108-}
2109-
2110-//TODO: this function is a kludge for not distributing a SessionMediator-like object to the internal clients.
2111-// we should have a the_internal_client_mediator() in the server configuration that would act as a factory
2112-// and mediator for internal clients, much like the mf::SessionMediator acts for ipc clients
2113+ std::unique_lock<std::mutex> lock(mutex);
2114+ set_focus_to_locked(lock, focus_sequence->default_focus());
2115+}
2116+
2117+void msh::SessionManager::focus_next()
2118+{
2119+ std::unique_lock<std::mutex> lock(mutex);
2120+ auto focus = focus_application.lock();
2121+ if (!focus)
2122+ {
2123+ focus = focus_sequence->default_focus();
2124+ }
2125+ else
2126+ {
2127+ focus = focus_sequence->successor_of(focus);
2128+ }
2129+ set_focus_to_locked(lock, focus);
2130+}
2131+
2132+std::weak_ptr<msh::Session> msh::SessionManager::focussed_application() const
2133+{
2134+ return focus_application;
2135+}
2136+
2137+// TODO: We use this to work around the lack of a SessionMediator-like object for internal clients.
2138+// we could have an internal client mediator which acts as a factory for internal clients, taking responsibility
2139+// for invoking handle_surface_created.
2140 mf::SurfaceId msh::SessionManager::create_surface_for(std::shared_ptr<mf::Session> const& session,
2141 msh::SurfaceCreationParameters const& params)
2142 {
2143 auto shell_session = std::dynamic_pointer_cast<Session>(session);
2144 auto id = shell_session->create_surface(params);
2145- handle_surface_created(shell_session);
2146+
2147+ handle_surface_created(session);
2148+
2149 return id;
2150 }
2151+
2152+void msh::SessionManager::handle_surface_created(std::shared_ptr<mf::Session> const& session)
2153+{
2154+ auto shell_session = std::dynamic_pointer_cast<Session>(session);
2155+
2156+ set_focus_to(shell_session);
2157+}
2158+
2159
2160=== modified file 'src/server/shell/surface.cpp'
2161--- src/server/shell/surface.cpp 2013-08-09 03:39:35 +0000
2162+++ src/server/shell/surface.cpp 2013-08-13 22:17:10 +0000
2163@@ -242,6 +242,9 @@
2164 BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface state."));
2165 result = state();
2166 break;
2167+ case mir_surface_attrib_focus:
2168+ notify_change(attrib, value);
2169+ break;
2170 case mir_surface_attrib_swapinterval:
2171 allow_dropping = (value == 0);
2172 allow_framedropping(allow_dropping);
2173@@ -267,7 +270,7 @@
2174 {
2175 bool valid = false;
2176
2177- if (t >= 0 && t < mir_surface_type_arraysize_)
2178+ if (t >= 0 && t < mir_surface_type_enum_max_)
2179 {
2180 type_value = t;
2181 valid = true;
2182@@ -286,7 +289,7 @@
2183 bool valid = false;
2184
2185 if (s > mir_surface_state_unknown &&
2186- s < mir_surface_state_arraysize_)
2187+ s < mir_surface_state_enum_max_)
2188 {
2189 state_value = s;
2190 valid = true;
2191
2192=== modified file 'src/server/shell/unauthorized_display_changer.cpp'
2193--- src/server/shell/unauthorized_display_changer.cpp 2013-08-13 22:17:09 +0000
2194+++ src/server/shell/unauthorized_display_changer.cpp 2013-08-12 17:20:29 +0000
2195@@ -33,17 +33,8 @@
2196 return changer->active_configuration();
2197 }
2198
2199-void msh::UnauthorizedDisplayChanger::store_configuration_for(
2200+void msh::UnauthorizedDisplayChanger::configure(
2201 std::weak_ptr<mf::Session> const&, std::shared_ptr<mg::DisplayConfiguration> const&)
2202 {
2203 BOOST_THROW_EXCEPTION(std::runtime_error("not authorized to apply display configurations"));
2204 }
2205-
2206-void msh::UnauthorizedDisplayChanger::apply_configuration_of(std::weak_ptr<mf::Session> const&)
2207-{
2208- BOOST_THROW_EXCEPTION(std::runtime_error("not authorized to apply display configurations"));
2209-}
2210-
2211-void msh::UnauthorizedDisplayChanger::remove_configuration_for(std::weak_ptr<mf::Session> const&)
2212-{
2213-}
2214
2215=== modified file 'src/shared/protobuf/mir_protobuf.proto'
2216--- src/shared/protobuf/mir_protobuf.proto 2013-08-12 08:58:59 +0000
2217+++ src/shared/protobuf/mir_protobuf.proto 2013-08-13 22:17:10 +0000
2218@@ -44,11 +44,6 @@
2219 optional string error = 127;
2220 }
2221
2222-message DisplayCard {
2223- required uint32 card_id = 1;
2224- required uint32 max_simultaneous_outputs = 2;
2225-}
2226-
2227 message DisplayMode {
2228 optional uint32 vertical_resolution = 1;
2229 optional uint32 horizontal_resolution = 2;
2230@@ -68,8 +63,6 @@
2231 optional uint32 used = 10;
2232 optional uint32 physical_width_mm = 11;
2233 optional uint32 physical_height_mm = 12;
2234- optional uint32 type = 13;
2235- optional uint32 preferred_mode = 14;
2236 }
2237
2238 // DEPRECATED
2239@@ -154,7 +147,6 @@
2240
2241 message DisplayConfiguration {
2242 repeated DisplayOutput display_output = 1;
2243- repeated DisplayCard display_card = 2;
2244 optional string error = 127;
2245 }
2246
2247
2248=== modified file 'tests/acceptance-tests/CMakeLists.txt'
2249--- tests/acceptance-tests/CMakeLists.txt 2013-08-08 02:34:31 +0000
2250+++ tests/acceptance-tests/CMakeLists.txt 2013-08-13 22:17:10 +0000
2251@@ -10,6 +10,7 @@
2252 test_test_framework.cpp
2253 test_focus_selection.cpp
2254 test_server_shutdown.cpp
2255+ test_client_focus_notification.cpp
2256 test_client_authorization.cpp
2257 test_shell_control_of_surface_configuration.cpp
2258 test_nested_mir.cpp
2259
2260=== added file 'tests/acceptance-tests/test_client_focus_notification.cpp'
2261--- tests/acceptance-tests/test_client_focus_notification.cpp 1970-01-01 00:00:00 +0000
2262+++ tests/acceptance-tests/test_client_focus_notification.cpp 2013-08-13 22:17:10 +0000
2263@@ -0,0 +1,231 @@
2264+/*
2265+ * Copyright © 2013 Canonical Ltd.
2266+ *
2267+ * This program is free software: you can redistribute it and/or modify
2268+ * it under the terms of the GNU General Public License version 3 as
2269+ * published by the Free Software Foundation.
2270+ *
2271+ * This program is distributed in the hope that it will be useful,
2272+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2273+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2274+ * GNU General Public License for more details.
2275+ *
2276+ * You should have received a copy of the GNU General Public License
2277+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2278+ *
2279+ * Authored by: Robert Carr <robert.carr@canonical.com>
2280+ */
2281+
2282+#include "mir_toolkit/mir_client_library.h"
2283+
2284+#include "mir_test/wait_condition.h"
2285+#include "mir_test/event_matchers.h"
2286+
2287+#include "mir_test_framework/display_server_test_fixture.h"
2288+#include "mir_test_framework/cross_process_sync.h"
2289+
2290+#include <gtest/gtest.h>
2291+#include <gmock/gmock.h>
2292+
2293+namespace mt = mir::test;
2294+namespace mtf = mir_test_framework;
2295+
2296+namespace
2297+{
2298+ char const* const mir_test_socket = mtf::test_socket_file().c_str();
2299+}
2300+
2301+namespace
2302+{
2303+struct ClientConfigCommon : TestingClientConfiguration
2304+{
2305+ ClientConfigCommon() :
2306+ connection(0),
2307+ surface(0)
2308+ {
2309+ }
2310+ static void connection_callback(MirConnection* connection, void* context)
2311+ {
2312+ ClientConfigCommon* config = reinterpret_cast<ClientConfigCommon *>(context);
2313+ config->connection = connection;
2314+ }
2315+ static void create_surface_callback(MirSurface* surface, void* context)
2316+ {
2317+ ClientConfigCommon* config = reinterpret_cast<ClientConfigCommon *>(context);
2318+ config->surface_created(surface);
2319+ }
2320+ static void release_surface_callback(MirSurface* surface, void* context)
2321+ {
2322+ ClientConfigCommon* config = reinterpret_cast<ClientConfigCommon *>(context);
2323+ config->surface_released(surface);
2324+ }
2325+ virtual void connected(MirConnection* new_connection)
2326+ {
2327+ connection = new_connection;
2328+ }
2329+ virtual void surface_created(MirSurface* new_surface)
2330+ {
2331+ surface = new_surface;
2332+ }
2333+ virtual void surface_released(MirSurface* /* released_surface */)
2334+ {
2335+ surface = nullptr;
2336+ }
2337+ MirConnection* connection;
2338+ MirSurface* surface;
2339+};
2340+
2341+struct MockEventObserver
2342+{
2343+ MOCK_METHOD1(see, void(MirEvent const*));
2344+};
2345+
2346+struct EventObservingClient : ClientConfigCommon
2347+{
2348+ EventObservingClient()
2349+ : observer(std::make_shared<MockEventObserver>())
2350+ {
2351+ }
2352+
2353+ static void handle_event(MirSurface* /* surface */, MirEvent const* ev, void* context)
2354+ {
2355+ auto client = static_cast<EventObservingClient *>(context);
2356+ client->observer->see(ev);
2357+ }
2358+
2359+ virtual void expect_events(mt::WaitCondition* /* all_events_received */) = 0;
2360+
2361+ void surface_created(MirSurface *surface_) override
2362+ {
2363+ // We need to set the event delegate from the surface_created
2364+ // callback so we can block the reading of new events
2365+ // until we are ready
2366+ MirEventDelegate const event_delegate =
2367+ {
2368+ handle_event,
2369+ this
2370+ };
2371+ surface = surface_;
2372+ mir_surface_set_event_handler(surface, &event_delegate);
2373+ }
2374+
2375+ void exec()
2376+ {
2377+ mt::WaitCondition all_events_received;
2378+ expect_events(&all_events_received);
2379+ mir_wait_for(mir_connect(mir_test_socket,
2380+ __PRETTY_FUNCTION__, connection_callback, this));
2381+ ASSERT_TRUE(connection != NULL);
2382+ MirSurfaceParameters const request_params =
2383+ {
2384+ __PRETTY_FUNCTION__,
2385+ surface_width, surface_height,
2386+ mir_pixel_format_abgr_8888,
2387+ mir_buffer_usage_hardware
2388+ };
2389+ mir_wait_for(mir_connection_create_surface(connection, &request_params, create_surface_callback, this));
2390+ all_events_received.wait_for_at_most_seconds(60);
2391+ mir_surface_release_sync(surface);
2392+ mir_connection_release(connection);
2393+
2394+ // The ClientConfig is not destroyed before the testing process
2395+ // exits.
2396+ observer.reset();
2397+ }
2398+ std::shared_ptr<MockEventObserver> observer;
2399+ static int const surface_width = 100;
2400+ static int const surface_height = 100;
2401+};
2402+
2403+}
2404+
2405+TEST_F(BespokeDisplayServerTestFixture, a_surface_is_notified_of_receiving_focus)
2406+{
2407+ using namespace ::testing;
2408+
2409+ TestingServerConfiguration server_config;
2410+ launch_server_process(server_config);
2411+
2412+ struct FocusObservingClient : public EventObservingClient
2413+ {
2414+ void expect_events(mt::WaitCondition* all_events_received) override
2415+ {
2416+ EXPECT_CALL(*observer, see(Pointee(mt::SurfaceEvent(mir_surface_attrib_focus, mir_surface_focused)))).Times(1)
2417+ .WillOnce(mt::WakeUp(all_events_received));
2418+ }
2419+ } client_config;
2420+ launch_client_process(client_config);
2421+}
2422+
2423+namespace
2424+{
2425+
2426+ACTION_P(SignalFence, fence)
2427+{
2428+ fence->try_signal_ready_for();
2429+}
2430+
2431+}
2432+
2433+TEST_F(BespokeDisplayServerTestFixture, two_surfaces_are_notified_of_gaining_and_losing_focus)
2434+{
2435+ using namespace ::testing;
2436+
2437+ TestingServerConfiguration server_config;
2438+ launch_server_process(server_config);
2439+
2440+ // We use this for synchronization to ensure the two clients
2441+ // are launched in a defined order.
2442+ mtf::CrossProcessSync ready_for_second_client;
2443+
2444+ struct FocusObservingClientOne : public EventObservingClient
2445+ {
2446+ mtf::CrossProcessSync ready_for_second_client;
2447+ FocusObservingClientOne(mtf::CrossProcessSync const& ready_for_second_client)
2448+ : ready_for_second_client(ready_for_second_client)
2449+ {
2450+ }
2451+
2452+ void expect_events(mt::WaitCondition* all_events_received) override
2453+ {
2454+ InSequence seq;
2455+ // We should receive focus as we are created
2456+ EXPECT_CALL(*observer, see(Pointee(mt::SurfaceEvent(mir_surface_attrib_focus,
2457+ mir_surface_focused)))).Times(1)
2458+ .WillOnce(SignalFence(&ready_for_second_client));
2459+
2460+ // And lose it as the second surface is created
2461+ EXPECT_CALL(*observer, see(Pointee(mt::SurfaceEvent(mir_surface_attrib_focus,
2462+ mir_surface_unfocused)))).Times(1);
2463+ // And regain it when the second surface is closed
2464+ EXPECT_CALL(*observer, see(Pointee(mt::SurfaceEvent(mir_surface_attrib_focus,
2465+ mir_surface_focused)))).Times(1).WillOnce(mt::WakeUp(all_events_received));
2466+ }
2467+
2468+ } client_one_config(ready_for_second_client);
2469+ launch_client_process(client_one_config);
2470+
2471+ struct FocusObservingClientTwo : public EventObservingClient
2472+ {
2473+ mtf::CrossProcessSync ready_for_second_client;
2474+ FocusObservingClientTwo(mtf::CrossProcessSync const& ready_for_second_client)
2475+ : ready_for_second_client(ready_for_second_client)
2476+ {
2477+ }
2478+ void exec() override
2479+ {
2480+ // We need some synchronization to ensure client two does not connect before client one.
2481+ ready_for_second_client.wait_for_signal_ready_for();
2482+ EventObservingClient::exec();
2483+ }
2484+
2485+ void expect_events(mt::WaitCondition* all_events_received) override
2486+ {
2487+ EXPECT_CALL(*observer, see(Pointee(
2488+ mt::SurfaceEvent(mir_surface_attrib_focus, mir_surface_focused))))
2489+ .Times(1).WillOnce(mt::WakeUp(all_events_received));
2490+ }
2491+ } client_two_config(ready_for_second_client);
2492+
2493+ launch_client_process(client_two_config);
2494+}
2495
2496=== modified file 'tests/acceptance-tests/test_client_input.cpp'
2497--- tests/acceptance-tests/test_client_input.cpp 2013-08-13 22:17:09 +0000
2498+++ tests/acceptance-tests/test_client_input.cpp 2013-08-13 22:17:10 +0000
2499@@ -149,12 +149,15 @@
2500 {
2501 std::cout << e.what() << std::endl;
2502 }
2503+
2504 }
2505
2506 static void handle_input(MirSurface* /* surface */, MirEvent const* ev, void* context)
2507 {
2508+ if (ev->type == mir_event_type_surface)
2509+ return;
2510+
2511 auto client = static_cast<InputClient *>(context);
2512-
2513 client->handler->handle_input(ev);
2514 }
2515
2516@@ -889,7 +892,6 @@
2517 fake_event_hub->synthesize_event(mis::a_motion_event().with_movement(1,1));
2518 }
2519 } server_config{fence, second_client_done_fence};
2520-
2521 launch_server_process(server_config);
2522
2523 struct ButtonClientOne : InputClient
2524@@ -899,10 +901,6 @@
2525 {
2526 }
2527
2528- void exec()
2529- {
2530- InputClient::exec();
2531- }
2532 void expect_input(mt::WaitCondition& events_received) override
2533 {
2534 EXPECT_CALL(*handler, handle_input(HoverEnterEvent())).Times(AnyNumber());
2535
2536=== modified file 'tests/acceptance-tests/test_focus_selection.cpp'
2537--- tests/acceptance-tests/test_focus_selection.cpp 2013-08-13 22:17:09 +0000
2538+++ tests/acceptance-tests/test_focus_selection.cpp 2013-08-13 22:17:10 +0000
2539@@ -38,6 +38,7 @@
2540 namespace mi = mir::input;
2541 namespace mt = mir::test;
2542 namespace mtd = mt::doubles;
2543+namespace mt = mir::test;
2544 namespace mtf = mir_test_framework;
2545
2546 namespace
2547@@ -117,6 +118,14 @@
2548
2549 }
2550
2551+namespace
2552+{
2553+MATCHER(NonNullSession, "")
2554+{
2555+ return arg != std::shared_ptr<msh::Session>();
2556+}
2557+}
2558+
2559 TEST_F(BespokeDisplayServerTestFixture, sessions_creating_surface_receive_focus)
2560 {
2561 struct ServerConfig : TestingServerConfiguration
2562@@ -131,14 +140,11 @@
2563
2564 auto focus_setter = std::make_shared<mtd::MockFocusSetter>();
2565 {
2566- Sequence seq;
2567-
2568- EXPECT_CALL(*focus_setter, session_opened(_))
2569- .InSequence(seq);
2570- EXPECT_CALL(*focus_setter, surface_created_for(_))
2571- .InSequence(seq);
2572- EXPECT_CALL(*focus_setter, session_closed(_))
2573- .InSequence(seq);
2574+ InSequence seq;
2575+ // Once on application registration and once on surface creation
2576+ EXPECT_CALL(*focus_setter, set_focus_to(NonNullSession())).Times(2);
2577+ // Focus is cleared when the session is closed
2578+ EXPECT_CALL(*focus_setter, set_focus_to(_)).Times(1);
2579 }
2580 // TODO: Counterexample ~racarr
2581
2582@@ -174,17 +180,14 @@
2583
2584 if (!expected)
2585 {
2586- Sequence seq;
2587- //connect session
2588- EXPECT_CALL(*targeter, focus_cleared())
2589- .InSequence(seq);
2590- //session has a default surface
2591- EXPECT_CALL(*targeter, focus_changed(_))
2592- .InSequence(seq);
2593- //session is destroyed
2594- EXPECT_CALL(*targeter, focus_cleared())
2595- .InSequence(seq);
2596- expected = true;
2597+
2598+ EXPECT_CALL(*targeter, focus_cleared()).Times(AtLeast(0));
2599+
2600+ {
2601+ InSequence seq;
2602+ EXPECT_CALL(*targeter, focus_changed(_)).Times(1);
2603+ expected = true;
2604+ }
2605 }
2606
2607 return targeter;
2608
2609=== modified file 'tests/acceptance-tests/test_shell_control_of_surface_configuration.cpp'
2610--- tests/acceptance-tests/test_shell_control_of_surface_configuration.cpp 2013-07-31 22:17:06 +0000
2611+++ tests/acceptance-tests/test_shell_control_of_surface_configuration.cpp 2013-08-13 22:17:10 +0000
2612@@ -81,6 +81,9 @@
2613 void exec() override
2614 {
2615 using namespace ::testing;
2616+
2617+ EXPECT_CALL(mock_configurator, select_attribute_value(_, mir_surface_attrib_focus, _)).Times(AnyNumber());
2618+ EXPECT_CALL(mock_configurator, attribute_set(_, mir_surface_attrib_focus, _)).Times(AnyNumber());
2619
2620 ON_CALL(mock_configurator, select_attribute_value(_, _, _)).WillByDefault(Return(mir_surface_type_freestyle));
2621 EXPECT_CALL(mock_configurator, select_attribute_value(_, mir_surface_attrib_type, Eq(mir_surface_type_freestyle))).Times(1);
2622@@ -116,6 +119,10 @@
2623 void exec() override
2624 {
2625 using namespace ::testing;
2626+
2627+ EXPECT_CALL(mock_configurator, select_attribute_value(_, mir_surface_attrib_focus, _)).Times(AnyNumber());
2628+ EXPECT_CALL(mock_configurator, attribute_set(_, mir_surface_attrib_focus, _)).Times(AnyNumber());
2629+
2630 EXPECT_CALL(mock_configurator, select_attribute_value(_, mir_surface_attrib_type, Eq(mir_surface_type_freestyle))).Times(1)
2631 .WillOnce(Return(mir_surface_type_normal));
2632 EXPECT_CALL(mock_configurator, attribute_set(_, mir_surface_attrib_type, Eq(mir_surface_type_normal))).Times(1);
2633
2634=== modified file 'tests/integration-tests/CMakeLists.txt'
2635--- tests/integration-tests/CMakeLists.txt 2013-08-12 08:58:58 +0000
2636+++ tests/integration-tests/CMakeLists.txt 2013-08-13 22:17:10 +0000
2637@@ -8,7 +8,6 @@
2638 test_display_server_main_loop_events.cpp
2639 test_surface_first_frame_sync.cpp
2640 test_swapinterval.cpp
2641- test_server_client_types.cpp
2642 )
2643
2644 add_subdirectory(client/)
2645
2646=== modified file 'tests/integration-tests/shell/CMakeLists.txt'
2647--- tests/integration-tests/shell/CMakeLists.txt 2013-08-13 22:17:09 +0000
2648+++ tests/integration-tests/shell/CMakeLists.txt 2013-06-25 15:20:05 +0000
2649@@ -1,6 +1,6 @@
2650 list(
2651 APPEND INTEGRATION_TESTS_SRCS
2652-# ${CMAKE_CURRENT_SOURCE_DIR}/test_session_manager.cpp
2653+ ${CMAKE_CURRENT_SOURCE_DIR}/test_session_manager.cpp
2654 ${CMAKE_CURRENT_SOURCE_DIR}/test_session.cpp
2655 )
2656
2657
2658=== modified file 'tests/integration-tests/test_display_info.cpp'
2659--- tests/integration-tests/test_display_info.cpp 2013-08-13 22:17:09 +0000
2660+++ tests/integration-tests/test_display_info.cpp 2013-08-12 17:20:29 +0000
2661@@ -25,7 +25,6 @@
2662 #include "mir/frontend/session_mediator.h"
2663 #include "mir/frontend/global_event_sender.h"
2664
2665-#include "mir_test_framework/cross_process_sync.h"
2666 #include "mir_test_framework/display_server_test_fixture.h"
2667 #include "mir_test_framework/cross_process_sync.h"
2668 #include "mir_test_doubles/stub_buffer.h"
2669@@ -298,12 +297,13 @@
2670 launch_client_process(client_config);
2671 }
2672
2673+
2674 namespace
2675 {
2676 class EventSinkSkimmingIpcFactory : public mf::ProtobufIpcFactory
2677 {
2678 public:
2679- explicit EventSinkSkimmingIpcFactory(
2680+ EventSinkSkimmingIpcFactory(
2681 std::shared_ptr<mf::Shell> const& shell,
2682 std::shared_ptr<mf::SessionMediatorReport> const& sm_report,
2683 std::shared_ptr<mf::MessageProcessorReport> const& mr_report,
2684@@ -321,10 +321,11 @@
2685 {
2686 }
2687
2688- void last_clients_event_sink()
2689+ std::shared_ptr<mf::EventSink> last_clients_event_sink()
2690 {
2691- last_event_sink.lock()->handle_display_config_change(StubChanger::stub_display_config);
2692+ return std::move(last_event_sink);
2693 }
2694+
2695 private:
2696 std::shared_ptr<mf::Shell> shell;
2697 std::shared_ptr<mf::SessionMediatorReport> const sm_report;
2698@@ -333,7 +334,7 @@
2699 std::shared_ptr<mg::Platform> const graphics_platform;
2700 std::shared_ptr<mf::DisplayChanger> const graphics_changer;
2701 std::shared_ptr<mg::GraphicBufferAllocator> const buffer_allocator;
2702- std::weak_ptr<mf::EventSink> last_event_sink;
2703+ std::shared_ptr<mf::EventSink> last_event_sink;
2704
2705 virtual std::shared_ptr<mir::protobuf::DisplayServer> make_ipc_server(
2706 std::shared_ptr<mf::EventSink> const& sink, bool)
2707@@ -358,86 +359,12 @@
2708 {
2709 return mp_report;
2710 }
2711-};
2712-
2713-class ConfigureNotifyingDisplay : public mtd::NullDisplay
2714-{
2715-public:
2716- ConfigureNotifyingDisplay(mtf::CrossProcessSync const& configure_fence)
2717- : configure_fence(configure_fence)
2718- {
2719- }
2720-
2721- std::shared_ptr<mg::DisplayConfiguration> configuration() override
2722- {
2723- return std::make_shared<mtd::StubDisplayConfig>();
2724- }
2725-
2726- void for_each_display_buffer(std::function<void(mg::DisplayBuffer&)> const& f) override
2727- {
2728- f(display_buffer);
2729- }
2730-
2731- void configure(mg::DisplayConfiguration const&) override
2732- {
2733- configure_fence.try_signal_ready_for(std::chrono::milliseconds(1000));
2734- }
2735-private:
2736- mtd::NullDisplayBuffer display_buffer;
2737- mtf::CrossProcessSync configure_fence;
2738+
2739 };
2740
2741 mtd::StubDisplayConfig changed_stub_display_config{1};
2742 }
2743
2744-TEST_F(BespokeDisplayServerTestFixture, display_change_request_for_authorized_client)
2745-{
2746- mtf::CrossProcessSync server_configure_fence;
2747-
2748- struct ServerConfig : TestingServerConfiguration
2749- {
2750- ServerConfig(mtf::CrossProcessSync const& fence)
2751- : configure_fence(fence)
2752- {
2753- }
2754-
2755- std::shared_ptr<mg::Display> the_display()
2756- {
2757- if (!display)
2758- display = std::make_shared<ConfigureNotifyingDisplay>(configure_fence);
2759- return display;
2760- }
2761-
2762- std::shared_ptr<ConfigureNotifyingDisplay> display;
2763- mtf::CrossProcessSync configure_fence;
2764-
2765- } server_config(server_configure_fence);
2766-
2767- launch_server_process(server_config);
2768-
2769- struct Client : TestingClientConfiguration
2770- {
2771- void exec()
2772- {
2773- auto connection = mir_connect_sync(mir_test_socket, __PRETTY_FUNCTION__);
2774- auto configuration = mir_connection_create_display_config(connection);
2775-
2776- mir_wait_for(mir_connection_apply_display_config(connection, configuration));
2777- EXPECT_STREQ(mir_connection_get_error_message(connection), "");
2778- mir_display_config_destroy(configuration);
2779-
2780- mir_connection_release(connection);
2781- }
2782- } client_config;
2783-
2784- launch_client_process(client_config);
2785-
2786- run_in_test_process([&]
2787- {
2788- server_configure_fence.wait_for_signal_ready_for(std::chrono::milliseconds(1000));
2789- });
2790-}
2791-
2792 TEST_F(BespokeDisplayServerTestFixture, display_change_notification_reaches_all_clients)
2793 {
2794 mtf::CrossProcessSync client_ready_fence;
2795@@ -462,31 +389,12 @@
2796 return platform;
2797 }
2798
2799- std::shared_ptr<mir::frontend::ProtobufIpcFactory> the_ipc_factory(
2800- std::shared_ptr<mf::Shell> const& shell,
2801- std::shared_ptr<mg::GraphicBufferAllocator> const& allocator) override
2802- {
2803- return ipc_factory([&]() {
2804- return std::make_shared<EventSinkSkimmingIpcFactory>(
2805- shell,
2806- the_session_mediator_report(),
2807- the_message_processor_report(),
2808- the_graphics_platform(),
2809- the_shell_display_changer(), allocator); });
2810- }
2811-
2812 void exec() override
2813 {
2814 change_thread = std::move(std::thread([this](){
2815 auto global_sender = the_global_event_sink();
2816
2817 send_event_fence.wait_for_signal_ready_for(std::chrono::milliseconds(1000));
2818- auto factory = ipc_factory([&]() { return nullptr; });
2819- if (factory)
2820- {
2821- factory->last_clients_event_sink();
2822- }
2823-
2824 global_sender->handle_display_config_change(changed_stub_display_config);
2825 events_sent.try_signal_ready_for(std::chrono::milliseconds(1000));
2826 }));
2827@@ -498,7 +406,6 @@
2828 }
2829
2830 mtf::CrossProcessSync send_event_fence;
2831- mir::CachedPtr<EventSinkSkimmingIpcFactory> ipc_factory;
2832 mtf::CrossProcessSync events_sent;
2833 std::shared_ptr<StubPlatform> platform;
2834 std::thread change_thread;
2835@@ -539,13 +446,12 @@
2836
2837 client_ready_fence.try_signal_ready_for(std::chrono::milliseconds(1000));
2838
2839- // while(!callback_called)
2840- // {
2841- // callback_wait.wait(lk);
2842- // }
2843+ while(!callback_called)
2844+ {
2845+ callback_wait.wait(lk);
2846+ }
2847
2848 mir_connection_release(connection);
2849- client_ready_fence.try_signal_ready_for(std::chrono::milliseconds(1000));
2850 }
2851
2852 mtf::CrossProcessSync client_ready_fence;
2853@@ -610,7 +516,7 @@
2854 unsubscribed_client_ready_fence.wait_for_signal_ready_for(std::chrono::milliseconds(1000));
2855
2856 send_event_fence.try_signal_ready_for(std::chrono::milliseconds(1000));
2857- client_ready_fence.wait_for_signal_ready_for(std::chrono::milliseconds(1000));
2858+ events_all_sent.wait_for_signal_ready_for(std::chrono::milliseconds(1000));
2859
2860 unsubscribed_check_fence.try_signal_ready_for(std::chrono::milliseconds(1000));
2861 });
2862
2863=== removed file 'tests/integration-tests/test_server_client_types.cpp'
2864--- tests/integration-tests/test_server_client_types.cpp 2013-08-12 08:58:58 +0000
2865+++ tests/integration-tests/test_server_client_types.cpp 1970-01-01 00:00:00 +0000
2866@@ -1,46 +0,0 @@
2867-/*
2868- * Copyright © 2013 Canonical Ltd.
2869- *
2870- * This program is free software: you can redistribute it and/or modify
2871- * it under the terms of the GNU General Public License version 3 as
2872- * published by the Free Software Foundation.
2873- *
2874- * This program is distributed in the hope that it will be useful,
2875- * but WITHOUT ANY WARRANTY; without even the implied warranty of
2876- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2877- * GNU General Public License for more details.
2878- *
2879- * You should have received a copy of the GNU General Public License
2880- * along with this program. If not, see <http://www.gnu.org/licenses/>.
2881- *
2882- * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
2883- */
2884-
2885-#include "mir_toolkit/client_types.h"
2886-#include "mir/graphics/display_configuration.h"
2887-
2888-#include <gtest/gtest.h>
2889-
2890-namespace mg = mir::graphics;
2891-
2892-#define EXPECT_DISPLAY_OUTPUT_TYPES_MATCH(TYPE) \
2893- EXPECT_EQ(static_cast<mg::DisplayConfigurationOutputType>(mir_display_output_type_##TYPE), \
2894- mg::DisplayConfigurationOutputType::TYPE)
2895-
2896-TEST(ServerClientTypes, display_output_types_match)
2897-{
2898- EXPECT_DISPLAY_OUTPUT_TYPES_MATCH(unknown);
2899- EXPECT_DISPLAY_OUTPUT_TYPES_MATCH(vga);
2900- EXPECT_DISPLAY_OUTPUT_TYPES_MATCH(dvid);
2901- EXPECT_DISPLAY_OUTPUT_TYPES_MATCH(dvia);
2902- EXPECT_DISPLAY_OUTPUT_TYPES_MATCH(composite);
2903- EXPECT_DISPLAY_OUTPUT_TYPES_MATCH(svideo);
2904- EXPECT_DISPLAY_OUTPUT_TYPES_MATCH(lvds);
2905- EXPECT_DISPLAY_OUTPUT_TYPES_MATCH(component);
2906- EXPECT_DISPLAY_OUTPUT_TYPES_MATCH(ninepindin);
2907- EXPECT_DISPLAY_OUTPUT_TYPES_MATCH(displayport);
2908- EXPECT_DISPLAY_OUTPUT_TYPES_MATCH(hdmia);
2909- EXPECT_DISPLAY_OUTPUT_TYPES_MATCH(hdmib);
2910- EXPECT_DISPLAY_OUTPUT_TYPES_MATCH(tv);
2911- EXPECT_DISPLAY_OUTPUT_TYPES_MATCH(edp);
2912-}
2913
2914=== modified file 'tests/mir_test/display_config_matchers.cpp'
2915--- tests/mir_test/display_config_matchers.cpp 2013-08-12 11:40:45 +0000
2916+++ tests/mir_test/display_config_matchers.cpp 2013-08-13 22:17:10 +0000
2917@@ -35,20 +35,6 @@
2918 public:
2919 TestDisplayConfiguration(mp::DisplayConfiguration const& protobuf_config)
2920 {
2921- /* Cards */
2922- for (int i = 0; i < protobuf_config.display_card_size(); i++)
2923- {
2924- auto const& protobuf_card = protobuf_config.display_card(i);
2925- mg::DisplayConfigurationCard display_card
2926- {
2927- mg::DisplayConfigurationCardId(protobuf_card.card_id()),
2928- protobuf_card.max_simultaneous_outputs(),
2929- };
2930-
2931- cards.push_back(display_card);
2932- }
2933-
2934- /* Outputs */
2935 for (int i = 0; i < protobuf_config.display_output_size(); i++)
2936 {
2937 auto const& protobuf_output = protobuf_config.display_output(i);
2938@@ -56,10 +42,8 @@
2939 {
2940 mg::DisplayConfigurationOutputId(protobuf_output.output_id()),
2941 mg::DisplayConfigurationCardId(protobuf_output.card_id()),
2942- static_cast<mg::DisplayConfigurationOutputType>(protobuf_output.type()),
2943- {},
2944- {},
2945- protobuf_output.preferred_mode(),
2946+ {},
2947+ {},
2948 geom::Size{protobuf_output.physical_width_mm(),
2949 protobuf_output.physical_height_mm()},
2950 static_cast<bool>(protobuf_output.connected()),
2951@@ -99,20 +83,6 @@
2952
2953 TestDisplayConfiguration(MirDisplayConfiguration const& client_config)
2954 {
2955- /* Cards */
2956- for (size_t i = 0; i < client_config.num_cards; i++)
2957- {
2958- auto const& client_card = client_config.cards[i];
2959- mg::DisplayConfigurationCard display_card
2960- {
2961- mg::DisplayConfigurationCardId(client_card.card_id),
2962- client_card.max_simultaneous_outputs,
2963- };
2964-
2965- cards.push_back(display_card);
2966- }
2967-
2968- /* Outputs */
2969 for (size_t i = 0; i < client_config.num_displays; i++)
2970 {
2971 auto const& client_output = client_config.displays[i];
2972@@ -120,10 +90,8 @@
2973 {
2974 mg::DisplayConfigurationOutputId(client_output.output_id),
2975 mg::DisplayConfigurationCardId(client_output.card_id),
2976- static_cast<mg::DisplayConfigurationOutputType>(client_output.type),
2977- {},
2978- {},
2979- client_output.preferred_mode,
2980+ {},
2981+ {},
2982 geom::Size{client_output.physical_width_mm,
2983 client_output.physical_height_mm},
2984 static_cast<bool>(client_output.connected),
2985@@ -161,10 +129,8 @@
2986 }
2987 }
2988
2989- void for_each_card(std::function<void(mg::DisplayConfigurationCard const&)> f) const
2990+ void for_each_card(std::function<void(mg::DisplayConfigurationCard const&)>) const
2991 {
2992- for (auto const& card : cards)
2993- f(card);
2994 }
2995
2996 void for_each_output(std::function<void(mg::DisplayConfigurationOutput const&)> f) const
2997@@ -179,48 +145,12 @@
2998 }
2999
3000 private:
3001- std::vector<mg::DisplayConfigurationCard> cards;
3002 std::vector<mg::DisplayConfigurationOutput> outputs;
3003 };
3004
3005 bool compare_display_configurations(mg::DisplayConfiguration const& config1,
3006 mg::DisplayConfiguration const& config2)
3007 {
3008- bool result = true;
3009-
3010- /* cards */
3011- std::vector<mg::DisplayConfigurationCard> cards1;
3012- std::vector<mg::DisplayConfigurationCard> cards2;
3013-
3014- config1.for_each_card(
3015- [&cards1](mg::DisplayConfigurationCard const& card)
3016- {
3017- cards1.push_back(card);
3018- });
3019- config2.for_each_card(
3020- [&cards2](mg::DisplayConfigurationCard const& card)
3021- {
3022- cards2.push_back(card);
3023- });
3024-
3025- if (cards1.size() == cards2.size())
3026- {
3027- for (size_t i = 0; i < cards1.size(); i++)
3028- {
3029- if (cards1[i] != cards2[i])
3030- {
3031- EXPECT_EQ(cards1[i], cards2[i]);
3032- result = false;
3033- }
3034- }
3035- }
3036- else
3037- {
3038- EXPECT_EQ(cards1.size(), cards2.size());
3039- result = false;
3040- }
3041-
3042- /* Outputs */
3043 std::vector<mg::DisplayConfigurationOutput> outputs1;
3044 std::vector<mg::DisplayConfigurationOutput> outputs2;
3045
3046@@ -235,21 +165,21 @@
3047 outputs2.push_back(output);
3048 });
3049
3050- if (outputs1.size() == outputs2.size())
3051- {
3052- for (size_t i = 0; i < outputs1.size(); i++)
3053- {
3054- if (outputs1[i] != outputs2[i])
3055- {
3056- EXPECT_EQ(outputs1[i], outputs2[i]);
3057- result = false;
3058- }
3059- }
3060- }
3061- else
3062+ if (outputs1.size() != outputs2.size())
3063 {
3064 EXPECT_EQ(outputs1.size(), outputs2.size());
3065- result = false;
3066+ return false;
3067+ }
3068+
3069+ bool result = true;
3070+
3071+ for (size_t i = 0; i < outputs1.size(); i++)
3072+ {
3073+ if (outputs1[i] != outputs2[i])
3074+ {
3075+ EXPECT_EQ(outputs1[i], outputs2[i]);
3076+ result = false;
3077+ }
3078 }
3079
3080 return result;
3081
3082=== modified file 'tests/mir_test_doubles/mock_drm.cpp'
3083--- tests/mir_test_doubles/mock_drm.cpp 2013-08-12 08:58:58 +0000
3084+++ tests/mir_test_doubles/mock_drm.cpp 2013-08-13 22:17:10 +0000
3085@@ -50,8 +50,8 @@
3086 uint32_t const connector1_id{31};
3087 uint32_t const all_crtcs_mask{0x3};
3088
3089- modes.push_back(create_mode(1920, 1080, 138500, 2080, 1111, PreferredMode));
3090- modes.push_back(create_mode(832, 624, 57284, 1152, 667, NormalMode));
3091+ modes.push_back(create_mode(1920, 1080, 138500, 2080, 1111));
3092+ modes.push_back(create_mode(832, 624, 57284, 1152, 667));
3093 connector_encoder_ids.push_back(encoder0_id);
3094 connector_encoder_ids.push_back(encoder1_id);
3095
3096@@ -61,11 +61,9 @@
3097 add_encoder(encoder0_id, invalid_id, all_crtcs_mask);
3098 add_encoder(encoder1_id, crtc1_id, all_crtcs_mask);
3099
3100- add_connector(connector0_id, DRM_MODE_CONNECTOR_VGA,
3101- DRM_MODE_DISCONNECTED, invalid_id,
3102+ add_connector(connector0_id, DRM_MODE_DISCONNECTED, invalid_id,
3103 modes_empty, connector_encoder_ids, geom::Size());
3104- add_connector(connector1_id, DRM_MODE_CONNECTOR_DVID,
3105- DRM_MODE_CONNECTED, encoder1_id,
3106+ add_connector(connector1_id, DRM_MODE_CONNECTED, encoder1_id,
3107 modes, connector_encoder_ids,
3108 geom::Size{121, 144});
3109
3110@@ -150,7 +148,6 @@
3111 }
3112
3113 void mgg::FakeDRMResources::add_connector(uint32_t connector_id,
3114- uint32_t type,
3115 drmModeConnection connection,
3116 uint32_t encoder_id,
3117 std::vector<drmModeModeInfo>& modes,
3118@@ -160,7 +157,6 @@
3119 drmModeConnector connector = drmModeConnector();
3120
3121 connector.connector_id = connector_id;
3122- connector.connector_type = type;
3123 connector.connection = connection;
3124 connector.encoder_id = encoder_id;
3125 connector.modes = modes.data();
3126@@ -206,8 +202,7 @@
3127
3128 drmModeModeInfo mgg::FakeDRMResources::create_mode(uint16_t hdisplay, uint16_t vdisplay,
3129 uint32_t clock, uint16_t htotal,
3130- uint16_t vtotal,
3131- ModePreference preferred)
3132+ uint16_t vtotal)
3133 {
3134 drmModeModeInfo mode = drmModeModeInfo();
3135
3136@@ -216,8 +211,6 @@
3137 mode.clock = clock;
3138 mode.htotal = htotal;
3139 mode.vtotal = vtotal;
3140- if (preferred)
3141- mode.type |= DRM_MODE_TYPE_PREFERRED;
3142
3143 return mode;
3144 }
3145
3146=== modified file 'tests/mir_test_framework/input_testing_server_options.cpp'
3147--- tests/mir_test_framework/input_testing_server_options.cpp 2013-08-07 07:18:03 +0000
3148+++ tests/mir_test_framework/input_testing_server_options.cpp 2013-08-13 22:17:10 +0000
3149@@ -21,6 +21,9 @@
3150 #include "mir/input/input_channel.h"
3151 #include "mir/surfaces/input_registrar.h"
3152 #include "mir/input/surface.h"
3153+#include "mir/shell/surface_creation_parameters.h"
3154+#include "mir/frontend/shell.h"
3155+#include "mir/frontend/session.h"
3156 #include "mir/input/composite_event_filter.h"
3157
3158 #include "mir_test/fake_event_hub.h"
3159@@ -34,6 +37,8 @@
3160 namespace mtf = mir_test_framework;
3161
3162 namespace ms = mir::surfaces;
3163+namespace msh = mir::shell;
3164+namespace mf = mir::frontend;
3165 namespace mg = mir::graphics;
3166 namespace mi = mir::input;
3167 namespace mia = mi::android;
3168@@ -48,7 +53,6 @@
3169 virtual ~SurfaceReadinessListener() = default;
3170
3171 virtual void channel_ready_for_input(std::string const& channel_name) = 0;
3172- virtual void channel_finished_for_input(std::string const& channel_name) = 0;
3173
3174 protected:
3175 SurfaceReadinessListener() = default;
3176@@ -56,36 +60,43 @@
3177 SurfaceReadinessListener& operator=(SurfaceReadinessListener const&) = delete;
3178 };
3179
3180-class ProxyInputRegistrar : public ms::InputRegistrar
3181+class ProxyShell : public mf::Shell
3182 {
3183 public:
3184- ProxyInputRegistrar(std::shared_ptr<ms::InputRegistrar> const underlying_registrar,
3185- std::shared_ptr<SurfaceReadinessListener> const listener)
3186- : underlying_registrar(underlying_registrar),
3187+ ProxyShell(std::shared_ptr<mf::Shell> const& underlying_shell,
3188+ std::shared_ptr<SurfaceReadinessListener> const listener)
3189+ : underlying_shell(underlying_shell),
3190 listener(listener)
3191 {
3192 }
3193
3194- ~ProxyInputRegistrar() noexcept(true) = default;
3195-
3196- void input_channel_opened(std::shared_ptr<mi::InputChannel> const& opened_channel,
3197- std::shared_ptr<mi::Surface> const& surface,
3198- mi::InputReceptionMode input_mode)
3199- {
3200- outstanding_channels[opened_channel] = surface->name();
3201- underlying_registrar->input_channel_opened(opened_channel, surface, input_mode);
3202- listener->channel_ready_for_input(surface->name());
3203- }
3204- void input_channel_closed(std::shared_ptr<mi::InputChannel> const& closed_channel)
3205- {
3206- auto channel = outstanding_channels[closed_channel];
3207- underlying_registrar->input_channel_closed(closed_channel);
3208- listener->channel_finished_for_input(channel);
3209+ ~ProxyShell() noexcept(true) = default;
3210+
3211+ mf::SurfaceId create_surface_for(std::shared_ptr<mf::Session> const& session,
3212+ msh::SurfaceCreationParameters const& params)
3213+ {
3214+ return underlying_shell->create_surface_for(session, params);
3215+ }
3216+
3217+ std::shared_ptr<mf::Session> open_session(std::string const& name,
3218+ std::shared_ptr<mf::EventSink> const& sink)
3219+ {
3220+ return underlying_shell->open_session(name, sink);
3221+ }
3222+
3223+ void close_session(std::shared_ptr<mf::Session> const& session)
3224+ {
3225+ underlying_shell->close_session(session);
3226+ }
3227+
3228+ void handle_surface_created(std::shared_ptr<mf::Session> const& session)
3229+ {
3230+ underlying_shell->handle_surface_created(session);
3231+ listener->channel_ready_for_input(session->name());
3232 }
3233
3234 private:
3235- std::map<std::shared_ptr<mi::InputChannel>, std::string> outstanding_channels;
3236- std::shared_ptr<ms::InputRegistrar> const underlying_registrar;
3237+ std::shared_ptr<mf::Shell> const underlying_shell;
3238 std::shared_ptr<SurfaceReadinessListener> const listener;
3239 };
3240
3241@@ -126,7 +137,7 @@
3242 return input_configuration;
3243 }
3244
3245-std::shared_ptr<ms::InputRegistrar> mtf::InputTestingServerConfiguration::the_input_registrar()
3246+std::shared_ptr<mf::Shell> mtf::InputTestingServerConfiguration::the_frontend_shell()
3247 {
3248 struct LifecycleTracker : public SurfaceReadinessListener
3249 {
3250@@ -145,27 +156,20 @@
3251 lifecycle_condition.notify_all();
3252 }
3253
3254- void channel_finished_for_input(std::string const& channel_name)
3255- {
3256- std::unique_lock<std::mutex> lg(lifecycle_lock);
3257- client_lifecycles[channel_name] = mtf::ClientLifecycleState::vanished;
3258- lifecycle_condition.notify_all();
3259- }
3260 std::mutex &lifecycle_lock;
3261 std::condition_variable &lifecycle_condition;
3262 std::map<std::string, mtf::ClientLifecycleState> &client_lifecycles;
3263 };
3264
3265- if (!input_registrar)
3266+ if (!frontend_shell)
3267 {
3268- auto registrar_listener = std::make_shared<LifecycleTracker>(lifecycle_lock,
3269+ auto readiness_listener = std::make_shared<LifecycleTracker>(lifecycle_lock,
3270 lifecycle_condition,
3271 client_lifecycles);
3272- input_registrar = std::make_shared<ProxyInputRegistrar>(the_input_configuration()->the_input_registrar(),
3273- registrar_listener);
3274+ frontend_shell = std::make_shared<ProxyShell>(DefaultServerConfiguration::the_frontend_shell(), readiness_listener);
3275 }
3276
3277- return input_registrar;
3278+ return frontend_shell;
3279 }
3280
3281 void mtf::InputTestingServerConfiguration::wait_until_client_appears(std::string const& channel_name)
3282@@ -185,22 +189,3 @@
3283 BOOST_THROW_EXCEPTION(std::runtime_error("Timed out waiting for client (" + channel_name + ") to appear"));
3284 }
3285 }
3286-
3287-void mtf::InputTestingServerConfiguration::wait_until_client_vanishes(std::string const& channel_name)
3288-{
3289- std::unique_lock<std::mutex> lg(lifecycle_lock);
3290-
3291- std::chrono::seconds timeout(60);
3292- auto end_time = std::chrono::system_clock::now() + timeout;
3293-
3294-
3295- if (client_lifecycles[channel_name] == appeared)
3296- {
3297- BOOST_THROW_EXCEPTION(std::runtime_error("Waiting for a client (" + channel_name + ") to vanish but it has already appeared"));
3298- }
3299- while (client_lifecycles[channel_name] != vanished)
3300- {
3301- if (lifecycle_condition.wait_until(lg, end_time) == std::cv_status::timeout)
3302- BOOST_THROW_EXCEPTION(std::runtime_error("Timed out waiting for client (" + channel_name + ") to vanish"));
3303- }
3304-}
3305
3306=== modified file 'tests/mir_test_framework/testing_server_options.cpp'
3307--- tests/mir_test_framework/testing_server_options.cpp 2013-08-12 08:58:58 +0000
3308+++ tests/mir_test_framework/testing_server_options.cpp 2013-08-13 22:17:10 +0000
3309@@ -79,9 +79,8 @@
3310 {
3311 mg::DisplayConfigurationOutput dummy_output_config{
3312 mg::DisplayConfigurationOutputId{0}, mg::DisplayConfigurationCardId{0},
3313- mg::DisplayConfigurationOutputType::vga,
3314 std::vector<geom::PixelFormat>{geom::PixelFormat::abgr_8888},
3315- modes, 0, geom::Size{}, true, true, geom::Point{0,0}, 0, 0};
3316+ modes, geom::Size{}, true, true, geom::Point{0,0}, 0, 0};
3317
3318 f(dummy_output_config);
3319 }
3320
3321=== modified file 'tests/unit-tests/client/test_client_display_conf.cpp'
3322--- tests/unit-tests/client/test_client_display_conf.cpp 2013-08-12 08:58:59 +0000
3323+++ tests/unit-tests/client/test_client_display_conf.cpp 2013-08-13 22:17:10 +0000
3324@@ -27,12 +27,6 @@
3325
3326 namespace
3327 {
3328-void fill(mp::DisplayCard* out)
3329-{
3330- out->set_card_id(7);
3331- out->set_max_simultaneous_outputs(3);
3332-}
3333-
3334 void fill(mp::DisplayOutput* out)
3335 {
3336 out->add_pixel_format(4);
3337@@ -58,9 +52,6 @@
3338 mp::DisplayConfiguration protobuf_config;
3339 fill(protobuf_config.add_display_output());
3340 fill(protobuf_config.add_display_output());
3341- fill(protobuf_config.add_display_card());
3342- fill(protobuf_config.add_display_card());
3343- fill(protobuf_config.add_display_card());
3344
3345 mcl::DisplayConfiguration internal_config;
3346
3347
3348=== modified file 'tests/unit-tests/client/test_mir_connection.cpp'
3349--- tests/unit-tests/client/test_mir_connection.cpp 2013-08-12 08:58:59 +0000
3350+++ tests/unit-tests/client/test_mir_connection.cpp 2013-08-13 22:17:10 +0000
3351@@ -373,7 +373,7 @@
3352 output.used = 0;
3353 output.position_x = 4;
3354 output.position_y = 6;
3355- MirDisplayConfiguration user_config{1, &output, 0, nullptr};
3356+ MirDisplayConfiguration user_config{1, &output};
3357
3358 auto verify_display_change = [&](mp::DisplayConfiguration const* config)
3359 {
3360
3361=== modified file 'tests/unit-tests/frontend/test_session_mediator.cpp'
3362--- tests/unit-tests/frontend/test_session_mediator.cpp 2013-08-13 22:17:09 +0000
3363+++ tests/unit-tests/frontend/test_session_mediator.cpp 2013-08-12 17:20:29 +0000
3364@@ -181,6 +181,7 @@
3365 using namespace ::testing;
3366
3367 ON_CALL(*shell, open_session(_, _)).WillByDefault(Return(stubbed_session));
3368+ ON_CALL(*shell, create_surface_for(_, _)).WillByDefault(Return(mf::SurfaceId{1}));
3369 }
3370
3371 std::shared_ptr<testing::NiceMock<mtd::MockShell>> const shell;
3372@@ -486,7 +487,7 @@
3373 .InSequence(seq);
3374 EXPECT_CALL(mock_display_config, configure_output(id1, used1, pt1, mode_index1))
3375 .InSequence(seq);
3376- EXPECT_CALL(*mock_display_selector, store_configuration_for(_,_))
3377+ EXPECT_CALL(*mock_display_selector, configure(_,_))
3378 .InSequence(seq);
3379
3380 mf::SessionMediator session_mediator{
3381@@ -515,58 +516,3 @@
3382
3383 session_mediator.disconnect(nullptr, nullptr, nullptr, null_callback.get());
3384 }
3385-
3386-TEST_F(SessionMediatorTest, apply_session_display_config)
3387-{
3388- using namespace testing;
3389- mp::ConnectParameters connect_parameters;
3390- mp::Connection connection;
3391- mp::SurfaceParameters request;
3392- mp::Surface response;
3393- mp::SurfaceId release_request;
3394- mp::Void ignored;
3395- mp::DisplayConfiguration configuration;
3396-
3397- NiceMock<MockConfig> mock_display_config;
3398- auto mock_display_selector = std::make_shared<mtd::MockDisplayChanger>();
3399-
3400- EXPECT_CALL(*mock_display_selector, active_configuration())
3401- .WillRepeatedly(Return(mt::fake_shared(mock_display_config)));
3402-
3403- EXPECT_CALL(*mock_display_selector, store_configuration_for(_,_))
3404- .Times(1);
3405- EXPECT_CALL(*mock_display_selector, remove_configuration_for(_))
3406- .Times(1);
3407-
3408- mf::SessionMediator session_mediator{
3409- shell, graphics_platform, mock_display_selector,
3410- buffer_allocator, report, std::make_shared<mtd::NullEventSink>(), resource_cache};
3411-
3412- session_mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get());
3413- session_mediator.configure_display(nullptr, &configuration, &ignored, null_callback.get());
3414- session_mediator.disconnect(nullptr, nullptr, nullptr, null_callback.get());
3415-}
3416-
3417-TEST_F(SessionMediatorTest, display_config_removed_if_no_disconnect)
3418-{
3419- using namespace testing;
3420- mp::ConnectParameters connect_parameters;
3421- mp::Connection connection;
3422- mp::SurfaceParameters request;
3423- mp::Surface response;
3424- mp::SurfaceId release_request;
3425-
3426- NiceMock<MockConfig> mock_display_config;
3427- auto mock_display_selector = std::make_shared<mtd::MockDisplayChanger>();
3428-
3429- EXPECT_CALL(*mock_display_selector, active_configuration())
3430- .WillOnce(Return(mt::fake_shared(mock_display_config)));
3431- EXPECT_CALL(*mock_display_selector, remove_configuration_for(_))
3432- .Times(1);
3433-
3434- mf::SessionMediator session_mediator{
3435- shell, graphics_platform, mock_display_selector,
3436- buffer_allocator, report, std::make_shared<mtd::NullEventSink>(), resource_cache};
3437-
3438- session_mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get());
3439-}
3440
3441=== modified file 'tests/unit-tests/graphics/gbm/test_gbm_cursor.cpp'
3442--- tests/unit-tests/graphics/gbm/test_gbm_cursor.cpp 2013-08-12 08:58:59 +0000
3443+++ tests/unit-tests/graphics/gbm/test_gbm_cursor.cpp 2013-08-13 22:17:10 +0000
3444@@ -90,13 +90,11 @@
3445 {
3446 mg::DisplayConfigurationOutputId{10},
3447 card_id,
3448- mg::DisplayConfigurationOutputType::vga,
3449 {},
3450 {
3451 {geom::Size{10, 20}, 59.9},
3452 {geom::Size{200, 100}, 59.9},
3453 },
3454- 1,
3455 geom::Size{324, 642},
3456 true,
3457 true,
3458@@ -108,13 +106,11 @@
3459 {
3460 mg::DisplayConfigurationOutputId{11},
3461 card_id,
3462- mg::DisplayConfigurationOutputType::vga,
3463 {},
3464 {
3465 {geom::Size{200, 200}, 59.9},
3466 {geom::Size{100, 200}, 59.9},
3467 },
3468- 0,
3469 geom::Size{566, 111},
3470 true,
3471 true,
3472@@ -126,7 +122,7 @@
3473
3474 void for_each_card(std::function<void(mg::DisplayConfigurationCard const&)> f) const
3475 {
3476- f({card_id, outputs.size()});
3477+ f({card_id});
3478 }
3479
3480 void for_each_output(std::function<void(mg::DisplayConfigurationOutput const&)> f) const
3481
3482=== modified file 'tests/unit-tests/graphics/gbm/test_gbm_display_configuration.cpp'
3483--- tests/unit-tests/graphics/gbm/test_gbm_display_configuration.cpp 2013-08-12 08:58:59 +0000
3484+++ tests/unit-tests/graphics/gbm/test_gbm_display_configuration.cpp 2013-08-13 22:17:10 +0000
3485@@ -104,13 +104,11 @@
3486
3487 void setup_sample_modes()
3488 {
3489- using fake = mtd::FakeDRMResources;
3490-
3491 /* Add DRM modes */
3492- modes0.push_back(fake::create_mode(1920, 1080, 138500, 2080, 1111, fake::NormalMode));
3493- modes0.push_back(fake::create_mode(1920, 1080, 148500, 2200, 1125, fake::PreferredMode));
3494- modes0.push_back(fake::create_mode(1680, 1050, 119000, 1840, 1080, fake::NormalMode));
3495- modes0.push_back(fake::create_mode(832, 624, 57284, 1152, 667, fake::NormalMode));
3496+ modes0.push_back(mtd::FakeDRMResources::create_mode(1920, 1080, 138500, 2080, 1111));
3497+ modes0.push_back(mtd::FakeDRMResources::create_mode(1920, 1080, 148500, 2200, 1125));
3498+ modes0.push_back(mtd::FakeDRMResources::create_mode(1680, 1050, 119000, 1840, 1080));
3499+ modes0.push_back(mtd::FakeDRMResources::create_mode(832, 624, 57284, 1152, 667));
3500
3501 /* Add the DisplayConfiguration modes corresponding to the DRM modes */
3502 for (auto const& mode : modes0)
3503@@ -148,7 +146,6 @@
3504 geom::Size const connector2_physical_size_mm{};
3505 std::vector<uint32_t> possible_encoder_ids_empty;
3506 uint32_t const possible_crtcs_mask_empty{0};
3507- size_t const max_simultaneous_outputs{1};
3508
3509 mtd::FakeDRMResources& resources(mock_drm.fake_drm);
3510
3511@@ -159,39 +156,26 @@
3512 resources.add_encoder(encoder0_id, crtc0_id, possible_crtcs_mask_empty);
3513 resources.add_encoder(encoder1_id, invalid_id, possible_crtcs_mask_empty);
3514
3515- resources.add_connector(connector0_id, DRM_MODE_CONNECTOR_HDMIA,
3516- DRM_MODE_CONNECTED, encoder0_id,
3517+ resources.add_connector(connector0_id, DRM_MODE_CONNECTED, encoder0_id,
3518 modes0, possible_encoder_ids_empty,
3519 connector0_physical_size_mm);
3520- resources.add_connector(connector1_id, DRM_MODE_CONNECTOR_Unknown,
3521- DRM_MODE_DISCONNECTED, invalid_id,
3522+ resources.add_connector(connector1_id, DRM_MODE_DISCONNECTED, invalid_id,
3523 modes_empty, possible_encoder_ids_empty,
3524 connector1_physical_size_mm);
3525- resources.add_connector(connector2_id, DRM_MODE_CONNECTOR_eDP,
3526- DRM_MODE_DISCONNECTED, encoder1_id,
3527+ resources.add_connector(connector2_id, DRM_MODE_DISCONNECTED, encoder1_id,
3528 modes_empty, possible_encoder_ids_empty,
3529 connector2_physical_size_mm);
3530
3531 resources.prepare();
3532
3533 /* Expected results */
3534- std::vector<mg::DisplayConfigurationCard> const expected_cards =
3535- {
3536- {
3537- mg::DisplayConfigurationCardId{0},
3538- max_simultaneous_outputs
3539- }
3540- };
3541-
3542 std::vector<mg::DisplayConfigurationOutput> const expected_outputs =
3543 {
3544 {
3545 mg::DisplayConfigurationOutputId{connector0_id},
3546 mg::DisplayConfigurationCardId{0},
3547- mg::DisplayConfigurationOutputType::hdmia,
3548 {},
3549 conf_modes0,
3550- 1,
3551 connector0_physical_size_mm,
3552 true,
3553 true,
3554@@ -202,10 +186,8 @@
3555 {
3556 mg::DisplayConfigurationOutputId{connector1_id},
3557 mg::DisplayConfigurationCardId{0},
3558- mg::DisplayConfigurationOutputType::unknown,
3559 {},
3560 std::vector<mg::DisplayConfigurationMode>(),
3561- std::numeric_limits<size_t>::max(),
3562 connector1_physical_size_mm,
3563 false,
3564 false,
3565@@ -216,10 +198,8 @@
3566 {
3567 mg::DisplayConfigurationOutputId{connector2_id},
3568 mg::DisplayConfigurationCardId{0},
3569- mg::DisplayConfigurationOutputType::edp,
3570 {},
3571 std::vector<mg::DisplayConfigurationMode>(),
3572- std::numeric_limits<size_t>::max(),
3573 connector2_physical_size_mm,
3574 false,
3575 false,
3576@@ -234,15 +214,6 @@
3577
3578 auto conf = display->configuration();
3579
3580- size_t card_count{0};
3581-
3582- conf->for_each_card([&](mg::DisplayConfigurationCard const& card)
3583- {
3584- ASSERT_LT(card_count, expected_cards.size());
3585- EXPECT_EQ(expected_cards[card_count], card) << "card_count: " << card_count;
3586- ++card_count;
3587- });
3588-
3589 size_t output_count{0};
3590
3591 conf->for_each_output([&](mg::DisplayConfigurationOutput const& output)
3592@@ -272,8 +243,7 @@
3593 resources.add_encoder(encoder0_id, crtc0_id, possible_crtcs_mask_empty);
3594 for (auto id : connector_ids)
3595 {
3596- resources.add_connector(id, DRM_MODE_CONNECTOR_DVID,
3597- DRM_MODE_CONNECTED, encoder0_id,
3598+ resources.add_connector(id, DRM_MODE_CONNECTED, encoder0_id,
3599 modes0, encoder_ids,
3600 geom::Size());
3601 }
3602@@ -315,8 +285,7 @@
3603 resources.add_encoder(encoder0_id, crtc0_id, possible_crtcs_mask_empty);
3604 for (auto id : connector_ids)
3605 {
3606- resources.add_connector(id, DRM_MODE_CONNECTOR_VGA,
3607- DRM_MODE_CONNECTED, encoder0_id,
3608+ resources.add_connector(id, DRM_MODE_CONNECTED, encoder0_id,
3609 modes0, encoder_ids,
3610 geom::Size());
3611 }
3612@@ -353,26 +322,15 @@
3613 };
3614 std::vector<uint32_t> possible_encoder_ids_empty;
3615 uint32_t const possible_crtcs_mask_empty{0};
3616- size_t const max_simultaneous_outputs{1};
3617
3618 /* Expected results */
3619- std::vector<mg::DisplayConfigurationCard> const expected_cards =
3620- {
3621- {
3622- mg::DisplayConfigurationCardId{0},
3623- max_simultaneous_outputs
3624- }
3625- };
3626-
3627 std::vector<mg::DisplayConfigurationOutput> const expected_outputs_before =
3628 {
3629 {
3630 mg::DisplayConfigurationOutputId(connector_ids[0]),
3631 mg::DisplayConfigurationCardId{0},
3632- mg::DisplayConfigurationOutputType::composite,
3633 {},
3634 conf_modes0,
3635- 1,
3636 connector_physical_sizes_mm_before[0],
3637 true,
3638 true,
3639@@ -383,10 +341,8 @@
3640 {
3641 mg::DisplayConfigurationOutputId(connector_ids[1]),
3642 mg::DisplayConfigurationCardId{0},
3643- mg::DisplayConfigurationOutputType::vga,
3644 {},
3645 std::vector<mg::DisplayConfigurationMode>(),
3646- std::numeric_limits<size_t>::max(),
3647 connector_physical_sizes_mm_before[1],
3648 false,
3649 false,
3650@@ -401,10 +357,8 @@
3651 {
3652 mg::DisplayConfigurationOutputId(connector_ids[0]),
3653 mg::DisplayConfigurationCardId{0},
3654- mg::DisplayConfigurationOutputType::composite,
3655 {},
3656 std::vector<mg::DisplayConfigurationMode>(),
3657- std::numeric_limits<size_t>::max(),
3658 connector_physical_sizes_mm_after[0],
3659 false,
3660 true,
3661@@ -415,10 +369,8 @@
3662 {
3663 mg::DisplayConfigurationOutputId(connector_ids[1]),
3664 mg::DisplayConfigurationCardId{0},
3665- mg::DisplayConfigurationOutputType::vga,
3666 {},
3667 conf_modes0,
3668- 1,
3669 connector_physical_sizes_mm_after[1],
3670 true,
3671 false,
3672@@ -438,12 +390,10 @@
3673 resources.add_encoder(encoder_ids[0], crtc_ids[0], possible_crtcs_mask_empty);
3674 resources.add_encoder(encoder_ids[1], invalid_id, possible_crtcs_mask_empty);
3675
3676- resources.add_connector(connector_ids[0], DRM_MODE_CONNECTOR_Composite,
3677- DRM_MODE_CONNECTED, encoder_ids[0],
3678+ resources.add_connector(connector_ids[0], DRM_MODE_CONNECTED, encoder_ids[0],
3679 modes0, possible_encoder_ids_empty,
3680 connector_physical_sizes_mm_before[0]);
3681- resources.add_connector(connector_ids[1], DRM_MODE_CONNECTOR_VGA,
3682- DRM_MODE_DISCONNECTED, invalid_id,
3683+ resources.add_connector(connector_ids[1], DRM_MODE_DISCONNECTED, invalid_id,
3684 modes_empty, possible_encoder_ids_empty,
3685 connector_physical_sizes_mm_before[1]);
3686
3687@@ -453,15 +403,6 @@
3688
3689 auto conf = display->configuration();
3690
3691- size_t card_count{0};
3692-
3693- conf->for_each_card([&](mg::DisplayConfigurationCard const& card)
3694- {
3695- ASSERT_LT(card_count, expected_cards.size());
3696- EXPECT_EQ(expected_cards[card_count], card) << "card_count: " << card_count;
3697- ++card_count;
3698- });
3699-
3700 size_t output_count{0};
3701
3702 conf->for_each_output([&](mg::DisplayConfigurationOutput const& output)
3703@@ -481,12 +422,10 @@
3704 resources.add_encoder(encoder_ids[0], invalid_id, possible_crtcs_mask_empty);
3705 resources.add_encoder(encoder_ids[1], crtc_ids[1], possible_crtcs_mask_empty);
3706
3707- resources.add_connector(connector_ids[0], DRM_MODE_CONNECTOR_Composite,
3708- DRM_MODE_DISCONNECTED, invalid_id,
3709+ resources.add_connector(connector_ids[0], DRM_MODE_DISCONNECTED, invalid_id,
3710 modes_empty, possible_encoder_ids_empty,
3711 connector_physical_sizes_mm_after[0]);
3712- resources.add_connector(connector_ids[1], DRM_MODE_CONNECTOR_VGA,
3713- DRM_MODE_CONNECTED, encoder_ids[1],
3714+ resources.add_connector(connector_ids[1], DRM_MODE_CONNECTED, encoder_ids[1],
3715 modes0, possible_encoder_ids_empty,
3716 connector_physical_sizes_mm_after[1]);
3717
3718@@ -494,15 +433,6 @@
3719
3720 conf = display->configuration();
3721
3722- card_count = 0;
3723-
3724- conf->for_each_card([&](mg::DisplayConfigurationCard const& card)
3725- {
3726- ASSERT_LT(card_count, expected_cards.size());
3727- EXPECT_EQ(expected_cards[card_count], card) << "card_count: " << card_count;
3728- ++card_count;
3729- });
3730-
3731 output_count = 0;
3732
3733 conf->for_each_output([&](mg::DisplayConfigurationOutput const& output)
3734
3735=== modified file 'tests/unit-tests/graphics/gbm/test_gbm_display_multi_monitor.cpp'
3736--- tests/unit-tests/graphics/gbm/test_gbm_display_multi_monitor.cpp 2013-08-12 08:58:58 +0000
3737+++ tests/unit-tests/graphics/gbm/test_gbm_display_multi_monitor.cpp 2013-08-13 22:17:10 +0000
3738@@ -51,13 +51,15 @@
3739 public:
3740 void apply_to(mg::DisplayConfiguration& conf)
3741 {
3742+ size_t const preferred_mode_index{0};
3743+
3744 conf.for_each_output(
3745 [&](mg::DisplayConfigurationOutput const& conf_output)
3746 {
3747 if (conf_output.connected && conf_output.modes.size() > 0)
3748 {
3749 conf.configure_output(conf_output.id, true, geom::Point{0, 0},
3750- conf_output.preferred_mode_index);
3751+ preferred_mode_index);
3752 }
3753 else
3754 {
3755@@ -73,6 +75,7 @@
3756 public:
3757 void apply_to(mg::DisplayConfiguration& conf)
3758 {
3759+ size_t const preferred_mode_index{0};
3760 int max_x = 0;
3761
3762 conf.for_each_output(
3763@@ -81,8 +84,8 @@
3764 if (conf_output.connected && conf_output.modes.size() > 0)
3765 {
3766 conf.configure_output(conf_output.id, true, geom::Point{max_x, 0},
3767- conf_output.preferred_mode_index);
3768- max_x += conf_output.modes[conf_output.preferred_mode_index].size.width.as_int();
3769+ preferred_mode_index);
3770+ max_x += conf_output.modes[0].size.width.as_int();
3771 }
3772 else
3773 {
3774@@ -149,15 +152,13 @@
3775
3776 void setup_outputs(int n)
3777 {
3778- using fake = mtd::FakeDRMResources;
3779-
3780 mtd::FakeDRMResources& resources(mock_drm.fake_drm);
3781
3782 modes0.clear();
3783- modes0.push_back(fake::create_mode(1920, 1080, 138500, 2080, 1111, fake::NormalMode));
3784- modes0.push_back(fake::create_mode(1920, 1080, 148500, 2200, 1125, fake::PreferredMode));
3785- modes0.push_back(fake::create_mode(1680, 1050, 119000, 1840, 1080, fake::NormalMode));
3786- modes0.push_back(fake::create_mode(832, 624, 57284, 1152, 667, fake::NormalMode));
3787+ modes0.push_back(mtd::FakeDRMResources::create_mode(1920, 1080, 138500, 2080, 1111));
3788+ modes0.push_back(mtd::FakeDRMResources::create_mode(1920, 1080, 148500, 2200, 1125));
3789+ modes0.push_back(mtd::FakeDRMResources::create_mode(1680, 1050, 119000, 1840, 1080));
3790+ modes0.push_back(mtd::FakeDRMResources::create_mode(832, 624, 57284, 1152, 667));
3791
3792 geom::Size const connector_physical_size_mm{1597, 987};
3793
3794@@ -185,8 +186,7 @@
3795 uint32_t const connector_id{connector_base_id + i};
3796
3797 connector_ids.push_back(connector_id);
3798- resources.add_connector(connector_id, DRM_MODE_CONNECTOR_VGA,
3799- DRM_MODE_CONNECTED, encoder_ids[i],
3800+ resources.add_connector(connector_id, DRM_MODE_CONNECTED, encoder_ids[i],
3801 modes0, encoder_ids, connector_physical_size_mm);
3802 }
3803
3804
3805=== modified file 'tests/unit-tests/graphics/gbm/test_overlapping_output_grouping.cpp'
3806--- tests/unit-tests/graphics/gbm/test_overlapping_output_grouping.cpp 2013-08-12 08:58:59 +0000
3807+++ tests/unit-tests/graphics/gbm/test_overlapping_output_grouping.cpp 2013-08-13 22:17:10 +0000
3808@@ -48,8 +48,7 @@
3809 {
3810 mg::DisplayConfigurationCard card
3811 {
3812- mg::DisplayConfigurationCardId{1},
3813- outputs.size()
3814+ mg::DisplayConfigurationCardId{1}
3815 };
3816
3817 f(card);
3818@@ -70,10 +69,8 @@
3819 {
3820 mg::DisplayConfigurationOutputId(i),
3821 mg::DisplayConfigurationCardId{1},
3822- mg::DisplayConfigurationOutputType::svideo,
3823 {},
3824 modes,
3825- i - 1,
3826 {100, 100},
3827 connected,
3828 used,
3829
3830=== modified file 'tests/unit-tests/graphics/gbm/test_real_kms_output.cpp'
3831--- tests/unit-tests/graphics/gbm/test_real_kms_output.cpp 2013-08-12 08:58:58 +0000
3832+++ tests/unit-tests/graphics/gbm/test_real_kms_output.cpp 2013-08-13 22:17:10 +0000
3833@@ -71,8 +71,7 @@
3834
3835 resources.add_crtc(crtc_ids[0], drmModeModeInfo());
3836 resources.add_encoder(encoder_ids[0], crtc_ids[0], possible_crtcs_mask);
3837- resources.add_connector(connector_ids[0], DRM_MODE_CONNECTOR_VGA,
3838- DRM_MODE_CONNECTED, encoder_ids[0],
3839+ resources.add_connector(connector_ids[0], DRM_MODE_CONNECTED, encoder_ids[0],
3840 modes_empty, possible_encoder_ids1, geom::Size());
3841
3842 resources.prepare();
3843@@ -90,11 +89,9 @@
3844 resources.add_crtc(crtc_ids[1], drmModeModeInfo());
3845 resources.add_encoder(encoder_ids[0], crtc_ids[0], possible_crtcs_mask1);
3846 resources.add_encoder(encoder_ids[1], invalid_id, possible_crtcs_mask_all);
3847- resources.add_connector(connector_ids[0], DRM_MODE_CONNECTOR_Composite,
3848- DRM_MODE_CONNECTED, invalid_id,
3849+ resources.add_connector(connector_ids[0], DRM_MODE_CONNECTED, invalid_id,
3850 modes_empty, possible_encoder_ids2, geom::Size());
3851- resources.add_connector(connector_ids[1], DRM_MODE_CONNECTOR_DVIA,
3852- DRM_MODE_CONNECTED, encoder_ids[0],
3853+ resources.add_connector(connector_ids[1], DRM_MODE_CONNECTED, encoder_ids[0],
3854 modes_empty, possible_encoder_ids2, geom::Size());
3855
3856 resources.prepare();
3857
3858=== modified file 'tests/unit-tests/graphics/test_default_display_configuration_policy.cpp'
3859--- tests/unit-tests/graphics/test_default_display_configuration_policy.cpp 2013-08-12 08:58:59 +0000
3860+++ tests/unit-tests/graphics/test_default_display_configuration_policy.cpp 2013-08-13 22:17:10 +0000
3861@@ -39,7 +39,6 @@
3862 {
3863 mg::DisplayConfigurationOutputId{10},
3864 card_id,
3865- mg::DisplayConfigurationOutputType::vga,
3866 {
3867 {geom::PixelFormat::abgr_8888}
3868 },
3869@@ -48,7 +47,6 @@
3870 {geom::Size{123, 111}, 59.9},
3871 {geom::Size{123, 111}, 59.9}
3872 },
3873- 2,
3874 geom::Size{324, 642},
3875 true,
3876 false,
3877@@ -61,10 +59,8 @@
3878 {
3879 mg::DisplayConfigurationOutputId{11},
3880 card_id,
3881- mg::DisplayConfigurationOutputType::vga,
3882- {},
3883- {},
3884- std::numeric_limits<size_t>::max(),
3885+ {},
3886+ {},
3887 geom::Size{566, 111},
3888 true,
3889 false,
3890@@ -77,14 +73,12 @@
3891 {
3892 mg::DisplayConfigurationOutputId{12},
3893 card_id,
3894- mg::DisplayConfigurationOutputType::vga,
3895 {
3896 {geom::PixelFormat::abgr_8888}
3897 },
3898 {
3899 {geom::Size{523, 555}, 60.0},
3900 },
3901- 0,
3902 geom::Size{324, 642},
3903 true,
3904 false,
3905@@ -97,12 +91,10 @@
3906 {
3907 mg::DisplayConfigurationOutputId{13},
3908 card_id,
3909- mg::DisplayConfigurationOutputType::vga,
3910 {
3911 {geom::PixelFormat::abgr_8888}
3912 },
3913 {},
3914- 0,
3915 geom::Size{324, 642},
3916 false,
3917 false,
3918@@ -114,7 +106,7 @@
3919
3920 void for_each_card(std::function<void(mg::DisplayConfigurationCard const&)> f) const
3921 {
3922- f({card_id, outputs.size()});
3923+ f({card_id});
3924 }
3925
3926 void for_each_output(std::function<void(mg::DisplayConfigurationOutput const&)> f) const
3927@@ -137,13 +129,14 @@
3928 {
3929 mg::DefaultDisplayConfigurationPolicy policy;
3930 MockDisplayConfiguration conf;
3931+ size_t const highest_mode{0};
3932
3933 conf.for_each_output([&conf](mg::DisplayConfigurationOutput const& output)
3934 {
3935 if (output.connected && output.modes.size() > 0)
3936 {
3937 EXPECT_CALL(conf, configure_output(output.id, true, geom::Point(),
3938- output.preferred_mode_index));
3939+ highest_mode));
3940 }
3941 else
3942 {
3943
3944=== modified file 'tests/unit-tests/graphics/test_display_configuration.cpp'
3945--- tests/unit-tests/graphics/test_display_configuration.cpp 2013-08-12 11:52:13 +0000
3946+++ tests/unit-tests/graphics/test_display_configuration.cpp 2013-08-13 22:17:10 +0000
3947@@ -30,7 +30,6 @@
3948 {
3949 mg::DisplayConfigurationOutputId{3},
3950 mg::DisplayConfigurationCardId{2},
3951- mg::DisplayConfigurationOutputType::dvid,
3952 {
3953 {geom::PixelFormat::abgr_8888}
3954 },
3955@@ -39,7 +38,6 @@
3956 {geom::Size{10, 20}, 59.0},
3957 {geom::Size{15, 20}, 59.0}
3958 },
3959- 0,
3960 geom::Size{10, 20},
3961 true,
3962 true,
3963@@ -50,39 +48,7 @@
3964
3965 }
3966
3967-TEST(DisplayConfiguration, same_cards_compare_equal)
3968-{
3969- mg::DisplayConfigurationCardId const id{1};
3970- size_t const max_outputs{3};
3971-
3972- mg::DisplayConfigurationCard const card1{id, max_outputs};
3973- mg::DisplayConfigurationCard const card2 = card1;
3974-
3975- EXPECT_EQ(card1, card1);
3976- EXPECT_EQ(card1, card2);
3977- EXPECT_EQ(card2, card1);
3978-}
3979-
3980-TEST(DisplayConfiguration, different_cards_compare_unequal)
3981-{
3982- mg::DisplayConfigurationCardId const id1{1};
3983- mg::DisplayConfigurationCardId const id2{2};
3984- size_t const max_outputs1{3};
3985- size_t const max_outputs2{4};
3986-
3987- mg::DisplayConfigurationCard const card1{id1, max_outputs1};
3988- mg::DisplayConfigurationCard const card2{id1, max_outputs2};
3989- mg::DisplayConfigurationCard const card3{id2, max_outputs1};
3990-
3991- EXPECT_NE(card1, card2);
3992- EXPECT_NE(card2, card1);
3993- EXPECT_NE(card2, card3);
3994- EXPECT_NE(card3, card2);
3995- EXPECT_NE(card1, card3);
3996- EXPECT_NE(card3, card1);
3997-}
3998-
3999-TEST(DisplayConfiguration, same_modes_compare_equal)
4000+TEST(DisplayConfiguration, mode_equality)
4001 {
4002 geom::Size const size{10, 20};
4003 double const vrefresh{59.9};
4004@@ -95,7 +61,7 @@
4005 EXPECT_EQ(mode2, mode1);
4006 }
4007
4008-TEST(DisplayConfiguration, different_modes_compare_unequal)
4009+TEST(DisplayConfiguration, mode_inequality)
4010 {
4011 geom::Size const size1{10, 20};
4012 geom::Size const size2{10, 21};
4013@@ -114,7 +80,7 @@
4014 EXPECT_NE(mode3, mode1);
4015 }
4016
4017-TEST(DisplayConfiguration, same_outputs_compare_equal)
4018+TEST(DisplayConfiguration, output_equality)
4019 {
4020 mg::DisplayConfigurationOutput const output1 = tmpl_output;
4021 mg::DisplayConfigurationOutput output2 = tmpl_output;
4022@@ -124,7 +90,7 @@
4023 EXPECT_EQ(output2, output1);
4024 }
4025
4026-TEST(DisplayConfiguration, outputs_with_different_ids_compare_unequal)
4027+TEST(DisplayConfiguration, output_inequality_id)
4028 {
4029 mg::DisplayConfigurationOutput const output1 = tmpl_output;
4030 mg::DisplayConfigurationOutput output2 = tmpl_output;
4031@@ -141,7 +107,7 @@
4032 EXPECT_NE(output3, output1);
4033 }
4034
4035-TEST(DisplayConfiguration, outupts_with_different_modes_compare_unequal)
4036+TEST(DisplayConfiguration, output_inequality_modes)
4037 {
4038 mg::DisplayConfigurationOutput const output1 = tmpl_output;
4039 mg::DisplayConfigurationOutput output2 = tmpl_output;
4040@@ -170,7 +136,7 @@
4041 EXPECT_NE(output3, output1);
4042 }
4043
4044-TEST(DisplayConfiguration, outputs_with_different_physical_size_compare_unequal)
4045+TEST(DisplayConfiguration, output_inequality_physical_size)
4046 {
4047 mg::DisplayConfigurationOutput const output1 = tmpl_output;
4048 mg::DisplayConfigurationOutput output2 = tmpl_output;
4049@@ -183,7 +149,7 @@
4050 EXPECT_NE(output2, output1);
4051 }
4052
4053-TEST(DisplayConfiguration, outputs_with_different_connected_status_compare_unequal)
4054+TEST(DisplayConfiguration, output_inequality_connection)
4055 {
4056 mg::DisplayConfigurationOutput const output1 = tmpl_output;
4057 mg::DisplayConfigurationOutput output2 = tmpl_output;
4058@@ -194,7 +160,7 @@
4059 EXPECT_NE(output2, output1);
4060 }
4061
4062-TEST(DisplayConfiguration, outputs_with_different_current_mode_index_compare_unequal)
4063+TEST(DisplayConfiguration, output_inequality_current_mode)
4064 {
4065 mg::DisplayConfigurationOutput const output1 = tmpl_output;
4066 mg::DisplayConfigurationOutput output2 = tmpl_output;
4067@@ -204,14 +170,3 @@
4068 EXPECT_NE(output1, output2);
4069 EXPECT_NE(output2, output1);
4070 }
4071-
4072-TEST(DisplayConfiguration, outputs_with_different_preferred_mode_index_compare_unequal)
4073-{
4074- mg::DisplayConfigurationOutput const output1 = tmpl_output;
4075- mg::DisplayConfigurationOutput output2 = tmpl_output;
4076-
4077- output2.preferred_mode_index = 1;
4078-
4079- EXPECT_NE(output1, output2);
4080- EXPECT_NE(output2, output1);
4081-}
4082
4083=== modified file 'tests/unit-tests/shell/CMakeLists.txt'
4084--- tests/unit-tests/shell/CMakeLists.txt 2013-08-13 22:17:09 +0000
4085+++ tests/unit-tests/shell/CMakeLists.txt 2013-08-12 17:20:29 +0000
4086@@ -10,7 +10,6 @@
4087 ${CMAKE_CURRENT_SOURCE_DIR}/test_threaded_snapshot_strategy.cpp
4088 ${CMAKE_CURRENT_SOURCE_DIR}/test_gl_pixel_buffer.cpp
4089 ${CMAKE_CURRENT_SOURCE_DIR}/test_graphics_display_layout.cpp
4090- ${CMAKE_CURRENT_SOURCE_DIR}/test_mediating_display_changer.cpp
4091 ${CMAKE_CURRENT_SOURCE_DIR}/test_unauthorized_display_changer.cpp
4092 ${CMAKE_CURRENT_SOURCE_DIR}/test_mediating_display_changer.cpp
4093 )
4094
4095=== modified file 'tests/unit-tests/shell/test_default_focus_mechanism.cpp'
4096--- tests/unit-tests/shell/test_default_focus_mechanism.cpp 2013-08-13 22:17:09 +0000
4097+++ tests/unit-tests/shell/test_default_focus_mechanism.cpp 2013-08-13 22:17:10 +0000
4098@@ -34,7 +34,6 @@
4099 #include "mir_test_doubles/stub_surface_controller.h"
4100 #include "mir_test_doubles/stub_input_targeter.h"
4101 #include "mir_test_doubles/mock_input_targeter.h"
4102-#include "mir_test_doubles/mock_session_listener.h"
4103 #include "mir_test_doubles/stub_surface_controller.h"
4104
4105 #include <gmock/gmock.h>
4106@@ -45,126 +44,83 @@
4107 namespace msh = mir::shell;
4108 namespace ms = mir::surfaces;
4109 namespace mf = mir::frontend;
4110-namespace mg = mir::graphics;
4111 namespace mt = mir::test;
4112 namespace mtd = mir::test::doubles;
4113
4114-namespace
4115-{
4116-struct MockShellSession : public msh::Session
4117-{
4118- MOCK_METHOD1(create_surface, mf::SurfaceId(msh::SurfaceCreationParameters const&));
4119- MOCK_METHOD1(destroy_surface, void(mf::SurfaceId));
4120- MOCK_CONST_METHOD1(get_surface, std::shared_ptr<mf::Surface>(mf::SurfaceId));
4121-
4122- MOCK_METHOD1(take_snapshot, void(msh::SnapshotCallback const&));
4123- MOCK_CONST_METHOD0(default_surface, std::shared_ptr<msh::Surface>());
4124-
4125- MOCK_CONST_METHOD0(name, std::string());
4126- MOCK_METHOD0(force_requests_to_complete, void());
4127-
4128- MOCK_METHOD0(hide, void());
4129- MOCK_METHOD0(show, void());
4130- MOCK_METHOD3(configure_surface, int(mf::SurfaceId, MirSurfaceAttrib, int));
4131- MOCK_METHOD1(send_display_config, void(mg::DisplayConfiguration const&));
4132-};
4133-
4134-struct MockFocusSequence : public msh::FocusSequence
4135-{
4136- MOCK_CONST_METHOD1(successor_of, std::shared_ptr<msh::Session>(std::shared_ptr<msh::Session> const&));
4137- MOCK_CONST_METHOD1(predecessor_of, std::shared_ptr<msh::Session>(std::shared_ptr<msh::Session> const&));
4138- MOCK_CONST_METHOD0(default_focus, std::shared_ptr<msh::Session>());
4139-};
4140-
4141-struct DefaultFocusMechanism : public testing::Test
4142-{
4143- void SetUp()
4144+TEST(DefaultFocusMechanism, raises_default_surface)
4145+{
4146+ using namespace ::testing;
4147+
4148+ NiceMock<mtd::MockShellSession> app1;
4149+ mtd::MockSurface mock_surface(&app1, std::make_shared<mtd::StubSurfaceBuilder>());
4150 {
4151- controller = std::make_shared<mtd::StubSurfaceController>();
4152-
4153- //TODO: extremely kludgy that a mock needs to be constructed this way
4154- mock_surface1 = std::make_shared<mtd::MockSurface>(&app1, std::make_shared<mtd::StubSurfaceBuilder>());
4155- mock_surface2 = std::make_shared<mtd::MockSurface>(&app2, std::make_shared<mtd::StubSurfaceBuilder>());
4156- ON_CALL(app1, default_surface())
4157- .WillByDefault(testing::Return(mock_surface1));
4158- ON_CALL(app2, default_surface())
4159- .WillByDefault(testing::Return(mock_surface2));
4160+ InSequence seq;
4161+ EXPECT_CALL(app1, default_surface()).Times(1)
4162+ .WillOnce(Return(mt::fake_shared(mock_surface)));
4163 }
4164
4165- std::shared_ptr<mtd::MockSurface> mock_surface1, mock_surface2;
4166- testing::NiceMock<MockShellSession> app1;
4167- testing::NiceMock<MockShellSession> app2;
4168- testing::NiceMock<mtd::MockSessionListener> mock_listener;
4169- testing::NiceMock<MockFocusSequence> focus_sequence;
4170- std::shared_ptr<msh::SurfaceController> controller;
4171-
4172+ auto controller = std::make_shared<mtd::StubSurfaceController>();
4173+ EXPECT_CALL(mock_surface, raise(Eq(controller))).Times(1);
4174 mtd::StubInputTargeter targeter;
4175-};
4176-
4177-}
4178-
4179-TEST_F(DefaultFocusMechanism, raises_default_surface)
4180-{
4181- using namespace ::testing;
4182-
4183- EXPECT_CALL(mock_listener, focused(_))
4184- .Times(1);
4185- EXPECT_CALL(*mock_surface1,
4186- raise(Eq(controller))).Times(1);
4187-
4188- msh::DefaultFocusMechanism focus_mechanism(mt::fake_shared(focus_sequence),
4189- mt::fake_shared(targeter), controller, mt::fake_shared(mock_listener));
4190-
4191- focus_mechanism.surface_created_for(mt::fake_shared(app1));
4192-}
4193-
4194-TEST_F(DefaultFocusMechanism, open_and_close)
4195-{
4196- using namespace ::testing;
4197-
4198- Sequence seq;
4199- EXPECT_CALL(mock_listener, focused(_))
4200- .InSequence(seq);
4201-
4202- EXPECT_CALL(focus_sequence, successor_of(_))
4203- .InSequence(seq)
4204- .WillOnce(Throw(std::logic_error("")));
4205- EXPECT_CALL(mock_listener, unfocused())
4206- .InSequence(seq);
4207-
4208- msh::DefaultFocusMechanism focus_mechanism(mt::fake_shared(focus_sequence),
4209- mt::fake_shared(targeter), controller, mt::fake_shared(mock_listener));
4210-
4211- auto app = mt::fake_shared(app1);
4212- focus_mechanism.session_opened(app);
4213- focus_mechanism.session_closed(app);
4214-}
4215-
4216-TEST_F(DefaultFocusMechanism, unfocus_only_on_close_active_session)
4217-{
4218- using namespace ::testing;
4219-
4220- EXPECT_CALL(mock_listener, focused(_))
4221- .Times(2);
4222- EXPECT_CALL(mock_listener, unfocused())
4223- .Times(0);
4224-
4225- msh::DefaultFocusMechanism focus_mechanism(mt::fake_shared(focus_sequence),
4226- mt::fake_shared(targeter), controller, mt::fake_shared(mock_listener));
4227-
4228- focus_mechanism.session_opened(mt::fake_shared(app1));
4229- focus_mechanism.session_opened(mt::fake_shared(app2));
4230- focus_mechanism.session_closed(mt::fake_shared(app1));
4231-}
4232-
4233-TEST_F(DefaultFocusMechanism, sets_input_focus)
4234-{
4235- using namespace ::testing;
4236-
4237- EXPECT_CALL(*mock_surface1, take_input_focus(_)).Times(1);
4238-
4239- msh::DefaultFocusMechanism focus_mechanism(mt::fake_shared(focus_sequence), mt::fake_shared(targeter), controller,
4240- mt::fake_shared(mock_listener));
4241-
4242- focus_mechanism.surface_created_for(mt::fake_shared(app1));
4243+ msh::DefaultFocusMechanism focus_mechanism(mt::fake_shared(targeter), controller);
4244+
4245+ focus_mechanism.set_focus_to(mt::fake_shared(app1));
4246+}
4247+
4248+TEST(DefaultFocusMechanism, mechanism_notifies_default_surface_of_focus_changes)
4249+{
4250+ using namespace ::testing;
4251+
4252+ NiceMock<mtd::MockShellSession> app1, app2;
4253+ mtd::MockSurface mock_surface1(&app1, std::make_shared<mtd::StubSurfaceBuilder>());
4254+ mtd::MockSurface mock_surface2(&app2, std::make_shared<mtd::StubSurfaceBuilder>());
4255+
4256+ ON_CALL(app1, default_surface()).WillByDefault(Return(mt::fake_shared(mock_surface1)));
4257+ ON_CALL(app2, default_surface()).WillByDefault(Return(mt::fake_shared(mock_surface2)));
4258+
4259+
4260+ {
4261+ InSequence seq;
4262+ EXPECT_CALL(mock_surface1, configure(mir_surface_attrib_focus, mir_surface_focused)).Times(1);
4263+ EXPECT_CALL(mock_surface1, configure(mir_surface_attrib_focus, mir_surface_unfocused)).Times(1);
4264+ EXPECT_CALL(mock_surface2, configure(mir_surface_attrib_focus, mir_surface_focused)).Times(1);
4265+ }
4266+
4267+ msh::DefaultFocusMechanism focus_mechanism(std::make_shared<mtd::StubInputTargeter>(),
4268+ std::make_shared<mtd::StubSurfaceController>());
4269+
4270+ focus_mechanism.set_focus_to(mt::fake_shared(app1));
4271+ focus_mechanism.set_focus_to(mt::fake_shared(app2));
4272+}
4273+
4274+TEST(DefaultFocusMechanism, sets_input_focus)
4275+{
4276+ using namespace ::testing;
4277+
4278+ NiceMock<mtd::MockShellSession> app1;
4279+ mtd::MockSurface mock_surface(&app1, std::make_shared<mtd::StubSurfaceBuilder>());
4280+ {
4281+ InSequence seq;
4282+ EXPECT_CALL(app1, default_surface()).Times(1)
4283+ .WillOnce(Return(mt::fake_shared(mock_surface)));
4284+ EXPECT_CALL(app1, default_surface()).Times(1)
4285+ .WillOnce(Return(std::shared_ptr<msh::Surface>()));
4286+ }
4287+
4288+ mtd::MockInputTargeter targeter;
4289+
4290+ msh::DefaultFocusMechanism focus_mechanism(mt::fake_shared(targeter), std::make_shared<mtd::StubSurfaceController>());
4291+
4292+ {
4293+ InSequence seq;
4294+ EXPECT_CALL(mock_surface, take_input_focus(_)).Times(1);
4295+ // When we have no default surface.
4296+ EXPECT_CALL(targeter, focus_cleared()).Times(1);
4297+ // When we have no session.
4298+ EXPECT_CALL(targeter, focus_cleared()).Times(1);
4299+ }
4300+
4301+ focus_mechanism.set_focus_to(mt::fake_shared(app1));
4302+ focus_mechanism.set_focus_to(mt::fake_shared(app1));
4303+ focus_mechanism.set_focus_to(std::shared_ptr<msh::Session>());
4304 }
4305
4306=== renamed file 'tests/unit-tests/shell/test_mediating_display_changer.cpp.moved' => 'tests/unit-tests/shell/test_mediating_display_changer.cpp'
4307=== removed file 'tests/unit-tests/shell/test_mediating_display_changer.cpp'
4308--- tests/unit-tests/shell/test_mediating_display_changer.cpp 2013-08-13 22:17:09 +0000
4309+++ tests/unit-tests/shell/test_mediating_display_changer.cpp 1970-01-01 00:00:00 +0000
4310@@ -1,179 +0,0 @@
4311-/*
4312- * Copyright © 2013 Canonical Ltd.
4313- *
4314- * This program is free software: you can redistribute it and/or modify
4315- * it under the terms of the GNU General Public License version 3 as
4316- * published by the Free Software Foundation.
4317- *
4318- * This program is distributed in the hope that it will be useful,
4319- * but WITHOUT ANY WARRANTY; without even the implied warranty of
4320- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4321- * GNU General Public License for more details.
4322- *
4323- * You should have received a copy of the GNU General Public License
4324- * along with this program. If not, see <http://www.gnu.org/licenses/>.
4325- *
4326- * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
4327- */
4328-
4329-#include "mir/shell/mediating_display_changer.h"
4330-#include "mir/shell/session.h"
4331-#include "mir/compositor/compositor.h"
4332-
4333-#include "mir_test_doubles/mock_display_changer.h"
4334-#include "mir_test_doubles/mock_session.h"
4335-#include "mir_test_doubles/stub_session.h"
4336-#include "mir_test_doubles/mock_display.h"
4337-#include "mir_test_doubles/null_display_configuration.h"
4338-#include "mir_test/fake_shared.h"
4339-#include <gtest/gtest.h>
4340-
4341-namespace mc = mir::compositor;
4342-namespace mf = mir::frontend;
4343-namespace mg = mir::graphics;
4344-namespace msh = mir::shell;
4345-namespace mt = mir::test;
4346-namespace mtd = mt::doubles;
4347-
4348-namespace
4349-{
4350-struct MockCompositor : public mc::Compositor
4351-{
4352- MOCK_METHOD0(start, void());
4353- MOCK_METHOD0(stop, void());
4354-};
4355-
4356-}
4357-
4358-struct MediatingDisplayChangerTest : public ::testing::Test
4359-{
4360- void SetUp()
4361- {
4362- using namespace testing;
4363- ON_CALL(mock_display, configuration())
4364- .WillByDefault(Return(mt::fake_shared(default_config)));
4365- }
4366- mtd::MockDisplay mock_display;
4367- MockCompositor mock_compositor;
4368-
4369- mtd::NullDisplayConfiguration default_config;
4370-};
4371-
4372-TEST_F(MediatingDisplayChangerTest, display_info)
4373-{
4374- using namespace testing;
4375- mtd::NullDisplayConfiguration conf;
4376- EXPECT_CALL(mock_display, configuration())
4377- .Times(1)
4378- .WillOnce(Return(mt::fake_shared(conf)));
4379-
4380- msh::MediatingDisplayChanger changer(mt::fake_shared(mock_display),
4381- mt::fake_shared(mock_compositor));
4382- auto returned_conf = changer.active_configuration();
4383- EXPECT_EQ(&conf, returned_conf.get());
4384-}
4385-
4386-namespace
4387-{
4388-struct StubShellSession : public msh::Session
4389-{
4390- mf::SurfaceId create_surface(msh::SurfaceCreationParameters const&)
4391- {
4392- return mf::SurfaceId{0};
4393- }
4394- void destroy_surface(mf::SurfaceId)
4395- {
4396- }
4397- std::shared_ptr<mf::Surface> get_surface(mf::SurfaceId) const
4398- {
4399- return std::shared_ptr<mf::Surface>();
4400- }
4401-
4402- std::string name() const
4403- {
4404- return std::string();
4405- }
4406- void force_requests_to_complete()
4407- {
4408- }
4409- void hide()
4410- {
4411- }
4412- void show()
4413- {
4414- }
4415- int configure_surface(mf::SurfaceId, MirSurfaceAttrib, int)
4416- {
4417- return 0;
4418- }
4419- void send_display_config(mg::DisplayConfiguration const&)
4420- {
4421- }
4422- void take_snapshot(msh::SnapshotCallback const&)
4423- {
4424- }
4425- std::shared_ptr<msh::Surface> default_surface() const
4426- {
4427- return std::shared_ptr<msh::Surface>();
4428- }
4429-
4430-};
4431-}
4432-
4433-namespace
4434-{
4435-MATCHER_P(ConfigPtrsMatch, config_ptr, "")
4436-{
4437- return (&arg == config_ptr);
4438-}
4439-
4440-}
4441-TEST_F(MediatingDisplayChangerTest, display_configure)
4442-{
4443- using namespace testing;
4444-
4445- auto session1 = std::make_shared<StubShellSession>();
4446- auto session2 = std::make_shared<StubShellSession>();
4447- auto base_config = std::make_shared<mtd::NullDisplayConfiguration>();
4448- auto applied_config1 = std::make_shared<mtd::NullDisplayConfiguration>();
4449- auto applied_config2 = std::make_shared<mtd::NullDisplayConfiguration>();
4450-
4451- //get base config
4452- EXPECT_CALL(mock_display, configuration())
4453- .Times(1)
4454- .WillOnce(Return(base_config));
4455-
4456- //apply session config
4457- Sequence seq;
4458- EXPECT_CALL(mock_compositor, stop())
4459- .InSequence(seq);
4460- EXPECT_CALL(mock_display, configure(ConfigPtrsMatch(applied_config1.get())))
4461- .InSequence(seq);
4462- EXPECT_CALL(mock_compositor, start())
4463- .InSequence(seq);
4464-
4465- EXPECT_CALL(mock_compositor, stop())
4466- .InSequence(seq);
4467- EXPECT_CALL(mock_display, configure(ConfigPtrsMatch(applied_config2.get())))
4468- .InSequence(seq);
4469- EXPECT_CALL(mock_compositor, start())
4470- .InSequence(seq);
4471-
4472- //apply base config
4473- EXPECT_CALL(mock_compositor, stop())
4474- .InSequence(seq);
4475- EXPECT_CALL(mock_display, configure(ConfigPtrsMatch(base_config.get())))
4476- .InSequence(seq);
4477- EXPECT_CALL(mock_compositor, start())
4478- .InSequence(seq);
4479-
4480- msh::MediatingDisplayChanger changer(mt::fake_shared(mock_display),
4481- mt::fake_shared(mock_compositor));
4482-
4483- changer.store_configuration_for(session1, applied_config1);
4484- changer.store_configuration_for(session2, applied_config2);
4485- changer.apply_configuration_of(session1);
4486- changer.apply_configuration_of(session2);
4487- changer.remove_configuration_for(session2);
4488- changer.remove_configuration_for(session1);
4489-}
4490
4491=== modified file 'tests/unit-tests/shell/test_session_manager.cpp'
4492--- tests/unit-tests/shell/test_session_manager.cpp 2013-08-13 22:17:09 +0000
4493+++ tests/unit-tests/shell/test_session_manager.cpp 2013-08-09 03:39:35 +0000
4494@@ -26,12 +26,9 @@
4495 #include "mir/shell/null_session_listener.h"
4496 #include "mir/shell/surface_creation_parameters.h"
4497 #include "mir/surfaces/surface.h"
4498-#include "mir/graphics/display_configuration.h"
4499
4500 #include "mir_test/fake_shared.h"
4501 #include "mir_test_doubles/mock_buffer_stream.h"
4502-#include "mir_test_doubles/mock_display_changer.h"
4503-#include "mir_test_doubles/mock_session.h"
4504 #include "mir_test_doubles/mock_surface_factory.h"
4505 #include "mir_test_doubles/mock_focus_setter.h"
4506 #include "mir_test_doubles/mock_session_listener.h"
4507@@ -45,7 +42,6 @@
4508
4509 namespace mc = mir::compositor;
4510 namespace mf = mir::frontend;
4511-namespace mg = mir::graphics;
4512 namespace msh = mir::shell;
4513 namespace ms = mir::surfaces;
4514 namespace geom = mir::geometry;
4515@@ -63,15 +59,22 @@
4516 ~MockSessionContainer() noexcept {}
4517 };
4518
4519+struct MockFocusSequence : public msh::FocusSequence
4520+{
4521+ MOCK_CONST_METHOD1(successor_of, std::shared_ptr<msh::Session>(std::shared_ptr<msh::Session> const&));
4522+ MOCK_CONST_METHOD1(predecessor_of, std::shared_ptr<msh::Session>(std::shared_ptr<msh::Session> const&));
4523+ MOCK_CONST_METHOD0(default_focus, std::shared_ptr<msh::Session>());
4524+};
4525+
4526 struct SessionManagerSetup : public testing::Test
4527 {
4528 SessionManagerSetup()
4529 : session_manager(mt::fake_shared(surface_factory),
4530 mt::fake_shared(container),
4531+ mt::fake_shared(focus_sequence),
4532 mt::fake_shared(focus_setter),
4533 std::make_shared<mtd::NullSnapshotStrategy>(),
4534- mt::fake_shared(session_listener),
4535- mt::fake_shared(mock_display_changer))
4536+ mt::fake_shared(session_listener))
4537 {
4538 }
4539
4540@@ -79,85 +82,127 @@
4541 mtd::StubSurfaceController surface_controller;
4542 mtd::MockSurfaceFactory surface_factory;
4543 testing::NiceMock<MockSessionContainer> container; // Inelegant but some tests need a stub
4544+ MockFocusSequence focus_sequence;
4545+ testing::NiceMock<mtd::MockFocusSetter> focus_setter; // Inelegant but some tests need a stub
4546+ msh::NullSessionListener session_listener;
4547+
4548+ msh::SessionManager session_manager;
4549+};
4550+
4551+}
4552+
4553+TEST_F(SessionManagerSetup, open_and_close_session)
4554+{
4555+ using namespace ::testing;
4556+
4557+ EXPECT_CALL(container, insert_session(_)).Times(1);
4558+ EXPECT_CALL(container, remove_session(_)).Times(1);
4559+ EXPECT_CALL(focus_setter, set_focus_to(_));
4560+ EXPECT_CALL(focus_setter, set_focus_to(std::shared_ptr<msh::Session>())).Times(1);
4561+
4562+ EXPECT_CALL(focus_sequence, default_focus()).WillOnce(Return((std::shared_ptr<msh::Session>())));
4563+
4564+ auto session = session_manager.open_session("Visual Basic Studio", std::shared_ptr<mf::EventSink>());
4565+ session_manager.close_session(session);
4566+}
4567+
4568+TEST_F(SessionManagerSetup, closing_session_removes_surfaces)
4569+{
4570+ using namespace ::testing;
4571+
4572+ EXPECT_CALL(surface_factory, create_surface(_, _, _, _)).Times(1);
4573+
4574+ ON_CALL(surface_factory, create_surface(_, _, _, _)).WillByDefault(
4575+ Return(std::make_shared<msh::Surface>(
4576+ nullptr,
4577+ mt::fake_shared(surface_builder), std::make_shared<mtd::NullSurfaceConfigurator>(),
4578+ msh::a_surface(),mf::SurfaceId{}, std::shared_ptr<mf::EventSink>())));
4579+
4580+
4581+ EXPECT_CALL(container, insert_session(_)).Times(1);
4582+ EXPECT_CALL(container, remove_session(_)).Times(1);
4583+
4584+ EXPECT_CALL(focus_setter, set_focus_to(_)).Times(1);
4585+ EXPECT_CALL(focus_setter, set_focus_to(std::shared_ptr<msh::Session>())).Times(1);
4586+
4587+ EXPECT_CALL(focus_sequence, default_focus()).WillOnce(Return((std::shared_ptr<msh::Session>())));
4588+
4589+ auto session = session_manager.open_session("Visual Basic Studio", std::shared_ptr<mf::EventSink>());
4590+ session->create_surface(msh::a_surface().of_size(geom::Size{geom::Width{1024}, geom::Height{768}}));
4591+
4592+ session_manager.close_session(session);
4593+}
4594+
4595+TEST_F(SessionManagerSetup, new_applications_receive_focus)
4596+{
4597+ using namespace ::testing;
4598+ std::shared_ptr<msh::Session> new_session;
4599+
4600+ EXPECT_CALL(container, insert_session(_)).Times(1);
4601+ EXPECT_CALL(focus_setter, set_focus_to(_)).WillOnce(SaveArg<0>(&new_session));
4602+
4603+ auto session = session_manager.open_session("Visual Basic Studio", std::shared_ptr<mf::EventSink>());
4604+ EXPECT_EQ(session, new_session);
4605+}
4606+
4607+TEST_F(SessionManagerSetup, create_surface_for_session_forwards_and_then_focuses_session)
4608+{
4609+ using namespace ::testing;
4610+ ON_CALL(surface_factory, create_surface(_, _, _, _)).WillByDefault(
4611+ Return(std::make_shared<msh::Surface>(
4612+ nullptr,
4613+ mt::fake_shared(surface_builder), std::make_shared<mtd::NullSurfaceConfigurator>(),
4614+ msh::a_surface(),mf::SurfaceId{}, std::shared_ptr<mf::EventSink>())));
4615+
4616+ // Once for session creation and once for surface creation
4617+ {
4618+ InSequence seq;
4619+
4620+ EXPECT_CALL(focus_setter, set_focus_to(_)).Times(1); // Session creation
4621+ EXPECT_CALL(surface_factory, create_surface(_, _, _, _)).Times(1);
4622+ EXPECT_CALL(focus_setter, set_focus_to(_)).Times(1); // Post Surface creation
4623+ }
4624+
4625+ auto session1 = session_manager.open_session("Weather Report", std::shared_ptr<mf::EventSink>());
4626+ session_manager.create_surface_for(session1, msh::a_surface());
4627+}
4628+
4629+namespace
4630+{
4631+
4632+struct SessionManagerSessionListenerSetup : public testing::Test
4633+{
4634+ SessionManagerSessionListenerSetup()
4635+ : session_manager(mt::fake_shared(surface_factory),
4636+ mt::fake_shared(container),
4637+ mt::fake_shared(focus_sequence),
4638+ mt::fake_shared(focus_setter),
4639+ std::make_shared<mtd::NullSnapshotStrategy>(),
4640+ mt::fake_shared(session_listener))
4641+ {
4642+ }
4643+
4644+ mtd::MockSurfaceFactory surface_factory;
4645+ testing::NiceMock<MockSessionContainer> container; // Inelegant but some tests need a stub
4646+ testing::NiceMock<MockFocusSequence> focus_sequence;
4647 testing::NiceMock<mtd::MockFocusSetter> focus_setter; // Inelegant but some tests need a stub
4648 mtd::MockSessionListener session_listener;
4649- testing::NiceMock<mtd::MockDisplayChanger> mock_display_changer;
4650
4651 msh::SessionManager session_manager;
4652 };
4653-
4654 }
4655
4656-TEST_F(SessionManagerSetup, open_and_close_session)
4657+TEST_F(SessionManagerSessionListenerSetup, session_listener_is_notified_of_lifecycle_and_focus)
4658 {
4659 using namespace ::testing;
4660
4661- Sequence seq;
4662- EXPECT_CALL(container, insert_session(_))
4663- .InSequence(seq);
4664- EXPECT_CALL(session_listener, starting(_))
4665- .InSequence(seq);
4666- EXPECT_CALL(focus_setter, session_opened(_))
4667- .InSequence(seq);
4668-
4669- EXPECT_CALL(container, remove_session(_))
4670- .InSequence(seq);
4671- EXPECT_CALL(session_listener, stopping(_))
4672- .InSequence(seq);
4673- EXPECT_CALL(focus_setter, session_closed(_))
4674- .InSequence(seq);
4675-
4676- auto session = session_manager.open_session("Visual Basic Studio", std::shared_ptr<mf::EventSink>());
4677- session_manager.close_session(session);
4678-}
4679-
4680-TEST_F(SessionManagerSetup, create_surface)
4681-{
4682- using namespace testing;
4683-
4684- std::shared_ptr<mf::Session> session;
4685- EXPECT_CALL(focus_setter, surface_created_for(_))
4686- .Times(1);
4687-
4688- session_manager.handle_surface_created(session);
4689-}
4690-
4691-namespace
4692-{
4693-struct MockShellSession : public msh::Session
4694-{
4695- MOCK_METHOD1(create_surface, mf::SurfaceId(msh::SurfaceCreationParameters const&));
4696- MOCK_METHOD1(destroy_surface, void(mf::SurfaceId));
4697- MOCK_CONST_METHOD1(get_surface, std::shared_ptr<mf::Surface>(mf::SurfaceId));
4698-
4699- MOCK_METHOD1(take_snapshot, void(msh::SnapshotCallback const&));
4700- MOCK_CONST_METHOD0(default_surface, std::shared_ptr<msh::Surface>());
4701-
4702- MOCK_CONST_METHOD0(name, std::string());
4703- MOCK_METHOD0(force_requests_to_complete, void());
4704-
4705- MOCK_METHOD0(hide, void());
4706- MOCK_METHOD0(show, void());
4707+ EXPECT_CALL(session_listener, starting(_)).Times(1);
4708+ EXPECT_CALL(session_listener, focused(_)).Times(1);
4709+ EXPECT_CALL(session_listener, stopping(_)).Times(1);
4710+ EXPECT_CALL(session_listener, unfocused()).Times(1);
4711+
4712+ EXPECT_CALL(focus_sequence, default_focus()).WillOnce(Return((std::shared_ptr<msh::Session>())));
4713
4714- MOCK_METHOD3(configure_surface, int(mf::SurfaceId, MirSurfaceAttrib, int));
4715- MOCK_METHOD1(send_display_config, void(mg::DisplayConfiguration const&));
4716-};
4717-}
4718-
4719-TEST_F(SessionManagerSetup, display_change_configuration)
4720-{
4721- using namespace testing;
4722-
4723- auto session1 = std::make_shared<MockShellSession>();
4724- auto session2 = std::make_shared<MockShellSession>();
4725-
4726- EXPECT_CALL(focus_setter, focused_session())
4727- .Times(2)
4728- .WillOnce(Return(session1))
4729- .WillOnce(Return(session2));
4730- EXPECT_CALL(mock_display_changer, apply_configuration_of(_))
4731- .Times(1);
4732-
4733- session_manager.handle_display_configuration(session2);
4734- session_manager.handle_display_configuration(session2);
4735+ auto session = session_manager.open_session("XPlane", std::shared_ptr<mf::EventSink>());
4736+ session_manager.close_session(session);
4737 }
4738
4739=== modified file 'tests/unit-tests/shell/test_surface.cpp'
4740--- tests/unit-tests/shell/test_surface.cpp 2013-08-09 03:39:35 +0000
4741+++ tests/unit-tests/shell/test_surface.cpp 2013-08-13 22:17:10 +0000
4742@@ -21,6 +21,8 @@
4743 #include "mir/shell/surface_creation_parameters.h"
4744 #include "mir/surfaces/surface_stack_model.h"
4745 #include "mir/shell/surface_builder.h"
4746+#include "mir/frontend/event_sink.h"
4747+#include "mir/graphics/display_configuration.h"
4748
4749 #include "mir_test_doubles/stub_surface_controller.h"
4750 #include "mir_test_doubles/mock_surface_controller.h"
4751@@ -35,6 +37,7 @@
4752 #include "mir_test_doubles/null_surface_configurator.h"
4753 #include "mir_test_doubles/mock_surface_configurator.h"
4754 #include "mir_test/fake_shared.h"
4755+#include "mir_test/event_matchers.h"
4756
4757 #include <stdexcept>
4758 #include <gmock/gmock.h>
4759@@ -52,6 +55,14 @@
4760
4761 namespace
4762 {
4763+
4764+struct MockEventSink : public mf::EventSink
4765+{
4766+ ~MockEventSink() noexcept(true) {}
4767+ MOCK_METHOD1(handle_event, void(MirEvent const&));
4768+ MOCK_METHOD1(handle_display_config_change, void(mg::DisplayConfiguration const&));
4769+};
4770+
4771 class StubSurfaceBuilder : public msh::SurfaceBuilder
4772 {
4773 public:
4774@@ -454,6 +465,29 @@
4775 EXPECT_EQ(mir_surface_state_fullscreen, surf.state());
4776 }
4777
4778+TEST_F(ShellSurface, focus)
4779+{
4780+ using namespace testing;
4781+
4782+ MockEventSink sink;
4783+
4784+ {
4785+ InSequence seq;
4786+ EXPECT_CALL(sink, handle_event(mt::SurfaceEvent(mir_surface_attrib_focus, mir_surface_focused)))
4787+ .Times(1);
4788+ EXPECT_CALL(sink, handle_event(mt::SurfaceEvent(mir_surface_attrib_focus, mir_surface_unfocused)))
4789+ .Times(1);
4790+ }
4791+
4792+ msh::Surface surf(
4793+ nullptr,
4794+ mt::fake_shared(surface_builder), std::make_shared<mtd::NullSurfaceConfigurator>(),
4795+ msh::a_surface(), stub_id, mt::fake_shared(sink));
4796+
4797+ surf.configure(mir_surface_attrib_focus, mir_surface_focused);
4798+ surf.configure(mir_surface_attrib_focus, mir_surface_unfocused);
4799+}
4800+
4801 TEST_F(ShellSurface, configurator_selects_attribute_values)
4802 {
4803 using namespace testing;
4804
4805=== modified file 'tests/unit-tests/shell/test_unauthorized_display_changer.cpp'
4806--- tests/unit-tests/shell/test_unauthorized_display_changer.cpp 2013-08-13 22:17:09 +0000
4807+++ tests/unit-tests/shell/test_unauthorized_display_changer.cpp 2013-08-12 17:20:29 +0000
4808@@ -36,17 +36,13 @@
4809 mtd::MockDisplayChanger underlying_changer;
4810 };
4811
4812-TEST_F(UnauthorizedDisplayChangerTest, change_store)
4813+TEST_F(UnauthorizedDisplayChangerTest, change_attempt)
4814 {
4815 mtd::NullDisplayConfiguration conf;
4816 msh::UnauthorizedDisplayChanger changer(mt::fake_shared(underlying_changer));
4817
4818 EXPECT_THROW({
4819- changer.store_configuration_for(std::weak_ptr<mf::Session>(), mt::fake_shared(conf));
4820- }, std::runtime_error);
4821-
4822- EXPECT_THROW({
4823- changer.apply_configuration_of(std::weak_ptr<mf::Session>());
4824+ changer.configure(std::weak_ptr<mf::Session>(), mt::fake_shared(conf));
4825 }, std::runtime_error);
4826 }
4827
4828@@ -62,11 +58,6 @@
4829 msh::UnauthorizedDisplayChanger changer(mt::fake_shared(underlying_changer));
4830
4831 auto returned_conf = changer.active_configuration();
4832-<<<<<<< TREE
4833
4834 EXPECT_EQ(&conf, returned_conf.get());
4835 }
4836-=======
4837- EXPECT_EQ(&conf, returned_conf.get());
4838-}
4839->>>>>>> MERGE-SOURCE

Subscribers

People subscribed via source and target branches