Mir

Merge lp:~andreas-pokorny/mir/fix-1261647 into lp:mir

Proposed by Andreas Pokorny
Status: Work in progress
Proposed branch: lp:~andreas-pokorny/mir/fix-1261647
Merge into: lp:mir
Diff against target: 1250 lines (+256/-284)
22 files modified
3rd_party/android-input/android/frameworks/base/include/androidfw/Input.h (+1/-21)
3rd_party/android-input/android/frameworks/base/include/androidfw/InputTransport.h (+0/-2)
3rd_party/android-input/android/frameworks/base/services/input/Input.cpp (+7/-72)
3rd_party/android-input/android/frameworks/base/services/input/InputDispatcher.cpp (+36/-50)
3rd_party/android-input/android/frameworks/base/services/input/InputDispatcher.h (+9/-14)
3rd_party/android-input/android/frameworks/base/services/input/InputTransport.cpp (+1/-8)
3rd_party/android-input/android/frameworks/base/services/input/InputWindow.cpp (+10/-9)
3rd_party/android-input/android/frameworks/base/services/input/InputWindow.h (+4/-12)
include/server/mir/input/surface.h (+3/-0)
include/shared/mir_toolkit/event.h (+4/-4)
include/test/mir_test_doubles/mock_input_surface.h (+3/-0)
src/client/logging/input_receiver_report.cpp (+0/-4)
src/server/graphics/nested/nested_output.cpp (+1/-11)
src/server/input/android/android_input_window_handle.cpp (+26/-14)
src/server/scene/basic_surface.cpp (+33/-3)
src/server/scene/basic_surface.h (+3/-1)
src/shared/input/android/android_input_lexicon.cpp (+6/-6)
tests/unit-tests/client/input/test_android_input_receiver.cpp (+0/-1)
tests/unit-tests/input/android/test_android_input_lexicon.cpp (+18/-21)
tests/unit-tests/input/android/test_android_input_registrar.cpp (+4/-0)
tests/unit-tests/input/android/test_android_input_window_handle.cpp (+1/-21)
tests/unit-tests/scene/test_basic_surface.cpp (+86/-10)
To merge this branch: bzr merge lp:~andreas-pokorny/mir/fix-1261647
Reviewer Review Type Date Requested Status
Daniel van Vugt Needs Fixing
PS Jenkins bot (community) continuous-integration Needs Fixing
Alan Griffiths Abstain
Alexandros Frantzis (community) Needs Information
Kevin DuBois (community) Needs Fixing
Andreas Pokorny Pending
Review via email: mp+212481@code.launchpad.net

Commit message

Transforming input coordinates according to what is configured at surfaces

This change removes further values from the InputWindowInfo structure and moves the responsibilities to input::Surface. The calculation of local motion coordinates now takes the transformation matrix applied to the surface when input is received. That change breaks with how PointerCoords works internally, to resolve that this change also drops the "raw" co-ordinates supplied with each co-ordinate in each event. To avoid client ABI changes for this, the items in the structure are just renamed.

The change leaves another TODO open. As soon as the renderer applies a different projection matrix than an orthographic matrix with the parameters (0, 0, screen_width, screen_height), touch positions and pixel positions will not match. For that use case to work the input stack needs means to access those parts/information of the scene.

Description of the change

Fixes the issues with the android input stack being out of sync with the mir surfaces by removing the members from the android input classes and a dedicated method to get a transformation matrix that turns screen into local co-ordinates.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote :

If we have a transformation() function on BasicSurface already, I'd rather the input stuff just use transformation() and then have getScreenToLocalTransformation compute the inverse. Seems like less interfaces to support for the already-overburdened surface classes.

I'd also rather leave the TODO in 735 out, seems too speculative about how the other parts of the code evolves.

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

> If we have a transformation() function on BasicSurface already, I'd rather the
> input stuff just use transformation() and then have
> getScreenToLocalTransformation compute the inverse. Seems like less interfaces
> to support for the already-overburdened surface classes.

I see that point, but I also need the inverse to make contains work properly.
Also non intuitive is that the term "transformation" in renderable also implies that the top left corner of the surface is located at -width/2,-height/2. Which means I do replicate parts of that in 737.

Additionally the adaptation code for android input sees only mir::input::Surface. If I also add that to Surface, I could just use mir::graphics::Renderable there instead. That might be closer to the upcoming scene graph rework. I mean we need input events - at least those that relate to graphical elements - to be dispatched through the scene.

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

733 + glm::mat4 getScreenToLocalTransformation() const override

Another option is to add a mi::Surface::screen_to_local_transformation() method instead of asking mi::Surface for all the info and doing the calculation in getScreenToLocalTransformation(). This also allows the surface to pre-calculate and cache the whole transformation.

"Needs Discussion"

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

> 733 + glm::mat4 getScreenToLocalTransformation() const override
>
> Another option is to add a mi::Surface::screen_to_local_transformation()
> method instead of asking mi::Surface for all the info and doing the
> calculation in getScreenToLocalTransformation(). This also allows the surface
> to pre-calculate and cache the whole transformation.
>
> "Needs Discussion"

Yes - needs discussion and together with kevins complaint: the overall question if we should delay further work here to when we move input dispatching into the scene?

Why not in Surface? - because previously InputDispatcher worked on a snapshot of the surface state. When the surface was changing while input was notified and then dispatched - I still find the InputDispatcher code confusing - it kept the position of then surface when the input notification to transform the PointerCoords when they get sent to the input receiver. If I move it to input::Surface entirely it can potentially change with every call.. and thats the only reason - I dont like the current solution either..

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

(1) A simple conflict needs fixing:
Text conflict in src/server/scene/basic_surface.cpp
1 conflicts encountered.

(2) 3rd_party/*: I know we've agreed it's OK to change 3rd_party stuff. Now I'm wondering at what point does it not count as 3rd party any more? If we've modified and made it Mir-specific then it's more like a community contribution. So maybe such libraries need to move out of 3rd party, marking them as more "permanent".

(3) Deprecating xoffset/yoffset: Do we have to remove this stuff or can we just comment it as unused (much less code change)? In theory we could at some point try to diff our android-input with the original tarball and use that to patch the same changes to a newer android-input release. In that case, minimizing changes would be ideal.

(4) Warning: I believe Chris is working on reducing/eliminating our use of android-input (maybe). Please talk to him as you might be modifying code he will remove completely.

(5) Whole-screen transformations:
735 + // TODO Still missing further affine transformations that are applied to the
736 + // whole screen i.e. if something other than a orthographic matrix used.
I think we shouldn't even comment that as TODO. I think we should just accept that input coordinates are only correct for surfaces which get mapped to the regular flat screen (Z=0 in screen space). It would be complicated and have potentially serious performance impact to try and read back the screen transformations from OpenGL. And even after you do, you'd lag a frame behind. So I think that's a "TODO" enhancement we should never do.

(6) I've mentioned this a few times now; Surface transformations (animations) are so short-lived that they're not relevant to input calculations in reality. So we don't need to apply surface [inverse_]transformation() to input handling at all. In fact I've said several times and it's clearly documented in renderable.h that the transformation() method could and probably should go away completely. So where we have:
877 glm::mat4 transformation() const override;
878 + glm::mat4 inverse_transformation() const override;
We may well in future replace all occurrences of inverse_transformation() with an identity matrix (no-op).

(7) Even after fixing conflict (1) there are also compile-time conflicts preventing it from building:
/home/dan/bzr/mir/tmp.647/tests/unit-tests/scene/test_basic_surface.cpp: In member function ‘virtual void BasicSurfaceTest_input_region_is_moved_with_surface_Test::TestBody()’:
/home/dan/bzr/mir/tmp.647/tests/unit-tests/scene/test_basic_surface.cpp:379:15: error: no matching function for call to ‘mir::scene::BasicSurface::BasicSurface(<brace-enclosed initializer list>)’
         report};
               ^

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

Manual testing of bug 1261647 passes :)

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

> (1) A simple conflict needs fixing:
> Text conflict in src/server/scene/basic_surface.cpp
> 1 conflicts encountered.

\o/

> (2) 3rd_party/*: I know we've agreed it's OK to change 3rd_party stuff. Now
> I'm wondering at what point does it not count as 3rd party any more? If we've
> modified and made it Mir-specific then it's more like a community
> contribution. So maybe such libraries need to move out of 3rd party, marking
> them as more "permanent".

I see InputDispatcher go away, Hence that bugfix is short lived. If pointless matrix debates continue I wont update that MP.

> (3) Deprecating xoffset/yoffset: Do we have to remove this stuff or can we
> just comment it as unused (much less code change)? In theory we could at some
> point try to diff our android-input with the original tarball and use that to
> patch the same changes to a newer android-input release. In that case,
> minimizing changes would be ideal.

Renamed it to see if downstream uses it somewhere. Nobody notices comment changes.

> (5) Whole-screen transformations:
> 735 + // TODO Still missing further affine transformations that are
> applied to the
> 736 + // whole screen i.e. if something other than a orthographic
> matrix used.
> I think we shouldn't even comment that as TODO. I think we should just accept
> that input coordinates are only correct for surfaces which get mapped to the
> regular flat screen (Z=0 in screen space). It would be complicated and have
> potentially serious performance impact to try and read back the screen
> transformations from OpenGL. And even after you do, you'd lag a frame behind.
> So I think that's a "TODO" enhancement we should never do.

Hmm I disagree to all points but the part about lacking one frame behind. But here
you always seem to assume animations. That limited pov seems to fail the morpheus test.

>
> (6) I've mentioned this a few times now; Surface transformations (animations)
> are so short-lived that they're not relevant to input calculations in reality.
> So we don't need to apply surface [inverse_]transformation() to input handling
> at all. In fact I've said several times and it's clearly documented in
> renderable.h that the transformation() method could and probably should go
> away completely. So where we have:
> 877 glm::mat4 transformation() const override;
> 878 + glm::mat4 inverse_transformation() const override;
> We may well in future replace all occurrences of inverse_transformation() with
> an identity matrix (no-op).

Ok will fix the comment in Renderable.

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

OK, if we can make it efficient and not get tangled up in disproportionate complexity for little gain, then I won't block your ambition to make input coordinate mapping completely accurate. If would be nice to have, but only if it's efficient and doesn't make things significantly more complicated.

You forgot to push your changes to launchpad. The merge proposal still shows the original revision 1500 from 25 March...

(1) The conflicts are growing:
Text conflict in src/server/scene/basic_surface.cpp
Text conflict in tests/unit-tests/scene/test_basic_surface.cpp
2 conflicts encountered.

review: Needs Fixing
Revision history for this message
Kevin DuBois (kdub) wrote :

> > If we have a transformation() function on BasicSurface already, I'd rather
> the
> > input stuff just use transformation() and then have
> > getScreenToLocalTransformation compute the inverse. Seems like less
> interfaces
> > to support for the already-overburdened surface classes.
>
> I see that point, but I also need the inverse to make contains work properly.
> Also non intuitive is that the term "transformation" in renderable also
> implies that the top left corner of the surface is located at
> -width/2,-height/2. Which means I do replicate parts of that in 737.
>
> Additionally the adaptation code for android input sees only
> mir::input::Surface. If I also add that to Surface, I could just use
> mir::graphics::Renderable there instead. That might be closer to the upcoming
> scene graph rework. I mean we need input events - at least those that relate
> to graphical elements - to be dispatched through the scene.

Sure, my objection though is that we're bulking up the Renderable interface with an inverse function, and I have been trying to trim and keep this interface lean.

like if there was an interface like:
Interface::is_ready()
Interface::is_not_ready()

all of the callers could just use !is_ready(). Likewise, someone who wants a matrix can reasonably be expected to do a matrix inverse operation, and the interface stays leaner.

Revision history for this message
Kevin DuBois (kdub) wrote :

> > (2) 3rd_party/*: I know we've agreed it's OK to change 3rd_party stuff. Now
> > I'm wondering at what point does it not count as 3rd party any more? If
> we've
> > modified and made it Mir-specific then it's more like a community
> > contribution. So maybe such libraries need to move out of 3rd party, marking
> > them as more "permanent".

Yeah, I worry about this too. (a larger-scoped topic than this review though)

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

> > > (2) 3rd_party/*: I know we've agreed it's OK to change 3rd_party stuff.
> Now
> > > I'm wondering at what point does it not count as 3rd party any more? If
> > we've
> > > modified and made it Mir-specific then it's more like a community
> > > contribution. So maybe such libraries need to move out of 3rd party,
> marking
> > > them as more "permanent".
>
> Yeah, I worry about this too. (a larger-scoped topic than this review though)

We've several times agreed that the input code is an independent fork and we're unlikely to try updating with a more recent version. In consequence we've also agreed that should have a home outside 3rd_party. This MP isn't a suitable place to revisit either discussion.

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

Alan clearly has a better memory than the rest of us. Although having discussed things in the past doesn't set them in stone. If better solutions can be conceived then I'm always happy to consider them. Enough on this tangent.

lp:~andreas-pokorny/mir/fix-1261647 updated
1501. By Andreas Pokorny

merged development branch

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

(8) Inversion is slow and shouldn't be done unconditionally. We should cache the inverse and recalculate it only on demand inside inverse_transformation()...

865 + inverse_matrix = glm::inverse(transformation_matrix);

(9) Shouldn't the parameters here be const references for efficiency?

799 +geom::Point to_point(glm::vec4 pos)
804 +glm::vec4 to_vec(geom::Point pos)
809 +glm::vec4 to_vec(geom::Size s)

(10) I'm still seeing bug 1261647 can occur and is not fully fixed:
  1. Start mir_demo_server_shell and rotate it sideways (Ctrl+Alt+Left/Right)
  2. Start mir_demo_client_fingerpaint. You'll see it doesn't fit the full screen properly by default.
  3. Rotate the screen back to normal (Ctrl+Alt+Up).
  4. Draw in fingerpaint. It works but not if the initial click is near the right hand side. Only if the click started near the left can the drawing extend to the right.
Is this still bug 1261647 or a new one? I think it's essentially still the same bug.

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

I am finally back into cleaning this up..

> (8) Inversion is slow and shouldn't be done unconditionally. We should cache
> the inverse and recalculate it only on demand inside
> inverse_transformation()...
>
> 865 + inverse_matrix = glm::inverse(transformation_matrix);

ack

> (9) Shouldn't the parameters here be const references for efficiency?
>
> 799 +geom::Point to_point(glm::vec4 pos)
> 804 +glm::vec4 to_vec(geom::Point pos)
> 809 +glm::vec4 to_vec(geom::Size s)

Intersting point - since I cannot say by just looking at the source code, I made a test. With optimizing gcc (-O3) and three different variants of the to_vec conversion functions. One that takes two references, one that takes one reference and returns by value, and one that looks like the one above. The one taking two references was always slightly faster. When I instead added the inline keyword, the order just turned around. The one taking copies was always faster. Overall the versions using inline was faster (and had a smaller binary). The difference I could spot was a slightly different order of operations, and more registers where used in parallel in the copying version.

>
> (10) I'm still seeing bug 1261647 can occur and is not fully fixed:
> 1. Start mir_demo_server_shell and rotate it sideways (Ctrl+Alt+Left/Right)
> 2. Start mir_demo_client_fingerpaint. You'll see it doesn't fit the full
> screen properly by default.
> 3. Rotate the screen back to normal (Ctrl+Alt+Up).
> 4. Draw in fingerpaint. It works but not if the initial click is near the
> right hand side. Only if the click started near the left can the drawing
> extend to the right.
> Is this still bug 1261647 or a new one? I think it's essentially still the
> same bug.

Ok. Will have to take a deeper look

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

this has to wait one or two days longer.. setting it to in progress for now.

@daniel could not reproduce, those cases seem to work fine with that branch updated to devel.

lp:~andreas-pokorny/mir/fix-1261647 updated
1502. By Andreas Pokorny

updated to development-branch

Unmerged revisions

1502. By Andreas Pokorny

updated to development-branch

1501. By Andreas Pokorny

merged development branch

1500. By Andreas Pokorny

Transforming input coordinates according to what is configured at surfaces

This change removes further values from the InputWindowInfo structure and moves
the responsibilities to input::Surface. The calculation of local motion coordinates
now takes the transformation matrix applied to the surface when input is received.
That change breaks with how PointerCoords works internally, to resolve that this
change also drops the "raw" co-ordinates supplied with each co-ordinate in each event.
To avoid client ABI changes for this, the items in the structure are just renamed.

The change leaves another TODO open. As soon as the renderer applies a different projection
matrix than an orthographic matrix with the parameters (0, 0, screen_width, screen_height),
touch positions and pixel positions will not match. For that use case to work the input
stack needs means to access those parts/information of the scene.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '3rd_party/android-input/android/frameworks/base/include/androidfw/Input.h'
2--- 3rd_party/android-input/android/frameworks/base/include/androidfw/Input.h 2014-03-06 06:05:17 +0000
3+++ 3rd_party/android-input/android/frameworks/base/include/androidfw/Input.h 2014-04-15 08:20:19 +0000
4@@ -344,10 +344,6 @@
5
6 inline int32_t getButtonState() const { return mButtonState; }
7
8- inline float getXOffset() const { return mXOffset; }
9-
10- inline float getYOffset() const { return mYOffset; }
11-
12 inline float getXPrecision() const { return mXPrecision; }
13
14 inline float getYPrecision() const { return mYPrecision; }
15@@ -372,17 +368,7 @@
16
17 inline nsecs_t getEventTime() const { return mSampleEventTimes[getHistorySize()]; }
18
19- const PointerCoords* getRawPointerCoords(size_t pointerIndex) const;
20-
21- float getRawAxisValue(int32_t axis, size_t pointerIndex) const;
22-
23- inline float getRawX(size_t pointerIndex) const {
24- return getRawAxisValue(AMOTION_EVENT_AXIS_X, pointerIndex);
25- }
26-
27- inline float getRawY(size_t pointerIndex) const {
28- return getRawAxisValue(AMOTION_EVENT_AXIS_Y, pointerIndex);
29- }
30+ const PointerCoords* getPointerCoords(size_t pointerIndex) const;
31
32 float getAxisValue(int32_t axis, size_t pointerIndex) const;
33
34@@ -501,8 +487,6 @@
35 int32_t edgeFlags,
36 int32_t metaState,
37 int32_t buttonState,
38- float xOffset,
39- float yOffset,
40 float xPrecision,
41 float yPrecision,
42 nsecs_t downTime,
43@@ -517,8 +501,6 @@
44 nsecs_t eventTime,
45 const PointerCoords* pointerCoords);
46
47- void offsetLocation(float xOffset, float yOffset);
48-
49 void scale(float scaleFactor);
50
51 #ifdef HAVE_ANDROID_OS
52@@ -548,8 +530,6 @@
53 int32_t mEdgeFlags;
54 int32_t mMetaState;
55 int32_t mButtonState;
56- float mXOffset;
57- float mYOffset;
58 float mXPrecision;
59 float mYPrecision;
60 nsecs_t mDownTime;
61
62=== modified file '3rd_party/android-input/android/frameworks/base/include/androidfw/InputTransport.h'
63--- 3rd_party/android-input/android/frameworks/base/include/androidfw/InputTransport.h 2014-03-06 06:05:17 +0000
64+++ 3rd_party/android-input/android/frameworks/base/include/androidfw/InputTransport.h 2014-04-15 08:20:19 +0000
65@@ -230,8 +230,6 @@
66 int32_t edgeFlags,
67 int32_t metaState,
68 int32_t buttonState,
69- float xOffset,
70- float yOffset,
71 float xPrecision,
72 float yPrecision,
73 nsecs_t downTime,
74
75=== modified file '3rd_party/android-input/android/frameworks/base/services/input/Input.cpp'
76--- 3rd_party/android-input/android/frameworks/base/services/input/Input.cpp 2013-05-03 16:38:07 +0000
77+++ 3rd_party/android-input/android/frameworks/base/services/input/Input.cpp 2014-04-15 08:20:19 +0000
78@@ -290,8 +290,6 @@
79 int32_t edgeFlags,
80 int32_t metaState,
81 int32_t buttonState,
82- float xOffset,
83- float yOffset,
84 float xPrecision,
85 float yPrecision,
86 nsecs_t downTime,
87@@ -305,8 +303,6 @@
88 mEdgeFlags = edgeFlags;
89 mMetaState = metaState;
90 mButtonState = buttonState;
91- mXOffset = xOffset;
92- mYOffset = yOffset;
93 mXPrecision = xPrecision;
94 mYPrecision = yPrecision;
95 mDownTime = downTime;
96@@ -324,8 +320,6 @@
97 mEdgeFlags = other->mEdgeFlags;
98 mMetaState = other->mMetaState;
99 mButtonState = other->mButtonState;
100- mXOffset = other->mXOffset;
101- mYOffset = other->mYOffset;
102 mXPrecision = other->mXPrecision;
103 mYPrecision = other->mYPrecision;
104 mDownTime = other->mDownTime;
105@@ -352,22 +346,12 @@
106 mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
107 }
108
109-const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
110+const PointerCoords* MotionEvent::getPointerCoords(size_t pointerIndex) const {
111 return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
112 }
113
114-float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
115- return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
116-}
117-
118 float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const {
119- float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis);
120- switch (axis) {
121- case AMOTION_EVENT_AXIS_X:
122- return value + mXOffset;
123- case AMOTION_EVENT_AXIS_Y:
124- return value + mYOffset;
125- }
126+ float value = getPointerCoords(pointerIndex)->getAxisValue(axis);
127 return value;
128 }
129
130@@ -383,14 +367,7 @@
131
132 float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
133 size_t historicalIndex) const {
134- float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
135- switch (axis) {
136- case AMOTION_EVENT_AXIS_X:
137- return value + mXOffset;
138- case AMOTION_EVENT_AXIS_Y:
139- return value + mYOffset;
140- }
141- return value;
142+ return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
143 }
144
145 ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const {
146@@ -403,14 +380,7 @@
147 return -1;
148 }
149
150-void MotionEvent::offsetLocation(float xOffset, float yOffset) {
151- mXOffset += xOffset;
152- mYOffset += yOffset;
153-}
154-
155 void MotionEvent::scale(float scaleFactor) {
156- mXOffset *= scaleFactor;
157- mYOffset *= scaleFactor;
158 mXPrecision *= scaleFactor;
159 mYPrecision *= scaleFactor;
160
161@@ -439,41 +409,6 @@
162 return result;
163 }
164
165-void MotionEvent::transform(const SkMatrix* matrix) {
166- float oldXOffset = mXOffset;
167- float oldYOffset = mYOffset;
168-
169- // The tricky part of this implementation is to preserve the value of
170- // rawX and rawY. So we apply the transformation to the first point
171- // then derive an appropriate new X/Y offset that will preserve rawX and rawY.
172- SkPoint point;
173- float rawX = getRawX(0);
174- float rawY = getRawY(0);
175- matrix->mapXY(SkFloatToScalar(rawX + oldXOffset), SkFloatToScalar(rawY + oldYOffset),
176- & point);
177- float newX = SkScalarToFloat(point.fX);
178- float newY = SkScalarToFloat(point.fY);
179- float newXOffset = newX - rawX;
180- float newYOffset = newY - rawY;
181-
182- mXOffset = newXOffset;
183- mYOffset = newYOffset;
184-
185- // Apply the transformation to all samples.
186- size_t numSamples = mSamplePointerCoords.size();
187- for (size_t i = 0; i < numSamples; i++) {
188- PointerCoords& c = mSamplePointerCoords.editItemAt(i);
189- float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset;
190- float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset;
191- matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), &point);
192- c.setAxisValue(AMOTION_EVENT_AXIS_X, SkScalarToFloat(point.fX) - newXOffset);
193- c.setAxisValue(AMOTION_EVENT_AXIS_Y, SkScalarToFloat(point.fY) - newYOffset);
194-
195- float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
196- c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(matrix, orientation));
197- }
198-}
199-
200 status_t MotionEvent::readFromParcel(Parcel* parcel) {
201 size_t pointerCount = parcel->readInt32();
202 size_t sampleCount = parcel->readInt32();
203@@ -488,8 +423,8 @@
204 mEdgeFlags = parcel->readInt32();
205 mMetaState = parcel->readInt32();
206 mButtonState = parcel->readInt32();
207- mXOffset = parcel->readFloat();
208- mYOffset = parcel->readFloat();
209+ parcel->readFloat(); // ABI compatibility x, y offset
210+ parcel->readFloat();
211 mXPrecision = parcel->readFloat();
212 mYPrecision = parcel->readFloat();
213 mDownTime = parcel->readInt64();
214@@ -535,8 +470,8 @@
215 parcel->writeInt32(mEdgeFlags);
216 parcel->writeInt32(mMetaState);
217 parcel->writeInt32(mButtonState);
218- parcel->writeFloat(mXOffset);
219- parcel->writeFloat(mYOffset);
220+ parcel->writeFloat(0.0f);
221+ parcel->writeFloat(0.0f);
222 parcel->writeFloat(mXPrecision);
223 parcel->writeFloat(mYPrecision);
224 parcel->writeInt64(mDownTime);
225
226=== modified file '3rd_party/android-input/android/frameworks/base/services/input/InputDispatcher.cpp'
227--- 3rd_party/android-input/android/frameworks/base/services/input/InputDispatcher.cpp 2014-03-11 11:50:11 +0000
228+++ 3rd_party/android-input/android/frameworks/base/services/input/InputDispatcher.cpp 2014-04-15 08:20:19 +0000
229@@ -49,6 +49,7 @@
230
231 #include <cutils/log.h>
232 #include <android/keycodes.h>
233+#include <glm/glm.hpp>
234
235 #include <stddef.h>
236 #include <unistd.h>
237@@ -169,6 +170,22 @@
238 return true;
239 }
240
241+static void transformPoints(glm::mat4 const& matrix, PointerCoords * coords, size_t count) {
242+ for (size_t i = 0;i != count; ++i) {
243+ glm::vec4 pos{
244+ coords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
245+ coords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
246+ 0.0,
247+ 1.0,
248+ };
249+ pos = matrix*pos;
250+ coords[i].setAxisValue(AMOTION_EVENT_AXIS_X, pos.x);
251+ coords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, pos.y);
252+ }
253+}
254+
255+
256+
257 // --- InputDispatcher ---
258
259 InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy,
260@@ -1547,9 +1564,7 @@
261 InputTarget& target = inputTargets.editTop();
262 target.inputChannel = windowInfo->inputChannel;
263 target.flags = targetFlags;
264- target.xOffset = - windowInfo->frameLeft;
265- target.yOffset = - windowInfo->frameTop;
266- target.scaleFactor = windowInfo->scaleFactor;
267+ target.screenToLocal = windowInfo->getScreenToLocalTransformation();
268 target.pointerIds = pointerIds;
269 }
270
271@@ -1577,10 +1592,8 @@
272 InputTarget& target = inputTargets.editTop();
273 target.inputChannel = mMonitoringChannels[i];
274 target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
275- target.xOffset = 0;
276- target.yOffset = 0;
277+ target.screenToLocal = target.screenToLocal;
278 target.pointerIds.clear();
279- target.scaleFactor = 1.0f;
280 }
281 }
282
283@@ -1697,11 +1710,9 @@
284 #if DEBUG_DISPATCH_CYCLE
285 std::string pointerIdsString = inputTarget->pointerIds.toString();
286 ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, "
287- "xOffset=%f, yOffset=%f, scaleFactor=%f, "
288 "pointerIds=%s",
289 connection->getInputChannelName(), inputTarget->flags,
290- inputTarget->xOffset, inputTarget->yOffset,
291- inputTarget->scaleFactor, pointerIdsString.c_str());
292+ pointerIdsString.c_str());
293 #endif
294
295 // Skip this event if the connection status is not normal.
296@@ -1777,8 +1788,7 @@
297 // This is a new event.
298 // Enqueue a new dispatch entry onto the outbound queue for this connection.
299 DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref
300- inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,
301- inputTarget->scaleFactor);
302+ inputTargetFlags, inputTarget->screenToLocal);
303
304 // Apply target flags and update the connection's input state.
305 switch (eventEntry->type) {
306@@ -1885,28 +1895,15 @@
307
308 case EventEntry::TYPE_MOTION: {
309 MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
310-
311 PointerCoords scaledCoords[MAX_POINTERS];
312- const PointerCoords* usingCoords = motionEntry->pointerCoords;
313+ PointerCoords * usingCoords = motionEntry->pointerCoords;
314
315- // Set the X and Y offset depending on the input source.
316- float xOffset, yOffset, scaleFactor;
317 if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
318 && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
319- scaleFactor = dispatchEntry->scaleFactor;
320- xOffset = dispatchEntry->xOffset * scaleFactor;
321- yOffset = dispatchEntry->yOffset * scaleFactor;
322- if (scaleFactor != 1.0f) {
323- for (size_t i = 0; i < motionEntry->pointerCount; i++) {
324- scaledCoords[i] = motionEntry->pointerCoords[i];
325- scaledCoords[i].scale(scaleFactor);
326- }
327- usingCoords = scaledCoords;
328- }
329+ memcpy(scaledCoords, motionEntry->pointerCoords, motionEntry->pointerCount * sizeof(PointerCoords));
330+ transformPoints( dispatchEntry->screenToLocal, scaledCoords, motionEntry->pointerCount );
331+ usingCoords = scaledCoords;
332 } else {
333- xOffset = 0.0f;
334- yOffset = 0.0f;
335- scaleFactor = 1.0f;
336
337 // We don't want the dispatch target to know.
338 if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
339@@ -1922,11 +1919,10 @@
340 motionEntry->deviceId, motionEntry->source,
341 dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
342 motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState,
343- xOffset, yOffset,
344 motionEntry->xPrecision, motionEntry->yPrecision,
345 motionEntry->downTime, motionEntry->eventTime,
346- motionEntry->pointerCount, motionEntry->pointerProperties,
347- usingCoords);
348+ motionEntry->pointerCount,
349+ motionEntry->pointerProperties, usingCoords);
350 input_report->published_motion_event(connection->inputChannel->getFd(),
351 dispatchEntry->seq,
352 motionEntry->eventTime);
353@@ -2144,13 +2140,7 @@
354 sp<InputWindowHandle> windowHandle = getWindowHandleLocked(connection->inputChannel);
355 if (windowHandle != NULL) {
356 const InputWindowInfo* windowInfo = windowHandle->getInfo();
357- target.xOffset = -windowInfo->frameLeft;
358- target.yOffset = -windowInfo->frameTop;
359- target.scaleFactor = windowInfo->scaleFactor;
360- } else {
361- target.xOffset = 0;
362- target.yOffset = 0;
363- target.scaleFactor = 1.0f;
364+ target.screenToLocal = windowInfo->getScreenToLocalTransformation();
365 }
366 target.inputChannel = connection->inputChannel;
367 target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
368@@ -2393,7 +2383,7 @@
369
370 MotionEvent event;
371 event.initialize(args->deviceId, args->source, args->action, args->flags,
372- args->edgeFlags, args->metaState, args->buttonState, 0, 0,
373+ args->edgeFlags, args->metaState, args->buttonState,
374 args->xPrecision, args->yPrecision,
375 args->downTime, args->eventTime,
376 args->pointerCount, args->pointerProperties, args->pointerCoords);
377@@ -3028,9 +3018,7 @@
378 const InputWindowInfo* windowInfo = windowHandle->getInfo();
379
380 appendFormat(dump, INDENT2 "name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
381- "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
382- "frame=[%d,%d][%d,%d], scale=%f, "
383- "touchableRegion=[%d,%d][%d,%d]",
384+ "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, ",
385 c_str(windowInfo->name),
386 toString(windowInfo->paused),
387 toString(windowInfo->hasFocus),
388@@ -3038,12 +3026,7 @@
389 toString(windowInfo->visible),
390 toString(windowInfo->canReceiveKeys),
391 windowInfo->layoutParamsFlags, windowInfo->layoutParamsType,
392- windowInfo->layer,
393- windowInfo->frameLeft, windowInfo->frameTop,
394- windowInfo->frameRight, windowInfo->frameBottom,
395- windowInfo->scaleFactor,
396- windowInfo->touchableRegionLeft, windowInfo->touchableRegionTop,
397- windowInfo->touchableRegionRight, windowInfo->touchableRegionBottom);
398+ windowInfo->layer);
399 appendFormat(dump, ", inputFeatures=0x%08x", windowInfo->inputFeatures);
400 appendFormat(dump, ", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
401 windowInfo->ownerPid, windowInfo->ownerUid,
402@@ -3763,6 +3746,9 @@
403 void InputDispatcher::MotionEntry::appendDescription(String8& msg) const {
404 appendFormat(msg, "MotionEvent(action=%d, deviceId=%d, source=0x%08x)",
405 action, deviceId, source);
406+ for (uint32_t i = 0; i != pointerCount; ++i) {
407+ appendFormat(msg, ", ptr%d(%f,%f)", i, pointerCoords[i].getX(), pointerCoords[i].getY());
408+ }
409 }
410
411
412@@ -3771,10 +3757,10 @@
413 android_atomic_int32_t InputDispatcher::DispatchEntry::sNextSeqAtomic;
414
415 InputDispatcher::DispatchEntry::DispatchEntry(EventEntry* eventEntry,
416- int32_t targetFlags, float xOffset, float yOffset, float scaleFactor) :
417+ int32_t targetFlags, glm::mat4 const& screenToLocal) :
418 seq(nextSeq()),
419 eventEntry(eventEntry), targetFlags(targetFlags),
420- xOffset(xOffset), yOffset(yOffset), scaleFactor(scaleFactor),
421+ screenToLocal(screenToLocal),
422 deliveryTime(0), resolvedAction(0), resolvedFlags(0) {
423 eventEntry->refCount += 1;
424 }
425
426=== modified file '3rd_party/android-input/android/frameworks/base/services/input/InputDispatcher.h'
427--- 3rd_party/android-input/android/frameworks/base/services/input/InputDispatcher.h 2014-03-06 06:05:17 +0000
428+++ 3rd_party/android-input/android/frameworks/base/services/input/InputDispatcher.h 2014-04-15 08:20:19 +0000
429@@ -31,6 +31,8 @@
430 #include <std/Thread.h>
431 #include <std/Mutex.h>
432
433+#include <glm/glm.hpp>
434+
435 #include <stddef.h>
436 #include <unistd.h>
437 #include <limits.h>
438@@ -92,9 +94,8 @@
439
440 /*
441 * An input target specifies how an input event is to be dispatched to a particular window
442- * including the window's input channel, control flags, a timeout, and an X / Y offset to
443- * be added to input event coordinates to compensate for the absolute position of the
444- * window area.
445+ * including the window's input channel, control flags, a timeout, and means to transform
446+ * absolute screen position to local window coordinates.
447 */
448 struct InputTarget {
449 enum {
450@@ -159,13 +160,9 @@
451 // Flags for the input target.
452 int32_t flags;
453
454- // The x and y offset to add to a MotionEvent as it is delivered.
455- // (ignored for KeyEvents)
456- float xOffset, yOffset;
457-
458- // Scaling factor to apply to MotionEvent as it is delivered.
459- // (ignored for KeyEvents)
460- float scaleFactor;
461+ // The transformation necessary to apply to a MotionEvent as it is delivered.
462+ // (ignored for KeyEvents)
463+ glm::mat4 screenToLocal;
464
465 // The subset of pointer ids to include in motion events dispatched to this input target
466 // if FLAG_SPLIT is set.
467@@ -565,9 +562,7 @@
468
469 EventEntry* eventEntry; // the event to dispatch
470 int32_t targetFlags;
471- float xOffset;
472- float yOffset;
473- float scaleFactor;
474+ glm::mat4 screenToLocal;
475 nsecs_t deliveryTime; // time when the event was actually delivered
476
477 // Set to the resolved action and flags when the event is enqueued.
478@@ -575,7 +570,7 @@
479 int32_t resolvedFlags;
480
481 DispatchEntry(EventEntry* eventEntry,
482- int32_t targetFlags, float xOffset, float yOffset, float scaleFactor);
483+ int32_t targetFlags, glm::mat4 const& screenToLocal);
484 ~DispatchEntry();
485
486 inline bool hasForegroundTarget() const {
487
488=== modified file '3rd_party/android-input/android/frameworks/base/services/input/InputTransport.cpp'
489--- 3rd_party/android-input/android/frameworks/base/services/input/InputTransport.cpp 2014-03-06 06:05:17 +0000
490+++ 3rd_party/android-input/android/frameworks/base/services/input/InputTransport.cpp 2014-04-15 08:20:19 +0000
491@@ -277,8 +277,6 @@
492 int32_t edgeFlags,
493 int32_t metaState,
494 int32_t buttonState,
495- float xOffset,
496- float yOffset,
497 float xPrecision,
498 float yPrecision,
499 nsecs_t downTime,
500@@ -289,12 +287,11 @@
501 #if DEBUG_TRANSPORT_ACTIONS
502 ALOGD("channel '%s' publisher ~ publishMotionEvent: seq=%u, deviceId=%d, source=0x%x, "
503 "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, buttonState=0x%x, "
504- "xOffset=%f, yOffset=%f, "
505 "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
506 "pointerCount=%d",
507 c_str(mChannel->getName()), seq,
508 deviceId, source, action, flags, edgeFlags, metaState, buttonState,
509- xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount);
510+ xPrecision, yPrecision, downTime, eventTime, pointerCount);
511 #endif
512
513 if (!seq) {
514@@ -318,8 +315,6 @@
515 msg.body.motion.edgeFlags = edgeFlags;
516 msg.body.motion.metaState = metaState;
517 msg.body.motion.buttonState = buttonState;
518- msg.body.motion.xOffset = xOffset;
519- msg.body.motion.yOffset = yOffset;
520 msg.body.motion.xPrecision = xPrecision;
521 msg.body.motion.yPrecision = yPrecision;
522 msg.body.motion.downTime = downTime;
523@@ -898,8 +893,6 @@
524 msg->body.motion.edgeFlags,
525 msg->body.motion.metaState,
526 msg->body.motion.buttonState,
527- msg->body.motion.xOffset,
528- msg->body.motion.yOffset,
529 msg->body.motion.xPrecision,
530 msg->body.motion.yPrecision,
531 msg->body.motion.downTime,
532
533=== modified file '3rd_party/android-input/android/frameworks/base/services/input/InputWindow.cpp'
534--- 3rd_party/android-input/android/frameworks/base/services/input/InputWindow.cpp 2012-11-06 18:05:11 +0000
535+++ 3rd_party/android-input/android/frameworks/base/services/input/InputWindow.cpp 2014-04-15 08:20:19 +0000
536@@ -23,15 +23,16 @@
537 namespace android {
538
539 // --- InputWindowInfo ---
540-
541-bool InputWindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const {
542- return x >= touchableRegionLeft && x <= touchableRegionRight
543- && y >= touchableRegionTop && y <= touchableRegionBottom;
544-}
545-
546-bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const {
547- return x >= frameLeft && x <= frameRight
548- && y >= frameTop && y <= frameBottom;
549+bool InputWindowInfo::touchableRegionContainsPoint(int32_t, int32_t) const {
550+ return false;
551+}
552+
553+glm::mat4 InputWindowInfo::getScreenToLocalTransformation() const {
554+ return glm::mat4{};
555+}
556+
557+bool InputWindowInfo::frameContainsPoint(int32_t, int32_t) const {
558+ return false;
559 }
560
561 bool InputWindowInfo::isTrustedOverlay() const {
562
563=== modified file '3rd_party/android-input/android/frameworks/base/services/input/InputWindow.h'
564--- 3rd_party/android-input/android/frameworks/base/services/input/InputWindow.h 2013-06-28 17:59:49 +0000
565+++ 3rd_party/android-input/android/frameworks/base/services/input/InputWindow.h 2014-04-15 08:20:19 +0000
566@@ -22,7 +22,9 @@
567 #include <std/RefBase.h>
568 #include <std/Timers.h>
569 #include <std/String8.h>
570+#include <glm/glm.hpp>
571
572+#include <functional>
573 #include "InputApplication.h"
574
575 namespace android {
576@@ -116,17 +118,6 @@
577 int32_t layoutParamsFlags;
578 int32_t layoutParamsType;
579 nsecs_t dispatchingTimeout;
580- int32_t frameLeft;
581- int32_t frameTop;
582- int32_t frameRight;
583- int32_t frameBottom;
584- float scaleFactor;
585-
586- //SkRegion touchableRegion; remove dependency from skia lib
587- int32_t touchableRegionLeft;
588- int32_t touchableRegionTop;
589- int32_t touchableRegionRight;
590- int32_t touchableRegionBottom;
591
592 bool visible;
593 bool canReceiveKeys;
594@@ -139,7 +130,8 @@
595 int32_t inputFeatures;
596
597 virtual bool touchableRegionContainsPoint(int32_t x, int32_t y) const;
598- bool frameContainsPoint(int32_t x, int32_t y) const;
599+ virtual glm::mat4 getScreenToLocalTransformation() const;
600+ virtual bool frameContainsPoint(int32_t x, int32_t y) const;
601
602 /* Returns true if the window is of a trusted type that is allowed to silently
603 * overlay other windows for the purpose of implementing the secure views feature.
604
605=== modified file 'include/server/mir/input/surface.h'
606--- include/server/mir/input/surface.h 2014-03-26 05:48:59 +0000
607+++ include/server/mir/input/surface.h 2014-04-15 08:20:19 +0000
608@@ -21,6 +21,8 @@
609
610 #include "mir/geometry/size.h"
611 #include "mir/geometry/point.h"
612+
613+#include <glm/glm.hpp>
614 #include <string>
615
616 namespace mir
617@@ -31,6 +33,7 @@
618 {
619 public:
620 virtual std::string name() const = 0;
621+ virtual glm::mat4 inverse_transformation() const = 0;
622 virtual geometry::Point top_left() const = 0;
623 virtual geometry::Size size() const = 0;
624 virtual bool contains(geometry::Point const& point) const = 0;
625
626=== modified file 'include/shared/mir_toolkit/event.h'
627--- include/shared/mir_toolkit/event.h 2014-03-06 06:05:17 +0000
628+++ include/shared/mir_toolkit/event.h 2014-04-15 08:20:19 +0000
629@@ -153,8 +153,8 @@
630
631 int32_t edge_flags;
632 MirMotionButton button_state;
633- float x_offset;
634- float y_offset;
635+ float x_offset_deprecated;
636+ float y_offset_deprecated;
637 float x_precision;
638 float y_precision;
639 nsecs_t down_time;
640@@ -164,8 +164,8 @@
641 struct
642 {
643 int id;
644- float x, raw_x;
645- float y, raw_y;
646+ float x, raw_x_deprecated;
647+ float y, raw_y_deprecated;
648 float touch_major;
649 float touch_minor;
650 float size;
651
652=== modified file 'include/test/mir_test_doubles/mock_input_surface.h'
653--- include/test/mir_test_doubles/mock_input_surface.h 2014-03-26 05:48:59 +0000
654+++ include/test/mir_test_doubles/mock_input_surface.h 2014-04-15 08:20:19 +0000
655@@ -44,8 +44,11 @@
656 static std::string n;
657 ON_CALL(*this, name())
658 .WillByDefault(testing::Return(n));
659+ ON_CALL(*this, inverse_transformation())
660+ .WillByDefault(testing::Return(glm::mat4{}));
661 }
662 ~MockInputSurface() noexcept {}
663+ MOCK_CONST_METHOD0(inverse_transformation, glm::mat4());
664 MOCK_CONST_METHOD0(top_left, geometry::Point());
665 MOCK_CONST_METHOD0(size, geometry::Size());
666 MOCK_CONST_METHOD0(name, std::string());
667
668=== modified file 'src/client/logging/input_receiver_report.cpp'
669--- src/client/logging/input_receiver_report.cpp 2014-03-06 06:05:17 +0000
670+++ src/client/logging/input_receiver_report.cpp 2014-04-15 08:20:19 +0000
671@@ -69,8 +69,6 @@
672 ss << " modifiers: " << ev.modifiers << std::endl;
673 ss << " edge_flags: " << ev.edge_flags << std::endl;
674 ss << " button_state: " << ev.button_state << std::endl;
675- ss << " x_offset: " << ev.x_offset << std::endl;
676- ss << " y_offset: " << ev.y_offset << std::endl;
677 ss << " x_precision: " << ev.x_precision << std::endl;
678 ss << " y_precision: " << ev.y_precision << std::endl;
679 ss << " down_time: " << ev.down_time << std::endl;
680@@ -81,9 +79,7 @@
681 ss << " pointer[" << i << "]{" << std::endl;
682 ss << " id: " << ev.pointer_coordinates[i].id << std::endl;
683 ss << " x: " << ev.pointer_coordinates[i].x << std::endl;
684- ss << " raw_x: " << ev.pointer_coordinates[i].raw_x << std::endl;
685 ss << " y: " << ev.pointer_coordinates[i].y << std::endl;
686- ss << " raw_y: " << ev.pointer_coordinates[i].raw_y << std::endl;
687 ss << " touch_major: " << ev.pointer_coordinates[i].touch_major << std::endl;
688 ss << " touch_minor: " << ev.pointer_coordinates[i].touch_minor << std::endl;
689 ss << " size: " << ev.pointer_coordinates[i].size << std::endl;
690
691=== modified file 'src/server/graphics/nested/nested_output.cpp'
692--- src/server/graphics/nested/nested_output.cpp 2014-03-26 05:48:59 +0000
693+++ src/server/graphics/nested/nested_output.cpp 2014-04-15 08:20:19 +0000
694@@ -116,15 +116,5 @@
695
696 void mgn::detail::NestedOutput::mir_event(MirEvent const& event)
697 {
698- if (event.type == mir_event_type_motion)
699- {
700- auto my_event = event;
701- my_event.motion.x_offset += area.top_left.x.as_float();
702- my_event.motion.y_offset += area.top_left.y.as_float();
703- event_handler->handle(my_event);
704- }
705- else
706- {
707- event_handler->handle(event);
708- }
709+ event_handler->handle(event);
710 }
711
712=== modified file 'src/server/input/android/android_input_window_handle.cpp'
713--- src/server/input/android/android_input_window_handle.cpp 2014-03-06 06:05:17 +0000
714+++ src/server/input/android/android_input_window_handle.cpp 2014-04-15 08:20:19 +0000
715@@ -21,8 +21,13 @@
716
717 #include "mir/input/input_channel.h"
718 #include "mir/input/surface.h"
719+#include "mir/geometry/displacement.h"
720
721 #include <androidfw/InputTransport.h>
722+#include <androidfw/Input.h>
723+
724+#define GLM_FORCE_RADIANS
725+#include <glm/gtx/transform.hpp>
726
727 #include <limits.h>
728
729@@ -44,6 +49,27 @@
730 return surface->contains(geom::Point{x, y});
731 }
732
733+ glm::mat4 getScreenToLocalTransformation() const override
734+ {
735+ // TODO Still missing further affine transformations that are applied to the
736+ // whole screen i.e. if something other than a orthographic matrix used.
737+ glm::mat4 transformation_matrix = surface->inverse_transformation();
738+ geom::Size size = surface->size();
739+ geom::Point top_left = surface->top_left();
740+ auto center = glm::vec3{size.width.as_int(), size.height.as_int(), 0}/2.0f;
741+ auto surface_center = glm::vec3{top_left.x.as_int(), top_left.y.as_int(), 0} + center;
742+
743+ return glm::translate(center) * transformation_matrix * glm::translate(-surface_center);
744+ }
745+
746+ bool frameContainsPoint(int32_t x, int32_t y) const override
747+ {
748+ // TODO frame vs touchableRegion?
749+ // shall we care about the difference and test against the surface rectangle instead
750+ // of the input regions specified?
751+ return surface->contains(geom::Point{x,y});
752+ }
753+
754 std::shared_ptr<mi::Surface> const surface;
755 };
756 }
757@@ -69,23 +95,9 @@
758 input_channel->server_fd());
759 }
760
761- auto surface_size = surface->size();
762- auto surface_position = surface->top_left();
763-
764- mInfo->frameLeft = surface_position.x.as_uint32_t();
765- mInfo->frameTop = surface_position.y.as_uint32_t();
766- mInfo->frameRight = mInfo->frameLeft + surface_size.width.as_uint32_t();
767- mInfo->frameBottom = mInfo->frameTop + surface_size.height.as_uint32_t();
768-
769- mInfo->touchableRegionLeft = mInfo->frameLeft;
770- mInfo->touchableRegionTop = mInfo->frameTop;
771- mInfo->touchableRegionRight = mInfo->frameRight;
772- mInfo->touchableRegionBottom = mInfo->frameBottom;
773-
774 mInfo->name = droidinput::String8(surface->name().c_str());
775 mInfo->layoutParamsFlags = droidinput::InputWindowInfo::FLAG_NOT_TOUCH_MODAL;
776 mInfo->layoutParamsType = droidinput::InputWindowInfo::TYPE_APPLICATION;
777- mInfo->scaleFactor = 1.f;
778 mInfo->visible = true;
779 mInfo->canReceiveKeys = true;
780 mInfo->hasFocus = true;
781
782=== modified file 'src/server/scene/basic_surface.cpp'
783--- src/server/scene/basic_surface.cpp 2014-04-15 05:31:19 +0000
784+++ src/server/scene/basic_surface.cpp 2014-04-15 08:20:19 +0000
785@@ -30,6 +30,7 @@
786
787 #include <boost/throw_exception.hpp>
788
789+#include <cmath>
790 #include <stdexcept>
791 #include <algorithm>
792
793@@ -40,6 +41,24 @@
794 namespace mi = mir::input;
795 namespace geom = mir::geometry;
796
797+namespace
798+{
799+geom::Point to_point(glm::vec4 pos)
800+{
801+ return geom::Point{std::round(pos.x), std::round(pos.y)};
802+}
803+
804+glm::vec4 to_vec(geom::Point pos)
805+{
806+ return glm::vec4{pos.x.as_int(), pos.y.as_int(), 0, 1};
807+}
808+
809+glm::vec4 to_vec(geom::Size s)
810+{
811+ return glm::vec4{s.width.as_int(), s.height.as_int(), 0, 1};
812+}
813+}
814+
815 void ms::SurfaceObservers::attrib_changed(MirSurfaceAttrib attrib, int value)
816 {
817 std::unique_lock<decltype(mutex)> lock(mutex);
818@@ -125,7 +144,7 @@
819 first_frame_posted(false),
820 hidden(false),
821 nonrectangular(nonrectangular),
822- input_rectangles{surface_rect},
823+ input_rectangles{geom::Rectangle{geom::Point{}, surface_rect.size}},
824 surface_buffer_stream(buffer_stream),
825 server_input_channel(input_channel),
826 configurator(configurator),
827@@ -278,15 +297,26 @@
828 return surface_rect.top_left;
829 }
830
831+glm::mat4 ms::BasicSurface::inverse_transformation() const
832+{
833+ std::unique_lock<std::mutex> lk(guard);
834+ return inverse_matrix;
835+}
836+
837 bool ms::BasicSurface::contains(geom::Point const& point) const
838 {
839 std::unique_lock<std::mutex> lock(guard);
840 if (hidden)
841 return false;
842
843+ auto center = to_vec(surface_rect.size)/2.0f;
844+ auto pos = to_vec(surface_rect.top_left) + center;
845+
846+ geom::Point transformed = to_point( inverse_matrix * (to_vec(point) - pos) + center);
847+
848 for (auto const& rectangle : input_rectangles)
849 {
850- if (rectangle.contains(point))
851+ if (rectangle.contains(transformed))
852 {
853 return true;
854 }
855@@ -303,12 +333,12 @@
856 observers.alpha_set_to(alpha);
857 }
858
859-
860 void ms::BasicSurface::set_transformation(glm::mat4 const& t)
861 {
862 {
863 std::unique_lock<std::mutex> lk(guard);
864 transformation_matrix = t;
865+ inverse_matrix = glm::inverse(transformation_matrix);
866 }
867 observers.transformation_set_to(t);
868 }
869
870=== modified file 'src/server/scene/basic_surface.h'
871--- src/server/scene/basic_surface.h 2014-04-15 05:31:19 +0000
872+++ src/server/scene/basic_surface.h 2014-04-15 08:20:19 +0000
873@@ -117,9 +117,10 @@
874 void set_alpha(float alpha) override;
875 void set_transformation(glm::mat4 const&) override;
876 glm::mat4 transformation() const override;
877+ glm::mat4 inverse_transformation() const override;
878
879 bool visible() const;
880-
881+
882 bool shaped() const override; // meaning the pixel format has alpha
883
884 // Renderable interface
885@@ -150,6 +151,7 @@
886 std::string const surface_name;
887 geometry::Rectangle surface_rect;
888 glm::mat4 transformation_matrix;
889+ glm::mat4 inverse_matrix;
890 float surface_alpha;
891 bool first_frame_posted;
892 bool hidden;
893
894=== modified file 'src/shared/input/android/android_input_lexicon.cpp'
895--- src/shared/input/android/android_input_lexicon.cpp 2014-03-06 06:05:17 +0000
896+++ src/shared/input/android/android_input_lexicon.cpp 2014-04-15 08:20:19 +0000
897@@ -55,8 +55,8 @@
898 mir_event.motion.modifiers = mev->getMetaState();
899 mir_event.motion.edge_flags = mev->getEdgeFlags();
900 mir_event.motion.button_state = static_cast<MirMotionButton>(mev->getButtonState());
901- mir_event.motion.x_offset = mev->getXOffset();
902- mir_event.motion.y_offset = mev->getYOffset();
903+ mir_event.motion.x_offset_deprecated = 0.0f;
904+ mir_event.motion.y_offset_deprecated = 0.0f;
905 mir_event.motion.x_precision = mev->getXPrecision();
906 mir_event.motion.y_precision = mev->getYPrecision();
907 mir_event.motion.down_time = mev->getDownTime();
908@@ -66,9 +66,9 @@
909 {
910 mir_event.motion.pointer_coordinates[i].id = mev->getPointerId(i);
911 mir_event.motion.pointer_coordinates[i].x = mev->getX(i);
912- mir_event.motion.pointer_coordinates[i].raw_x = mev->getRawX(i);
913+ mir_event.motion.pointer_coordinates[i].raw_x_deprecated = 0.0f;
914 mir_event.motion.pointer_coordinates[i].y = mev->getY(i);
915- mir_event.motion.pointer_coordinates[i].raw_y = mev->getRawY(i);
916+ mir_event.motion.pointer_coordinates[i].raw_y_deprecated = 0.0f;
917 mir_event.motion.pointer_coordinates[i].touch_major = mev->getTouchMajor(i);
918 mir_event.motion.pointer_coordinates[i].touch_minor = mev->getTouchMinor(i);
919 mir_event.motion.pointer_coordinates[i].size = mev->getSize(i);
920@@ -76,10 +76,10 @@
921 mir_event.motion.pointer_coordinates[i].orientation = mev->getOrientation(i);
922
923 mir_event.motion.pointer_coordinates[i].vscroll =
924- mev->getRawAxisValue(AMOTION_EVENT_AXIS_VSCROLL, i);
925+ mev->getAxisValue(AMOTION_EVENT_AXIS_VSCROLL, i);
926
927 mir_event.motion.pointer_coordinates[i].hscroll =
928- mev->getRawAxisValue(AMOTION_EVENT_AXIS_HSCROLL, i);
929+ mev->getAxisValue(AMOTION_EVENT_AXIS_HSCROLL, i);
930
931 mir_event.motion.pointer_coordinates[i].tool_type =
932 static_cast<MirMotionToolType>(mev->getToolType(i));
933
934=== modified file 'tests/unit-tests/client/input/test_android_input_receiver.cpp'
935--- tests/unit-tests/client/input/test_android_input_receiver.cpp 2014-03-06 06:05:17 +0000
936+++ tests/unit-tests/client/input/test_android_input_receiver.cpp 2014-04-15 08:20:19 +0000
937@@ -82,7 +82,6 @@
938 0 /* edge_flags */,
939 0 /* meta_state */,
940 0 /* button_state */,
941- 0 /* x_offset */, 0 /* y_offset */,
942 0 /* x_precision */, 0 /* y_precision */,
943 0 /* down_time */,
944 0 /* event_time */,
945
946=== modified file 'tests/unit-tests/input/android/test_android_input_lexicon.cpp'
947--- tests/unit-tests/input/android/test_android_input_lexicon.cpp 2014-03-06 06:05:17 +0000
948+++ tests/unit-tests/input/android/test_android_input_lexicon.cpp 2014-04-15 08:20:19 +0000
949@@ -110,8 +110,8 @@
950 const float hscroll = 900.0;
951 const MirMotionToolType tool_type = mir_motion_tool_type_mouse;
952
953- pointer_coords.setAxisValue(AMOTION_EVENT_AXIS_X, x_axis);
954- pointer_coords.setAxisValue(AMOTION_EVENT_AXIS_Y, y_axis);
955+ pointer_coords.setAxisValue(AMOTION_EVENT_AXIS_X, x_axis + x_offset);
956+ pointer_coords.setAxisValue(AMOTION_EVENT_AXIS_Y, y_axis + y_offset);
957 pointer_coords.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touch_major);
958 pointer_coords.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touch_minor);
959 pointer_coords.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
960@@ -121,10 +121,9 @@
961 pointer_coords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
962 pointer_properties.toolType = tool_type;
963
964- android_motion_ev->initialize(device_id, source_id, action, flags, edge_flags,
965- meta_state, button_state, x_offset, y_offset,
966- x_precision, y_precision, down_time,
967- event_time, pointer_count, &pointer_properties, &pointer_coords);
968+ android_motion_ev->initialize(device_id, source_id, action, flags, edge_flags, meta_state, button_state,
969+ x_precision, y_precision, down_time, event_time, pointer_count, &pointer_properties,
970+ &pointer_coords);
971
972 MirEvent mir_ev;
973 mia::Lexicon::translate(android_motion_ev, mir_ev);
974@@ -143,8 +142,8 @@
975
976 EXPECT_EQ(mir_motion_ev->edge_flags, edge_flags);
977 EXPECT_EQ(mir_motion_ev->button_state, button_state);
978- EXPECT_EQ(mir_motion_ev->x_offset, x_offset);
979- EXPECT_EQ(mir_motion_ev->y_offset, y_offset);
980+ EXPECT_EQ(mir_motion_ev->x_offset_deprecated, 0.0f);
981+ EXPECT_EQ(mir_motion_ev->y_offset_deprecated, 0.0f);
982 EXPECT_EQ(mir_motion_ev->x_precision, x_precision);
983 EXPECT_EQ(mir_motion_ev->y_precision, y_precision);
984 EXPECT_EQ(mir_motion_ev->down_time, down_time);
985@@ -158,8 +157,8 @@
986 // Notice these two coordinates are offset by x/y offset
987 EXPECT_EQ(mir_pointer_coords->x, x_axis + x_offset);
988 EXPECT_EQ(mir_pointer_coords->y, y_axis + y_offset);
989- EXPECT_EQ(mir_pointer_coords->raw_x, x_axis);
990- EXPECT_EQ(mir_pointer_coords->raw_y, y_axis);
991+ EXPECT_EQ(mir_pointer_coords->raw_x_deprecated, 0.0f);
992+ EXPECT_EQ(mir_pointer_coords->raw_y_deprecated, 0.0f);
993 EXPECT_EQ(mir_pointer_coords->touch_major, touch_major);
994 EXPECT_EQ(mir_pointer_coords->touch_minor, touch_minor);
995 EXPECT_EQ(mir_pointer_coords->size, size);
996@@ -218,8 +217,8 @@
997 {
998 pointer_properties[p].id = pointer_id[p];
999
1000- pointer_coords[p].setAxisValue(AMOTION_EVENT_AXIS_X, x_axis[p]);
1001- pointer_coords[p].setAxisValue(AMOTION_EVENT_AXIS_Y, y_axis[p]);
1002+ pointer_coords[p].setAxisValue(AMOTION_EVENT_AXIS_X, x_offset + x_axis[p]);
1003+ pointer_coords[p].setAxisValue(AMOTION_EVENT_AXIS_Y, y_offset + y_axis[p]);
1004 pointer_coords[p].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR,
1005 touch_major[p]);
1006 pointer_coords[p].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR,
1007@@ -237,11 +236,9 @@
1008 pointer_properties[p].toolType = tool_types[p];
1009 }
1010
1011- android_motion_ev->initialize(device_id, source_id, action, flags,
1012- edge_flags, meta_state, button_state,
1013- x_offset, y_offset, x_precision, y_precision,
1014- down_time, event_time, pointer_count,
1015- pointer_properties, pointer_coords);
1016+ android_motion_ev->initialize(device_id, source_id, action, flags, edge_flags, meta_state, button_state,
1017+ x_precision, y_precision, down_time, event_time, pointer_count, pointer_properties,
1018+ pointer_coords);
1019
1020 MirEvent mir_ev;
1021 mia::Lexicon::translate(android_motion_ev, mir_ev);
1022@@ -260,8 +257,8 @@
1023
1024 EXPECT_EQ(mir_motion_ev->edge_flags, edge_flags);
1025 EXPECT_EQ(mir_motion_ev->button_state, button_state);
1026- EXPECT_EQ(mir_motion_ev->x_offset, x_offset);
1027- EXPECT_EQ(mir_motion_ev->y_offset, y_offset);
1028+ EXPECT_EQ(mir_motion_ev->x_offset_deprecated, 0.0f);
1029+ EXPECT_EQ(mir_motion_ev->y_offset_deprecated, 0.0f);
1030 EXPECT_EQ(mir_motion_ev->x_precision, x_precision);
1031 EXPECT_EQ(mir_motion_ev->y_precision, y_precision);
1032 EXPECT_EQ(mir_motion_ev->down_time, down_time);
1033@@ -275,8 +272,8 @@
1034 EXPECT_EQ(pointer[p].id, pointer_id[p]);
1035 EXPECT_EQ(pointer[p].x, x_axis[p] + x_offset);
1036 EXPECT_EQ(pointer[p].y, y_axis[p] + y_offset);
1037- EXPECT_EQ(pointer[p].raw_x, x_axis[p]);
1038- EXPECT_EQ(pointer[p].raw_y, y_axis[p]);
1039+ EXPECT_EQ(pointer[p].raw_x_deprecated, 0.0f);
1040+ EXPECT_EQ(pointer[p].raw_y_deprecated, 0.0f);
1041 EXPECT_EQ(pointer[p].touch_major, touch_major[p]);
1042 EXPECT_EQ(pointer[p].touch_minor, touch_minor[p]);
1043 EXPECT_EQ(pointer[p].size, size[p]);
1044
1045=== modified file 'tests/unit-tests/input/android/test_android_input_registrar.cpp'
1046--- tests/unit-tests/input/android/test_android_input_registrar.cpp 2014-03-26 05:48:59 +0000
1047+++ tests/unit-tests/input/android/test_android_input_registrar.cpp 2014-04-15 08:20:19 +0000
1048@@ -80,6 +80,10 @@
1049 {
1050 return true;
1051 }
1052+ glm::mat4 inverse_transformation() const override
1053+ {
1054+ return glm::mat4{};
1055+ }
1056 };
1057
1058 MATCHER_P(WindowHandleFor, channel, "")
1059
1060=== modified file 'tests/unit-tests/input/android/test_android_input_window_handle.cpp'
1061--- tests/unit-tests/input/android/test_android_input_window_handle.cpp 2014-03-26 14:20:14 +0000
1062+++ tests/unit-tests/input/android/test_android_input_window_handle.cpp 2014-04-15 08:20:19 +0000
1063@@ -56,12 +56,10 @@
1064
1065 }
1066
1067-TEST(AndroidInputWindowHandle, update_info_uses_geometry_and_channel_from_surface)
1068+TEST(AndroidInputWindowHandle, update_info_uses_name_and_channel_from_surface)
1069 {
1070 using namespace ::testing;
1071
1072- geom::Size const default_surface_size{256, 256};
1073- geom::Point const default_surface_top_left = geom::Point{geom::X{10}, geom::Y{10}};
1074 std::string const testing_surface_name = "Test";
1075
1076 int testing_server_fd;
1077@@ -87,14 +85,6 @@
1078 .Times(1)
1079 .WillOnce(Return(testing_server_fd));
1080
1081- // For now since we are just doing keyboard input we only need surface size,
1082- // for touch/pointer events we will need a position
1083- EXPECT_CALL(mock_surface, size())
1084- .Times(1)
1085- .WillOnce(Return(default_surface_size));
1086- EXPECT_CALL(mock_surface, top_left())
1087- .Times(1)
1088- .WillOnce(Return(default_surface_top_left));
1089 EXPECT_CALL(mock_surface, name())
1090 .Times(1)
1091 .WillOnce(Return(testing_surface_name));
1092@@ -107,14 +97,4 @@
1093 EXPECT_EQ(droidinput::String8(testing_surface_name.c_str()), info->name);
1094
1095 EXPECT_EQ(testing_server_fd, info->inputChannel->getFd());
1096-
1097- EXPECT_EQ(default_surface_top_left.x.as_uint32_t(), (uint32_t)(info->frameLeft));
1098- EXPECT_EQ(default_surface_top_left.y.as_uint32_t(), (uint32_t)(info->frameTop));
1099- EXPECT_EQ(default_surface_size.height.as_uint32_t(), (uint32_t)(info->frameRight - info->frameLeft));
1100- EXPECT_EQ(default_surface_size.height.as_uint32_t(), (uint32_t)(info->frameBottom - info->frameTop));
1101-
1102- EXPECT_EQ(info->frameLeft, info->touchableRegionLeft);
1103- EXPECT_EQ(info->frameTop, info->touchableRegionTop);
1104- EXPECT_EQ(info->frameRight, info->touchableRegionRight);
1105- EXPECT_EQ(info->frameBottom, info->touchableRegionBottom);
1106 }
1107
1108=== modified file 'tests/unit-tests/scene/test_basic_surface.cpp'
1109--- tests/unit-tests/scene/test_basic_surface.cpp 2014-04-15 05:31:19 +0000
1110+++ tests/unit-tests/scene/test_basic_surface.cpp 2014-04-15 08:20:19 +0000
1111@@ -21,6 +21,7 @@
1112
1113 #include "mir/frontend/event_sink.h"
1114 #include "mir/geometry/rectangle.h"
1115+#include "mir/geometry/displacement.h"
1116 #include "mir/scene/surface_configurator.h"
1117
1118 #include "mir_test_doubles/mock_buffer_stream.h"
1119@@ -29,6 +30,8 @@
1120
1121 #include "src/server/report/null_report_factory.h"
1122
1123+#include <glm/gtx/euler_angles.hpp>
1124+
1125 #include <algorithm>
1126 #include <gtest/gtest.h>
1127 #include <gmock/gmock.h>
1128@@ -369,9 +372,6 @@
1129 stub_configurator,
1130 report};
1131
1132- auto const observer = std::make_shared<ms::LegacySurfaceChangeNotification>(mock_change_cb);
1133- surface.add_observer(observer);
1134-
1135 std::vector<geom::Point> contained_pt
1136 {
1137 geom::Point{geom::X{1}, geom::Y{1}}
1138@@ -395,6 +395,85 @@
1139 }
1140 }
1141
1142+TEST_F(BasicSurfaceTest, input_region_is_moved_with_surface)
1143+{
1144+ geom::Point pt(1,1);
1145+ geom::Size one_by_one{geom::Width{1}, geom::Height{1}};
1146+ ms::BasicSurface surface_state{
1147+ name,
1148+ geom::Rectangle{pt, one_by_one},
1149+ false,
1150+ mock_buffer_stream,
1151+ std::shared_ptr<mi::InputChannel>(),
1152+ stub_configurator,
1153+ report};
1154+
1155+ geom::Point newPos{13,66};
1156+ surface_state.move_to(newPos);
1157+
1158+ for(auto x = newPos.x.as_int() - 1; x <= 3; x++)
1159+ {
1160+ for(auto y = newPos.y.as_int() - 1; y <= 3; y++)
1161+ {
1162+ auto test_pt = geom::Point{x, y};
1163+ auto contains = surface_state.contains(test_pt);
1164+ if (newPos == test_pt)
1165+ {
1166+ EXPECT_TRUE(contains);
1167+ }
1168+ else
1169+ {
1170+ EXPECT_FALSE(contains);
1171+ }
1172+ }
1173+ }
1174+}
1175+
1176+TEST_F(BasicSurfaceTest, input_region_is_rotated_with_surface)
1177+{
1178+ geom::Point pt(1,1);
1179+ geom::Size one_by_five{geom::Width{2}, geom::Height{6}};
1180+ ms::BasicSurface surface_state{
1181+ name,
1182+ geom::Rectangle{pt, one_by_five},
1183+ false,
1184+ mock_buffer_stream,
1185+ std::shared_ptr<mi::InputChannel>(),
1186+ stub_configurator,
1187+ report};
1188+
1189+ geom::Point newPos{10,10};
1190+ surface_state.move_to(newPos);
1191+ surface_state.set_transformation(glm::eulerAngleZ(glm::radians(90.0f)));
1192+
1193+ std::vector<geom::Point> contained_pt
1194+ {
1195+ geom::Point{geom::X{9}, geom::Y{12}},geom::Point{geom::X{9}, geom::Y{13}},
1196+ geom::Point{geom::X{10}, geom::Y{12}},geom::Point{geom::X{10}, geom::Y{13}},
1197+ geom::Point{geom::X{11}, geom::Y{12}},geom::Point{geom::X{11}, geom::Y{13}},
1198+ geom::Point{geom::X{12}, geom::Y{12}},geom::Point{geom::X{12}, geom::Y{13}},
1199+ geom::Point{geom::X{13}, geom::Y{12}},geom::Point{geom::X{13}, geom::Y{13}},
1200+ geom::Point{geom::X{14}, geom::Y{12}},geom::Point{geom::X{14}, geom::Y{13}},
1201+ };
1202+
1203+ for(auto x = 7; x <= 15; x++)
1204+ {
1205+ for(auto y = 6; y <= 15; y++)
1206+ {
1207+ auto test_pt = geom::Point{x, y};
1208+ auto contains = surface_state.contains(test_pt);
1209+ if (std::find(contained_pt.begin(), contained_pt.end(), test_pt) != contained_pt.end())
1210+ {
1211+ EXPECT_TRUE(contains);
1212+ }
1213+ else
1214+ {
1215+ EXPECT_FALSE(contains);
1216+ }
1217+ }
1218+ }
1219+}
1220+
1221 TEST_F(BasicSurfaceTest, set_input_region)
1222 {
1223 std::vector<geom::Rectangle> const rectangles = {
1224@@ -411,22 +490,19 @@
1225 stub_configurator,
1226 report};
1227
1228- auto const observer = std::make_shared<ms::LegacySurfaceChangeNotification>(mock_change_cb);
1229- surface.add_observer(observer);
1230-
1231 surface.set_input_region(rectangles);
1232
1233 std::vector<geom::Point> contained_pt
1234 {
1235 //region0 points
1236- geom::Point{geom::X{0}, geom::Y{0}},
1237+ rect.top_left,
1238 //region1 points
1239- geom::Point{geom::X{1}, geom::Y{1}},
1240+ rect.top_left + geom::Displacement{1, 1}
1241 };
1242
1243- for(auto x = 0; x <= 3; x++)
1244+ for(auto x = rect.top_left.x.as_int() - 3; x <= rect.top_left.x.as_int() + 3; ++x)
1245 {
1246- for(auto y = 0; y <= 3; y++)
1247+ for(auto y = rect.top_left.y.as_int() - 3; y <= rect.top_left.y.as_int() + 3; ++y)
1248 {
1249 auto test_pt = geom::Point{x, y};
1250 auto contains = surface.contains(test_pt);

Subscribers

People subscribed via source and target branches