Merge lp:~dandrader/qtmir/coordinateTranslator into lp:qtmir
- coordinateTranslator
- Merge into trunk
Status: | Rejected |
---|---|
Rejected by: | Daniel d'Andrada |
Proposed branch: | lp:~dandrader/qtmir/coordinateTranslator |
Merge into: | lp:qtmir |
Diff against target: |
708 lines (+527/-2) 12 files modified
src/modules/Unity/Application/mirsurface.cpp (+9/-0) src/modules/Unity/Application/mirsurfaceitem.cpp (+42/-0) src/modules/Unity/Application/mirsurfaceitem.h (+8/-1) src/platforms/mirserver/CMakeLists.txt (+1/-0) src/platforms/mirserver/coordinatetranslator.cpp (+145/-0) src/platforms/mirserver/coordinatetranslator.h (+84/-0) src/platforms/mirserver/mirserver.cpp (+6/-0) tests/mirserver/CMakeLists.txt (+2/-1) tests/mirserver/CoordinateTranslator/CMakeLists.txt (+48/-0) tests/mirserver/CoordinateTranslator/FakeMirSurfaceItem.cpp (+40/-0) tests/mirserver/CoordinateTranslator/FakeMirSurfaceItem.h (+37/-0) tests/mirserver/CoordinateTranslator/coordinatetranslator_test.cpp (+105/-0) |
To merge this branch: | bzr merge lp:~dandrader/qtmir/coordinateTranslator |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel d'Andrada (community) | Disapprove | ||
MichaĆ Sawicz | Abstain | ||
Unity8 CI Bot (community) | continuous-integration | Approve | |
Gerry Boland (community) | Approve | ||
Review via email: mp+298258@code.launchpad.net |
This proposal supersedes a proposal from 2016-04-13.
Commit message
Implement mir::scene:
Description of the change
* Are there any related MPs required for this MP to build/function as expected? Please list.
https:/
* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes. I used lp:~dandrader/+junk/getScreenPointMir for that.
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
Not applicable
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal | # |
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:472
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal | # |
On 13/04/2016 12:01, Gerry Boland wrote:
> qtmircoordinate
> we don't need "qtmir" in the filename.
removed the file prefix
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:473
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:474
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal | # |
I dislike that it is MirSurface & MirSurfaceItem's responsibility to subscribe themselves to this CoordinateTrans
I also dislike that CoordinateTrans
Why did you rule out this possibility: having the MirSurfaceItem position update the position of the corresponding mir::Surface in Mir's model? If Mir's model was roughly correct, we wouldn't need to replace the default CoordinateTrans
Also, I want to avoid us just replacing parts of Mir whenever we feel like it. I'd like you to try using Mir's CoordinateTransform implementation, and if it is unworkable, we should communicate why that is to the Mir team.
+ if (CoordinateTran
+ CoordinateTrans
+ }
Why would there not be an instance returned? Having to check this every time is a pain. Singleton pattern requires instance() returns a valid object.
All the custom event stuff you've done is equivalent to a BlockingQueuedC
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal | # |
On 14/04/2016 07:34, Gerry Boland wrote:
> Why did you rule out this possibility: having the MirSurfaceItem position update the position of the corresponding mir::Surface in Mir's model? If Mir's model was roughly correct, we wouldn't need to replace the default CoordinateTrans
A QQuickItem has no knowledge of whether its transformation
(translation, rotation and scaling) relative to the root item has
changed. Nor it should as that would be pretty bad performance-wise
(imagine moving a parent would generate a deluge of signals to all the
children in its subtree). Trying to go that way would be a mistake in my
opinion.
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal | # |
On 14/04/2016 07:34, Gerry Boland wrote:
> Also, I want to avoid us just replacing parts of Mir whenever we feel like it. I'd like you to try using Mir's CoordinateTransform implementation, and if it is unworkable, we should communicate why that is to the Mir team.
Mir's default CoordinateTransform is oblivious to our QML scene and
that's why it must be replaced in qtmir. And, as explained before,
having a QQuickItem aware of changes to its scene position (so it could
update its mir model counterpart) is not feasible.
The only way to have it working the way you want (QML keeping some mir
scene model in sync with it) is to have untiy8 QML code *explicitly*
calling scene sync functions at key moments. This is error prone and
clutters QML code and could easily impact performance negatively.
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal | # |
On 14/04/2016 07:34, Gerry Boland wrote:
> + if (CoordinateTran
> + CoordinateTrans
> + }
> Why would there not be an instance returned? Having to check this every time is a pain. Singleton pattern requires instance() returns a valid object.
CoordinateTrans
It's created by MirServer here:
"""
override_
{
return std::make_
});
"""
CoordinateTrans
instance, if any.
How do you conciliate the Singleton pattern you expect with the way
things get created in MirServer?
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal | # |
On 14/04/2016 07:34, Gerry Boland wrote:
> All the custom event stuff you've done is equivalent to a BlockingQueuedC
You mean CoordinateTrans
Qt::BlockingQue
it boils down to the same indeed. So here I am reinventing the wheel.
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal | # |
Please merge trunk. I'll revisit this review, as this is needed, and I can't propose a better approach currently
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:521
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:521
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Gerry Boland (gerboland) wrote : | # |
Ok let's run with this for a while
MichaĆ Sawicz (saviq) wrote : | # |
../../framework
/«BUILDDIR»
../../framework
/«BUILDDIR»
../../framework
../../framework
../../framework
/«BUILDDIR»
/«BUILDDIR»
collect2: error: ld returned 1 exit status
tests/mirserver
make[4]: *** [tests/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:521
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 540. By Daniel d'Andrada
-
Implement mir::scene:
:CoordinateTran slator
Daniel d'Andrada (dandrader) wrote : | # |
> ../../framework
> static_
> `qtmir:
> /«BUILDDIR»
> desktop/
> to `qtmir:
> [...]
Fixed.
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:540
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
MichaĆ Sawicz (saviq) : | # |
Daniel d'Andrada (dandrader) wrote : | # |
Plan now is to go this way:
https:/
Along with https:/
Unmerged revisions
- 540. By Daniel d'Andrada
-
Implement mir::scene:
:CoordinateTran slator
Preview Diff
1 | === modified file 'src/modules/Unity/Application/mirsurface.cpp' |
2 | --- src/modules/Unity/Application/mirsurface.cpp 2016-07-30 21:17:59 +0000 |
3 | +++ src/modules/Unity/Application/mirsurface.cpp 2016-08-10 13:46:47 +0000 |
4 | @@ -23,6 +23,7 @@ |
5 | #include <debughelpers.h> |
6 | |
7 | // mirserver |
8 | +#include <coordinatetranslator.h> |
9 | #include <surfaceobserver.h> |
10 | #include "screen.h" |
11 | |
12 | @@ -245,6 +246,10 @@ |
13 | QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); |
14 | |
15 | setCloseTimer(new Timer); |
16 | + |
17 | + if (CoordinateTranslator::instance()) { |
18 | + CoordinateTranslator::instance()->registerMirSurface(this, surface.get()); |
19 | + } |
20 | } |
21 | |
22 | MirSurface::~MirSurface() |
23 | @@ -253,6 +258,10 @@ |
24 | |
25 | Q_ASSERT(m_views.isEmpty()); |
26 | |
27 | + if (CoordinateTranslator::instance()) { |
28 | + CoordinateTranslator::instance()->unregisterMirSurface(m_surface.get()); |
29 | + } |
30 | + |
31 | QMutexLocker locker(&m_mutex); |
32 | m_surface->remove_observer(m_surfaceObserver); |
33 | |
34 | |
35 | === modified file 'src/modules/Unity/Application/mirsurfaceitem.cpp' |
36 | --- src/modules/Unity/Application/mirsurfaceitem.cpp 2016-06-20 14:23:40 +0000 |
37 | +++ src/modules/Unity/Application/mirsurfaceitem.cpp 2016-08-10 13:46:47 +0000 |
38 | @@ -26,6 +26,9 @@ |
39 | // common |
40 | #include <debughelpers.h> |
41 | |
42 | +// mirserver |
43 | +#include <coordinatetranslator.h> |
44 | + |
45 | // Qt |
46 | #include <QDebug> |
47 | #include <QGuiApplication> |
48 | @@ -603,6 +606,9 @@ |
49 | |
50 | if (m_surface) { |
51 | disconnect(m_surface, nullptr, this, nullptr); |
52 | + if (CoordinateTranslator::instance()) { |
53 | + CoordinateTranslator::instance()->unregisterMirSurfaceItem(this, m_surface); |
54 | + } |
55 | m_surface->unregisterView((qintptr)this); |
56 | unsetCursor(); |
57 | } |
58 | @@ -611,6 +617,7 @@ |
59 | |
60 | if (m_surface) { |
61 | m_surface->registerView((qintptr)this); |
62 | + updateCoordinateTranslatorRegistration(); |
63 | |
64 | // When a new mir frame gets posted we notify the QML engine that this item needs redrawing, |
65 | // schedules call to updatePaintNode() from the rendering thread |
66 | @@ -697,6 +704,21 @@ |
67 | } |
68 | } |
69 | |
70 | +void MirSurfaceItem::updateCoordinateTranslatorRegistration() |
71 | +{ |
72 | + auto coordinateTranslator = CoordinateTranslator::instance(); |
73 | + |
74 | + if (!surface() || !coordinateTranslator) { |
75 | + return; |
76 | + } |
77 | + |
78 | + if (surfaceWidth() != -1 && surfaceHeight() != -1) { |
79 | + coordinateTranslator->registerMirSurfaceItem(this, surface()); |
80 | + } else { |
81 | + coordinateTranslator->unregisterMirSurfaceItem(this, surface()); |
82 | + } |
83 | +} |
84 | + |
85 | int MirSurfaceItem::surfaceWidth() const |
86 | { |
87 | return m_surfaceWidth; |
88 | @@ -708,6 +730,7 @@ |
89 | m_surfaceWidth = value; |
90 | scheduleMirSurfaceSizeUpdate(); |
91 | Q_EMIT surfaceWidthChanged(value); |
92 | + updateCoordinateTranslatorRegistration(); |
93 | } |
94 | } |
95 | |
96 | @@ -727,6 +750,7 @@ |
97 | m_surfaceHeight = value; |
98 | scheduleMirSurfaceSizeUpdate(); |
99 | Q_EMIT surfaceHeightChanged(value); |
100 | + updateCoordinateTranslatorRegistration(); |
101 | } |
102 | } |
103 | |
104 | @@ -743,6 +767,24 @@ |
105 | } |
106 | } |
107 | |
108 | +bool MirSurfaceItem::event(QEvent *ev) |
109 | +{ |
110 | + if (ev->type() == PointMappingEvent::pointMappingEventType()) { |
111 | + processPointMappingEvent(static_cast<PointMappingEvent*>(ev)); |
112 | + return true; |
113 | + } else { |
114 | + return QQuickItem::event(ev); |
115 | + } |
116 | +} |
117 | + |
118 | +void MirSurfaceItem::processPointMappingEvent(PointMappingEvent *event) |
119 | +{ |
120 | + PointMappingQuery &query = event->query(); |
121 | + |
122 | + query.screenPoint = mapToScene(query.localPoint); |
123 | + query.semaphore.release(); |
124 | +} |
125 | + |
126 | } // namespace qtmir |
127 | |
128 | #include "mirsurfaceitem.moc" |
129 | |
130 | === modified file 'src/modules/Unity/Application/mirsurfaceitem.h' |
131 | --- src/modules/Unity/Application/mirsurfaceitem.h 2016-06-20 14:23:40 +0000 |
132 | +++ src/modules/Unity/Application/mirsurfaceitem.h 2016-08-10 13:46:47 +0000 |
133 | @@ -34,6 +34,7 @@ |
134 | class MirSurfaceManager; |
135 | class QSGMirSurfaceNode; |
136 | class MirTextureProvider; |
137 | +class PointMappingEvent; |
138 | |
139 | class MirSurfaceItem : public unity::shell::application::MirSurfaceItemInterface |
140 | { |
141 | @@ -79,6 +80,10 @@ |
142 | QSGTextureProvider *textureProvider() const override; |
143 | |
144 | //////// |
145 | + // QObject |
146 | + bool event(QEvent *e) override; |
147 | + |
148 | + //////// |
149 | // own API |
150 | |
151 | // to allow easy touch event injection from tests |
152 | @@ -88,7 +93,6 @@ |
153 | const QList<QTouchEvent::TouchPoint> &touchPoints, |
154 | Qt::TouchPointStates touchPointStates); |
155 | |
156 | - |
157 | public Q_SLOTS: |
158 | // Called by QQuickWindow from the rendering thread |
159 | void invalidateSceneGraph(); |
160 | @@ -138,6 +142,9 @@ |
161 | const QList<QTouchEvent::TouchPoint> &touchPoints, |
162 | Qt::TouchPointStates touchPointStates); |
163 | |
164 | + void processPointMappingEvent(PointMappingEvent *event); |
165 | + void updateCoordinateTranslatorRegistration(); |
166 | + |
167 | MirSurfaceInterface* m_surface; |
168 | QQuickWindow* m_window; |
169 | |
170 | |
171 | === modified file 'src/platforms/mirserver/CMakeLists.txt' |
172 | --- src/platforms/mirserver/CMakeLists.txt 2016-07-15 15:09:41 +0000 |
173 | +++ src/platforms/mirserver/CMakeLists.txt 2016-08-10 13:46:47 +0000 |
174 | @@ -84,6 +84,7 @@ |
175 | clipboard.cpp |
176 | creationhints.cpp |
177 | tracepoints.c |
178 | + coordinatetranslator.cpp |
179 | # We need to run moc on these headers |
180 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h |
181 | ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirMousePointerInterface.h |
182 | |
183 | === added file 'src/platforms/mirserver/coordinatetranslator.cpp' |
184 | --- src/platforms/mirserver/coordinatetranslator.cpp 1970-01-01 00:00:00 +0000 |
185 | +++ src/platforms/mirserver/coordinatetranslator.cpp 2016-08-10 13:46:47 +0000 |
186 | @@ -0,0 +1,145 @@ |
187 | +/* |
188 | + * Copyright (C) 2016 Canonical, Ltd. |
189 | + * |
190 | + * This program is free software: you can redistribute it and/or modify it under |
191 | + * the terms of the GNU Lesser General Public License version 3, as published by |
192 | + * the Free Software Foundation. |
193 | + * |
194 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
195 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
196 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
197 | + * Lesser General Public License for more details. |
198 | + * |
199 | + * You should have received a copy of the GNU Lesser General Public License |
200 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
201 | + */ |
202 | + |
203 | +#include "coordinatetranslator.h" |
204 | + |
205 | +#include <QCoreApplication> |
206 | +#include <QDebug> |
207 | + |
208 | +using namespace qtmir; |
209 | + |
210 | +////////////////// |
211 | +// PointMappingQuery |
212 | + |
213 | +PointMappingQuery::PointMappingQuery(int32_t localPointX, int32_t localPointY) |
214 | + : localPoint(localPointX, localPointY) |
215 | +{ |
216 | +} |
217 | + |
218 | +////////////////// |
219 | +// PointMappingEvent |
220 | + |
221 | +int PointMappingEvent::m_pointMappingEventType = 0; |
222 | + |
223 | +QEvent::Type PointMappingEvent::pointMappingEventType() |
224 | +{ |
225 | + if (!m_pointMappingEventType) { |
226 | + m_pointMappingEventType = QEvent::registerEventType(); |
227 | + } |
228 | + return static_cast<QEvent::Type>(m_pointMappingEventType); |
229 | +} |
230 | + |
231 | +PointMappingEvent::PointMappingEvent(QSharedPointer<PointMappingQuery> query) |
232 | + : QEvent(pointMappingEventType()) |
233 | +{ |
234 | + m_query = query; |
235 | +} |
236 | + |
237 | +PointMappingQuery &PointMappingEvent::query() |
238 | +{ |
239 | + return *m_query.data(); |
240 | +} |
241 | + |
242 | +////////////////// |
243 | +// CoordinateTranslator |
244 | + |
245 | +CoordinateTranslator *CoordinateTranslator::m_instance = nullptr; |
246 | + |
247 | +CoordinateTranslator::CoordinateTranslator() |
248 | +{ |
249 | + Q_ASSERT(m_instance == nullptr); |
250 | + m_instance = this; |
251 | +} |
252 | + |
253 | +CoordinateTranslator::~CoordinateTranslator() |
254 | +{ |
255 | + Q_ASSERT(m_instance); |
256 | + m_instance = nullptr; |
257 | +} |
258 | + |
259 | +CoordinateTranslator *CoordinateTranslator::instance() |
260 | +{ |
261 | + return m_instance; |
262 | +} |
263 | + |
264 | +void CoordinateTranslator::registerMirSurfaceItem(QObject *item, unity::shell::application::MirSurfaceInterface* unitySurface) |
265 | +{ |
266 | + QMutexLocker mutexLocker(&m_mutex); |
267 | + m_unitySurfaceToItemHash[unitySurface] = item; |
268 | +} |
269 | + |
270 | +void CoordinateTranslator::unregisterMirSurfaceItem(QObject *item, unity::shell::application::MirSurfaceInterface* unitySurface) |
271 | +{ |
272 | + QMutexLocker mutexLocker(&m_mutex); |
273 | + if (m_unitySurfaceToItemHash.find(unitySurface) != m_unitySurfaceToItemHash.end() |
274 | + && m_unitySurfaceToItemHash[unitySurface] == item) { |
275 | + m_unitySurfaceToItemHash.remove(unitySurface); |
276 | + } |
277 | +} |
278 | + |
279 | +void CoordinateTranslator::registerMirSurface(unity::shell::application::MirSurfaceInterface *unitySurface, |
280 | + mir::frontend::Surface *mirSurface) |
281 | +{ |
282 | + QMutexLocker mutexLocker(&m_mutex); |
283 | + m_mirToUnitySurfaceHash[mirSurface] = unitySurface; |
284 | +} |
285 | + |
286 | +void CoordinateTranslator::unregisterMirSurface(mir::frontend::Surface *mirSurface) |
287 | +{ |
288 | + QMutexLocker mutexLocker(&m_mutex); |
289 | + m_mirToUnitySurfaceHash.remove(mirSurface); |
290 | +} |
291 | + |
292 | +mir::geometry::Point CoordinateTranslator::surface_to_screen(std::shared_ptr<mir::frontend::Surface> surface, |
293 | + int32_t localX, int32_t localY) |
294 | +{ |
295 | + QObject *item = nullptr; |
296 | + mir::geometry::Point screenPoint; |
297 | + |
298 | + { |
299 | + QMutexLocker mutexLocker(&m_mutex); |
300 | + |
301 | + unity::shell::application::MirSurfaceInterface *unitySurface = nullptr; |
302 | + { |
303 | + auto it = m_mirToUnitySurfaceHash.find(surface.get()); |
304 | + if (it != m_mirToUnitySurfaceHash.end()) { |
305 | + unitySurface = it.value(); |
306 | + } |
307 | + } |
308 | + |
309 | + |
310 | + if (unitySurface) { |
311 | + auto it = m_unitySurfaceToItemHash.find(unitySurface); |
312 | + if (it != m_unitySurfaceToItemHash.end()) { |
313 | + item = it.value(); |
314 | + } |
315 | + } |
316 | + } |
317 | + |
318 | + if (item) { |
319 | + QSharedPointer<PointMappingQuery> query(new PointMappingQuery(localX, localY)); |
320 | + PointMappingEvent *event = new PointMappingEvent(query); |
321 | + QCoreApplication::postEvent(item, event); |
322 | + query->semaphore.acquire(); |
323 | + |
324 | + screenPoint.x = mir::geometry::X{query->screenPoint.x()}; |
325 | + screenPoint.y = mir::geometry::Y{query->screenPoint.y()}; |
326 | + } else { |
327 | + qWarning() << "qtmir::CoordinateTranslator::mapToScreen - no MirSurfaceItem found for the given surface"; |
328 | + } |
329 | + |
330 | + return screenPoint; |
331 | +} |
332 | |
333 | === added file 'src/platforms/mirserver/coordinatetranslator.h' |
334 | --- src/platforms/mirserver/coordinatetranslator.h 1970-01-01 00:00:00 +0000 |
335 | +++ src/platforms/mirserver/coordinatetranslator.h 2016-08-10 13:46:47 +0000 |
336 | @@ -0,0 +1,84 @@ |
337 | +/* |
338 | + * Copyright (C) 2016 Canonical, Ltd. |
339 | + * |
340 | + * This program is free software: you can redistribute it and/or modify it under |
341 | + * the terms of the GNU Lesser General Public License version 3, as published by |
342 | + * the Free Software Foundation. |
343 | + * |
344 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
345 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
346 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
347 | + * Lesser General Public License for more details. |
348 | + * |
349 | + * You should have received a copy of the GNU Lesser General Public License |
350 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
351 | + */ |
352 | + |
353 | +#include <QEvent> |
354 | +#include <QMutex> |
355 | +#include <QMutexLocker> |
356 | +#include <QPointF> |
357 | +#include <QSemaphore> |
358 | +#include <QSharedPointer> |
359 | + |
360 | +#include <mir/scene/coordinate_translator.h> |
361 | + |
362 | +namespace unity { |
363 | + namespace shell { |
364 | + namespace application { |
365 | + class MirSurfaceInterface; |
366 | + } |
367 | + } |
368 | +} |
369 | + |
370 | +namespace qtmir { |
371 | + |
372 | +class PointMappingQuery { |
373 | +public: |
374 | + PointMappingQuery(int32_t localPointX, int32_t localPointY); |
375 | + QSemaphore semaphore; |
376 | + QPointF localPoint; |
377 | + QPointF screenPoint; |
378 | +}; |
379 | + |
380 | +class PointMappingEvent : public QEvent { |
381 | +public: |
382 | + static Type pointMappingEventType(); |
383 | + PointMappingEvent(QSharedPointer<PointMappingQuery> query); |
384 | + PointMappingQuery &query(); |
385 | +private: |
386 | + static int m_pointMappingEventType; |
387 | + QSharedPointer<PointMappingQuery> m_query; |
388 | +}; |
389 | + |
390 | +/* |
391 | + A mir::scene::CoordinateTranslator implementation for qtmir |
392 | + |
393 | + Acts as a bridge between mir::scene::CoordinateTranslator::surface_to_screen() and |
394 | + QQuickItem::mapToScene(). |
395 | + */ |
396 | +class CoordinateTranslator : public mir::scene::CoordinateTranslator |
397 | +{ |
398 | +public: |
399 | + CoordinateTranslator(); |
400 | + virtual ~CoordinateTranslator(); |
401 | + static CoordinateTranslator *instance(); |
402 | + |
403 | + // Called from Qt's GUI thread |
404 | + void registerMirSurfaceItem(QObject *item, unity::shell::application::MirSurfaceInterface *surface); |
405 | + void unregisterMirSurfaceItem(QObject *item, unity::shell::application::MirSurfaceInterface *surface); |
406 | + void registerMirSurface(unity::shell::application::MirSurfaceInterface *unitySurface, mir::frontend::Surface *mirSurface); |
407 | + void unregisterMirSurface(mir::frontend::Surface *mirSurface); |
408 | + |
409 | + // Called from some Mir thread |
410 | + mir::geometry::Point surface_to_screen(std::shared_ptr<mir::frontend::Surface> surface, |
411 | + int32_t x, int32_t y) override; |
412 | + |
413 | +private: |
414 | + QMutex m_mutex; |
415 | + QHash<unity::shell::application::MirSurfaceInterface*, QObject*> m_unitySurfaceToItemHash; |
416 | + QHash<mir::frontend::Surface*, unity::shell::application::MirSurfaceInterface*> m_mirToUnitySurfaceHash; |
417 | + static CoordinateTranslator *m_instance; |
418 | +}; |
419 | + |
420 | +} // namespace qtmir |
421 | |
422 | === modified file 'src/platforms/mirserver/mirserver.cpp' |
423 | --- src/platforms/mirserver/mirserver.cpp 2016-05-19 13:45:08 +0000 |
424 | +++ src/platforms/mirserver/mirserver.cpp 2016-08-10 13:46:47 +0000 |
425 | @@ -20,6 +20,7 @@ |
426 | |
427 | // local |
428 | #include "argvHelper.h" |
429 | +#include "coordinatetranslator.h" |
430 | #include "mircursorimages.h" |
431 | #include "mirdisplayconfigurationpolicy.h" |
432 | #include "mirglconfig.h" |
433 | @@ -104,6 +105,11 @@ |
434 | return std::make_shared<MirGLConfig>(); |
435 | }); |
436 | |
437 | + override_the_coordinate_translator([] |
438 | + { |
439 | + return std::make_shared<qtmir::CoordinateTranslator>(); |
440 | + }); |
441 | + |
442 | override_the_server_status_listener([] |
443 | { |
444 | return std::make_shared<MirServerStatusListener>(); |
445 | |
446 | === modified file 'tests/mirserver/CMakeLists.txt' |
447 | --- tests/mirserver/CMakeLists.txt 2016-04-13 14:25:42 +0000 |
448 | +++ tests/mirserver/CMakeLists.txt 2016-08-10 13:46:47 +0000 |
449 | @@ -1,6 +1,7 @@ |
450 | add_subdirectory(ArgvHelper) |
451 | +add_subdirectory(Clipboard) |
452 | +add_subdirectory(CoordinateTranslator) |
453 | add_subdirectory(QtEventFeeder) |
454 | -add_subdirectory(Clipboard) |
455 | add_subdirectory(Screen) |
456 | add_subdirectory(ScreensModel) |
457 | add_subdirectory(WindowManager) |
458 | |
459 | === added directory 'tests/mirserver/CoordinateTranslator' |
460 | === added file 'tests/mirserver/CoordinateTranslator/CMakeLists.txt' |
461 | --- tests/mirserver/CoordinateTranslator/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
462 | +++ tests/mirserver/CoordinateTranslator/CMakeLists.txt 2016-08-10 13:46:47 +0000 |
463 | @@ -0,0 +1,48 @@ |
464 | +set( |
465 | + COORDINATE_TRANSLATOR_TEST_SOURCES |
466 | + coordinatetranslator_test.cpp |
467 | + FakeMirSurfaceItem.cpp |
468 | + ${CMAKE_SOURCE_DIR}/src/common/debughelpers.cpp |
469 | +# We need to run moc on these headers |
470 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h |
471 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h |
472 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h |
473 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirFocusControllerInterface.h |
474 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h |
475 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceItemInterface.h |
476 | + ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceListInterface.h |
477 | +# Feed the automoc monster |
478 | + ${CMAKE_SOURCE_DIR}/src/modules/Unity/Application/session_interface.h |
479 | + ${CMAKE_SOURCE_DIR}/src/modules/Unity/Application/applicationinfo.h |
480 | + ${CMAKE_SOURCE_DIR}/src/modules/Unity/Application/taskcontroller.h |
481 | + ${CMAKE_SOURCE_DIR}/src/modules/Unity/Application/settings_interface.h |
482 | + ${CMAKE_SOURCE_DIR}/src/modules/Unity/Application/mirsurfaceinterface.h |
483 | + ${CMAKE_SOURCE_DIR}/src/modules/Unity/Application/mirsurfacelistmodel.h |
484 | +) |
485 | + |
486 | +include_directories( |
487 | + ${CMAKE_SOURCE_DIR}/src/platforms/mirserver |
488 | + ${CMAKE_SOURCE_DIR}/src/modules |
489 | + ${CMAKE_SOURCE_DIR}/src/common |
490 | + ${CMAKE_SOURCE_DIR}/tests/framework |
491 | + ${MIRSERVER_INCLUDE_DIRS} |
492 | +) |
493 | + |
494 | +add_executable(QtMirCoordinateTranslatorTest ${COORDINATE_TRANSLATOR_TEST_SOURCES}) |
495 | + |
496 | +add_dependencies(QtMirCoordinateTranslatorTest qtmir-test-framework-static) |
497 | + |
498 | +target_link_libraries( |
499 | + QtMirCoordinateTranslatorTest |
500 | + |
501 | + qpa-mirserver |
502 | + unityapplicationplugin |
503 | + |
504 | + -L${CMAKE_BINARY_DIR}/tests/framework |
505 | + qtmir-test-framework-static |
506 | + |
507 | + ${GTEST_BOTH_LIBRARIES} |
508 | + ${GMOCK_LIBRARIES} |
509 | +) |
510 | + |
511 | +add_test(QtMirCoordinateTranslator QtMirCoordinateTranslatorTest) |
512 | |
513 | === added file 'tests/mirserver/CoordinateTranslator/FakeMirSurfaceItem.cpp' |
514 | --- tests/mirserver/CoordinateTranslator/FakeMirSurfaceItem.cpp 1970-01-01 00:00:00 +0000 |
515 | +++ tests/mirserver/CoordinateTranslator/FakeMirSurfaceItem.cpp 2016-08-10 13:46:47 +0000 |
516 | @@ -0,0 +1,40 @@ |
517 | +/* |
518 | + * Copyright (C) 2016 Canonical, Ltd. |
519 | + * |
520 | + * This program is free software: you can redistribute it and/or modify it under |
521 | + * the terms of the GNU Lesser General Public License version 3, as published by |
522 | + * the Free Software Foundation. |
523 | + * |
524 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
525 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
526 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
527 | + * Lesser General Public License for more details. |
528 | + * |
529 | + * You should have received a copy of the GNU Lesser General Public License |
530 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
531 | + */ |
532 | + |
533 | +#include "FakeMirSurfaceItem.h" |
534 | + |
535 | +// mirserver |
536 | +#include <coordinatetranslator.h> |
537 | + |
538 | +using namespace qtmir; |
539 | + |
540 | +bool FakeMirSurfaceItem::event(QEvent *ev) |
541 | +{ |
542 | + if (ev->type() == PointMappingEvent::pointMappingEventType()) { |
543 | + processPointMappingEvent(static_cast<PointMappingEvent*>(ev)); |
544 | + return true; |
545 | + } else { |
546 | + return QObject::event(ev); |
547 | + } |
548 | +} |
549 | + |
550 | +void FakeMirSurfaceItem::processPointMappingEvent(PointMappingEvent* event) |
551 | +{ |
552 | + PointMappingQuery &query = event->query(); |
553 | + |
554 | + query.screenPoint = query.localPoint * 2; |
555 | + query.semaphore.release(); |
556 | +} |
557 | |
558 | === added file 'tests/mirserver/CoordinateTranslator/FakeMirSurfaceItem.h' |
559 | --- tests/mirserver/CoordinateTranslator/FakeMirSurfaceItem.h 1970-01-01 00:00:00 +0000 |
560 | +++ tests/mirserver/CoordinateTranslator/FakeMirSurfaceItem.h 2016-08-10 13:46:47 +0000 |
561 | @@ -0,0 +1,37 @@ |
562 | +/* |
563 | + * Copyright (C) 2016 Canonical, Ltd. |
564 | + * |
565 | + * This program is free software: you can redistribute it and/or modify it under |
566 | + * the terms of the GNU Lesser General Public License version 3, as published by |
567 | + * the Free Software Foundation. |
568 | + * |
569 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
570 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
571 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
572 | + * Lesser General Public License for more details. |
573 | + * |
574 | + * You should have received a copy of the GNU Lesser General Public License |
575 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
576 | + */ |
577 | + |
578 | +#ifndef FAKEMIRSURFACEITEM_H |
579 | +#define FAKEMIRSURFACEITEM_H |
580 | + |
581 | +#include <QObject> |
582 | + |
583 | +namespace qtmir { |
584 | + |
585 | +class PointMappingEvent; |
586 | + |
587 | +class FakeMirSurfaceItem : public QObject |
588 | +{ |
589 | + Q_OBJECT |
590 | +public: |
591 | + bool event(QEvent *e) override; |
592 | +private: |
593 | + void processPointMappingEvent(PointMappingEvent* event); |
594 | +}; |
595 | + |
596 | +} // namespace qtmir |
597 | + |
598 | +#endif // FAKEMIRSURFACEITEM_H |
599 | |
600 | === added file 'tests/mirserver/CoordinateTranslator/coordinatetranslator_test.cpp' |
601 | --- tests/mirserver/CoordinateTranslator/coordinatetranslator_test.cpp 1970-01-01 00:00:00 +0000 |
602 | +++ tests/mirserver/CoordinateTranslator/coordinatetranslator_test.cpp 2016-08-10 13:46:47 +0000 |
603 | @@ -0,0 +1,105 @@ |
604 | +/* |
605 | + * Copyright (C) 2016 Canonical, Ltd. |
606 | + * |
607 | + * This program is free software: you can redistribute it and/or modify it under |
608 | + * the terms of the GNU Lesser General Public License version 3, as published by |
609 | + * the Free Software Foundation. |
610 | + * |
611 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
612 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
613 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
614 | + * Lesser General Public License for more details. |
615 | + * |
616 | + * You should have received a copy of the GNU Lesser General Public License |
617 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
618 | + */ |
619 | + |
620 | +#include <gtest/gtest.h> |
621 | + |
622 | +// mirserver |
623 | +#include <coordinatetranslator.h> |
624 | + |
625 | +// tests/framework |
626 | +#include <fake_mirsurface.h> |
627 | +#include <mock_surface.h> |
628 | + |
629 | +// local |
630 | +#include "FakeMirSurfaceItem.h" |
631 | + |
632 | +// Qt |
633 | +#include <QCoreApplication> |
634 | +#include <QMutex> |
635 | +#include <QThread> |
636 | +#include <QWaitCondition> |
637 | + |
638 | +using namespace qtmir; |
639 | + |
640 | +class FakeQtGuiThread : public QThread |
641 | +{ |
642 | + Q_OBJECT |
643 | + |
644 | +public: |
645 | + std::shared_ptr<mir::scene::MockSurface> mirSurface; |
646 | + |
647 | + QMutex mutex; |
648 | + QWaitCondition waitCondition; |
649 | + |
650 | +protected: |
651 | + void run() override |
652 | + { |
653 | + int argc = 0; |
654 | + char* argv[0]; |
655 | + QCoreApplication qtApp(argc, argv); |
656 | + |
657 | + qtmir::FakeMirSurfaceItem surfaceItem; |
658 | + qtmir::FakeMirSurface unitySurface; |
659 | + |
660 | + CoordinateTranslator::instance()->registerMirSurface(&unitySurface, mirSurface.get()); |
661 | + CoordinateTranslator::instance()->registerMirSurfaceItem(&surfaceItem, &unitySurface); |
662 | + |
663 | + // sync-point |
664 | + mutex.lock(); |
665 | + mutex.unlock(); |
666 | + waitCondition.wakeAll(); |
667 | + |
668 | + qtApp.exec(); |
669 | + } |
670 | +}; |
671 | + |
672 | +class QtMirCoordinateTranslatorTest : public ::testing::Test |
673 | +{ |
674 | +public: |
675 | + QtMirCoordinateTranslatorTest() |
676 | + { |
677 | + } |
678 | + |
679 | + CoordinateTranslator coordinateTranslator; |
680 | +}; |
681 | + |
682 | +TEST_F(QtMirCoordinateTranslatorTest, surface_to_screen) |
683 | +{ |
684 | + |
685 | + auto mirSurface = std::make_shared<mir::scene::MockSurface>(); |
686 | + |
687 | + FakeQtGuiThread fakeQtGuiThread; |
688 | + fakeQtGuiThread.mirSurface = mirSurface; |
689 | + |
690 | + fakeQtGuiThread.mutex.lock(); |
691 | + fakeQtGuiThread.start(); |
692 | + |
693 | + // sync-point |
694 | + fakeQtGuiThread.waitCondition.wait(&fakeQtGuiThread.mutex); |
695 | + fakeQtGuiThread.mutex.unlock(); |
696 | + |
697 | + // The tests's own thread acts as the Mir thread that calls surface_to_screen() |
698 | + mir::geometry::Point screenPoint = coordinateTranslator.surface_to_screen(mirSurface, 10, 30); |
699 | + |
700 | + // FakeMirSurfaceItem will just multiply each coordinate by 2 |
701 | + EXPECT_EQ(screenPoint.x.as_int(), 10*2); |
702 | + EXPECT_EQ(screenPoint.y.as_int(), 30*2); |
703 | + |
704 | + QCoreApplication::instance()->quit(); |
705 | + fakeQtGuiThread.wait(); |
706 | +} |
707 | + |
708 | +#include "coordinatetranslator_test.moc" |
qtmircoordinate translator. cpp
we don't need "qtmir" in the filename.