Mir

Merge lp:~andreas-pokorny/mir/map-touchscreen-to-output into lp:mir

Proposed by Andreas Pokorny
Status: Merged
Approved by: Daniel van Vugt
Approved revision: no longer in the source branch.
Merged at revision: 4067
Proposed branch: lp:~andreas-pokorny/mir/map-touchscreen-to-output
Merge into: lp:mir
Prerequisite: lp:~andreas-pokorny/mir/add-touchscreen-settings
Diff against target: 1859 lines (+946/-126)
29 files modified
include/client/mir_toolkit/client_types.h (+1/-0)
include/client/mir_toolkit/mir_input_device.h (+68/-0)
include/core/mir_toolkit/mir_input_device_types.h (+2/-2)
include/platform/mir/input/input_sink.h (+34/-1)
include/platform/mir/input/touchscreen_settings.h (+5/-0)
include/test/mir_test_framework/fake_input_device.h (+9/-0)
src/client/mir_input_device_api.cpp (+35/-0)
src/client/symbols.map (+6/-0)
src/include/server/mir/input/seat.h (+5/-1)
src/platforms/evdev/libinput_device.cpp (+49/-4)
src/platforms/evdev/libinput_device.h (+3/-0)
src/server/graphics/nested/input_platform.cpp (+18/-2)
src/server/input/basic_seat.cpp (+132/-12)
src/server/input/basic_seat.h (+15/-7)
src/server/input/default_configuration.cpp (+1/-1)
src/server/input/default_input_device_hub.cpp (+9/-1)
src/server/input/default_input_device_hub.h (+2/-1)
src/server/input/seat_input_device_tracker.cpp (+8/-4)
src/server/input/seat_input_device_tracker.h (+11/-2)
src/server/scene/surface_stack.cpp (+1/-5)
tests/acceptance-tests/test_client_input.cpp (+207/-33)
tests/include/mir/test/doubles/mock_input_seat.h (+3/-1)
tests/include/mir/test/doubles/mock_input_sink.h (+1/-0)
tests/integration-tests/input/test_single_seat_setup.cpp (+47/-14)
tests/mir_test_framework/fake_input_device_impl.cpp (+76/-14)
tests/mir_test_framework/fake_input_device_impl.h (+14/-0)
tests/unit-tests/input/evdev/test_libinput_device.cpp (+181/-15)
tests/unit-tests/input/test_seat_input_device_tracker.cpp (+1/-4)
tests/unit-tests/scene/test_surface_stack.cpp (+2/-2)
To merge this branch: bzr merge lp:~andreas-pokorny/mir/map-touchscreen-to-output
Reviewer Review Type Date Requested Status
Daniel van Vugt Abstain
Mir CI Bot continuous-integration Approve
Alan Griffiths Approve
Review via email: mp+316709@code.launchpad.net

Commit message

Map Touchscreen to Output: Allow clients to configure a relation between touchscreen and display outputs

When configured the touch contact coordinates will be mapped into the screen space occupied by the output. Previously the first output was used as default and orientation information was ignored. This default behavior is still in place - when not configured the builtin output on android devices will be used. Additionally the connection between input devices and outputs is used to disable input events from deactivated outputs.

Description of the change

This change allows clients to configure a mapping of touchscreen onto actual outputs. Such that the coordinates originating from the configured device will map into the screen space occupied by the output.

This change also bypasses the existing code around InputRegion which removed the output information to early in the stack..

The information about output to input device relation is forwarded to the host server, and handled in stub and evdev platform. Thus the feature needed an ABI/API break in input platform - which is the second inside the yet unreleased 0.27 series - so there is no ABI bump in this MP.

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

FAILED: Continuous integration, rev:4009
https://mir-jenkins.ubuntu.com/job/mir-ci/2954/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/3915/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4001/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/3991/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/3991/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/3991/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/3942/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/3942/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/3942/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/3942/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/3942/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/3942/console

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

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

FAILED: Continuous integration, rev:4011
https://mir-jenkins.ubuntu.com/job/mir-ci/2962/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/3930/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4016/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4006/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4006/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4006/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/3957/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/3957/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/3957/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/3957/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/3957/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/3957/console

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+void mir_touchscreen_config_set_mapping_mode(MirTouchscreenConfig* config, enum MirTouchscreenMappingMode mode);

We shouldn't need to type "enum MirTouchscreenMappingMode" in C code. There's a missing typedef in the existing code...

    enum MirTouchscreenMappingMode
    {
    ...
    };

=>

    typedef enum MirTouchscreenMappingMode
    {
    ...
    } MirTouchscreenMappingMode;

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

1. Is it worthwhile having both mutable and immutable MirTouchscreenConfig?

2. Are we confident this API won't ever change? (If it might change then it ought to be accessed via the extensions mechanism.)

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

> 1. Is it worthwhile having both mutable and immutable MirTouchscreenConfig?

We have a non const / const API for all configurations. Touchscreen is not different or special in that reguard.

> 2. Are we confident this API won't ever change? (If it might change then it
> ought to be accessed via the extensions mechanism.)

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

> 2. Are we confident this API won't ever change? (If it might change then it
> ought to be accessed via the extensions mechanism.)

I cannot respond for the group but this proposal contains the minimum necessary information to get touchscreen coordinates into the system.. I do not expect we would need less in the future - maybe more.. but even that is rather unlikely.

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

FAILED: Continuous integration, rev:4019
https://mir-jenkins.ubuntu.com/job/mir-ci/3048/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4074/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4161/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4151/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4151/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4151/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4101/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4101/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4101/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4101/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4101/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4101/console

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

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

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

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

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

Nits:

+enum MirTouchscreenMappingMode mir_touchscreen_config_get_mapping_mode(MirTouchscreenConfig const* device);
...
+void mir_touchscreen_config_set_mapping_mode(MirTouchscreenConfig* config, enum MirTouchscreenMappingMode mode);

Don't need "enum" now.

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

I'm slightly concerned about this (but only if it hasn't been tested):

527 + if (output.current_mode_index < output.modes.size())
528 + {
529 + data.output_size = output.modes[output.current_mode_index].size;
530 + if (data.active)
531 + output_rectangles.add(output.extents());
532 + }

Can you confirm that the touch coordinates are correct (like in target or fingerpaint) when the current mode is lower resolution than the screen's native mode? In future the opposite might also be true (screen is mirroring a higher res output and is scaled down)...

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

Don't we want preferred_mode_index rather than current_mode_index?

preferred_mode_index will more reliably tell you the pixel-size of the screen that will more likely match with touchscreen coordinates.

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

The current_mode_index is already taken into consideration in the implementation of extents(). So that's your (target) logical rectangle. Your (source) physical touchscreen rectangle should be from preferred_mode_index.

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

> Don't we want preferred_mode_index rather than current_mode_index?
>
> preferred_mode_index will more reliably tell you the pixel-size of the screen
> that will more likely match with touchscreen coordinates.

But the intent is not to get the original screen size but the position size and orientation of the output inside the scene. Actually the native resolution does not matter all..

If the touchscreen coordinate values are not in the range defined by the evdev axis for x and y. The system vendor should either fix the kernel driver or the users has to set a calibration matrix via udev. libinput uses the evdev axis ranges and the calibration matrix to return proper device coordinates.

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

If preferred_mode_index is incorrect then so is current_mode_index. Because in the near future we'll have a logical output size that's different to the current mode dimensions (bug 1639226). So the current mode dimensions must be ignored. Instead please use "extents().size" to get the correct size of the output in the scene.

Soon "output.modes[output.current_mode_index].size" will be completely irrelevant to the logical size of the screen. Although in some cases "output.modes[output.preferred_mode_index].size" might be useful for figuring out the physical pixel size.

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

> If preferred_mode_index is incorrect then so is current_mode_index. Because in
> the near future we'll have a logical output size that's different to the
> current mode dimensions (bug 1639226). So the current mode dimensions must be
> ignored. Instead please use "extents().size" to get the correct size of the
> output in the scene.

So you are requiring a change based on an future change that may or may not affect the validity of the modes vector?

But you do understand that I do need an untransformed coordinate range for the x and y axis of the touchscreen? I can use the preferred_mode_index as a basis for that, but then I need to do additional scaling after that to get to the current mode. Or instead use the current size directly.
extents().size would be incorrect now and later since it already applies rotation.

I do think about changing the Output to expose a transformation matrix instead of the output orientation and output position. But then still libinput needs an output size.

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

> So you are requiring a change based on an future change that may or may not
> affect the validity of the modes vector?

Yes, that "future change" I am told is my #1 priority to get working for Mir 1.0 (bug 1639226).

> But you do understand that I do need an untransformed coordinate range for the
> x and y axis of the touchscreen? I can use the preferred_mode_index as a basis
> for that,

Yes, that's why I suggested preferred_mode_index.

> I do think about changing the Output to expose a transformation matrix instead
> of the output orientation and output position. But then still libinput needs
> an output size.

Yes, I agree and have been thinking that Output may soon need to expose a transformation matrix. DisplayBuffer already does (since r4001), but I think it may need to be guided by a transformation matrix of the output in future.

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

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

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

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

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

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

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

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

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

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

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

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

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

Oh, sorry... Are you using current_mode_index because the raw touch coordinates from the kernel/libinput change based on the current display mode? I was assuming raw touch coordinates from the kernel would always just match the native resolution (preferred_mode_index).

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

> Oh, sorry... Are you using current_mode_index because the raw touch
> coordinates from the kernel/libinput change based on the current display mode?
> I was assuming raw touch coordinates from the kernel would always just match
> the native resolution (preferred_mode_index).

No neither is true. The kernel gives touch coordinates in the ranges the device offers. The two ranges sometimes contain information to calculate physical coordinates (as in mm or inch), but on android device that factor is either zero or one. We cannot assume that the ranges given will match the display resolution. (side note: one can affect the values by setting udev properties, but those are meant to make the coordinate axis align with the display axis, those calibration settings cannot account for runtime configuration of the display) Because of that libinput requires a range parameter when reading pixel coordinates from touch screens. Since the touchscreen itself is not rotated when the display is rotated via kms or software rotation I use the number of pixels in unrotated x and y direction (extent() gives me the axis ranges after rotation). By already using the (currently) final scalings of the x and y coordinate axis the code that does rotation and translation to the scene setup of the output is easier to follow.. i.e does not involve further scaling steps..

So with the last change I tried to detangle the display configuration properties from the touchscreen to output mapping. No more orientation enum and position parameter. So with a transformation matrix in place you will be able to modify that as needed.. I.e. make all scalings inside the matrix and make the output sizes such that the coordinates get mapped into unit-square.. or supply an already scaled output size..

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

OK. If there are any real problems with this approach, we won't notice any time soon. It's unlikely many people will be using touchscreens in the non-native mode or as clones other outputs.

I mean we may hit bugs in this code but we'll really need to release it first to see what those bugs are...

review: Abstain

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/client/mir_toolkit/client_types.h'
2--- include/client/mir_toolkit/client_types.h 2017-02-22 14:36:45 +0000
3+++ include/client/mir_toolkit/client_types.h 2017-03-01 16:08:29 +0000
4@@ -394,6 +394,7 @@
5 typedef struct MirKeyboardConfig MirKeyboardConfig;
6 typedef struct MirPointerConfig MirPointerConfig;
7 typedef struct MirTouchpadConfig MirTouchpadConfig;
8+typedef struct MirTouchscreenConfig MirTouchscreenConfig;
9
10 /**
11 * MirScreencastParameters is the structure of required information that
12
13=== modified file 'include/client/mir_toolkit/mir_input_device.h'
14--- include/client/mir_toolkit/mir_input_device.h 2017-02-14 16:08:27 +0000
15+++ include/client/mir_toolkit/mir_input_device.h 2017-03-01 16:08:29 +0000
16@@ -572,6 +572,74 @@
17 void mir_touchpad_config_set_disable_while_typing(
18 MirTouchpadConfig* conf, bool active);
19
20+/**
21+ * Retrieve a structure containing the touchscreen related config options
22+ * of the input device.
23+ *
24+ * If the input device does not contain a touchscreen, there are no
25+ * config options, and the function will return a null pointer.
26+ *
27+ * \param [in] device The input device
28+ *
29+ * \return The touchscreen config
30+ */
31+MirTouchscreenConfig const* mir_input_device_get_touchscreen_config(
32+ MirInputDevice const* device);
33+
34+/**
35+ * Get the output ID of the display the coordinates of this device will be mapped to.
36+ *
37+ * This setting is ignored when the mapping mode is set to
38+ * mir_touchscreen_mapping_mode_to_display_wall.
39+ *
40+ * \param [in] device The touchscreen configuration
41+ *
42+ * \return The output id
43+ */
44+uint32_t mir_touchscreen_config_get_output_id(MirTouchscreenConfig const* device);
45+
46+/**
47+ * Get the mapping mode used for the touchscreen
48+ *
49+ * \param [in] device The touchscreen configuration
50+ *
51+ * \return The mapping mode
52+ */
53+enum MirTouchscreenMappingMode mir_touchscreen_config_get_mapping_mode(MirTouchscreenConfig const* device);
54+
55+/**
56+ * Retrieve a mutable structure containing the touchscreen related options
57+ * of the input device to change the device configuration.
58+ *
59+ * If the input device does not contain a touchscreen, there are no
60+ * config options, and the function will return a null pointer.
61+ *
62+ * \param [in] device The input device
63+ *
64+ * \return The touchscreen config
65+ */
66+MirTouchscreenConfig* mir_input_device_get_mutable_touchscreen_config(
67+ MirInputDevice* device);
68+
69+/**
70+ * Set the output ID of the display the coordinates of this device will be mapped to.
71+ *
72+ * This setting is ignored when the mapping mode is set to
73+ * mir_touchscreen_mapping_mode_to_display_wall.
74+ *
75+ * \param [in] config The touchscreen configuration
76+ * \param [in] output The output id
77+ */
78+void mir_touchscreen_config_set_output_id(MirTouchscreenConfig* config, uint32_t output);
79+
80+/**
81+ * Set the mapping mode used for the touchscreen.
82+ *
83+ * \param [in] config The touchscreen configuration
84+ * \param [in] mode The mapping mode
85+ */
86+void mir_touchscreen_config_set_mapping_mode(MirTouchscreenConfig* config, enum MirTouchscreenMappingMode mode);
87+
88 #ifdef __cplusplus
89 }
90 #endif
91
92=== modified file 'include/core/mir_toolkit/mir_input_device_types.h'
93--- include/core/mir_toolkit/mir_input_device_types.h 2017-01-18 02:29:37 +0000
94+++ include/core/mir_toolkit/mir_input_device_types.h 2017-03-01 16:08:29 +0000
95@@ -113,7 +113,7 @@
96 * i.e handheld devices with builtin touchscreens or external graphic tablets or
97 * external monitors with touchscreen capabilities.
98 */
99-enum MirTouchscreenMappingMode
100+typedef enum MirTouchscreenMappingMode
101 {
102 /**
103 * Map the device coordinates onto specific output.
104@@ -123,7 +123,7 @@
105 * Map the device coordinates onto the whole wall of outputs.
106 */
107 mir_touchscreen_mapping_mode_to_display_wall
108-};
109+} MirTouchscreenMappingMode;
110
111
112 #ifdef __cplusplus
113
114=== modified file 'include/platform/mir/input/input_sink.h'
115--- include/platform/mir/input/input_sink.h 2016-07-07 09:59:19 +0000
116+++ include/platform/mir/input/input_sink.h 2017-03-01 16:08:29 +0000
117@@ -22,14 +22,40 @@
118
119 #include "mir_toolkit/event.h"
120 #include "mir/geometry/rectangle.h"
121-#include "mir/geometry/displacement.h"
122+#include "mir/geometry/point.h"
123
124 #include <vector>
125+#include <array>
126
127 namespace mir
128 {
129 namespace input
130 {
131+
132+struct OutputInfo
133+{
134+ using Matrix = std::array<float,6>; // 2x3 row major matrix
135+ OutputInfo() {}
136+ OutputInfo(bool active, geometry::Size size, Matrix const& transformation)
137+ : active{active}, output_size{size}, output_to_scene(transformation)
138+ {}
139+
140+ bool active{false};
141+ geometry::Size output_size;
142+ Matrix output_to_scene{{1,0,0,
143+ 0,1,0}};
144+
145+ inline void transform_to_scene(float& x, float& y) const
146+ {
147+ auto original_x = x;
148+ auto original_y = y;
149+ auto const& mat = output_to_scene;
150+
151+ x = mat[0]*original_x + mat[1]*original_y + mat[2]*1;
152+ y = mat[3]*original_x + mat[4]*original_y + mat[5]*1;
153+ }
154+};
155+
156 class InputSink
157 {
158 public:
159@@ -41,6 +67,13 @@
160 */
161 virtual mir::geometry::Rectangle bounding_rectangle() const = 0;
162
163+ /**!
164+ * Obtain the output information for a specific ouput.
165+ *
166+ * \param[in] output_id the id of the output
167+ */
168+ virtual OutputInfo output_info(uint32_t output_id) const = 0;
169+
170 /**
171 * \name Device State interface of InputSink
172 *
173
174=== modified file 'include/platform/mir/input/touchscreen_settings.h'
175--- include/platform/mir/input/touchscreen_settings.h 2017-02-03 13:42:56 +0000
176+++ include/platform/mir/input/touchscreen_settings.h 2017-03-01 16:08:29 +0000
177@@ -30,6 +30,11 @@
178
179 struct TouchscreenSettings
180 {
181+ TouchscreenSettings() {}
182+ TouchscreenSettings(uint32_t output_id, MirTouchscreenMappingMode mode)
183+ : output_id{output_id}, mapping_mode{mode}
184+ {}
185+
186 /**
187 * Configures the output the input device should map its coordinates to.
188 * The value of this setting is only relevant when the mapping mode is
189
190=== modified file 'include/test/mir_test_framework/fake_input_device.h'
191--- include/test/mir_test_framework/fake_input_device.h 2017-01-18 02:29:37 +0000
192+++ include/test/mir_test_framework/fake_input_device.h 2017-03-01 16:08:29 +0000
193@@ -24,6 +24,14 @@
194 #include <chrono>
195 #include <functional>
196
197+namespace mir
198+{
199+namespace input
200+{
201+class InputDevice;
202+}
203+}
204+
205 namespace mir_test_framework
206 {
207
208@@ -52,6 +60,7 @@
209 virtual void emit_touch_sequence(std::function<mir::input::synthesis::TouchParameters(int)> const& generate_parameters,
210 int count,
211 std::chrono::duration<double> delay) = 0;
212+ virtual void on_new_configuration_do(std::function<void(mir::input::InputDevice const& device)> callback) = 0;
213
214 FakeInputDevice(FakeInputDevice const&) = delete;
215 FakeInputDevice& operator=(FakeInputDevice const&) = delete;
216
217=== modified file 'src/client/mir_input_device_api.cpp'
218--- src/client/mir_input_device_api.cpp 2017-02-09 10:49:40 +0000
219+++ src/client/mir_input_device_api.cpp 2017-03-01 16:08:29 +0000
220@@ -20,6 +20,7 @@
221 #include "mir/input/mir_keyboard_config.h"
222 #include "mir/input/mir_pointer_config.h"
223 #include "mir/input/mir_touchpad_config.h"
224+#include "mir/input/mir_touchscreen_config.h"
225 #include "mir/require.h"
226 #include "handle_event_exception.h"
227
228@@ -282,3 +283,37 @@
229 {
230 conf->disable_while_typing(active);
231 })
232+
233+MirTouchscreenConfig const* mir_input_device_get_touchscreen_config(MirInputDevice const* device) MIR_HANDLE_EVENT_EXCEPTION(
234+{
235+ if (device->has_touchscreen_config())
236+ return &device->touchscreen_config();
237+ return nullptr;
238+})
239+
240+uint32_t mir_touchscreen_config_get_output_id(MirTouchscreenConfig const* config) MIR_HANDLE_EVENT_EXCEPTION(
241+{
242+ return config->output_id();
243+})
244+
245+MirTouchscreenMappingMode mir_touchscreen_config_get_mapping_mode(MirTouchscreenConfig const* config) MIR_HANDLE_EVENT_EXCEPTION(
246+{
247+ return config->mapping_mode();
248+})
249+
250+MirTouchscreenConfig* mir_input_device_get_mutable_touchscreen_config(MirInputDevice* device) MIR_HANDLE_EVENT_EXCEPTION(
251+{
252+ if (device->has_touchscreen_config())
253+ return &device->touchscreen_config();
254+ return nullptr;
255+})
256+
257+void mir_touchscreen_config_set_output_id(MirTouchscreenConfig* config, uint32_t id) MIR_HANDLE_EVENT_EXCEPTION(
258+{
259+ return config->output_id(id);
260+})
261+
262+void mir_touchscreen_config_set_mapping_mode(MirTouchscreenConfig* config, MirTouchscreenMappingMode mode) MIR_HANDLE_EVENT_EXCEPTION(
263+{
264+ return config->mapping_mode(mode);
265+})
266
267=== modified file 'src/client/symbols.map'
268--- src/client/symbols.map 2017-02-24 14:11:28 +0000
269+++ src/client/symbols.map 2017-03-01 16:08:29 +0000
270@@ -616,6 +616,8 @@
271 mir_get_client_api_version;
272 mir_input_device_get_keyboard_config;
273 mir_input_device_get_mutable_keyboard_config;
274+ mir_input_device_get_mutable_touchscreen_config;
275+ mir_input_device_get_touchscreen_config;
276 mir_keyboard_config_get_keymap_layout;
277 mir_keyboard_config_get_keymap_model;
278 mir_keyboard_config_get_keymap_options;
279@@ -627,4 +629,8 @@
280 mir_keyboard_event_key_text;
281 mir_output_get_logical_height;
282 mir_output_get_logical_width;
283+ mir_touchscreen_config_get_mapping_mode;
284+ mir_touchscreen_config_get_output_id;
285+ mir_touchscreen_config_set_mapping_mode;
286+ mir_touchscreen_config_set_output_id;
287 } MIR_CLIENT_0.26.1;
288
289=== modified file 'src/include/server/mir/input/seat.h'
290--- src/include/server/mir/input/seat.h 2017-01-18 02:29:37 +0000
291+++ src/include/server/mir/input/seat.h 2017-03-01 16:08:29 +0000
292@@ -33,6 +33,8 @@
293 namespace input
294 {
295 class Device;
296+class OutputInfo;
297+
298 class Seat
299 {
300 public:
301@@ -41,7 +43,6 @@
302 virtual void add_device(Device const& device) = 0;
303 virtual void remove_device(Device const& device) = 0;
304 virtual void dispatch_event(MirEvent& event) = 0;
305- virtual geometry::Rectangle get_rectangle_for(Device const& dev) = 0;
306 virtual EventUPtr create_device_state() = 0;
307
308 virtual void set_key_state(Device const& dev, std::vector<uint32_t> const& scan_codes) = 0;
309@@ -49,6 +50,9 @@
310 virtual void set_cursor_position(float cursor_x, float cursor_y) = 0;
311 virtual void set_confinement_regions(geometry::Rectangles const& regions) = 0;
312 virtual void reset_confinement_regions() = 0;
313+
314+ virtual geometry::Rectangle bounding_rectangle() const = 0;
315+ virtual input::OutputInfo output_info(uint32_t output_id) const = 0;
316 private:
317 Seat(Seat const&) = delete;
318 Seat& operator=(Seat const&) = delete;
319
320=== modified file 'src/platforms/evdev/libinput_device.cpp'
321--- src/platforms/evdev/libinput_device.cpp 2017-02-03 01:10:42 +0000
322+++ src/platforms/evdev/libinput_device.cpp 2017-03-01 16:08:29 +0000
323@@ -114,7 +114,10 @@
324 // Not yet provided by libinput.
325 break;
326 case LIBINPUT_EVENT_TOUCH_FRAME:
327- sink->handle_input(*convert_touch_frame(libinput_event_get_touch_event(event)));
328+ if (is_output_active())
329+ {
330+ sink->handle_input(*convert_touch_frame(libinput_event_get_touch_event(event)));
331+ }
332 break;
333 default:
334 break;
335@@ -184,6 +187,7 @@
336 auto const action = mir_pointer_action_motion;
337 auto const hscroll_value = 0.0f;
338 auto const vscroll_value = 0.0f;
339+ // either the bounding box .. or the specific output ..
340 auto const screen = sink->bounding_rectangle();
341 uint32_t const width = screen.size.width.as_int();
342 uint32_t const height = screen.size.height.as_int();
343@@ -290,9 +294,10 @@
344
345 void mie::LibInputDevice::update_contact_data(ContactData & data, MirTouchAction action, libinput_event_touch* touch)
346 {
347- auto const screen = sink->bounding_rectangle();
348- uint32_t const width = screen.size.width.as_int();
349- uint32_t const height = screen.size.height.as_int();
350+ auto info = get_output_info();
351+
352+ uint32_t width = info.output_size.width.as_int();
353+ uint32_t height = info.output_size.height.as_int();
354
355 data.action = action;
356 data.pressure = libinput_event_touch_get_pressure(touch);
357@@ -300,6 +305,8 @@
358 data.y = libinput_event_touch_get_y_transformed(touch, height);
359 data.major = libinput_event_touch_get_major_transformed(touch, width, height);
360 data.minor = libinput_event_touch_get_minor_transformed(touch, width, height);
361+
362+ info.transform_to_scene(data.x, data.y);
363 }
364
365 void mie::LibInputDevice::handle_touch_motion(libinput_event_touch* touch)
366@@ -351,6 +358,10 @@
367 }
368 }
369
370+ if (contains(caps, mi::DeviceCapability::touchscreen) &&
371+ !contains(info.capabilities, mi::DeviceCapability::touchscreen))
372+ touchscreen = mi::TouchscreenSettings{};
373+
374 info = mi::InputDeviceInfo{name, unique_id.str(), caps};
375 }
376
377@@ -364,6 +375,40 @@
378 return devices.front().get();
379 }
380
381+mi::OutputInfo mie::LibInputDevice::get_output_info() const
382+{
383+ if (touchscreen.is_set() && touchscreen.value().mapping_mode == mir_touchscreen_mapping_mode_to_output)
384+ {
385+ return sink->output_info(touchscreen.value().output_id);
386+ }
387+ else
388+ {
389+ auto scene_bbox = sink->bounding_rectangle();
390+ return mi::OutputInfo(
391+ true,
392+ scene_bbox.size,
393+ mi::OutputInfo::Matrix{{1.0f, 0.0f, float(scene_bbox.top_left.x.as_int()),
394+ 0.0f, 1.0f, float(scene_bbox.top_left.y.as_int())}});
395+ }
396+}
397+
398+bool mie::LibInputDevice::is_output_active() const
399+{
400+ if (!sink)
401+ return false;
402+
403+ if (touchscreen.is_set())
404+ {
405+ auto const& touchscreen_config = touchscreen.value();
406+ if (touchscreen_config.mapping_mode == mir_touchscreen_mapping_mode_to_output)
407+ {
408+ auto output = sink->output_info(touchscreen_config.output_id);
409+ return output.active;
410+ }
411+ }
412+ return true;
413+}
414+
415 mir::optional_value<mi::PointerSettings> mie::LibInputDevice::get_pointer_settings() const
416 {
417 if (!contains(info.capabilities, mi::DeviceCapability::pointer))
418
419=== modified file 'src/platforms/evdev/libinput_device.h'
420--- src/platforms/evdev/libinput_device.h 2017-02-03 01:10:42 +0000
421+++ src/platforms/evdev/libinput_device.h 2017-03-01 16:08:29 +0000
422@@ -41,6 +41,7 @@
423 {
424 namespace input
425 {
426+class OutputInfo;
427 class InputReport;
428 namespace evdev
429 {
430@@ -77,6 +78,8 @@
431 void handle_touch_up(libinput_event_touch* touch);
432 void handle_touch_motion(libinput_event_touch* touch);
433 void update_device_info();
434+ bool is_output_active() const;
435+ OutputInfo get_output_info() const;
436
437 std::shared_ptr<InputReport> report;
438 std::shared_ptr<::libinput> lib;
439
440=== modified file 'src/server/graphics/nested/input_platform.cpp'
441--- src/server/graphics/nested/input_platform.cpp 2017-02-20 13:19:28 +0000
442+++ src/server/graphics/nested/input_platform.cpp 2017-03-01 16:08:29 +0000
443@@ -104,7 +104,15 @@
444 touchpad_settings = settings;
445 }
446
447- // TODO Forwars config when mirclient API is there
448+ auto touchscreen_config = mir_input_device_get_touchscreen_config(dev);
449+ if (touchscreen_config && contains(device_info.capabilities, mi::DeviceCapability::touchscreen))
450+ {
451+ mi::TouchscreenSettings settings;
452+ settings.output_id = mir_touchscreen_config_get_output_id(touchscreen_config);
453+ settings.mapping_mode = mir_touchscreen_config_get_mapping_mode(touchscreen_config);
454+
455+ touchscreen_settings = settings;
456+ }
457 }
458
459 void start(mi::InputSink* destination, mi::EventBuilder* builder) override
460@@ -251,7 +259,15 @@
461 if (touchscreen_settings.is_set() && touchscreen_settings.value() == new_settings)
462 return;
463
464- // TODO update the MirInputConfig..
465+ auto ts_conf = mir_input_device_get_mutable_touchscreen_config(device);
466+
467+ if (ts_conf)
468+ {
469+ mir_touchscreen_config_set_output_id(ts_conf, new_settings.output_id);
470+ mir_touchscreen_config_set_mapping_mode(ts_conf, new_settings.mapping_mode);
471+
472+ emit_device_change();
473+ }
474 }
475
476 MirInputDeviceId device_id;
477
478=== modified file 'src/server/input/basic_seat.cpp'
479--- src/server/input/basic_seat.cpp 2017-01-18 02:29:37 +0000
480+++ src/server/input/basic_seat.cpp 2017-03-01 16:08:29 +0000
481@@ -19,29 +19,147 @@
482
483 #include "basic_seat.h"
484 #include "mir/input/device.h"
485-#include "mir/input/input_region.h"
486+#include "mir/input/input_sink.h"
487+#include "mir/graphics/display_configuration_observer.h"
488+#include "mir/graphics/display_configuration.h"
489+#include "mir/graphics/transformation.h"
490+#include "mir/geometry/rectangle.h"
491+#include "mir/geometry/point.h"
492+#include "mir/geometry/size.h"
493+#include "mir_toolkit/common.h"
494
495 #include <algorithm>
496+#include <array>
497
498 namespace mi = mir::input;
499 namespace mf = mir::frontend;
500+namespace mg = mir::graphics;
501+namespace geom = mir::geometry;
502+
503+struct mi::BasicSeat::OutputTracker : mg::DisplayConfigurationObserver
504+{
505+ OutputTracker(SeatInputDeviceTracker& tracker)
506+ : input_state_tracker{tracker}
507+ {
508+ }
509+
510+ void update_outputs(mg::DisplayConfiguration const& conf)
511+ {
512+ std::lock_guard<std::mutex> lock(output_mutex);
513+ outputs.clear();
514+ geom::Rectangles output_rectangles;
515+ conf.for_each_output(
516+ [this, &output_rectangles](mg::DisplayConfigurationOutput const& output)
517+ {
518+ if (!output.used || !output.connected)
519+ return;
520+ if (!output.valid() || (output.current_mode_index >= output.modes.size()))
521+ return;
522+
523+ // TODO make the decision whether display that is used but powered off should emit
524+ // touch screen events in a policy
525+ bool active = output.power_mode == mir_power_mode_on;
526+
527+ auto output_size = output.modes[output.current_mode_index].size;
528+ auto width = output_size.width.as_int();
529+ auto height = output_size.height.as_int();
530+ OutputInfo::Matrix output_matrix{{
531+ 1.0f, 0.0f, float(output.top_left.x.as_int()),
532+ 0.0f, 1.0f, float(output.top_left.y.as_int())}};
533+
534+ switch(output.orientation)
535+ {
536+ case mir_orientation_left:
537+ output_matrix[3] = -1;
538+ output_matrix[5] += width;
539+ break;
540+ case mir_orientation_right:
541+ output_matrix[1] = -1;
542+ output_matrix[2] += height;
543+ break;
544+ case mir_orientation_inverted:
545+ output_matrix[0] = -1;
546+ output_matrix[2] += width;
547+ output_matrix[4] = -1;
548+ output_matrix[5] += height;
549+ default:
550+ break;
551+ }
552+ if (active)
553+ output_rectangles.add(output.extents());
554+ outputs.insert(std::make_pair(output.id.as_value(), OutputInfo{active, output_size, output_matrix}));
555+ });
556+ input_state_tracker.update_outputs(output_rectangles);
557+ bounding_rectangle = output_rectangles.bounding_rectangle();
558+ }
559+
560+ void initial_configuration(std::shared_ptr<mg::DisplayConfiguration const> const& config) override
561+ {
562+ update_outputs(*config.get());
563+ }
564+
565+ void configuration_applied(std::shared_ptr<mg::DisplayConfiguration const> const& config) override
566+ {
567+ update_outputs(*config.get());
568+ }
569+
570+ void base_configuration_updated(std::shared_ptr<mg::DisplayConfiguration const> const&) override
571+ {}
572+
573+ void session_configuration_applied(std::shared_ptr<mf::Session> const&,
574+ std::shared_ptr<mg::DisplayConfiguration> const&) override
575+ {}
576+
577+ void session_configuration_removed(std::shared_ptr<mf::Session> const&) override
578+ {}
579+
580+ void configuration_failed(
581+ std::shared_ptr<mg::DisplayConfiguration const> const&,
582+ std::exception const&) override
583+ {}
584+
585+ void catastrophic_configuration_error(
586+ std::shared_ptr<mg::DisplayConfiguration const> const&,
587+ std::exception const&) override
588+ {}
589+
590+ geom::Rectangle get_bounding_rectangle() const
591+ {
592+ std::lock_guard<std::mutex> lock(output_mutex);
593+ return bounding_rectangle;
594+ }
595+
596+ mi::OutputInfo get_output_info(uint32_t output) const
597+ {
598+ std::lock_guard<std::mutex> lock(output_mutex);
599+ auto pos = outputs.find(output);
600+ if (pos != end(outputs))
601+ return pos->second;
602+ return OutputInfo{};
603+ }
604+private:
605+ mutable std::mutex output_mutex;
606+ mi::SeatInputDeviceTracker& input_state_tracker;
607+ std::unordered_map<uint32_t, mi::OutputInfo> outputs;
608+ geom::Rectangle bounding_rectangle;
609+};
610
611 mi::BasicSeat::BasicSeat(std::shared_ptr<mi::InputDispatcher> const& dispatcher,
612 std::shared_ptr<mi::TouchVisualizer> const& touch_visualizer,
613 std::shared_ptr<mi::CursorListener> const& cursor_listener,
614- std::shared_ptr<mi::InputRegion> const& input_region,
615+ std::shared_ptr<Registrar> const& registrar,
616 std::shared_ptr<mi::KeyMapper> const& key_mapper,
617 std::shared_ptr<time::Clock> const& clock,
618 std::shared_ptr<mi::SeatObserver> const& observer) :
619 input_state_tracker{dispatcher,
620 touch_visualizer,
621 cursor_listener,
622- input_region,
623 key_mapper,
624 clock,
625 observer},
626- input_region{input_region}
627+ output_tracker{std::make_shared<OutputTracker>(input_state_tracker)}
628 {
629+ registrar->register_interest(output_tracker);
630 }
631
632 void mi::BasicSeat::add_device(input::Device const& device)
633@@ -59,13 +177,14 @@
634 input_state_tracker.dispatch(event);
635 }
636
637-mir::geometry::Rectangle mi::BasicSeat::get_rectangle_for(input::Device const&)
638-{
639- // TODO: With knowledge of the outputs attached to this seat and the output the given input
640- // device is associated this method should only return the rectangle of that output. For now
641- // we rely on the existing workaround in DisplayInputRegion::bounding_rectangle() which
642- // assumes that only the first output may have a touch screen associated to it.
643- return input_region->bounding_rectangle();
644+geom::Rectangle mi::BasicSeat::bounding_rectangle() const
645+{
646+ return output_tracker->get_bounding_rectangle();
647+}
648+
649+mi::OutputInfo mi::BasicSeat::output_info(uint32_t output_id) const
650+{
651+ return output_tracker->get_output_info(output_id);
652 }
653
654 mir::EventUPtr mi::BasicSeat::create_device_state()
655@@ -88,7 +207,7 @@
656 input_state_tracker.set_cursor_position(cursor_x, cursor_y);
657 }
658
659-void mi::BasicSeat::set_confinement_regions(geometry::Rectangles const& regions)
660+void mi::BasicSeat::set_confinement_regions(geom::Rectangles const& regions)
661 {
662 input_state_tracker.set_confinement_regions(regions);
663 }
664@@ -97,3 +216,4 @@
665 {
666 input_state_tracker.reset_confinement_regions();
667 }
668+
669
670=== modified file 'src/server/input/basic_seat.h'
671--- src/server/input/basic_seat.h 2017-01-18 02:29:37 +0000
672+++ src/server/input/basic_seat.h 2017-03-01 16:08:29 +0000
673@@ -20,9 +20,10 @@
674 #ifndef MIR_BASIC_SEAT_H_
675 #define MIR_BASIC_SEAT_H_
676
677+#include "seat_input_device_tracker.h"
678 #include "mir/input/seat.h"
679 #include "mir/frontend/event_sink.h"
680-#include "seat_input_device_tracker.h"
681+#include "mir/observer_registrar.h"
682
683 #include <mutex>
684
685@@ -32,6 +33,10 @@
686 {
687 class Clock;
688 }
689+namespace graphics
690+{
691+class DisplayConfigurationObserver;
692+}
693 namespace input
694 {
695 class TouchVisualizer;
696@@ -44,10 +49,11 @@
697 class BasicSeat : public Seat
698 {
699 public:
700+ using Registrar = ObserverRegistrar<graphics::DisplayConfigurationObserver>;
701 BasicSeat(std::shared_ptr<InputDispatcher> const& dispatcher,
702 std::shared_ptr<TouchVisualizer> const& touch_visualizer,
703 std::shared_ptr<CursorListener> const& cursor_listener,
704- std::shared_ptr<InputRegion> const& input_region,
705+ std::shared_ptr<Registrar> const& registrar,
706 std::shared_ptr<KeyMapper> const& key_mapper,
707 std::shared_ptr<time::Clock> const& clock,
708 std::shared_ptr<SeatObserver> const& observer);
709@@ -55,17 +61,19 @@
710 void add_device(Device const& device) override;
711 void remove_device(Device const& device) override;
712 void dispatch_event(MirEvent& event) override;
713- geometry::Rectangle get_rectangle_for(Device const& dev) override;
714- virtual EventUPtr create_device_state() override;
715- virtual void set_confinement_regions(geometry::Rectangles const& regions) override;
716- virtual void reset_confinement_regions() override;
717+ geometry::Rectangle bounding_rectangle() const override;
718+ input::OutputInfo output_info(uint32_t output_id) const override;
719+ EventUPtr create_device_state() override;
720+ void set_confinement_regions(geometry::Rectangles const& regions) override;
721+ void reset_confinement_regions() override;
722
723 void set_key_state(Device const& dev, std::vector<uint32_t> const& scan_codes) override;
724 void set_pointer_state(Device const& dev, MirPointerButtons buttons) override;
725 void set_cursor_position(float cursor_x, float cursor_y) override;
726 private:
727 SeatInputDeviceTracker input_state_tracker;
728- std::shared_ptr<InputRegion> const input_region;
729+ struct OutputTracker;
730+ std::shared_ptr<OutputTracker> const output_tracker;
731 };
732 }
733 }
734
735=== modified file 'src/server/input/default_configuration.cpp'
736--- src/server/input/default_configuration.cpp 2017-02-16 05:44:15 +0000
737+++ src/server/input/default_configuration.cpp 2017-03-01 16:08:29 +0000
738@@ -297,7 +297,7 @@
739 the_input_dispatcher(),
740 the_touch_visualizer(),
741 the_cursor_listener(),
742- the_input_region(),
743+ the_display_configuration_observer_registrar(),
744 the_key_mapper(),
745 the_clock(),
746 the_seat_observer());
747
748=== modified file 'src/server/input/default_input_device_hub.cpp'
749--- src/server/input/default_input_device_hub.cpp 2017-02-27 18:23:08 +0000
750+++ src/server/input/default_input_device_hub.cpp 2017-03-01 16:08:29 +0000
751@@ -201,7 +201,15 @@
752 if (!seat)
753 BOOST_THROW_EXCEPTION(std::runtime_error("Device not started and has no seat assigned"));
754
755- return seat->get_rectangle_for(*handle);
756+ return seat->bounding_rectangle();
757+}
758+
759+mi::OutputInfo mi::DefaultInputDeviceHub::RegisteredDevice::output_info(uint32_t output_id) const
760+{
761+ if (!seat)
762+ BOOST_THROW_EXCEPTION(std::runtime_error("Device not started and has no seat assigned"));
763+
764+ return seat->output_info(output_id);
765 }
766
767 void mi::DefaultInputDeviceHub::RegisteredDevice::key_state(std::vector<uint32_t> const& scan_codes)
768
769=== modified file 'src/server/input/default_input_device_hub.h'
770--- src/server/input/default_input_device_hub.h 2017-02-27 18:23:08 +0000
771+++ src/server/input/default_input_device_hub.h 2017-03-01 16:08:29 +0000
772@@ -104,7 +104,8 @@
773 std::shared_ptr<cookie::Authority> const& cookie_authority,
774 std::shared_ptr<DefaultDevice> const& handle);
775 void handle_input(MirEvent& event) override;
776- mir::geometry::Rectangle bounding_rectangle() const override;
777+ geometry::Rectangle bounding_rectangle() const override;
778+ input::OutputInfo output_info(uint32_t output_id) const override;
779 bool device_matches(std::shared_ptr<InputDevice> const& dev) const;
780 void start(std::shared_ptr<Seat> const& seat);
781 void stop();
782
783=== modified file 'src/server/input/seat_input_device_tracker.cpp'
784--- src/server/input/seat_input_device_tracker.cpp 2017-02-17 07:03:56 +0000
785+++ src/server/input/seat_input_device_tracker.cpp 2017-03-01 16:08:29 +0000
786@@ -20,7 +20,6 @@
787 #include "seat_input_device_tracker.h"
788 #include "mir/input/device.h"
789 #include "mir/input/cursor_listener.h"
790-#include "mir/input/input_region.h"
791 #include "mir/input/input_dispatcher.h"
792 #include "mir/input/key_mapper.h"
793 #include "mir/input/seat_observer.h"
794@@ -45,12 +44,11 @@
795 mi::SeatInputDeviceTracker::SeatInputDeviceTracker(std::shared_ptr<InputDispatcher> const& dispatcher,
796 std::shared_ptr<TouchVisualizer> const& touch_visualizer,
797 std::shared_ptr<CursorListener> const& cursor_listener,
798- std::shared_ptr<InputRegion> const& input_region,
799 std::shared_ptr<KeyMapper> const& key_mapper,
800 std::shared_ptr<time::Clock> const& clock,
801 std::shared_ptr<SeatObserver> const& observer)
802 : dispatcher{dispatcher}, touch_visualizer{touch_visualizer}, cursor_listener{cursor_listener},
803- input_region{input_region}, key_mapper{key_mapper}, clock{clock}, observer{observer}, buttons{0}
804+ key_mapper{key_mapper}, clock{clock}, observer{observer}, buttons{0}
805 {
806 }
807
808@@ -231,10 +229,16 @@
809 observer->seat_reset_confinement_regions();
810 }
811
812+void mi::SeatInputDeviceTracker::update_outputs(geom::Rectangles const& output_regions)
813+{
814+ std::lock_guard<std::mutex> lg(output_mutex);
815+ input_region = output_regions;
816+}
817+
818 void mi::SeatInputDeviceTracker::confine_function(mir::geometry::Point& p) const
819 {
820 std::lock_guard<std::mutex> lg(region_mutex);
821- input_region->confine(p);
822+ input_region.confine(p);
823 confined_region.confine(p);
824 }
825
826
827=== modified file 'src/server/input/seat_input_device_tracker.h'
828--- src/server/input/seat_input_device_tracker.h 2017-02-17 07:03:56 +0000
829+++ src/server/input/seat_input_device_tracker.h 2017-03-01 16:08:29 +0000
830@@ -23,7 +23,10 @@
831 #include "mir/input/touch_visualizer.h"
832 #include "mir/geometry/point.h"
833 #include "mir/geometry/rectangles.h"
834+#include "mir/geometry/size.h"
835+#include "mir/optional_value.h"
836 #include "mir_toolkit/event.h"
837+
838 #include <unordered_map>
839 #include <memory>
840 #include <mutex>
841@@ -56,7 +59,6 @@
842 SeatInputDeviceTracker(std::shared_ptr<InputDispatcher> const& dispatcher,
843 std::shared_ptr<TouchVisualizer> const& touch_visualizer,
844 std::shared_ptr<CursorListener> const& cursor_listener,
845- std::shared_ptr<InputRegion> const& input_region,
846 std::shared_ptr<KeyMapper> const& key_mapper,
847 std::shared_ptr<time::Clock> const& clock,
848 std::shared_ptr<SeatObserver> const& observer);
849@@ -74,6 +76,8 @@
850 void set_cursor_position(float cursor_x, float cursor_y);
851 void set_confinement_regions(geometry::Rectangles const& region);
852 void reset_confinement_regions();
853+
854+ void update_outputs(geometry::Rectangles const& outputs);
855 private:
856 void update_seat_properties(MirInputEvent const* event);
857 void update_cursor(MirPointerEvent const* event);
858@@ -86,7 +90,6 @@
859 std::shared_ptr<InputDispatcher> const dispatcher;
860 std::shared_ptr<TouchVisualizer> const touch_visualizer;
861 std::shared_ptr<CursorListener> const cursor_listener;
862- std::shared_ptr<InputRegion> const input_region;
863 std::shared_ptr<KeyMapper> const key_mapper;
864 std::shared_ptr<time::Clock> const clock;
865 std::shared_ptr<SeatObserver> const observer;
866@@ -102,6 +105,9 @@
867 MirPointerButtons buttons{0};
868 std::vector<TouchVisualizer::Spot> spots;
869 std::vector<uint32_t> scan_codes;
870+
871+ MirTouchscreenMappingMode mapping_mode{mir_touchscreen_mapping_mode_to_output};
872+ mir::optional_value<uint32_t> output_id;
873 };
874
875 // Libinput's acceleration curve means the cursor moves by non-integer
876@@ -115,6 +121,9 @@
877
878 std::mutex mutable device_state_mutex;
879 std::mutex mutable region_mutex;
880+
881+ std::mutex mutable output_mutex;
882+ geometry::Rectangles input_region;
883 };
884
885 }
886
887=== modified file 'src/server/scene/surface_stack.cpp'
888--- src/server/scene/surface_stack.cpp 2017-01-20 12:32:45 +0000
889+++ src/server/scene/surface_stack.cpp 2017-03-01 16:08:29 +0000
890@@ -309,11 +309,7 @@
891 RecursiveReadLock lg(guard);
892 for (auto &surface : surfaces)
893 {
894- if (surface->query(mir_window_attrib_visibility) ==
895- MirWindowVisibility::mir_window_visibility_exposed)
896- {
897- callback(surface);
898- }
899+ callback(surface);
900 }
901 }
902
903
904=== modified file 'tests/acceptance-tests/test_client_input.cpp'
905--- tests/acceptance-tests/test_client_input.cpp 2017-02-22 14:36:45 +0000
906+++ tests/acceptance-tests/test_client_input.cpp 2017-03-01 16:08:29 +0000
907@@ -24,6 +24,8 @@
908 #include "mir/scene/surface.h"
909 #include "mir/input/mir_touchpad_config.h"
910 #include "mir/input/mir_input_config.h"
911+#include "mir/input/input_device.h"
912+#include "mir/input/touchscreen_settings.h"
913
914 #include "mir_test_framework/headless_in_process_server.h"
915 #include "mir_test_framework/fake_input_device.h"
916@@ -95,6 +97,22 @@
917 }
918 };
919
920+
921+template<typename SetCallback, typename Apply>
922+void apply_and_wait_for_completion(MirConnection* connection, SetCallback set_callback, Apply apply)
923+{
924+ mt::Signal change_complete;
925+ set_callback(connection,
926+ [](MirConnection*, void* context)
927+ {
928+ static_cast<mt::Signal*>(context)->raise();
929+ },
930+ &change_complete
931+ );
932+ apply(connection);
933+ ASSERT_TRUE(change_complete.wait_for(10s));
934+}
935+
936 const int surface_width = 100;
937 const int surface_height = 100;
938
939@@ -356,6 +374,35 @@
940 }
941 };
942
943+struct TestClientInputWithTwoScreens : TestClientInput
944+{
945+ geom::Rectangle second_screen{{1000,0}, {200,400}};
946+
947+ int const width{second_screen.size.width.as_int()};
948+ int const height{second_screen.size.height.as_int()};
949+ float const touch_range = mtf::FakeInputDevice::maximum_touch_axis_value - mtf::FakeInputDevice::minimum_touch_axis_value + 1;
950+ float const scale_to_device_width = touch_range / width;
951+ float const scale_to_device_height = touch_range / height;
952+
953+ void SetUp() override
954+ {
955+ initial_display_layout({screen_geometry, second_screen});
956+
957+ server.wrap_shell(
958+ [this](std::shared_ptr<mir::shell::Shell> const& wrapped)
959+ {
960+ shell = std::make_shared<mtf::PlacementApplyingShell>(wrapped, input_regions, positions);
961+ return shell;
962+ });
963+
964+ HeadlessInProcessServer::SetUp();
965+
966+ // make surface span over both outputs to test coordinates mapped into second ouput:
967+ positions[first] =
968+ geom::Rectangle{{0, 0}, {second_screen.bottom_right().x.as_int(), second_screen.bottom_right().y.as_int()}};
969+ }
970+};
971+
972 }
973
974 TEST_F(TestClientInput, clients_receive_keys)
975@@ -1246,19 +1293,14 @@
976 mir_pointer_config_set_acceleration(pointer_config, mir_pointer_acceleration_adaptive);
977 mir_pointer_config_set_acceleration_bias(pointer_config, increased_acceleration);
978
979- mt::Signal changes_complete;
980- mir_connection_set_input_config_change_callback(
981+ apply_and_wait_for_completion(
982 a_client.connection,
983- [](MirConnection*, void* context)
984+ mir_connection_set_input_config_change_callback,
985+ [config](MirConnection* connection)
986 {
987- static_cast<mt::Signal*>(context)->raise();
988- },
989- &changes_complete
990- );
991- mir_connection_apply_session_input_config(a_client.connection, config);
992- mir_input_config_release(config);
993-
994- EXPECT_TRUE(changes_complete.wait_for(10s));
995+ mir_connection_apply_session_input_config(connection, config);
996+ mir_input_config_release(config);
997+ });
998
999 config = mir_connection_create_input_config(a_client.connection);
1000 mouse = get_mutable_device_with_capabilities(config, mir_input_device_capability_pointer);
1001@@ -1353,19 +1395,14 @@
1002
1003 mir_pointer_config_set_acceleration(pointer_config, mir_pointer_acceleration_adaptive);
1004
1005- mt::Signal changes_complete;
1006- mir_connection_set_input_config_change_callback(
1007+ apply_and_wait_for_completion(
1008 unfocused_client.connection,
1009- [](MirConnection*, void* context)
1010+ mir_connection_set_input_config_change_callback,
1011+ [config](MirConnection* connection)
1012 {
1013- static_cast<mt::Signal*>(context)->raise();
1014- },
1015- &changes_complete
1016- );
1017- mir_connection_set_base_input_config(unfocused_client.connection, config);
1018- mir_input_config_release(config);
1019-
1020- EXPECT_TRUE(changes_complete.wait_for(10s));
1021+ mir_connection_set_base_input_config(connection, config);
1022+ mir_input_config_release(config);
1023+ });
1024
1025 config = mir_connection_create_input_config(unfocused_client.connection);
1026 mouse = get_mutable_device_with_capabilities(config, mir_input_device_capability_pointer);
1027@@ -1414,19 +1451,14 @@
1028
1029 mir_pointer_config_set_acceleration(pointer_config, mir_pointer_acceleration_adaptive);
1030
1031- mt::Signal changes_complete;
1032- mir_connection_set_input_config_change_callback(
1033+ apply_and_wait_for_completion(
1034 focused_client.connection,
1035- [](MirConnection*, void* context)
1036+ mir_connection_set_input_config_change_callback,
1037+ [config](MirConnection* connection)
1038 {
1039- static_cast<mt::Signal*>(context)->raise();
1040- },
1041- &changes_complete
1042- );
1043- mir_connection_set_base_input_config(focused_client.connection, config);
1044- mir_input_config_release(config);
1045-
1046- changes_complete.wait_for(10s);
1047+ mir_connection_set_base_input_config(connection, config);
1048+ mir_input_config_release(config);
1049+ });
1050
1051 config = mir_connection_create_input_config(focused_client.connection);
1052 mouse = get_mutable_device_with_capabilities(config, mir_input_device_capability_pointer);
1053@@ -1511,3 +1543,145 @@
1054
1055 EXPECT_TRUE(wait_for_error.wait_for(10s));
1056 }
1057+
1058+TEST_F(TestClientInput, touchscreen_config_is_mutable)
1059+{
1060+ wait_for_input_devices();
1061+
1062+ Client a_client(new_connection(), first);
1063+ auto config = mir_connection_create_input_config(a_client.connection);
1064+ auto touchscreen = get_mutable_device_with_capabilities(config,
1065+ mir_input_device_capability_touchscreen|
1066+ mir_input_device_capability_multitouch);
1067+ ASSERT_THAT(touchscreen, Ne(nullptr));
1068+
1069+ auto touchscreen_config = mir_input_device_get_mutable_touchscreen_config(touchscreen);
1070+
1071+ mir_touchscreen_config_set_output_id(touchscreen_config, 4);
1072+ mir_touchscreen_config_set_mapping_mode(touchscreen_config, mir_touchscreen_mapping_mode_to_display_wall);
1073+
1074+ EXPECT_THAT(mir_touchscreen_config_get_mapping_mode(touchscreen_config), Eq(mir_touchscreen_mapping_mode_to_display_wall));
1075+ EXPECT_THAT(mir_touchscreen_config_get_output_id(touchscreen_config), Eq(4));
1076+
1077+ mir_input_config_release(config);
1078+}
1079+
1080+TEST_F(TestClientInputWithTwoScreens, touchscreen_can_be_mapped_to_second_output)
1081+{
1082+ wait_for_input_devices();
1083+ uint32_t const second_output = 2;
1084+ int const touch_x = 10;
1085+ int const touch_y = 10;
1086+
1087+ int const expected_x = touch_x + second_screen.top_left.x.as_int();
1088+ int const expected_y = touch_y + second_screen.top_left.y.as_int();
1089+
1090+ mt::Signal touchscreen_ready;
1091+ fake_touch_screen->on_new_configuration_do(
1092+ [&touchscreen_ready, second_output](mi::InputDevice const& dev)
1093+ {
1094+ auto ts = dev.get_touchscreen_settings();
1095+ if (ts.is_set() && ts.value().output_id == second_output)
1096+ touchscreen_ready.raise();
1097+ });
1098+
1099+ Client client(new_connection(), first);
1100+ auto config = mir_connection_create_input_config(client.connection);
1101+ auto touchscreen = get_mutable_device_with_capabilities(config,
1102+ mir_input_device_capability_touchscreen|
1103+ mir_input_device_capability_multitouch);
1104+ auto touchscreen_config = mir_input_device_get_mutable_touchscreen_config(touchscreen);
1105+ mir_touchscreen_config_set_output_id(touchscreen_config, second_output);
1106+ mir_touchscreen_config_set_mapping_mode(touchscreen_config, mir_touchscreen_mapping_mode_to_output);
1107+
1108+ apply_and_wait_for_completion(
1109+ client.connection,
1110+ mir_connection_set_input_config_change_callback,
1111+ [config](MirConnection* connection)
1112+ {
1113+ mir_connection_set_base_input_config(connection, config);
1114+ mir_input_config_release(config);
1115+ });
1116+
1117+ EXPECT_TRUE(touchscreen_ready.wait_for(10s));
1118+ EXPECT_CALL(client, handle_input(mt::TouchEvent(expected_x, expected_y)))
1119+ .WillOnce(mt::WakeUp(&client.all_events_received));
1120+ fake_touch_screen->emit_event(mis::a_touch_event()
1121+ .at_position({touch_x*scale_to_device_width, touch_y*scale_to_device_height}));
1122+
1123+ EXPECT_TRUE(client.all_events_received.wait_for(10s));
1124+}
1125+
1126+TEST_F(TestClientInputWithTwoScreens, touchscreen_mapped_to_deactivated_output_is_filtered_out)
1127+{
1128+ wait_for_input_devices();
1129+ uint32_t const second_output = 2;
1130+ int const touch_x = 10;
1131+ int const touch_y = 10;
1132+
1133+ int const expected_x = second_screen.top_left.x.as_int() + touch_x;
1134+ int const expected_y = second_screen.top_left.y.as_int() + touch_y;
1135+
1136+ Client client(new_connection(), first);
1137+ auto display_config = mir_connection_create_display_configuration(client.connection);
1138+ auto second_output_ptr = mir_display_config_get_mutable_output(display_config, 1);
1139+ mir_output_set_power_mode(second_output_ptr, mir_power_mode_off);
1140+
1141+ apply_and_wait_for_completion(
1142+ client.connection,
1143+ mir_connection_set_display_config_change_callback,
1144+ [display_config](MirConnection* con)
1145+ {
1146+ mir_connection_preview_base_display_configuration(con, display_config, 10);
1147+ });
1148+
1149+ apply_and_wait_for_completion(
1150+ client.connection,
1151+ mir_connection_set_display_config_change_callback,
1152+ [display_config](MirConnection* con)
1153+ {
1154+ mir_connection_confirm_base_display_configuration(con, display_config);
1155+ mir_display_config_release(display_config);
1156+ });
1157+
1158+ display_config = mir_connection_create_display_configuration(client.connection);
1159+ ASSERT_THAT(mir_output_get_power_mode(mir_display_config_get_output(display_config, 1)), Eq(mir_power_mode_off));
1160+ mir_display_config_release(display_config);
1161+
1162+ mt::Signal touchscreen_ready;
1163+ fake_touch_screen->on_new_configuration_do(
1164+ [&touchscreen_ready, second_output](mi::InputDevice const& dev)
1165+ {
1166+ auto ts = dev.get_touchscreen_settings();
1167+ if (ts.is_set()
1168+ && ts.value().output_id == second_output
1169+ && ts.value().mapping_mode == mir_touchscreen_mapping_mode_to_output)
1170+ touchscreen_ready.raise();
1171+ });
1172+
1173+ auto config = mir_connection_create_input_config(client.connection);
1174+ auto touchscreen = get_mutable_device_with_capabilities(config,
1175+ mir_input_device_capability_touchscreen|
1176+ mir_input_device_capability_multitouch);
1177+ auto touchscreen_config = mir_input_device_get_mutable_touchscreen_config(touchscreen);
1178+
1179+ mir_touchscreen_config_set_output_id(touchscreen_config, second_output);
1180+ mir_touchscreen_config_set_mapping_mode(touchscreen_config, mir_touchscreen_mapping_mode_to_output);
1181+
1182+ apply_and_wait_for_completion(
1183+ client.connection,
1184+ mir_connection_set_input_config_change_callback,
1185+ [config](MirConnection* connection)
1186+ {
1187+ mir_connection_set_base_input_config(connection, config);
1188+ mir_input_config_release(config);
1189+ });
1190+
1191+ EXPECT_TRUE(touchscreen_ready.wait_for(10s));
1192+ ON_CALL(client, handle_input(mt::TouchEvent(expected_x, expected_y)))
1193+ .WillByDefault(mt::WakeUp(&client.all_events_received));
1194+ fake_touch_screen->emit_event(mis::a_touch_event()
1195+ .at_position({touch_x*scale_to_device_width, touch_y*scale_to_device_height}));
1196+
1197+ EXPECT_FALSE(client.all_events_received.wait_for(5s));
1198+}
1199
1200=== modified file 'tests/include/mir/test/doubles/mock_input_seat.h'
1201--- tests/include/mir/test/doubles/mock_input_seat.h 2017-01-18 02:29:37 +0000
1202+++ tests/include/mir/test/doubles/mock_input_seat.h 2017-03-01 16:08:29 +0000
1203@@ -21,6 +21,7 @@
1204
1205 #include "mir/input/seat.h"
1206 #include "mir/input/device.h"
1207+#include "mir/input/input_sink.h"
1208 #include "mir/test/gmock_fixes.h"
1209
1210 #include <gmock/gmock.h>
1211@@ -36,13 +37,14 @@
1212 MOCK_METHOD1(add_device, void(input::Device const& device));
1213 MOCK_METHOD1(remove_device, void(input::Device const& device));
1214 MOCK_METHOD1(dispatch_event, void(MirEvent& event));
1215- MOCK_METHOD1(get_rectangle_for, geometry::Rectangle(input::Device const& dev));
1216 MOCK_METHOD0(create_device_state, mir::EventUPtr());
1217 MOCK_METHOD2(set_key_state, void(input::Device const&, std::vector<uint32_t> const&));
1218 MOCK_METHOD2(set_pointer_state, void (input::Device const&, MirPointerButtons));
1219 MOCK_METHOD2(set_cursor_position, void (float, float));
1220 MOCK_METHOD1(set_confinement_regions, void(geometry::Rectangles const&));
1221 MOCK_METHOD0(reset_confinement_regions, void());
1222+ MOCK_CONST_METHOD0(bounding_rectangle, geometry::Rectangle());
1223+ MOCK_CONST_METHOD1(output_info, input::OutputInfo(uint32_t));
1224 };
1225 }
1226 }
1227
1228=== modified file 'tests/include/mir/test/doubles/mock_input_sink.h'
1229--- tests/include/mir/test/doubles/mock_input_sink.h 2016-07-07 09:59:19 +0000
1230+++ tests/include/mir/test/doubles/mock_input_sink.h 2017-03-01 16:08:29 +0000
1231@@ -35,6 +35,7 @@
1232 MOCK_METHOD1(handle_input, void(MirEvent&));
1233 MOCK_METHOD1(confine_pointer, void(mir::geometry::Point&));
1234 MOCK_CONST_METHOD0(bounding_rectangle, mir::geometry::Rectangle());
1235+ MOCK_CONST_METHOD1(output_info, mir::input::OutputInfo(uint32_t));
1236 MOCK_METHOD1(key_state, void(std::vector<uint32_t> const&));
1237 MOCK_METHOD1(pointer_state, void(MirPointerButtons));
1238 };
1239
1240=== modified file 'tests/integration-tests/input/test_single_seat_setup.cpp'
1241--- tests/integration-tests/input/test_single_seat_setup.cpp 2017-02-15 07:38:33 +0000
1242+++ tests/integration-tests/input/test_single_seat_setup.cpp 2017-03-01 16:08:29 +0000
1243@@ -24,7 +24,6 @@
1244 #include "mir/test/doubles/mock_input_device.h"
1245 #include "mir/test/doubles/mock_input_device_observer.h"
1246 #include "mir/test/doubles/mock_input_dispatcher.h"
1247-#include "mir/test/doubles/mock_input_region.h"
1248 #include "mir/test/doubles/mock_touch_visualizer.h"
1249 #include "mir/test/doubles/mock_cursor_listener.h"
1250 #include "mir/test/doubles/mock_input_manager.h"
1251@@ -36,10 +35,12 @@
1252 #include "mir/test/event_matchers.h"
1253 #include "mir/test/doubles/advanceable_clock.h"
1254 #include "mir/test/fake_shared.h"
1255+#include "mir/test/doubles/stub_display_configuration.h"
1256
1257 #include "mir/dispatch/multiplexing_dispatchable.h"
1258 #include "mir/cookie/authority.h"
1259 #include "mir/graphics/buffer.h"
1260+#include "mir/graphics/display_configuration_observer.h"
1261
1262 #include "mir/input/device.h"
1263 #include "mir/input/xkb_mapper.h"
1264@@ -73,17 +74,47 @@
1265 }
1266 }
1267
1268+namespace
1269+{
1270+
1271 MATCHER_P(DeviceMatches, device_info, "")
1272 {
1273 return arg.name() == device_info.name &&
1274 arg.unique_id() == device_info.unique_id;
1275 }
1276
1277+struct FakeDisplayConfigurationObserverRegistrar : mir::ObserverRegistrar<mir::graphics::DisplayConfigurationObserver>
1278+{
1279+ using Observer = mir::graphics::DisplayConfigurationObserver;
1280+ mtd::StubDisplayConfig output{{geom::Rectangle{{0, 0}, {100, 100}}}};
1281+ void register_interest(std::weak_ptr<Observer> const& obs) override
1282+ {
1283+ observer = obs;
1284+ auto o = observer.lock();
1285+ o->initial_configuration(mt::fake_shared(output));
1286+ }
1287+ void register_interest(
1288+ std::weak_ptr<Observer> const& obs,
1289+ mir::Executor&) override
1290+ {
1291+ observer = obs;
1292+ }
1293+ void unregister_interest(Observer const&) override
1294+ {
1295+ observer.reset();
1296+ }
1297+ void update_output(geom::Size const& output_size)
1298+ {
1299+ output.outputs[0].modes[0].size = output_size;
1300+ auto o = observer.lock();
1301+ o->configuration_applied(mt::fake_shared(output));
1302+ }
1303+ std::weak_ptr<Observer> observer;
1304+};
1305 struct SingleSeatInputDeviceHubSetup : ::testing::Test
1306 {
1307 mtd::TriggeredMainLoop observer_loop;
1308 NiceMock<mtd::MockInputDispatcher> mock_dispatcher;
1309- NiceMock<mtd::MockInputRegion> mock_region;
1310 std::shared_ptr<mir::cookie::Authority> cookie_authority = mir::cookie::Authority::create();
1311 NiceMock<mtd::MockCursorListener> mock_cursor_listener;
1312 NiceMock<mtd::MockTouchVisualizer> mock_visualizer;
1313@@ -95,12 +126,14 @@
1314 mtd::MockInputManager mock_input_manager;
1315 mtd::StubSessionContainer stub_session_container;
1316 ms::BroadcastingSessionEventSink session_event_sink;
1317- mi::BasicSeat seat{
1318- mt::fake_shared(mock_dispatcher),mt::fake_shared(mock_visualizer), mt::fake_shared(mock_cursor_listener),
1319- mt::fake_shared(mock_region), mt::fake_shared(key_mapper), mt::fake_shared(clock), mt::fake_shared(mock_seat_observer)};
1320- mi::DefaultInputDeviceHub hub{
1321- mt::fake_shared(seat), mt::fake_shared(multiplexer), mt::fake_shared(observer_loop),
1322- cookie_authority, mt::fake_shared(key_mapper), mt::fake_shared(mock_status_listener)};
1323+ FakeDisplayConfigurationObserverRegistrar display_config;
1324+ mi::BasicSeat seat{mt::fake_shared(mock_dispatcher), mt::fake_shared(mock_visualizer),
1325+ mt::fake_shared(mock_cursor_listener), mt::fake_shared(display_config),
1326+ mt::fake_shared(key_mapper), mt::fake_shared(clock),
1327+ mt::fake_shared(mock_seat_observer)};
1328+ mi::DefaultInputDeviceHub hub{mt::fake_shared(seat), mt::fake_shared(multiplexer),
1329+ mt::fake_shared(observer_loop), cookie_authority,
1330+ mt::fake_shared(key_mapper), mt::fake_shared(mock_status_listener)};
1331 NiceMock<mtd::MockInputDeviceObserver> mock_observer;
1332 mi::ConfigChanger changer{
1333 mt::fake_shared(mock_input_manager),
1334@@ -130,6 +163,8 @@
1335 }
1336 };
1337
1338+}
1339+
1340 TEST_F(SingleSeatInputDeviceHubSetup, input_sink_posts_events_to_input_dispatcher)
1341 {
1342 mi::InputSink* sink;
1343@@ -198,13 +233,12 @@
1344 sink->handle_input(*touch_event_4);
1345 }
1346
1347-
1348 TEST_F(SingleSeatInputDeviceHubSetup, tracks_pointer_position)
1349 {
1350 geom::Point first{10,10}, second{20,20}, third{10,30};
1351- EXPECT_CALL(mock_region, confine(first));
1352- EXPECT_CALL(mock_region, confine(second));
1353- EXPECT_CALL(mock_region, confine(third));
1354+ EXPECT_CALL(mock_cursor_listener, cursor_moved_to(first.x.as_int(), first.y.as_int()));
1355+ EXPECT_CALL(mock_cursor_listener, cursor_moved_to(second.x.as_int(), second.y.as_int()));
1356+ EXPECT_CALL(mock_cursor_listener, cursor_moved_to(third.x.as_int(), third.y.as_int()));
1357
1358 mi::InputSink* sink;
1359 mi::EventBuilder* builder;
1360@@ -223,9 +257,8 @@
1361 TEST_F(SingleSeatInputDeviceHubSetup, confines_pointer_movement)
1362 {
1363 geom::Point confined_pos{10, 18};
1364+ display_config.update_output(geom::Size{confined_pos.x.as_int() + 1, confined_pos.y.as_int() + 1});
1365
1366- ON_CALL(mock_region,confine(_))
1367- .WillByDefault(SetArgReferee<0>(confined_pos));
1368 EXPECT_CALL(mock_cursor_listener, cursor_moved_to(confined_pos.x.as_int(), confined_pos.y.as_int())).Times(2);
1369
1370 mi::InputSink* sink;
1371
1372=== modified file 'tests/mir_test_framework/fake_input_device_impl.cpp'
1373--- tests/mir_test_framework/fake_input_device_impl.cpp 2017-02-03 01:10:42 +0000
1374+++ tests/mir_test_framework/fake_input_device_impl.cpp 2017-03-01 16:08:29 +0000
1375@@ -110,14 +110,27 @@
1376 });
1377 }
1378
1379+void mtf::FakeInputDeviceImpl::on_new_configuration_do(std::function<void(mir::input::InputDevice const& device)> callback)
1380+{
1381+ device->set_apply_settings_callback(callback);
1382+}
1383+void mtf::FakeInputDeviceImpl::InputDevice::set_apply_settings_callback(std::function<void(mir::input::InputDevice const&)> const& callback)
1384+{
1385+ std::lock_guard<std::mutex> lock(config_callback_mutex);
1386+ this->callback = callback;
1387+}
1388
1389 mtf::FakeInputDeviceImpl::InputDevice::InputDevice(mi::InputDeviceInfo const& info,
1390 std::shared_ptr<mir::dispatch::Dispatchable> const& dispatchable)
1391- : info(info), queue{dispatchable}, buttons{0}
1392+ : info(info), queue{dispatchable}, buttons{0}, callback([](mir::input::InputDevice const&){})
1393 {
1394 // the default setup results in a direct mapping of input velocity to output velocity.
1395 settings.acceleration = mir_pointer_acceleration_none;
1396 settings.cursor_acceleration_bias = 0.0;
1397+
1398+ // add default setup for touchscreen..
1399+ if (contains(info.capabilities, mi::DeviceCapability::touchscreen))
1400+ touchscreen = mi::TouchscreenSettings{};
1401 }
1402
1403 void mtf::FakeInputDeviceImpl::InputDevice::synthesize_events(synthesis::KeyParameters const& key_params)
1404@@ -211,13 +224,15 @@
1405 float abs_x = touch.abs_x;
1406 float abs_y = touch.abs_y;
1407 map_touch_coordinates(abs_x, abs_y);
1408- // those values would need scaling too as soon as they can be controlled by the caller
1409-
1410- auto touch_event = builder->touch_event(
1411- event_time,
1412- {{MirTouchId{1}, touch_action, mir_touch_tooltype_finger, abs_x, abs_y, 1.0f, 8.0f, 5.0f, 0.0f}});
1413-
1414- sink->handle_input(*touch_event);
1415+
1416+ if (is_output_active())
1417+ {
1418+ auto touch_event = builder->touch_event(
1419+ event_time,
1420+ {{MirTouchId{1}, touch_action, mir_touch_tooltype_finger, abs_x, abs_y, 1.0f, 8.0f, 5.0f, 0.0f}});
1421+
1422+ sink->handle_input(*touch_event);
1423+ }
1424 }
1425
1426 mir::optional_value<mi::PointerSettings> mtf::FakeInputDeviceImpl::InputDevice::get_pointer_settings() const
1427@@ -235,6 +250,7 @@
1428 if (!contains(info.capabilities, mi::DeviceCapability::pointer))
1429 return;
1430 this->settings = settings;
1431+ trigger_callback();
1432 }
1433
1434 mir::optional_value<mi::TouchpadSettings> mtf::FakeInputDeviceImpl::InputDevice::get_touchpad_settings() const
1435@@ -250,6 +266,17 @@
1436 {
1437 // Not applicable for configuration since FakeInputDevice just
1438 // forwards already interpreted events.
1439+ trigger_callback();
1440+}
1441+
1442+void mtf::FakeInputDeviceImpl::InputDevice::trigger_callback() const
1443+{
1444+ decltype(callback) stored_callback;
1445+ {
1446+ std::lock_guard<std::mutex> lock(config_callback_mutex);
1447+ stored_callback = callback;
1448+ }
1449+ stored_callback(*this);
1450 }
1451
1452 mir::optional_value<mi::TouchscreenSettings> mtf::FakeInputDeviceImpl::InputDevice::get_touchscreen_settings() const
1453@@ -267,17 +294,22 @@
1454 if (!contains(info.capabilities, mi::DeviceCapability::touchscreen))
1455 return;
1456 this->touchscreen = new_settings;
1457+
1458+ trigger_callback();
1459 }
1460
1461 void mtf::FakeInputDeviceImpl::InputDevice::map_touch_coordinates(float& x, float& y)
1462 {
1463- // TODO take orientation of input sink into account?
1464- auto area = sink->bounding_rectangle();
1465+ auto info = get_output_info();
1466 auto touch_range = FakeInputDevice::maximum_touch_axis_value - FakeInputDevice::minimum_touch_axis_value + 1;
1467- auto x_scale = area.size.width.as_int() / float(touch_range);
1468- auto y_scale = area.size.height.as_int() / float(touch_range);
1469- x = (x - float(FakeInputDevice::minimum_touch_axis_value))*x_scale + area.top_left.x.as_int();
1470- y = (y - float(FakeInputDevice::minimum_touch_axis_value))*y_scale + area.top_left.y.as_int();
1471+ auto const width = info.output_size.width.as_int();
1472+ auto const height = info.output_size.height.as_int();
1473+ auto x_scale = width / float(touch_range);
1474+ auto y_scale = height / float(touch_range);
1475+ x = (x - float(FakeInputDevice::minimum_touch_axis_value))*x_scale;
1476+ y = (y - float(FakeInputDevice::minimum_touch_axis_value))*y_scale;
1477+
1478+ info.transform_to_scene(x, y);
1479 }
1480
1481 void mtf::FakeInputDeviceImpl::InputDevice::start(mi::InputSink* destination, mi::EventBuilder* event_builder)
1482@@ -293,3 +325,33 @@
1483 builder = nullptr;
1484 mtf::StubInputPlatform::unregister_dispatchable(queue);
1485 }
1486+
1487+mi::OutputInfo mtf::FakeInputDeviceImpl::InputDevice::get_output_info() const
1488+{
1489+ if (touchscreen.mapping_mode == mir_touchscreen_mapping_mode_to_output)
1490+ {
1491+ return sink->output_info(touchscreen.output_id);
1492+ }
1493+ else
1494+ {
1495+ auto scene_bbox = sink->bounding_rectangle();
1496+ return mi::OutputInfo(
1497+ true,
1498+ scene_bbox.size,
1499+ mi::OutputInfo::Matrix{{1.0f, 0.0f, float(scene_bbox.top_left.x.as_int()),
1500+ 0.0f, 1.0f, float(scene_bbox.top_left.y.as_int())}});
1501+ }
1502+}
1503+
1504+bool mtf::FakeInputDeviceImpl::InputDevice::is_output_active() const
1505+{
1506+ if (!sink)
1507+ return false;
1508+
1509+ if (touchscreen.mapping_mode == mir_touchscreen_mapping_mode_to_output)
1510+ {
1511+ auto output = sink->output_info(touchscreen.output_id);
1512+ return output.active;
1513+ }
1514+ return true;
1515+}
1516
1517=== modified file 'tests/mir_test_framework/fake_input_device_impl.h'
1518--- tests/mir_test_framework/fake_input_device_impl.h 2017-02-03 01:10:42 +0000
1519+++ tests/mir_test_framework/fake_input_device_impl.h 2017-03-01 16:08:29 +0000
1520@@ -27,8 +27,15 @@
1521 #include "mir/input/input_device_info.h"
1522 #include "mir/geometry/point.h"
1523
1524+#include <mutex>
1525+#include <functional>
1526+
1527 namespace mir
1528 {
1529+namespace input
1530+{
1531+class OutputInfo;
1532+}
1533 namespace dispatch
1534 {
1535 class ActionQueue;
1536@@ -50,6 +57,7 @@
1537 void emit_touch_sequence(std::function<mir::input::synthesis::TouchParameters(int)> const& event_generator,
1538 int count,
1539 std::chrono::duration<double> delay) override;
1540+ virtual void on_new_configuration_do(std::function<void(mir::input::InputDevice const& device)> callback) override;
1541
1542 private:
1543 class InputDevice : public mir::input::InputDevice
1544@@ -76,11 +84,15 @@
1545 void apply_settings(mir::input::TouchpadSettings const& settings) override;
1546 mir::optional_value<mir::input::TouchscreenSettings> get_touchscreen_settings() const override;
1547 void apply_settings(mir::input::TouchscreenSettings const& settings) override;
1548+ void set_apply_settings_callback(std::function<void(mir::input::InputDevice const&)> const& callback);
1549
1550 private:
1551 MirPointerAction update_buttons(mir::input::synthesis::EventAction action, MirPointerButton button);
1552 void update_position(int rel_x, int rel_y);
1553 void map_touch_coordinates(float& x, float& y);
1554+ mir::input::OutputInfo get_output_info() const;
1555+ bool is_output_active() const;
1556+ void trigger_callback() const;
1557
1558 mir::input::InputSink* sink{nullptr};
1559 mir::input::EventBuilder* builder{nullptr};
1560@@ -90,6 +102,8 @@
1561 MirPointerButtons buttons;
1562 mir::input::PointerSettings settings;
1563 mir::input::TouchscreenSettings touchscreen;
1564+ mutable std::mutex config_callback_mutex;
1565+ std::function<void(mir::input::InputDevice const&)> callback;
1566 };
1567 std::shared_ptr<mir::dispatch::ActionQueue> queue;
1568 std::shared_ptr<InputDevice> device;
1569
1570=== modified file 'tests/unit-tests/input/evdev/test_libinput_device.cpp'
1571--- tests/unit-tests/input/evdev/test_libinput_device.cpp 2017-01-18 02:29:37 +0000
1572+++ tests/unit-tests/input/evdev/test_libinput_device.cpp 2017-03-01 16:08:29 +0000
1573@@ -31,6 +31,7 @@
1574 #include "mir/test/event_matchers.h"
1575 #include "mir/test/doubles/mock_libinput.h"
1576 #include "mir/test/doubles/mock_input_seat.h"
1577+#include "mir/test/doubles/mock_input_sink.h"
1578 #include "mir/test/gmock_fixes.h"
1579 #include "mir/test/fake_shared.h"
1580 #include "mir/udev/wrapper.h"
1581@@ -63,20 +64,7 @@
1582 };
1583
1584 using namespace ::testing;
1585-
1586-struct MockInputSink : mi::InputSink
1587-{
1588- MockInputSink()
1589- {
1590- ON_CALL(*this, bounding_rectangle())
1591- .WillByDefault(Return(geom::Rectangle({0,0}, {100,100})));
1592- }
1593- MOCK_METHOD1(handle_input,void(MirEvent &));
1594- MOCK_METHOD1(confine_pointer, void(geom::Point&));
1595- MOCK_CONST_METHOD0(bounding_rectangle, geom::Rectangle());
1596- MOCK_METHOD1(key_state, void(std::vector<uint32_t> const&));
1597- MOCK_METHOD1(pointer_state, void(MirPointerButtons));
1598-};
1599+using Matrix = mi::OutputInfo::Matrix;
1600
1601 struct MockEventBuilder : mi::EventBuilder
1602 {
1603@@ -128,7 +116,7 @@
1604 struct LibInputDevice : public ::testing::Test
1605 {
1606 mtf::LibInputEnvironment env;
1607- ::testing::NiceMock<MockInputSink> mock_sink;
1608+ ::testing::NiceMock<mtd::MockInputSink> mock_sink;
1609 ::testing::NiceMock<MockEventBuilder> mock_builder;
1610 std::shared_ptr<libinput> lib;
1611
1612@@ -145,6 +133,8 @@
1613
1614 LibInputDevice()
1615 {
1616+ ON_CALL(mock_sink, bounding_rectangle())
1617+ .WillByDefault(Return(geom::Rectangle({0,0}, {100,100})));
1618 lib = mie::make_libinput(fake_udev);
1619 }
1620
1621@@ -268,6 +258,16 @@
1622 {
1623 libinput_device*const fake_device = setup_touchscreen();
1624 mie::LibInputDevice touch_screen{mir::report::null_input_report(), mie::make_libinput_device(lib, fake_device)};
1625+
1626+ const float x = 10;
1627+ const float y = 5;
1628+ const uint32_t output_id = 2;
1629+ const float output_x_pos = 20;
1630+ const float output_y_pos = 50;
1631+ const float screen_x_pos = 70;
1632+ const float screen_y_pos = 30;
1633+ const int width = 100;
1634+ const int height = 200;
1635 };
1636
1637 struct LibInputDeviceOnTouchpad : public LibInputDevice
1638@@ -777,3 +777,169 @@
1639 lib.reset();
1640 device_ptr.reset();
1641 }
1642+
1643+TEST_F(LibInputDeviceOnTouchScreen, device_maps_to_selected_output)
1644+{
1645+ const float x = 30;
1646+ const float y = 20;
1647+ const uint32_t output_id = 2;
1648+ const float output_x_pos = 20;
1649+ const float output_y_pos = 50;
1650+ const int width = 100;
1651+ const int height = 200;
1652+
1653+ EXPECT_CALL(mock_sink, bounding_rectangle())
1654+ .Times(0);
1655+ EXPECT_CALL(mock_sink, output_info(output_id))
1656+ .WillRepeatedly(Return(
1657+ mi::OutputInfo{
1658+ true,
1659+ geom::Size{width, height},
1660+ Matrix{{1.0f, 0.0f, output_x_pos,
1661+ 0.0f, 1.0f, output_y_pos}}}));
1662+ EXPECT_CALL(mock_sink,
1663+ handle_input(
1664+ mt::TouchContact(
1665+ 0,
1666+ mir_touch_action_down,
1667+ x + output_x_pos,
1668+ y + output_y_pos)))
1669+ .Times(1);
1670+
1671+ touch_screen.apply_settings(mi::TouchscreenSettings{output_id, mir_touchscreen_mapping_mode_to_output});
1672+ touch_screen.start(&mock_sink, &mock_builder);
1673+
1674+ env.mock_libinput.setup_touch_event(fake_device, LIBINPUT_EVENT_TOUCH_DOWN, event_time_1, 0, x, y, 0, 0, 0, 0);
1675+ env.mock_libinput.setup_touch_frame(fake_device, event_time_1);
1676+
1677+ process_events(touch_screen);
1678+}
1679+
1680+TEST_F(LibInputDeviceOnTouchScreen, device_maps_to_left_rotated_output)
1681+{
1682+ const float x = 10;
1683+ const float y = 5;
1684+ const uint32_t output_id = 2;
1685+ const float output_x_pos = 20;
1686+ const float output_y_pos = 50;
1687+ const int width = 100;
1688+ const int height = 200;
1689+
1690+ EXPECT_CALL(mock_sink, bounding_rectangle())
1691+ .Times(0);
1692+ EXPECT_CALL(mock_sink, output_info(output_id))
1693+ .WillRepeatedly(Return(
1694+ mi::OutputInfo{
1695+ true,
1696+ geom::Size{width, height},
1697+ Matrix{{0.0f, 1.0f, output_x_pos,
1698+ -1.0f, 0.0f, width + output_y_pos}}}));
1699+ EXPECT_CALL(mock_sink,
1700+ handle_input(
1701+ mt::TouchContact(
1702+ 0,
1703+ mir_touch_action_down,
1704+ output_x_pos + y,
1705+ output_y_pos + width - x)))
1706+ .Times(1);
1707+
1708+ touch_screen.apply_settings(mi::TouchscreenSettings{output_id, mir_touchscreen_mapping_mode_to_output});
1709+ touch_screen.start(&mock_sink, &mock_builder);
1710+
1711+ env.mock_libinput.setup_touch_event(fake_device, LIBINPUT_EVENT_TOUCH_DOWN, event_time_1, 0, x, y, 0, 0, 0, 0);
1712+ env.mock_libinput.setup_touch_frame(fake_device, event_time_1);
1713+
1714+ process_events(touch_screen);
1715+}
1716+
1717+TEST_F(LibInputDeviceOnTouchScreen, device_maps_to_right_rotated_output)
1718+{
1719+ EXPECT_CALL(mock_sink, bounding_rectangle())
1720+ .Times(0);
1721+ EXPECT_CALL(mock_sink, output_info(output_id))
1722+ .WillRepeatedly(Return(
1723+ mi::OutputInfo{
1724+ true,
1725+ geom::Size{width, height},
1726+ Matrix{{0.0f, -1.0f, height + output_x_pos,
1727+ 1.0f, 0.0f, output_y_pos}}}));
1728+ EXPECT_CALL(mock_sink,
1729+ handle_input(
1730+ mt::TouchContact(
1731+ 0,
1732+ mir_touch_action_down,
1733+ output_x_pos + height - y,
1734+ output_y_pos + x)))
1735+ .Times(1);
1736+
1737+ touch_screen.apply_settings(mi::TouchscreenSettings{output_id, mir_touchscreen_mapping_mode_to_output});
1738+ touch_screen.start(&mock_sink, &mock_builder);
1739+
1740+ env.mock_libinput.setup_touch_event(fake_device, LIBINPUT_EVENT_TOUCH_DOWN, event_time_1, 0, x, y, 0, 0, 0, 0);
1741+ env.mock_libinput.setup_touch_frame(fake_device, event_time_1);
1742+
1743+ process_events(touch_screen);
1744+}
1745+
1746+TEST_F(LibInputDeviceOnTouchScreen, device_maps_to_inverted_output)
1747+{
1748+ EXPECT_CALL(mock_sink, bounding_rectangle())
1749+ .Times(0);
1750+ EXPECT_CALL(mock_sink, output_info(output_id))
1751+ .WillRepeatedly(Return(
1752+ mi::OutputInfo{
1753+ true,
1754+ geom::Size{width, height},
1755+ Matrix{{-1.0f, 0.0f, width + output_x_pos,
1756+ 0.0f, -1.0f, height + output_y_pos}}}));
1757+ EXPECT_CALL(mock_sink,
1758+ handle_input(
1759+ mt::TouchContact(
1760+ 0,
1761+ mir_touch_action_down,
1762+ output_x_pos + width - x,
1763+ output_y_pos + height - y)))
1764+ .Times(1);
1765+
1766+ touch_screen.apply_settings(mi::TouchscreenSettings{output_id, mir_touchscreen_mapping_mode_to_output});
1767+ touch_screen.start(&mock_sink, &mock_builder);
1768+
1769+ env.mock_libinput.setup_touch_event(fake_device, LIBINPUT_EVENT_TOUCH_DOWN, event_time_1, 0, x, y, 0, 0, 0, 0);
1770+ env.mock_libinput.setup_touch_frame(fake_device, event_time_1);
1771+
1772+ process_events(touch_screen);
1773+}
1774+
1775+TEST_F(LibInputDeviceOnTouchScreen, display_wall_device_maps_to_bounding_rectangle)
1776+{
1777+ EXPECT_CALL(mock_sink, output_info(output_id))
1778+ .Times(0);
1779+ EXPECT_CALL(mock_sink, bounding_rectangle())
1780+ .WillOnce(Return(geom::Rectangle{geom::Point{screen_x_pos, screen_y_pos}, geom::Size{100, 100}}));
1781+ EXPECT_CALL(mock_sink, handle_input(mt::TouchContact(0, mir_touch_action_down, x + screen_x_pos, y + screen_y_pos)))
1782+ .Times(1);
1783+
1784+ touch_screen.apply_settings(mi::TouchscreenSettings{output_id, mir_touchscreen_mapping_mode_to_display_wall});
1785+ touch_screen.start(&mock_sink, &mock_builder);
1786+
1787+ env.mock_libinput.setup_touch_event(fake_device, LIBINPUT_EVENT_TOUCH_DOWN, event_time_1, 0, x, y, 0, 0, 0, 0);
1788+ env.mock_libinput.setup_touch_frame(fake_device, event_time_1);
1789+
1790+ process_events(touch_screen);
1791+}
1792+
1793+TEST_F(LibInputDeviceOnTouchScreen, drops_touchscreen_event_on_deactivated_output)
1794+{
1795+ EXPECT_CALL(mock_sink, handle_input(_)).Times(0);
1796+
1797+ ON_CALL(mock_sink, output_info(output_id))
1798+ .WillByDefault(Return(mi::OutputInfo{false, geom::Size{width, height}, Matrix{{1,0,0,0,1,0}}}));
1799+
1800+ touch_screen.apply_settings(mi::TouchscreenSettings{output_id, mir_touchscreen_mapping_mode_to_output});
1801+
1802+ touch_screen.start(&mock_sink, &mock_builder);
1803+ env.mock_libinput.setup_touch_event(fake_device, LIBINPUT_EVENT_TOUCH_DOWN, event_time_1, 0, x, y, 0, 0, 0, 0);
1804+ env.mock_libinput.setup_touch_frame(fake_device, event_time_1);
1805+
1806+ process_events(touch_screen);
1807+}
1808
1809=== modified file 'tests/unit-tests/input/test_seat_input_device_tracker.cpp'
1810--- tests/unit-tests/input/test_seat_input_device_tracker.cpp 2017-01-18 02:29:37 +0000
1811+++ tests/unit-tests/input/test_seat_input_device_tracker.cpp 2017-03-01 16:08:29 +0000
1812@@ -22,7 +22,6 @@
1813 #include "mir/input/xkb_mapper.h"
1814 #include "mir/test/doubles/mock_input_device.h"
1815 #include "mir/test/doubles/mock_input_dispatcher.h"
1816-#include "mir/test/doubles/mock_input_region.h"
1817 #include "mir/test/doubles/mock_cursor_listener.h"
1818 #include "mir/test/doubles/mock_touch_visualizer.h"
1819 #include "mir/test/doubles/mock_input_seat.h"
1820@@ -53,7 +52,6 @@
1821 {
1822 mi::EventBuilder* builder;
1823 Nice<mtd::MockInputDispatcher> mock_dispatcher;
1824- Nice<mtd::MockInputRegion> mock_region;
1825 Nice<mtd::MockCursorListener> mock_cursor_listener;
1826 Nice<mtd::MockTouchVisualizer> mock_visualizer;
1827 Nice<mtd::MockInputSeat> mock_seat;
1828@@ -70,8 +68,7 @@
1829 mi::receiver::XKBMapper mapper;
1830 mi::SeatInputDeviceTracker tracker{
1831 mt::fake_shared(mock_dispatcher), mt::fake_shared(mock_visualizer), mt::fake_shared(mock_cursor_listener),
1832- mt::fake_shared(mock_region), mt::fake_shared(mapper), mt::fake_shared(clock),
1833- mt::fake_shared(mock_seat_report)};
1834+ mt::fake_shared(mapper), mt::fake_shared(clock), mt::fake_shared(mock_seat_report)};
1835
1836 std::chrono::nanoseconds arbitrary_timestamp;
1837 };
1838
1839=== modified file 'tests/unit-tests/scene/test_surface_stack.cpp'
1840--- tests/unit-tests/scene/test_surface_stack.cpp 2017-02-15 14:45:41 +0000
1841+++ tests/unit-tests/scene/test_surface_stack.cpp 2017-03-01 16:08:29 +0000
1842@@ -989,7 +989,7 @@
1843 stack.emit_scene_changed();
1844 }
1845
1846-TEST_F(SurfaceStack, only_enumerates_exposed_input_surfaces)
1847+TEST_F(SurfaceStack, for_each_enumerates_all_input_surfaces)
1848 {
1849 using namespace ::testing;
1850
1851@@ -1007,7 +1007,7 @@
1852 };
1853
1854 stack.for_each(count_exposed_surfaces);
1855- EXPECT_THAT(num_exposed_surfaces, Eq(1));
1856+ EXPECT_THAT(num_exposed_surfaces, Eq(3));
1857 }
1858
1859 using namespace ::testing;

Subscribers

People subscribed via source and target branches