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: 4835 lines (+957/-1610)
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 (+12/-3)
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)
To merge this branch: bzr merge lp:~robertcarr/mir/client-focus-notifications
Reviewer Review Type Date Requested Status
Daniel van Vugt Needs Resubmitting
Alan Griffiths Needs Resubmitting
PS Jenkins bot (community) continuous-integration Approve
Alexandros Frantzis Pending
Chris Halse Rogers Pending
Review via email: mp+180011@code.launchpad.net

This proposal supersedes a proposal from 2013-08-12.

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

Commit message

Send focus notifications to clients.

Description of the change

Another iteration. This time I've removed the dependency on connect-display-request-merge-trunk. I've adapted the handle_surface_created idea from that branch (thanks kevin :D) to enable things to work without the cloggable sink.

Currently the shell mixes responsibilities of a factory interface, and reactive behavior (largely through acting as part of the factory/builder). I hope we can run with this and split out the factory part, in to classes which do that, and be left with a sensible interface like:

mf::Shell
{
handle_session_created
handle_sesssion_destroyed
handle_surface_created
handle_surface_destroyed
etc etc
}

The session mediator (and presumably a to be coming InternalClientMediator) then acts to notify the shell after building the objects.

=== Last description ==
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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

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 : Posted in a previous version of this proposal

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 : 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

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 : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:772
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/180011/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mir-ci/1296/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-android-saucy-i386-build/1727/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-clang-saucy-amd64-build/1612/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-saucy-amd64-ci/534/console

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

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

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

The diff is a mess. It is not a good idea to have a prerequisite branch (connect-display-request-merge-trunk) that's been rejected.

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

What Alan said.

review: Needs Resubmitting

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

Subscribers

People subscribed via source and target branches