Mir

Merge lp:~andreas-pokorny/mir/move-config-changer-to-input-thread into lp:mir

Proposed by Andreas Pokorny
Status: Merged
Approved by: Andreas Pokorny
Approved revision: no longer in the source branch.
Merged at revision: 4109
Proposed branch: lp:~andreas-pokorny/mir/move-config-changer-to-input-thread
Merge into: lp:mir
Diff against target: 1036 lines (+408/-127)
13 files modified
src/include/server/mir/default_server_configuration.h (+1/-0)
src/server/input/default_configuration.cpp (+7/-3)
src/server/input/default_input_device_hub.cpp (+119/-35)
src/server/input/default_input_device_hub.h (+25/-7)
tests/acceptance-tests/test_client_input.cpp (+3/-2)
tests/acceptance-tests/test_input_device_hub.cpp (+4/-2)
tests/acceptance-tests/test_nested_input.cpp (+8/-7)
tests/include/mir/test/doubles/mock_device.h (+71/-0)
tests/integration-tests/input/test_single_seat_setup.cpp (+26/-26)
tests/unit-tests/input/CMakeLists.txt (+1/-0)
tests/unit-tests/input/test_config_changer.cpp (+3/-30)
tests/unit-tests/input/test_default_input_device_hub.cpp (+21/-15)
tests/unit-tests/input/test_external_input_device_hub.cpp (+119/-0)
To merge this branch: bzr merge lp:~andreas-pokorny/mir/move-config-changer-to-input-thread
Reviewer Review Type Date Requested Status
Mir CI Bot continuous-integration Approve
Alexandros Frantzis (community) Approve
Alan Griffiths Approve
Review via email: mp+319840@code.launchpad.net

Commit message

Move execution of InputDeviceObservers into input thread

To ensure that the messages about available input devices reach clients before respective input events and input device state events the InputDeviceObservers are now executed inside the same thread that dispatches the input events. Since downstream shells might also implement InputDeviceObservers, the existing behavior is kept due to a new wrapper around DefaultInputDeviceHub that runs inside the ServerActionQueue.

Description of the change

This is the alternative to
lp:~andreas-pokorny/mir/wait-for-input-config-before-emitting-input-state

Instead of catching the case inside the nested input platform the ordering is guaranteed because the mir::input::ConfigChanger receives the new devices before they get advertised to the seat or allowed to emit input events (via mir::InputDevice::start).

Maybe the attached bugs have already been fixed or are just more rare due to other changes:
* removal of the per-surface fds
* updated surface input dispatcher logic in mir::input::SurfaceInputDispatcher::for_each)

Still this change is closely related as it ensures that the input device state events will occur after respective input config messages. If the Input device state event happens before the first input config message containing the input devices it would be filtered out in the nested platform.

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

PASSED: Continuous integration, rev:4085
https://mir-jenkins.ubuntu.com/job/mir-ci/3159/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4238
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4325
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4315
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4315
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4315
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4265
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4265/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4265
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4265/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4265
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4265/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4265
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4265/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4265
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4265/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4265
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4265/artifact/output/*zip*/output.zip

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

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

PASSED: Continuous integration, rev:4086
https://mir-jenkins.ubuntu.com/job/mir-ci/3160/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4240
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4327
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4317
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4317
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4317
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4267
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4267/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4267
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4267/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4267
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4267/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4267
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4267/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4267
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4267/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4267
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4267/artifact/output/*zip*/output.zip

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

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

PASSED: Continuous integration, rev:4087
https://mir-jenkins.ubuntu.com/job/mir-ci/3165/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4247
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4334
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4324
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4324
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4324
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4274
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4274/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4274
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4274/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4274
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4274/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4274
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4274/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4274
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4274/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4274
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4274/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

OK

review: Approve
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

+ return std::make_shared<mi::ExternalInputDeviceHub>(the_default_input_device_hub(),
+ the_main_loop());

The ExternalInputDeviceHub doesn't hold a strong reference to the the_default_input_device_hub(), so
depending on the order of initialization (i.e., if we haven't already stored a strong reference to default_input_device_hub()) we will end up immediately destroying the default hub we just created.

Perhaps this doesn't actually happen in our current configuration, but it is currently not easy to reason about the correctness of the lifecycle, and this could be a pain point in future refactorings.

> void mi::ExternalInputDeviceHub::remove_observer
> mi::ExternalInputDeviceHub::for_each_input_device
> mi::ExternalInputDeviceHub::for_each_mutable_input_device

In the above function we are using the result of weak_ptr.lock() without checking if it's valid. Is it safe to do so?

Looks good otherwise.

review: Needs Information
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

> + return
> std::make_shared<mi::ExternalInputDeviceHub>(the_default_input_device_hub(),
> + the_main_loop());
>
> The ExternalInputDeviceHub doesn't hold a strong reference to the
> the_default_input_device_hub(), so
> depending on the order of initialization (i.e., if we haven't already stored a
> strong reference to default_input_device_hub()) we will end up immediately
> destroying the default hub we just created.
>
> Perhaps this doesn't actually happen in our current configuration, but it is
> currently not easy to reason about the correctness of the lifecycle, and this
> could be a pain point in future refactorings.

Yes the actual input device hub is kept alive via loaded platform / input manager / DisplayServer and also via ipc factory / Connector / DisplayServer. I am using a weak_ptr to avoid a cycle between hub and observers.

> > void mi::ExternalInputDeviceHub::remove_observer
> > mi::ExternalInputDeviceHub::for_each_input_device
> > mi::ExternalInputDeviceHub::for_each_mutable_input_device
>
> In the above function we are using the result of weak_ptr.lock() without
> checking if it's valid. Is it safe to do so?

Changed that..

I think I could also wrap weak_ptr to make it match Element concept of ThreadSafeList

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

PASSED: Continuous integration, rev:4088
https://mir-jenkins.ubuntu.com/job/mir-ci/3210/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4321
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4408
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4398
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4398
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4398
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4353
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4353/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4353
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4353/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4353
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4353/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4353
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4353/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4353
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4353/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4353
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4353/artifact/output/*zip*/output.zip

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

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

PASSED: Continuous integration, rev:4089
https://mir-jenkins.ubuntu.com/job/mir-ci/3212/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4323
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4410
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4400
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4400
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4400
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4355
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4355/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4355
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4355/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4355
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4355/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4355
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4355/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4355
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4355/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4355
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4355/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> Yes the actual input device hub is kept alive via loaded platform / input manager / DisplayServer
> and also via ipc factory / Connector / DisplayServer. I am using a weak_ptr to avoid a cycle
> between hub and observers.

Hmm, still... the fact that if one calls mir::DefaultServerConfiguration::the_input_device_hub() as the first or only input-related method, they will get a broken InputDeviceHub is super-unintuitive and makes me very uneasy.

Couldn't mi::ExternalInputDeviceHub hold a shared_ptr<> to the hub? It makes sense for a wrapper to hold a strong reference, not a weak one. The Internal/Observer class would continue to hold a weak_ptr (or even a raw pointer, if we can guarantee the related lifetimes) to break the cycle.

Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

> > Yes the actual input device hub is kept alive via loaded platform / input
> manager / DisplayServer
> > and also via ipc factory / Connector / DisplayServer. I am using a weak_ptr
> to avoid a cycle
> > between hub and observers.
>
> Hmm, still... the fact that if one calls
> mir::DefaultServerConfiguration::the_input_device_hub() as the first or only
> input-related method, they will get a broken InputDeviceHub is super-
> unintuitive and makes me very uneasy.
>
> Couldn't mi::ExternalInputDeviceHub hold a shared_ptr<> to the hub? It makes
> sense for a wrapper to hold a strong reference, not a weak one. The
> Internal/Observer class would continue to hold a weak_ptr (or even a raw
> pointer, if we can guarantee the related lifetimes) to break the cycle.

Oh I have not thought of that... pushed.

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

PASSED: Continuous integration, rev:4090
https://mir-jenkins.ubuntu.com/job/mir-ci/3216/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4328
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4415
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4405
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4405
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4405
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4360
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4360/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4360
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4360/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4360
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4360/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4360
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4360/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4360
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4360/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4360
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4360/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> + std::weak_ptr<InputDeviceHub> hub;

Seems this is not needed anymore?

> + auto observer = obs.lock();

Probably needs a validity check, unless there is an implied validity guarantee I am not aware of.

review: Needs Fixing
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

> > + std::weak_ptr<InputDeviceHub> hub;
>
> Seems this is not needed anymore?

oh right..

>
> > + auto observer = obs.lock();
>
> Probably needs a validity check, unless there is an implied validity guarantee
> I am not aware of.

Hm only that nothing happens if the validity check fails..

Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

Looks good.

> Hm only that nothing happens if the validity check fails..

Good point.

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

PASSED: Continuous integration, rev:4091
https://mir-jenkins.ubuntu.com/job/mir-ci/3226/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4341
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4428
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4418
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4418
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4418
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4373
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4373/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4373
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4373/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4373
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4373/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4373
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4373/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4373
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4373/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4373
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4373/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/include/server/mir/default_server_configuration.h'
--- src/include/server/mir/default_server_configuration.h 2017-03-13 08:12:52 +0000
+++ src/include/server/mir/default_server_configuration.h 2017-03-23 16:31:26 +0000
@@ -384,6 +384,7 @@
384 CachedPtr<input::InputManager> input_manager;384 CachedPtr<input::InputManager> input_manager;
385 CachedPtr<input::SurfaceInputDispatcher> surface_input_dispatcher;385 CachedPtr<input::SurfaceInputDispatcher> surface_input_dispatcher;
386 CachedPtr<input::DefaultInputDeviceHub> default_input_device_hub;386 CachedPtr<input::DefaultInputDeviceHub> default_input_device_hub;
387 CachedPtr<input::InputDeviceHub> input_device_hub;
387 CachedPtr<dispatch::MultiplexingDispatchable> input_reading_multiplexer;388 CachedPtr<dispatch::MultiplexingDispatchable> input_reading_multiplexer;
388 CachedPtr<input::InputDispatcher> input_dispatcher;389 CachedPtr<input::InputDispatcher> input_dispatcher;
389 CachedPtr<shell::InputTargeter> input_targeter;390 CachedPtr<shell::InputTargeter> input_targeter;
390391
=== modified file 'src/server/input/default_configuration.cpp'
--- src/server/input/default_configuration.cpp 2017-03-14 02:26:28 +0000
+++ src/server/input/default_configuration.cpp 2017-03-23 16:31:26 +0000
@@ -301,7 +301,12 @@
301301
302std::shared_ptr<mi::InputDeviceHub> mir::DefaultServerConfiguration::the_input_device_hub()302std::shared_ptr<mi::InputDeviceHub> mir::DefaultServerConfiguration::the_input_device_hub()
303{303{
304 return the_default_input_device_hub();304 return input_device_hub(
305 [this]()
306 {
307 return std::make_shared<mi::ExternalInputDeviceHub>(the_default_input_device_hub(),
308 the_main_loop());
309 });
305}310}
306311
307std::shared_ptr<mi::DefaultInputDeviceHub> mir::DefaultServerConfiguration::the_default_input_device_hub()312std::shared_ptr<mi::DefaultInputDeviceHub> mir::DefaultServerConfiguration::the_default_input_device_hub()
@@ -314,7 +319,6 @@
314 auto hub = std::make_shared<mi::DefaultInputDeviceHub>(319 auto hub = std::make_shared<mi::DefaultInputDeviceHub>(
315 the_seat(),320 the_seat(),
316 the_input_reading_multiplexer(),321 the_input_reading_multiplexer(),
317 the_main_loop(),
318 the_cookie_authority(),322 the_cookie_authority(),
319 the_key_mapper(),323 the_key_mapper(),
320 the_server_status_listener());324 the_server_status_listener());
@@ -359,7 +363,7 @@
359 return input_configuration_changer(363 return input_configuration_changer(
360 [this]()364 [this]()
361 {365 {
362 return std::make_shared<mi::ConfigChanger>(the_input_manager(), the_input_device_hub(), the_session_container(), the_session_event_handler_register());366 return std::make_shared<mi::ConfigChanger>(the_input_manager(), the_default_input_device_hub(), the_session_container(), the_session_event_handler_register());
363 }367 }
364 );368 );
365}369}
366370
=== modified file 'src/server/input/default_input_device_hub.cpp'
--- src/server/input/default_input_device_hub.cpp 2017-03-14 02:26:28 +0000
+++ src/server/input/default_input_device_hub.cpp 2017-03-23 16:31:26 +0000
@@ -41,16 +41,122 @@
4141
42namespace mi = mir::input;42namespace mi = mir::input;
4343
44struct mi::ExternalInputDeviceHub::Internal : InputDeviceObserver
45{
46 Internal(std::shared_ptr<ServerActionQueue> const& queue) :
47 observer_queue{queue}
48 {}
49 void device_added(std::shared_ptr<Device> const& device) override;
50 void device_changed(std::shared_ptr<Device> const& device) override;
51 void device_removed(std::shared_ptr<Device> const& device) override;
52 void changes_complete() override;
53
54 std::shared_ptr<ServerActionQueue> const observer_queue;
55 ThreadSafeList<std::shared_ptr<InputDeviceObserver>> observers;
56 std::vector<std::shared_ptr<Device>> devices_added;
57 std::vector<std::shared_ptr<Device>> devices_changed;
58 std::vector<std::shared_ptr<Device>> devices_removed;
59 std::vector<std::shared_ptr<Device>> handles;
60};
61
62mi::ExternalInputDeviceHub::ExternalInputDeviceHub(std::shared_ptr<mi::InputDeviceHub> const& hub, std::shared_ptr<mir::ServerActionQueue> const& queue)
63 : data{std::make_shared<mi::ExternalInputDeviceHub::Internal>(queue)}, hub{hub}
64{
65 hub->add_observer(data);
66}
67
68mi::ExternalInputDeviceHub::~ExternalInputDeviceHub()
69{
70 data->observer_queue->pause_processing_for(data.get());
71}
72
73void mi::ExternalInputDeviceHub::add_observer(std::shared_ptr<InputDeviceObserver> const& observer)
74{
75 data->observer_queue->enqueue(
76 data.get(),
77 [observer, data = this->data]
78 {
79 for (auto const& item : data->handles)
80 observer->device_added(item);
81 observer->changes_complete();
82 data->observers.add(observer);
83 });
84}
85
86void mi::ExternalInputDeviceHub::remove_observer(std::weak_ptr<InputDeviceObserver> const& obs)
87{
88 auto observer = obs.lock();
89 if (observer)
90 data->observers.remove(observer);
91}
92
93void mi::ExternalInputDeviceHub::for_each_input_device(std::function<void(Device const& device)> const& callback)
94{
95 hub->for_each_input_device(callback);
96}
97
98void mi::ExternalInputDeviceHub::for_each_mutable_input_device(std::function<void(Device& device)> const& callback)
99{
100 hub->for_each_mutable_input_device(callback);
101}
102
103void mi::ExternalInputDeviceHub::Internal::device_added(std::shared_ptr<Device> const& device)
104{
105 devices_added.push_back(device);
106}
107
108void mi::ExternalInputDeviceHub::Internal::device_changed(std::shared_ptr<Device> const& device)
109{
110 devices_changed.push_back(device);
111}
112
113void mi::ExternalInputDeviceHub::Internal::device_removed(std::shared_ptr<Device> const& device)
114{
115 devices_removed.push_back(device);
116}
117
118void mi::ExternalInputDeviceHub::Internal::changes_complete()
119{
120 decltype(devices_added) added, changed, removed;
121
122 std::swap(devices_added, added);
123 std::swap(devices_changed, changed);
124 std::swap(devices_removed, removed);
125
126 if (!(added.empty() && changed.empty() && removed.empty()))
127 observer_queue->enqueue(
128 this,
129 [this, added, changed, removed]
130 {
131 observers.for_each([&](std::shared_ptr<InputDeviceObserver> const& observer)
132 {
133 for (auto const& dev : added)
134 observer->device_added(dev);
135 for (auto const& dev : changed)
136 observer->device_changed(dev);
137 for (auto const& dev : removed)
138 observer->device_removed(dev);
139 observer->changes_complete();
140 });
141
142 auto end_it = handles.end();
143 for (auto const& dev : removed)
144 end_it = remove(begin(handles), end(handles), dev);
145 if (end_it != handles.end())
146 handles.erase(end_it, end(handles));
147 for (auto const& dev : added)
148 handles.push_back(dev);
149 });
150}
151
44mi::DefaultInputDeviceHub::DefaultInputDeviceHub(152mi::DefaultInputDeviceHub::DefaultInputDeviceHub(
45 std::shared_ptr<mi::Seat> const& seat,153 std::shared_ptr<mi::Seat> const& seat,
46 std::shared_ptr<dispatch::MultiplexingDispatchable> const& input_multiplexer,154 std::shared_ptr<dispatch::MultiplexingDispatchable> const& input_multiplexer,
47 std::shared_ptr<mir::ServerActionQueue> const& observer_queue,
48 std::shared_ptr<mir::cookie::Authority> const& cookie_authority,155 std::shared_ptr<mir::cookie::Authority> const& cookie_authority,
49 std::shared_ptr<mi::KeyMapper> const& key_mapper,156 std::shared_ptr<mi::KeyMapper> const& key_mapper,
50 std::shared_ptr<mir::ServerStatusListener> const& server_status_listener)157 std::shared_ptr<mir::ServerStatusListener> const& server_status_listener)
51 : seat{seat},158 : seat{seat},
52 input_dispatchable{input_multiplexer},159 input_dispatchable{input_multiplexer},
53 observer_queue(observer_queue),
54 device_queue(std::make_shared<dispatch::ActionQueue>()),160 device_queue(std::make_shared<dispatch::ActionQueue>()),
55 cookie_authority(cookie_authority),161 cookie_authority(cookie_authority),
56 key_mapper(key_mapper),162 key_mapper(key_mapper),
@@ -81,17 +187,10 @@
81 device, id, input_dispatchable, cookie_authority, handle));187 device, id, input_dispatchable, cookie_authority, handle));
82188
83 auto const& dev = devices.back();189 auto const& dev = devices.back();
190 add_device_handle(handle);
84191
85 seat->add_device(*handle);192 seat->add_device(*handle);
86 dev->start(seat);193 dev->start(seat);
87
88 // pass input device handle to observer loop..
89 observer_queue->enqueue(this,
90 [this, handle]()
91 {
92 add_device_handle(handle);
93 });
94
95 }194 }
96 else195 else
97 {196 {
@@ -118,13 +217,7 @@
118 seat->remove_device(*item->handle);217 seat->remove_device(*item->handle);
119 item->stop();218 item->stop();
120 }219 }
121 // send input device info to observer queue..220 remove_device_handle(item->id());
122 observer_queue->enqueue(
123 this,
124 [this,id = item->id()]()
125 {
126 remove_device_handle(id);
127 });
128221
129 return true;222 return true;
130 }223 }
@@ -230,18 +323,15 @@
230323
231void mi::DefaultInputDeviceHub::add_observer(std::shared_ptr<InputDeviceObserver> const& observer)324void mi::DefaultInputDeviceHub::add_observer(std::shared_ptr<InputDeviceObserver> const& observer)
232{325{
233 observer_queue->enqueue(326 device_queue->enqueue(
234 this,327 [this,observer]()
235 [observer,this]
236 {328 {
329 std::unique_lock<std::mutex> lock(handles_guard);
330 for (auto const& item : handles)
331 observer->device_added(item);
332 observer->changes_complete();
237 observers.add(observer);333 observers.add(observer);
238 for (auto const& item : handles)334 });
239 {
240 observer->device_added(item);
241 }
242 observer->changes_complete();
243 }
244 );
245}335}
246336
247void mi::DefaultInputDeviceHub::for_each_input_device(std::function<void(Device const&)> const& callback)337void mi::DefaultInputDeviceHub::for_each_input_device(std::function<void(Device const&)> const& callback)
@@ -270,12 +360,7 @@
270void mi::DefaultInputDeviceHub::remove_observer(std::weak_ptr<InputDeviceObserver> const& element)360void mi::DefaultInputDeviceHub::remove_observer(std::weak_ptr<InputDeviceObserver> const& element)
271{361{
272 auto observer = element.lock();362 auto observer = element.lock();
273363 observers.remove(observer);
274 observer_queue->enqueue(this,
275 [observer, this]
276 {
277 observers.remove(observer);
278 });
279}364}
280365
281void mi::DefaultInputDeviceHub::add_device_handle(std::shared_ptr<DefaultDevice> const& handle)366void mi::DefaultInputDeviceHub::add_device_handle(std::shared_ptr<DefaultDevice> const& handle)
@@ -285,7 +370,7 @@
285 handles.push_back(handle);370 handles.push_back(handle);
286 }371 }
287372
288 observers.for_each([&handle](std::shared_ptr<InputDeviceObserver> const& observer)373 observers.for_each([&handle, this](std::shared_ptr<InputDeviceObserver> const& observer)
289 {374 {
290 observer->device_added(handle);375 observer->device_added(handle);
291 observer->changes_complete();376 observer->changes_complete();
@@ -395,4 +480,3 @@
395 });480 });
396 }481 }
397}482}
398
399483
=== modified file 'src/server/input/default_input_device_hub.h'
--- src/server/input/default_input_device_hub.h 2017-03-20 11:44:40 +0000
+++ src/server/input/default_input_device_hub.h 2017-03-23 16:31:26 +0000
@@ -25,6 +25,7 @@
25#include "mir/input/input_sink.h"25#include "mir/input/input_sink.h"
26#include "mir/input/seat.h"26#include "mir/input/seat.h"
27#include "mir/input/input_device_hub.h"27#include "mir/input/input_device_hub.h"
28#include "mir/input/input_device_observer.h"
28#include "mir/input/input_device_info.h"29#include "mir/input/input_device_info.h"
29#include "mir/input/mir_input_config.h"30#include "mir/input/mir_input_config.h"
30#include "mir/thread_safe_list.h"31#include "mir/thread_safe_list.h"
@@ -57,13 +58,32 @@
57class DefaultDevice;58class DefaultDevice;
58class Seat;59class Seat;
59class KeyMapper;60class KeyMapper;
6061class DefaultInputDeviceHub;
61class DefaultInputDeviceHub : public InputDeviceRegistry, public InputDeviceHub62
63struct ExternalInputDeviceHub : InputDeviceHub
64{
65 ExternalInputDeviceHub(std::shared_ptr<InputDeviceHub> const& actual_hub,
66 std::shared_ptr<ServerActionQueue> const& observer_queue);
67 ~ExternalInputDeviceHub();
68
69 void add_observer(std::shared_ptr<InputDeviceObserver> const&) override;
70 void remove_observer(std::weak_ptr<InputDeviceObserver> const&) override;
71 void for_each_input_device(std::function<void(Device const& device)> const& callback) override;
72 void for_each_mutable_input_device(std::function<void(Device& device)> const& callback) override;
73
74private:
75 struct Internal;
76 std::shared_ptr<Internal> data;
77 std::shared_ptr<InputDeviceHub> hub;
78};
79
80class DefaultInputDeviceHub :
81 public InputDeviceRegistry,
82 public InputDeviceHub
62{83{
63public:84public:
64 DefaultInputDeviceHub(std::shared_ptr<Seat> const& seat,85 DefaultInputDeviceHub(std::shared_ptr<Seat> const& seat,
65 std::shared_ptr<dispatch::MultiplexingDispatchable> const& input_multiplexer,86 std::shared_ptr<dispatch::MultiplexingDispatchable> const& input_multiplexer,
66 std::shared_ptr<ServerActionQueue> const& observer_queue,
67 std::shared_ptr<cookie::Authority> const& cookie_authority,87 std::shared_ptr<cookie::Authority> const& cookie_authority,
68 std::shared_ptr<KeyMapper> const& key_mapper,88 std::shared_ptr<KeyMapper> const& key_mapper,
69 std::shared_ptr<ServerStatusListener> const& server_status_listener);89 std::shared_ptr<ServerStatusListener> const& server_status_listener);
@@ -77,18 +97,16 @@
77 void remove_observer(std::weak_ptr<InputDeviceObserver> const&) override;97 void remove_observer(std::weak_ptr<InputDeviceObserver> const&) override;
78 void for_each_input_device(std::function<void(Device const& device)> const& callback) override;98 void for_each_input_device(std::function<void(Device const& device)> const& callback) override;
79 void for_each_mutable_input_device(std::function<void(Device& device)> const& callback) override;99 void for_each_mutable_input_device(std::function<void(Device& device)> const& callback) override;
80
81
82private:100private:
83 void add_device_handle(std::shared_ptr<DefaultDevice> const& handle);101 void add_device_handle(std::shared_ptr<DefaultDevice> const& handle);
84 void remove_device_handle(MirInputDeviceId id);102 void remove_device_handle(MirInputDeviceId id);
85 void device_changed(Device* dev);103 void device_changed(Device* dev);
86 void emit_changed_devices();104 void emit_changed_devices();
87 MirInputDeviceId create_new_device_id();105 MirInputDeviceId create_new_device_id();
106
88 std::shared_ptr<Seat> const seat;107 std::shared_ptr<Seat> const seat;
89 std::shared_ptr<dispatch::MultiplexingDispatchable> const input_dispatchable;108 std::shared_ptr<dispatch::MultiplexingDispatchable> const input_dispatchable;
90 std::mutex handles_guard;109 std::mutex mutable handles_guard;
91 std::shared_ptr<ServerActionQueue> const observer_queue;
92 std::shared_ptr<dispatch::ActionQueue> const device_queue;110 std::shared_ptr<dispatch::ActionQueue> const device_queue;
93 std::shared_ptr<cookie::Authority> const cookie_authority;111 std::shared_ptr<cookie::Authority> const cookie_authority;
94 std::shared_ptr<KeyMapper> const key_mapper;112 std::shared_ptr<KeyMapper> const key_mapper;
95113
=== modified file 'tests/acceptance-tests/test_client_input.cpp'
--- tests/acceptance-tests/test_client_input.cpp 2017-03-22 07:01:56 +0000
+++ tests/acceptance-tests/test_client_input.cpp 2017-03-23 16:31:26 +0000
@@ -343,12 +343,13 @@
343 devices_available.raise();343 devices_available.raise();
344 });344 });
345345
346 server.the_input_device_hub()->add_observer(counter);346 auto hub = server.the_input_device_hub();
347 hub->add_observer(counter);
347348
348 devices_available.wait_for(5s);349 devices_available.wait_for(5s);
349 ASSERT_THAT(counter->count_devices, Eq(expected_number_of_input_devices));350 ASSERT_THAT(counter->count_devices, Eq(expected_number_of_input_devices));
350351
351 server.the_input_device_hub()->remove_observer(counter);352 hub->remove_observer(counter);
352 }353 }
353354
354 MirInputDevice const* get_device_with_capabilities(MirInputConfig const* config, MirInputDeviceCapabilities caps)355 MirInputDevice const* get_device_with_capabilities(MirInputConfig const* config, MirInputDeviceCapabilities caps)
355356
=== modified file 'tests/acceptance-tests/test_input_device_hub.cpp'
--- tests/acceptance-tests/test_input_device_hub.cpp 2017-01-18 02:29:37 +0000
+++ tests/acceptance-tests/test_input_device_hub.cpp 2017-03-23 16:31:26 +0000
@@ -60,7 +60,8 @@
60 EXPECT_CALL(observer, changes_complete())60 EXPECT_CALL(observer, changes_complete())
61 .WillOnce(mt::WakeUp(&observer_registered));61 .WillOnce(mt::WakeUp(&observer_registered));
6262
63 server.the_input_device_hub()->add_observer(mt::fake_shared(observer));63 auto device_hub = server.the_input_device_hub();
64 device_hub->add_observer(mt::fake_shared(observer));
64 observer_registered.wait_for(std::chrono::seconds{4});65 observer_registered.wait_for(std::chrono::seconds{4});
65}66}
6667
@@ -75,7 +76,8 @@
75 EXPECT_CALL(observer, changes_complete())76 EXPECT_CALL(observer, changes_complete())
76 .WillOnce(mt::WakeUp(&callbacks_received));77 .WillOnce(mt::WakeUp(&callbacks_received));
7778
78 server.the_input_device_hub()->add_observer(mt::fake_shared(observer));79 auto device_hub = server.the_input_device_hub();
80 device_hub->add_observer(mt::fake_shared(observer));
79 observer_registered.wait_for(std::chrono::seconds{4});81 observer_registered.wait_for(std::chrono::seconds{4});
8082
81 keep_on_living = mtf::add_fake_input_device(mi::InputDeviceInfo{"keyboard", "keyboard-uid", mir::input::DeviceCapability::keyboard});83 keep_on_living = mtf::add_fake_input_device(mi::InputDeviceInfo{"keyboard", "keyboard-uid", mir::input::DeviceCapability::keyboard});
8284
=== modified file 'tests/acceptance-tests/test_nested_input.cpp'
--- tests/acceptance-tests/test_nested_input.cpp 2017-03-16 03:23:51 +0000
+++ tests/acceptance-tests/test_nested_input.cpp 2017-03-23 16:31:26 +0000
@@ -112,13 +112,12 @@
112112
113struct NestedInput : public mtf::HeadlessInProcessServer113struct NestedInput : public mtf::HeadlessInProcessServer
114{114{
115
116 void SetUp()115 void SetUp()
117 {116 {
118 initial_display_layout(display_geometry);117 initial_display_layout(display_geometry);
119 mtf::HeadlessInProcessServer::SetUp();118 mtf::HeadlessInProcessServer::SetUp();
120 }119 }
121 120
122 mtd::NestedMockEGL mock_egl;121 mtd::NestedMockEGL mock_egl;
123122
124 std::unique_ptr<mtf::FakeInputDevice> fake_keyboard{123 std::unique_ptr<mtf::FakeInputDevice> fake_keyboard{
@@ -301,13 +300,12 @@
301 NestedServerWithMockEventFilter nested_mir{new_connection()};300 NestedServerWithMockEventFilter nested_mir{new_connection()};
302 auto nested_hub = nested_mir.server.the_input_device_hub();301 auto nested_hub = nested_mir.server.the_input_device_hub();
303302
304 EXPECT_CALL(*mock_observer, device_added(_)).Times(1);303 EXPECT_CALL(*mock_observer, device_added(_))
305 EXPECT_CALL(*mock_observer, changes_complete())
306 .Times(1)
307 .WillOnce(mt::WakeUp(&input_device_changes_complete));304 .WillOnce(mt::WakeUp(&input_device_changes_complete));
308305
309 nested_hub->add_observer(mock_observer);306 nested_hub->add_observer(mock_observer);
310 input_device_changes_complete.wait_for(10s);307 input_device_changes_complete.wait_for(10s);
308 nested_hub->remove_observer(mock_observer);
311}309}
312310
313TEST_F(NestedInput, device_added_on_host_triggeres_nested_device_observer)311TEST_F(NestedInput, device_added_on_host_triggeres_nested_device_observer)
@@ -315,15 +313,18 @@
315 NestedServerWithMockEventFilter nested_mir{new_connection()};313 NestedServerWithMockEventFilter nested_mir{new_connection()};
316 auto nested_hub = nested_mir.server.the_input_device_hub();314 auto nested_hub = nested_mir.server.the_input_device_hub();
317315
318 EXPECT_CALL(*mock_observer, changes_complete()).Times(1)316 // wait until we see the keyboard from the fixture:
317 EXPECT_CALL(*mock_observer, device_added(_)).Times(1)
319 .WillOnce(mt::WakeUp(&input_device_changes_complete));318 .WillOnce(mt::WakeUp(&input_device_changes_complete));
320 nested_hub->add_observer(mock_observer);319 nested_hub->add_observer(mock_observer);
321320
322 input_device_changes_complete.wait_for(10s);321 input_device_changes_complete.wait_for(10s);
323 EXPECT_THAT(input_device_changes_complete.raised(), Eq(true));322 EXPECT_THAT(input_device_changes_complete.raised(), Eq(true));
324 input_device_changes_complete.reset();323 input_device_changes_complete.reset();
324 ::testing::Mock::VerifyAndClearExpectations(&mock_observer);
325325
326 EXPECT_CALL(*mock_observer, changes_complete())326 // wait for the fake mouse
327 EXPECT_CALL(*mock_observer, device_added(_)).Times(1)
327 .WillOnce(mt::WakeUp(&input_device_changes_complete));328 .WillOnce(mt::WakeUp(&input_device_changes_complete));
328329
329 auto mouse = mtf::add_fake_input_device(mi::InputDeviceInfo{"mouse", "mouse-uid" , mi::DeviceCapability::pointer});330 auto mouse = mtf::add_fake_input_device(mi::InputDeviceInfo{"mouse", "mouse-uid" , mi::DeviceCapability::pointer});
330331
=== added file 'tests/include/mir/test/doubles/mock_device.h'
--- tests/include/mir/test/doubles/mock_device.h 1970-01-01 00:00:00 +0000
+++ tests/include/mir/test/doubles/mock_device.h 2017-03-23 16:31:26 +0000
@@ -0,0 +1,71 @@
1/*
2 * Copyright © 2017 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
17 */
18
19#ifndef MIR_TEST_DOUBLES_MOCK_DEVICE_H_
20#define MIR_TEST_DOUBLES_MOCK_DEVICE_H_
21
22#include "mir/input/device.h"
23#include "mir/input/device_capability.h"
24#include "mir/input/mir_pointer_config.h"
25#include "mir/input/mir_keyboard_config.h"
26#include "mir/input/mir_touchpad_config.h"
27#include "mir/input/mir_touchscreen_config.h"
28#include "mir/optional_value.h"
29
30#include <string>
31
32namespace mir
33{
34namespace test
35{
36namespace doubles
37{
38
39struct MockDevice : input::Device
40{
41 MockDevice(MirInputDeviceId id, input::DeviceCapabilities caps, std::string const& name, std::string const& unique_id)
42 {
43 ON_CALL(*this, id()).WillByDefault(testing::Return(id));
44 ON_CALL(*this, name()).WillByDefault(testing::Return(name));
45 ON_CALL(*this, unique_id()).WillByDefault(testing::Return(unique_id));
46 ON_CALL(*this, capabilities()).WillByDefault(testing::Return(caps));
47 ON_CALL(*this, pointer_configuration()).WillByDefault(testing::Return(MirPointerConfig{}));
48 ON_CALL(*this, keyboard_configuration()).WillByDefault(testing::Return(MirKeyboardConfig{}));
49 ON_CALL(*this, touchpad_configuration()).WillByDefault(testing::Return(MirTouchpadConfig{}));
50 ON_CALL(*this, touchscreen_configuration()).WillByDefault(testing::Return(MirTouchscreenConfig{}));
51 }
52
53 MOCK_CONST_METHOD0(id, MirInputDeviceId());
54 MOCK_CONST_METHOD0(capabilities, input::DeviceCapabilities());
55 MOCK_CONST_METHOD0(name, std::string());
56 MOCK_CONST_METHOD0(unique_id, std::string());
57 MOCK_CONST_METHOD0(pointer_configuration, optional_value<MirPointerConfig>());
58 MOCK_CONST_METHOD0(touchpad_configuration, optional_value<MirTouchpadConfig>());
59 MOCK_CONST_METHOD0(keyboard_configuration, optional_value<MirKeyboardConfig>());
60 MOCK_CONST_METHOD0(touchscreen_configuration, optional_value<MirTouchscreenConfig>());
61 MOCK_METHOD1(apply_pointer_configuration, void(MirPointerConfig const&));
62 MOCK_METHOD1(apply_touchpad_configuration, void(MirTouchpadConfig const&));
63 MOCK_METHOD1(apply_keyboard_configuration, void(MirKeyboardConfig const&));
64 MOCK_METHOD1(apply_touchscreen_configuration, void(MirTouchscreenConfig const&));
65};
66}
67}
68}
69
70#endif
71
072
=== modified file 'tests/integration-tests/input/test_single_seat_setup.cpp'
--- tests/integration-tests/input/test_single_seat_setup.cpp 2017-03-14 02:26:28 +0000
+++ tests/integration-tests/input/test_single_seat_setup.cpp 2017-03-23 16:31:26 +0000
@@ -51,6 +51,7 @@
51#include "mir/input/input_device_info.h"51#include "mir/input/input_device_info.h"
52#include "mir/geometry/rectangles.h"52#include "mir/geometry/rectangles.h"
53#include "mir/test/input_config_matchers.h"53#include "mir/test/input_config_matchers.h"
54#include "mir/test/fd_utils.h"
5455
55#include <gmock/gmock.h>56#include <gmock/gmock.h>
56#include <gtest/gtest.h>57#include <gtest/gtest.h>
@@ -131,9 +132,9 @@
131 mt::fake_shared(mock_cursor_listener), mt::fake_shared(display_config),132 mt::fake_shared(mock_cursor_listener), mt::fake_shared(display_config),
132 mt::fake_shared(key_mapper), mt::fake_shared(clock),133 mt::fake_shared(key_mapper), mt::fake_shared(clock),
133 mt::fake_shared(mock_seat_observer)};134 mt::fake_shared(mock_seat_observer)};
134 mi::DefaultInputDeviceHub hub{mt::fake_shared(seat), mt::fake_shared(multiplexer),135 mi::DefaultInputDeviceHub hub{mt::fake_shared(seat), mt::fake_shared(multiplexer),
135 mt::fake_shared(observer_loop), cookie_authority,136 cookie_authority, mt::fake_shared(key_mapper),
136 mt::fake_shared(key_mapper), mt::fake_shared(mock_status_listener)};137 mt::fake_shared(mock_status_listener)};
137 NiceMock<mtd::MockInputDeviceObserver> mock_observer;138 NiceMock<mtd::MockInputDeviceObserver> mock_observer;
138 mi::ConfigChanger changer{139 mi::ConfigChanger changer{
139 mt::fake_shared(mock_input_manager),140 mt::fake_shared(mock_input_manager),
@@ -151,6 +152,21 @@
151152
152 std::chrono::nanoseconds arbitrary_timestamp;153 std::chrono::nanoseconds arbitrary_timestamp;
153154
155 void SetUp()
156 {
157 // execute registration of ConfigChanger
158 expect_and_execute_multiplexer();
159 }
160
161 void expect_and_execute_multiplexer(int count = 1)
162 {
163 for (int i = 0; i != count; ++i)
164 {
165 mt::fd_becomes_readable(multiplexer.watch_fd(), 5s);
166 multiplexer.dispatch(mir::dispatch::FdEvent::readable);
167 }
168 }
169
154 void capture_input_sink(NiceMock<mtd::MockInputDevice>& dev, mi::InputSink*& sink, mi::EventBuilder*& builder)170 void capture_input_sink(NiceMock<mtd::MockInputDevice>& dev, mi::InputSink*& sink, mi::EventBuilder*& builder)
155 {171 {
156 ON_CALL(dev,start(_,_))172 ON_CALL(dev,start(_,_))
@@ -173,14 +189,13 @@
173189
174 capture_input_sink(device, sink, builder);190 capture_input_sink(device, sink, builder);
175191
176 EXPECT_CALL(mock_observer,device_added(_))192 EXPECT_CALL(mock_observer, device_added(_))
177 .WillOnce(SaveArg<0>(&handle));193 .WillOnce(SaveArg<0>(&handle));
178194
179 hub.add_observer(mt::fake_shared(mock_observer));195 hub.add_observer(mt::fake_shared(mock_observer));
196 expect_and_execute_multiplexer(1);
180 hub.add_device(mt::fake_shared(device));197 hub.add_device(mt::fake_shared(device));
181198
182 observer_loop.trigger_server_actions();
183
184 auto event = builder->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0,199 auto event = builder->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0,
185 KEY_A);200 KEY_A);
186201
@@ -198,8 +213,6 @@
198213
199 hub.add_device(mt::fake_shared(device));214 hub.add_device(mt::fake_shared(device));
200215
201 observer_loop.trigger_server_actions();
202
203 auto touch_event_1 = builder->touch_event(216 auto touch_event_1 = builder->touch_event(
204 arbitrary_timestamp,217 arbitrary_timestamp,
205 {{0, mir_touch_action_down, mir_touch_tooltype_finger, 21.0f, 34.0f, 50.0f, 15.0f, 5.0f, 4.0f}});218 {{0, mir_touch_action_down, mir_touch_tooltype_finger, 21.0f, 34.0f, 50.0f, 15.0f, 5.0f, 4.0f}});
@@ -245,7 +258,6 @@
245 capture_input_sink(device, sink, builder);258 capture_input_sink(device, sink, builder);
246259
247 hub.add_device(mt::fake_shared(device));260 hub.add_device(mt::fake_shared(device));
248 observer_loop.trigger_server_actions();
249 sink->handle_input(261 sink->handle_input(
250 *builder->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0.0f, 0.0f, 10.0f, 10.0f));262 *builder->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0.0f, 0.0f, 10.0f, 10.0f));
251 sink->handle_input(263 sink->handle_input(
@@ -265,7 +277,6 @@
265 mi::EventBuilder* builder;277 mi::EventBuilder* builder;
266 capture_input_sink(device, sink, builder);278 capture_input_sink(device, sink, builder);
267 hub.add_device(mt::fake_shared(device));279 hub.add_device(mt::fake_shared(device));
268 observer_loop.trigger_server_actions();
269280
270 sink->handle_input(281 sink->handle_input(
271 *builder->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0.0f, 0.0f, 10.0f, 20.0f));282 *builder->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0.0f, 0.0f, 10.0f, 20.0f));
@@ -295,8 +306,8 @@
295 ON_CALL(mock_observer, device_added(_)).WillByDefault(SaveArg<0>(&dev));306 ON_CALL(mock_observer, device_added(_)).WillByDefault(SaveArg<0>(&dev));
296307
297 hub.add_observer(mt::fake_shared(mock_observer));308 hub.add_observer(mt::fake_shared(mock_observer));
309 expect_and_execute_multiplexer();
298 hub.add_device(mt::fake_shared(touchpad));310 hub.add_device(mt::fake_shared(touchpad));
299 observer_loop.trigger_server_actions();
300311
301 EXPECT_CALL(touchpad, apply_settings(Matcher<mi::PointerSettings const&>(_)));312 EXPECT_CALL(touchpad, apply_settings(Matcher<mi::PointerSettings const&>(_)));
302313
@@ -311,8 +322,8 @@
311 ON_CALL(mock_observer, device_added(_)).WillByDefault(SaveArg<0>(&dev));322 ON_CALL(mock_observer, device_added(_)).WillByDefault(SaveArg<0>(&dev));
312323
313 hub.add_observer(mt::fake_shared(mock_observer));324 hub.add_observer(mt::fake_shared(mock_observer));
325 expect_and_execute_multiplexer();
314 hub.add_device(mt::fake_shared(touchpad));326 hub.add_device(mt::fake_shared(touchpad));
315 observer_loop.trigger_server_actions();
316327
317 EXPECT_CALL(touchpad, apply_settings(Matcher<mi::TouchpadSettings const&>(_)));328 EXPECT_CALL(touchpad, apply_settings(Matcher<mi::TouchpadSettings const&>(_)));
318329
@@ -334,9 +345,9 @@
334 .WillOnce(SaveArg<0>(&key_handle));345 .WillOnce(SaveArg<0>(&key_handle));
335346
336 hub.add_observer(mt::fake_shared(mock_observer));347 hub.add_observer(mt::fake_shared(mock_observer));
348 expect_and_execute_multiplexer();
337 hub.add_device(mt::fake_shared(another_device));349 hub.add_device(mt::fake_shared(another_device));
338350
339 observer_loop.trigger_server_actions();
340351
341 const MirInputEventModifiers shift_left = mir_input_event_modifier_shift_left | mir_input_event_modifier_shift;352 const MirInputEventModifiers shift_left = mir_input_event_modifier_shift_left | mir_input_event_modifier_shift;
342 auto shift_down =353 auto shift_down =
@@ -370,11 +381,10 @@
370 .WillOnce(SaveArg<0>(&key_handle));381 .WillOnce(SaveArg<0>(&key_handle));
371382
372 hub.add_observer(mt::fake_shared(mock_observer));383 hub.add_observer(mt::fake_shared(mock_observer));
384 expect_and_execute_multiplexer();
373 hub.add_device(mt::fake_shared(device));385 hub.add_device(mt::fake_shared(device));
374 hub.add_device(mt::fake_shared(another_device));386 hub.add_device(mt::fake_shared(another_device));
375387
376 observer_loop.trigger_server_actions();
377
378 const MirInputEventModifiers r_alt_modifier = mir_input_event_modifier_alt_right | mir_input_event_modifier_alt;388 const MirInputEventModifiers r_alt_modifier = mir_input_event_modifier_alt_right | mir_input_event_modifier_alt;
379 auto key =389 auto key =
380 key_event_builder->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_RIGHTALT);390 key_event_builder->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_RIGHTALT);
@@ -415,6 +425,7 @@
415 .WillOnce(SaveArg<0>(&key_handle_2));425 .WillOnce(SaveArg<0>(&key_handle_2));
416426
417 hub.add_observer(mt::fake_shared(mock_observer));427 hub.add_observer(mt::fake_shared(mock_observer));
428 expect_and_execute_multiplexer();
418 hub.add_device(mt::fake_shared(device));429 hub.add_device(mt::fake_shared(device));
419 hub.add_device(mt::fake_shared(another_device));430 hub.add_device(mt::fake_shared(another_device));
420 hub.add_device(mt::fake_shared(third_device));431 hub.add_device(mt::fake_shared(third_device));
@@ -423,8 +434,6 @@
423 const MirInputEventModifiers l_ctrl_modifier = mir_input_event_modifier_ctrl_left | mir_input_event_modifier_ctrl;434 const MirInputEventModifiers l_ctrl_modifier = mir_input_event_modifier_ctrl_left | mir_input_event_modifier_ctrl;
424 const MirInputEventModifiers combined_modifier = r_alt_modifier | l_ctrl_modifier;435 const MirInputEventModifiers combined_modifier = r_alt_modifier | l_ctrl_modifier;
425436
426 observer_loop.trigger_server_actions();
427
428 auto alt_down = key_event_builder_1->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_RIGHTALT);437 auto alt_down = key_event_builder_1->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_RIGHTALT);
429 auto ctrl_down = key_event_builder_2->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_LEFTCTRL);438 auto ctrl_down = key_event_builder_2->key_event(arbitrary_timestamp, mir_keyboard_action_down, 0, KEY_LEFTCTRL);
430 auto ctrl_up = key_event_builder_2->key_event(arbitrary_timestamp, mir_keyboard_action_up, 0, KEY_LEFTCTRL);439 auto ctrl_up = key_event_builder_2->key_event(arbitrary_timestamp, mir_keyboard_action_up, 0, KEY_LEFTCTRL);
@@ -462,8 +471,6 @@
462 hub.add_device(mt::fake_shared(device));471 hub.add_device(mt::fake_shared(device));
463 hub.add_device(mt::fake_shared(another_device));472 hub.add_device(mt::fake_shared(another_device));
464473
465 observer_loop.trigger_server_actions();
466
467 auto motion_1 =474 auto motion_1 =
468 mouse_event_builder_1->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0, 0, 23, 20);475 mouse_event_builder_1->pointer_event(arbitrary_timestamp, mir_pointer_action_motion, 0, 0, 0, 23, 20);
469 auto motion_2 =476 auto motion_2 =
@@ -495,8 +502,6 @@
495 hub.add_device(mt::fake_shared(device));502 hub.add_device(mt::fake_shared(device));
496 hub.add_device(mt::fake_shared(another_device));503 hub.add_device(mt::fake_shared(another_device));
497504
498 observer_loop.trigger_server_actions();
499
500 auto motion_1 =505 auto motion_1 =
501 mouse_event_builder_1->pointer_event(arbitrary_timestamp, mir_pointer_action_button_down, mir_pointer_button_primary, 0, 0, 0, 0);506 mouse_event_builder_1->pointer_event(arbitrary_timestamp, mir_pointer_action_button_down, mir_pointer_button_primary, 0, 0, 0, 0);
502 auto motion_2 =507 auto motion_2 =
@@ -525,7 +530,6 @@
525530
526 EXPECT_CALL(session, send_input_config(UnorderedElementsAre(DeviceMatches(device.get_device_info()))));531 EXPECT_CALL(session, send_input_config(UnorderedElementsAre(DeviceMatches(device.get_device_info()))));
527 hub.add_device(mt::fake_shared(device));532 hub.add_device(mt::fake_shared(device));
528 observer_loop.trigger_server_actions();
529}533}
530534
531TEST_F(SingleSeatInputDeviceHubSetup, input_device_changes_sent_to_session_multiple_devices)535TEST_F(SingleSeatInputDeviceHubSetup, input_device_changes_sent_to_session_multiple_devices)
@@ -534,25 +538,21 @@
534 stub_session_container.insert_session(mt::fake_shared(session));538 stub_session_container.insert_session(mt::fake_shared(session));
535539
536 hub.add_device(mt::fake_shared(device));540 hub.add_device(mt::fake_shared(device));
537 observer_loop.trigger_server_actions();
538541
539 EXPECT_CALL(session,542 EXPECT_CALL(session,
540 send_input_config(UnorderedElementsAre(DeviceMatches(device.get_device_info()),543 send_input_config(UnorderedElementsAre(DeviceMatches(device.get_device_info()),
541 DeviceMatches(another_device.get_device_info()))));544 DeviceMatches(another_device.get_device_info()))));
542 hub.add_device(mt::fake_shared(another_device));545 hub.add_device(mt::fake_shared(another_device));
543 observer_loop.trigger_server_actions();
544}546}
545547
546TEST_F(SingleSeatInputDeviceHubSetup, input_device_changes_sent_to_sink_removal)548TEST_F(SingleSeatInputDeviceHubSetup, input_device_changes_sent_to_sink_removal)
547{549{
548 hub.add_device(mt::fake_shared(device));550 hub.add_device(mt::fake_shared(device));
549 hub.add_device(mt::fake_shared(another_device));551 hub.add_device(mt::fake_shared(another_device));
550 observer_loop.trigger_server_actions();
551552
552 NiceMock<mtd::MockSceneSession> session;553 NiceMock<mtd::MockSceneSession> session;
553 stub_session_container.insert_session(mt::fake_shared(session));554 stub_session_container.insert_session(mt::fake_shared(session));
554 EXPECT_CALL(session,555 EXPECT_CALL(session,
555 send_input_config(UnorderedElementsAre(DeviceMatches(another_device.get_device_info()))));556 send_input_config(UnorderedElementsAre(DeviceMatches(another_device.get_device_info()))));
556 hub.remove_device(mt::fake_shared(device));557 hub.remove_device(mt::fake_shared(device));
557 observer_loop.trigger_server_actions();
558}558}
559559
=== modified file 'tests/unit-tests/input/CMakeLists.txt'
--- tests/unit-tests/input/CMakeLists.txt 2017-03-13 08:12:52 +0000
+++ tests/unit-tests/input/CMakeLists.txt 2017-03-23 16:31:26 +0000
@@ -8,6 +8,7 @@
8 ${CMAKE_CURRENT_SOURCE_DIR}/test_input_event.cpp8 ${CMAKE_CURRENT_SOURCE_DIR}/test_input_event.cpp
9 ${CMAKE_CURRENT_SOURCE_DIR}/test_config_changer.cpp9 ${CMAKE_CURRENT_SOURCE_DIR}/test_config_changer.cpp
10 ${CMAKE_CURRENT_SOURCE_DIR}/test_event_builders.cpp10 ${CMAKE_CURRENT_SOURCE_DIR}/test_event_builders.cpp
11 ${CMAKE_CURRENT_SOURCE_DIR}/test_external_input_device_hub.cpp
11 ${CMAKE_CURRENT_SOURCE_DIR}/test_default_device.cpp12 ${CMAKE_CURRENT_SOURCE_DIR}/test_default_device.cpp
12 ${CMAKE_CURRENT_SOURCE_DIR}/test_default_input_device_hub.cpp13 ${CMAKE_CURRENT_SOURCE_DIR}/test_default_input_device_hub.cpp
13 ${CMAKE_CURRENT_SOURCE_DIR}/test_default_input_manager.cpp14 ${CMAKE_CURRENT_SOURCE_DIR}/test_default_input_manager.cpp
1415
=== modified file 'tests/unit-tests/input/test_config_changer.cpp'
--- tests/unit-tests/input/test_config_changer.cpp 2017-02-28 08:53:57 +0000
+++ tests/unit-tests/input/test_config_changer.cpp 2017-03-23 16:31:26 +0000
@@ -29,6 +29,7 @@
2929
30#include "mir/test/doubles/mock_input_device_hub.h"30#include "mir/test/doubles/mock_input_device_hub.h"
31#include "mir/test/doubles/mock_input_manager.h"31#include "mir/test/doubles/mock_input_manager.h"
32#include "mir/test/doubles/mock_device.h"
32#include "mir/test/doubles/mock_scene_session.h"33#include "mir/test/doubles/mock_scene_session.h"
33#include "mir/test/doubles/stub_session.h"34#include "mir/test/doubles/stub_session.h"
34#include "mir/test/doubles/stub_session_container.h"35#include "mir/test/doubles/stub_session_container.h"
@@ -47,34 +48,6 @@
47namespace48namespace
48{49{
4950
50struct MockDevice : mir::input::Device
51{
52 MockDevice(MirInputDeviceId id, mi::DeviceCapabilities caps, std::string const& name, std::string const& unique_id)
53 {
54 ON_CALL(*this, id()).WillByDefault(Return(id));
55 ON_CALL(*this, name()).WillByDefault(Return(name));
56 ON_CALL(*this, unique_id()).WillByDefault(Return(unique_id));
57 ON_CALL(*this, capabilities()).WillByDefault(Return(caps));
58 ON_CALL(*this, pointer_configuration()).WillByDefault(Return(MirPointerConfig{}));
59 ON_CALL(*this, keyboard_configuration()).WillByDefault(Return(MirKeyboardConfig{}));
60 ON_CALL(*this, touchpad_configuration()).WillByDefault(Return(MirTouchpadConfig{}));
61 ON_CALL(*this, touchscreen_configuration()).WillByDefault(Return(MirTouchscreenConfig{}));
62 }
63
64 MOCK_CONST_METHOD0(id, MirInputDeviceId());
65 MOCK_CONST_METHOD0(capabilities, mir::input::DeviceCapabilities());
66 MOCK_CONST_METHOD0(name, std::string());
67 MOCK_CONST_METHOD0(unique_id, std::string());
68 MOCK_CONST_METHOD0(pointer_configuration, mir::optional_value<MirPointerConfig>());
69 MOCK_CONST_METHOD0(touchpad_configuration, mir::optional_value<MirTouchpadConfig>());
70 MOCK_CONST_METHOD0(keyboard_configuration, mir::optional_value<MirKeyboardConfig>());
71 MOCK_CONST_METHOD0(touchscreen_configuration, mir::optional_value<MirTouchscreenConfig>());
72 MOCK_METHOD1(apply_pointer_configuration, void(MirPointerConfig const&));
73 MOCK_METHOD1(apply_touchpad_configuration, void(MirTouchpadConfig const&));
74 MOCK_METHOD1(apply_keyboard_configuration, void(MirKeyboardConfig const&));
75 MOCK_METHOD1(apply_touchscreen_configuration, void(MirTouchscreenConfig const&));
76};
77
78struct FakeInputDeviceHub : mir::input::InputDeviceHub51struct FakeInputDeviceHub : mir::input::InputDeviceHub
79{52{
80 std::shared_ptr<mi::InputDeviceObserver> observer;53 std::shared_ptr<mi::InputDeviceObserver> observer;
@@ -86,8 +59,8 @@
86 mi::DeviceCapability::keyboard | mi::DeviceCapability::alpha_numeric |59 mi::DeviceCapability::keyboard | mi::DeviceCapability::alpha_numeric |
87 mi::DeviceCapability::touchscreen;60 mi::DeviceCapability::touchscreen;
8861
89 NiceMock<MockDevice> first_device{first_id, caps, first, first};62 NiceMock<mtd::MockDevice> first_device{first_id, caps, first, first};
90 NiceMock<MockDevice> second_device{second_id, caps, second, second};63 NiceMock<mtd::MockDevice> second_device{second_id, caps, second, second};
91 std::vector<std::shared_ptr<mir::input::Device>> active_devices;64 std::vector<std::shared_ptr<mir::input::Device>> active_devices;
9265
93 void add_observer(std::shared_ptr<mi::InputDeviceObserver> const& obs) override66 void add_observer(std::shared_ptr<mi::InputDeviceObserver> const& obs) override
9467
=== modified file 'tests/unit-tests/input/test_default_input_device_hub.cpp'
--- tests/unit-tests/input/test_default_input_device_hub.cpp 2017-03-13 08:12:52 +0000
+++ tests/unit-tests/input/test_default_input_device_hub.cpp 2017-03-23 16:31:26 +0000
@@ -30,6 +30,7 @@
30#include "mir/test/doubles/triggered_main_loop.h"30#include "mir/test/doubles/triggered_main_loop.h"
31#include "mir/test/event_matchers.h"31#include "mir/test/event_matchers.h"
32#include "mir/test/fake_shared.h"32#include "mir/test/fake_shared.h"
33#include "mir/test/fd_utils.h"
3334
34#include "mir/dispatch/action_queue.h"35#include "mir/dispatch/action_queue.h"
35#include "mir/geometry/rectangles.h"36#include "mir/geometry/rectangles.h"
@@ -77,14 +78,14 @@
7778
78struct InputDeviceHubTest : ::testing::Test79struct InputDeviceHubTest : ::testing::Test
79{80{
80 mtd::TriggeredMainLoop observer_loop;
81 std::shared_ptr<mir::cookie::Authority> cookie_authority = mir::cookie::Authority::create();81 std::shared_ptr<mir::cookie::Authority> cookie_authority = mir::cookie::Authority::create();
82 mir::dispatch::MultiplexingDispatchable multiplexer;82 mir::dispatch::MultiplexingDispatchable multiplexer;
83 NiceMock<mtd::MockInputSeat> mock_seat;83 NiceMock<mtd::MockInputSeat> mock_seat;
84 NiceMock<mtd::MockKeyMapper> mock_key_mapper;84 NiceMock<mtd::MockKeyMapper> mock_key_mapper;
85 NiceMock<mtd::MockServerStatusListener> mock_server_status_listener;85 NiceMock<mtd::MockServerStatusListener> mock_server_status_listener;
86 mi::DefaultInputDeviceHub hub{mt::fake_shared(mock_seat), mt::fake_shared(multiplexer),86 mi::DefaultInputDeviceHub hub{mt::fake_shared(mock_seat), mt::fake_shared(multiplexer),
87 mt::fake_shared(observer_loop), cookie_authority, mt::fake_shared(mock_key_mapper), mt::fake_shared(mock_server_status_listener)};87 cookie_authority, mt::fake_shared(mock_key_mapper),
88 mt::fake_shared(mock_server_status_listener)};
88 NiceMock<mtd::MockInputDeviceObserver> mock_observer;89 NiceMock<mtd::MockInputDeviceObserver> mock_observer;
89 NiceMock<mtd::MockInputDevice> device{"device","dev-1", mi::DeviceCapability::unknown};90 NiceMock<mtd::MockInputDevice> device{"device","dev-1", mi::DeviceCapability::unknown};
90 NiceMock<mtd::MockInputDevice> another_device{"another_device","dev-2", mi::DeviceCapability::keyboard};91 NiceMock<mtd::MockInputDevice> another_device{"another_device","dev-2", mi::DeviceCapability::keyboard};
@@ -104,6 +105,12 @@
104 }105 }
105 ));106 ));
106 }107 }
108
109 void expect_and_execute_multiplexer()
110 {
111 mt::fd_becomes_readable(multiplexer.watch_fd(), 2s);
112 multiplexer.dispatch(mir::dispatch::FdEvent::readable);
113 }
107};114};
108115
109TEST_F(InputDeviceHubTest, input_device_hub_starts_device)116TEST_F(InputDeviceHubTest, input_device_hub_starts_device)
@@ -161,8 +168,7 @@
161 hub.add_device(mt::fake_shared(another_device));168 hub.add_device(mt::fake_shared(another_device));
162 hub.add_observer(mt::fake_shared(mock_observer));169 hub.add_observer(mt::fake_shared(mock_observer));
163170
164 observer_loop.trigger_server_actions();171 expect_and_execute_multiplexer();
165
166 EXPECT_THAT(handle_1,Ne(handle_2));172 EXPECT_THAT(handle_1,Ne(handle_2));
167 EXPECT_THAT(handle_1->unique_id(),Ne(handle_2->unique_id()));173 EXPECT_THAT(handle_1->unique_id(),Ne(handle_2->unique_id()));
168}174}
@@ -208,10 +214,13 @@
208 EXPECT_CALL(mock_observer, changes_complete());214 EXPECT_CALL(mock_observer, changes_complete());
209215
210 hub.add_observer(mt::fake_shared(mock_observer));216 hub.add_observer(mt::fake_shared(mock_observer));
217 expect_and_execute_multiplexer();
218
211 hub.add_device(mt::fake_shared(device));219 hub.add_device(mt::fake_shared(device));
220 expect_and_execute_multiplexer();
221
212 hub.remove_device(mt::fake_shared(device));222 hub.remove_device(mt::fake_shared(device));
213223 expect_and_execute_multiplexer();
214 observer_loop.trigger_server_actions();
215}224}
216225
217TEST_F(InputDeviceHubTest, emit_ready_to_receive_input_after_first_device_added)226TEST_F(InputDeviceHubTest, emit_ready_to_receive_input_after_first_device_added)
@@ -219,8 +228,6 @@
219 EXPECT_CALL(mock_server_status_listener, ready_for_user_input()).Times(1);228 EXPECT_CALL(mock_server_status_listener, ready_for_user_input()).Times(1);
220 hub.add_device(mt::fake_shared(device));229 hub.add_device(mt::fake_shared(device));
221 hub.add_device(mt::fake_shared(another_device));230 hub.add_device(mt::fake_shared(another_device));
222
223 observer_loop.trigger_server_actions();
224}231}
225232
226TEST_F(InputDeviceHubTest, emit_stop_receiving_input_after_last_device_added)233TEST_F(InputDeviceHubTest, emit_stop_receiving_input_after_last_device_added)
@@ -231,7 +238,6 @@
231238
232 hub.remove_device(mt::fake_shared(device));239 hub.remove_device(mt::fake_shared(device));
233 hub.remove_device(mt::fake_shared(another_device));240 hub.remove_device(mt::fake_shared(another_device));
234 observer_loop.trigger_server_actions();
235}241}
236242
237TEST_F(InputDeviceHubTest, when_pointer_configuration_is_applied_successfully_observer_is_triggerd)243TEST_F(InputDeviceHubTest, when_pointer_configuration_is_applied_successfully_observer_is_triggerd)
@@ -243,13 +249,13 @@
243249
244 hub.add_device(mt::fake_shared(mouse));250 hub.add_device(mt::fake_shared(mouse));
245 hub.add_observer(mt::fake_shared(mock_observer));251 hub.add_observer(mt::fake_shared(mock_observer));
246 observer_loop.trigger_server_actions();252 expect_and_execute_multiplexer();
247253
248 EXPECT_CALL(mock_observer, device_changed(WithName("mouse")));254 EXPECT_CALL(mock_observer, device_changed(WithName("mouse")));
249 EXPECT_CALL(mock_observer, changes_complete());255 EXPECT_CALL(mock_observer, changes_complete());
250256
251 dev_ptr->apply_pointer_configuration(pointer_conf);257 dev_ptr->apply_pointer_configuration(pointer_conf);
252 observer_loop.trigger_server_actions();258 expect_and_execute_multiplexer();
253}259}
254260
255TEST_F(InputDeviceHubTest, when_tpd_configuration_is_applied_successfully_observer_is_triggerd)261TEST_F(InputDeviceHubTest, when_tpd_configuration_is_applied_successfully_observer_is_triggerd)
@@ -261,13 +267,13 @@
261267
262 hub.add_device(mt::fake_shared(touchpad));268 hub.add_device(mt::fake_shared(touchpad));
263 hub.add_observer(mt::fake_shared(mock_observer));269 hub.add_observer(mt::fake_shared(mock_observer));
264 observer_loop.trigger_server_actions();270 expect_and_execute_multiplexer();
265271
266 EXPECT_CALL(mock_observer, device_changed(WithName("tpd")));272 EXPECT_CALL(mock_observer, device_changed(WithName("tpd")));
267 EXPECT_CALL(mock_observer, changes_complete());273 EXPECT_CALL(mock_observer, changes_complete());
268274
269 dev_ptr->apply_touchpad_configuration(tpd_conf);275 dev_ptr->apply_touchpad_configuration(tpd_conf);
270 observer_loop.trigger_server_actions();276 expect_and_execute_multiplexer();
271}277}
272278
273TEST_F(InputDeviceHubTest, when_configuration_attempt_fails_observer_is_not_triggerd)279TEST_F(InputDeviceHubTest, when_configuration_attempt_fails_observer_is_not_triggerd)
@@ -279,12 +285,12 @@
279285
280 hub.add_device(mt::fake_shared(mouse));286 hub.add_device(mt::fake_shared(mouse));
281 hub.add_observer(mt::fake_shared(mock_observer));287 hub.add_observer(mt::fake_shared(mock_observer));
282 observer_loop.trigger_server_actions();288 expect_and_execute_multiplexer();
283289
284 EXPECT_CALL(mock_observer, device_changed(WithName("mouse"))).Times(0);290 EXPECT_CALL(mock_observer, device_changed(WithName("mouse"))).Times(0);
285 EXPECT_CALL(mock_observer, changes_complete()).Times(0);291 EXPECT_CALL(mock_observer, changes_complete()).Times(0);
286292
287 try {dev_ptr->apply_touchpad_configuration(tpd_conf); } catch (...) {}293 try {dev_ptr->apply_touchpad_configuration(tpd_conf); } catch (...) {}
288 observer_loop.trigger_server_actions();294 expect_and_execute_multiplexer();
289 ::testing::Mock::VerifyAndClearExpectations(&mock_observer);295 ::testing::Mock::VerifyAndClearExpectations(&mock_observer);
290}296}
291297
=== added file 'tests/unit-tests/input/test_external_input_device_hub.cpp'
--- tests/unit-tests/input/test_external_input_device_hub.cpp 1970-01-01 00:00:00 +0000
+++ tests/unit-tests/input/test_external_input_device_hub.cpp 2017-03-23 16:31:26 +0000
@@ -0,0 +1,119 @@
1/*
2 * Copyright © 2017 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
17 */
18
19#include "src/server/input/default_input_device_hub.h"
20#include "mir/test/doubles/mock_input_device_hub.h"
21#include "mir/test/doubles/mock_device.h"
22#include "mir/test/doubles/mock_input_device_observer.h"
23#include "mir/test/doubles/triggered_main_loop.h"
24#include "mir/test/fake_shared.h"
25
26namespace mt = mir::test;
27namespace mtd = mt::doubles;
28namespace mi = mir::input;
29using namespace testing;
30
31namespace
32{
33
34struct WrappedHub : mtd::MockInputDeviceHub
35{
36 std::shared_ptr<mi::InputDeviceObserver> external_hub;
37 void add_observer(std::shared_ptr<mi::InputDeviceObserver> const& observer)
38 {
39 external_hub = observer;
40 }
41};
42
43struct ExternalInputDeviceHub : ::testing::Test
44{
45 mtd::TriggeredMainLoop server_actions;
46 std::shared_ptr<WrappedHub> wrapped_hub{std::make_shared<WrappedHub>()};
47 mi::ExternalInputDeviceHub hub{wrapped_hub, mt::fake_shared(server_actions)};
48 NiceMock<mtd::MockInputDeviceObserver> mock_observer;
49
50 NiceMock<mtd::MockDevice> device{1, mi::DeviceCapability::unknown, "name", "name-id-1"};
51 NiceMock<mtd::MockDevice> another_device{2, mi::DeviceCapability::keyboard, "keyboard", "keyboard-id-2"};
52
53 void submit_device_to_hub(std::shared_ptr<mi::Device> const& dev)
54 {
55 wrapped_hub->external_hub->device_added(dev);
56 wrapped_hub->external_hub->changes_complete();
57 }
58
59 void remove_device_to_hub(std::shared_ptr<mi::Device> const& dev)
60 {
61 wrapped_hub->external_hub->device_removed(dev);
62 wrapped_hub->external_hub->changes_complete();
63 }
64};
65}
66
67TEST_F(ExternalInputDeviceHub, is_observer_to_wrapped_hub)
68{
69 EXPECT_THAT(wrapped_hub->external_hub, Ne(nullptr));
70}
71
72TEST_F(ExternalInputDeviceHub, new_observer_is_called_through_server_action)
73{
74 EXPECT_CALL(mock_observer, changes_complete()).Times(1);
75 hub.add_observer(mt::fake_shared(mock_observer));
76 server_actions.trigger_server_actions();
77}
78
79TEST_F(ExternalInputDeviceHub, informs_observer_about_existing_devices)
80{
81 submit_device_to_hub(mt::fake_shared(device));
82 submit_device_to_hub(mt::fake_shared(another_device));
83
84 EXPECT_CALL(mock_observer, device_added(_)).Times(2);
85 EXPECT_CALL(mock_observer, changes_complete()).Times(1);
86 hub.add_observer(mt::fake_shared(mock_observer));
87 server_actions.trigger_server_actions();
88}
89
90TEST_F(ExternalInputDeviceHub, informs_observer_about_added_devices)
91{
92 InSequence seq;
93
94 EXPECT_CALL(mock_observer, changes_complete());
95 EXPECT_CALL(mock_observer, device_added(_));
96 EXPECT_CALL(mock_observer, changes_complete());
97 hub.add_observer(mt::fake_shared(mock_observer));
98 server_actions.trigger_server_actions();
99
100 submit_device_to_hub(mt::fake_shared(device));
101
102 server_actions.trigger_server_actions();
103}
104
105TEST_F(ExternalInputDeviceHub, triggers_observer_on_removed_devices)
106{
107 submit_device_to_hub(mt::fake_shared(device));
108
109 EXPECT_CALL(mock_observer, device_added(_)).Times(1);
110 EXPECT_CALL(mock_observer, changes_complete()).Times(1);
111 hub.add_observer(mt::fake_shared(mock_observer));
112 server_actions.trigger_server_actions();
113
114 EXPECT_CALL(mock_observer, device_removed(_)).Times(1);
115 EXPECT_CALL(mock_observer, changes_complete()).Times(1);
116
117 remove_device_to_hub(mt::fake_shared(device));
118 server_actions.trigger_server_actions();
119}

Subscribers

People subscribed via source and target branches