Merge lp:~dandrader/qtmir/coordinateTranslator into lp:qtmir

Proposed by Daniel d'Andrada
Status: Superseded
Proposed branch: lp:~dandrader/qtmir/coordinateTranslator
Merge into: lp:qtmir
Prerequisite: lp:~dandrader/qtmir/surfaceListModel
Diff against target: 704 lines (+523/-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 (+44/-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
Reviewer Review Type Date Requested Status
Unity8 CI Bot (community) continuous-integration Approve
Gerry Boland (community) Needs Fixing
Review via email: mp+291768@code.launchpad.net

This proposal has been superseded by a proposal from 2016-06-23.

Commit message

Implement mir::scene::CoordinateTranslator

Description of the change

* Are there any related MPs required for this MP to build/function as expected? Please list.
https://code.launchpad.net/~gerboland/qtubuntu/enable-debug-mode/+merge/276293

* 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

To post a comment you must log in.
Revision history for this message
Gerry Boland (gerboland) wrote :

qtmircoordinatetranslator.cpp
we don't need "qtmir" in the filename.

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
471. By Daniel d'Andrada

Logging of Qt's OpenGL debug messages now must be enabled via CMake option
Approved by: Gerry Boland

472. By Daniel d'Andrada

Application: improve debug logging

Minimize boilerplate in logging code, as well as standardise its format.
Approved by: Gerry Boland

473. By Daniel d'Andrada

Remove application screenshot provider

It's no longer needed now that QML provides a "item-snapshot" feature.

Besides, it has no purpose in a surface-based window management.
Approved by: Lukáš Tinkl, Gerry Boland

474. By Daniel d'Andrada

MirSurface: replace keymapLayout and keymapVariant with keymap

That's easier for unity8 to use, leads to declarative code.
Approved by: Lukáš Tinkl

475. By Daniel d'Andrada

Surface-based window management

- Session is no longer exported to QML. It's now an internal qtmir concept.
Approved by: Gerry Boland

476. By Michał Sawicz

Inline -gles packaging.
Approved by: Gerry Boland

477. By CI Train Bot Account

Releasing 0.4.8+16.04.20160413-0ubuntu1

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

On 13/04/2016 12:01, Gerry Boland wrote:
> qtmircoordinatetranslator.cpp
> we don't need "qtmir" in the filename.

removed the file prefix

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote :

I dislike that it is MirSurface & MirSurfaceItem's responsibility to subscribe themselves to this CoordinateTranslator. I would much prefer using the publish-subscribe model that Qt's signal/slots offer us, where MirSurface{,Item} would signal their creation, and CoordinateTranslator would operate on that.

I also dislike that CoordinateTranslator duplicates the list of MirSurfaces that SurfaceManager already has.

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 CoordinateTranslator implementation. That option strikes me as simpler, with less code in qtmir, and less cross-thread synchronisation to deal with.

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 (CoordinateTranslator::instance()) {
+ CoordinateTranslator::instance()->registerMirSurface(this, surface.get());
+ }
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 BlockingQueuedConnection afaics. Am curious why you avoided it.

review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

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 CoordinateTranslator implementation. That option strikes me as simpler, with less code in qtmir, and less cross-thread synchronisation to deal with.

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.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

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.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

On 14/04/2016 07:34, Gerry Boland wrote:
> + if (CoordinateTranslator::instance()) {
> + CoordinateTranslator::instance()->registerMirSurface(this, surface.get());
> + }
> 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.

CoordinateTranslator has no control over the creation of its instance.

It's created by MirServer here:

"""
     override_the_coordinate_translator([]
         {
             return std::make_shared<qtmir::CoordinateTranslator>();
         });
"""

CoordinateTranslator::instance() simply returns its single existing
instance, if any.

How do you conciliate the Singleton pattern you expect with the way
things get created in MirServer?

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

On 14/04/2016 07:34, Gerry Boland wrote:
> All the custom event stuff you've done is equivalent to a BlockingQueuedConnection afaics. Am curious why you avoided it.

You mean CoordinateTranslator calling QMetaObject::invokeMethod([...],
Qt::BlockingQueuedConnection , [...]) on a MirSurfaceItem? Yeah, I think
it boils down to the same indeed. So here I am reinventing the wheel.

478. By Alberto Aguirre

Mir 0.22 compatibility
Approved by: Cemil Azizoglu, Kevin DuBois, Brandon Schaefer

479. By CI Train Bot Account

Releasing 0.4.8+16.04.20160426-0ubuntu1

480. By Michael Terry

Use latest UbuntuAppLaunch API which supports libertine apps.
Approved by: Nick Dedekind

481. By Lukáš Tinkl

Regression fix: restore window title handling Fixes: #1563522
Approved by: Nick Dedekind

482. By CI Train Bot Account

Releasing 0.4.8+16.04.20160428-0ubuntu1

483. By Gerry Boland

Enhance ScreenController & the DisplayConfigurationPolicy to implement dynamic grid units.

- Rename ScreenController to ScreenModel, as it just reflects current screen state, does not offer means to configure it
- ScreenController can update state of existing Screens, based on Mir DisplayConfiguration changes.
- Expand Screen to include scale & form factor properties, with getter/notifier in NativeInterface. This enables the dynamic grid units in the shell
- Add a Unity.Screens qml module to give QML better information about connected screens, and allow basic reconfiguring.
- Implement a basic display configuration policy to set suitable scale and form factor on an external display (needed for dynamic grid units) Fixes: #1573532
Approved by: Unity8 CI Bot, Daniel d'Andrada

484. By CI Train Bot Account

Releasing 0.4.8+16.04.20160429.1-0ubuntu1

485. By Daniel d'Andrada

Session: Add a blank surface to the public list if it already has child prompt surfaces

A prompt session may come in too early, before its parent session got a chance
to draw its surface's first frame.

Normally that wouldn't be a problem and we could withhold that parent surface until
it's finally drawn to. But unfortunately the application process might be blocked,
unable to draw anything, until its child prompt session gets dismissed.

Because of that we have no option but to expose this blank surface to shell so that
it can display it along with the prompt surface on top of it, so that the user can
interact with it right away and finally unblock the application. Fixes: #1578665
Approved by: Unity8 CI Bot

486. By CI Train Bot Account

Releasing 0.4.8+16.04.20160511-0ubuntu1

487. By Daniel d'Andrada

Fix ProxySurfaceListModel::countChanged signal
Approved by: Unity8 CI Bot

488. By Daniel d'Andrada

Move prompt surfaces from MirSurface to Application and emit firstChanged signal

489. By CI Train Bot Account

Releasing 0.4.8+16.04.20160518.1-0ubuntu1

490. By Gerry Boland

UAL can throw on creating Application if invalid appId, catch instead of aborting Fixes: #1578258
Approved by: Unity8 CI Bot, Michael Terry

491. By Daniel d'Andrada

Application: Don't respawn if closed while still starting up

+ refactoring of Application::onSessionStateChanged to explicitly cover every single internal state on session stopping. Fixes: #1575577
Approved by: Gerry Boland, Unity8 CI Bot, Michael Terry

492. By Alan Griffiths

Reduce coupling to MirServer - it has been misused as a context object.
Approved by: Alan Griffiths, Unity8 CI Bot, Daniel d'Andrada

493. By Michał Sawicz

Centralize logging categories

The header part is already centralized. Make the cpp the same.

Moves all logging category symbols to the mirserver lib.

Enables mirserver to use logging categories that were previously declared in the Unity.Application module.
Approved by: Unity8 CI Bot, Michael Terry

494. By Daniel d'Andrada

Also interpret the cursor names used by Mir client API Fixes: #1447839
Approved by: Unity8 CI Bot, Michał Sawicz

495. By Timo Jyrinki

Use FindQt5PlatformSupport to find platform support, other methods not available on Qt 5.6 anymore. Fixes: #1554404
Approved by: Gerry Boland

496. By CI Train Bot Account

Releasing 0.4.8+16.10.20160520.1-0ubuntu1

497. By Daniel d'Andrada

Bump unity-api versions
Approved by: Lukáš Tinkl

498. By Alan Griffiths

Drop the (unused) prototype Window Management code
Approved by: Gerry Boland, Unity8 CI Bot

499. By Daniel d'Andrada

Fix mir::scene::Surface focus attribute updates
Approved by: Unity8 CI Bot

500. By Albert Astals Cid

Enable workaround_brokenFBOReadBack on various chipsets

Gives for impressive improvements in QSGDefaultDistanceFieldGlyphCache::storeGlyphs
impressive = 788ms -> 6ms

Copied from qtubuntu
 Fixes: #1581123
Approved by: Gerry Boland, Unity8 CI Bot

501. By Alan Griffiths

Remove workaround for lp:1502200
Approved by: Unity8 CI Bot, Daniel d'Andrada

502. By CI Train Bot Account

Releasing 0.4.8+16.10.20160525.2-0ubuntu1

503. By Kevin DuBois

rebuild for mir 0.23

504. By CI Train Bot Account

Releasing 0.4.8+16.10.20160602-0ubuntu1

505. By Michael Zanetti

Adding ApplicationInfo::surfaceCount property

506. By Albert Astals Cid

Add support for compiler sanitizers via ECM

507. By Albert Astals Cid

Compile with -fsanitize=undefined

508. By Albert Astals Cid

Fix leak in ScreensModelTest (LP: #1585502)

509. By Albert Astals Cid

Fix leak in SessionManager test (LP: #1585498)

510. By Albert Astals Cid

Remove unused m_sessions member

511. By Albert Astals Cid

Add missing breaks

512. By Albert Astals Cid

Initialize m_lastX and m_lastY

513. By Albert Astals Cid

Initialize m_sessionId

514. By Albert Astals Cid

Give the locker a name

515. By Albert Astals Cid

Fix memory leak in QtEventFeederTest (LP: #1585503)

516. By Albert Astals Cid

Fix leaks in application_manager_test (LP: #1585501)

517. By Daniel d'Andrada

Improve Session debug logging

518. By Daniel d'Andrada

MirSurfaceListModel: prepending a surface always causes firstChanged() emission

519. By Gerry Boland

Release temporary GL context ASAP, fixes QtMir on X11. Add some hotpath branching hints (LP: #1588921)

520. By CI Train Bot Account

Releasing 0.4.8+16.10.20160614-0ubuntu1

Revision history for this message
Gerry Boland (gerboland) wrote :

Please merge trunk. I'll revisit this review, as this is needed, and I can't propose a better approach currently

review: Needs Fixing
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:521
https://unity8-jenkins.ubuntu.com/job/lp-qtmir-ci/294/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/2139
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/2167
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2076
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2076
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2076
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2067
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/2067/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2067
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/2067/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2067
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/2067/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2067
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/2067/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2067
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/2067/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2067
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/2067/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2067
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/2067/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2067
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/2067/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2067
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/2067/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtmir-ci/294/rebuild

review: Approve (continuous-integration)
521. By Daniel d'Andrada

com.canonical.Unity.FocusInfo D-Bus service for providing focus information

522. By CI Train Bot Account

Releasing 0.4.8+16.10.20160704.1-0ubuntu1

523. By Michał Sawicz

Don't use root dbus path (LP: #1599145)

524. By CI Train Bot Account

Releasing 0.4.8+16.10.20160705.2-0ubuntu1

525. By Łukasz Zemczak

Build the qtmir-android package for arm64 as well.

526. By CI Train Bot Account

Releasing 0.4.8+16.10.20160712-0ubuntu1

527. By Daniel d'Andrada

Implement MirSurface::inputBounds and make use of mir's input region

This allows us to finally drop the UbuntuKeyboardInfo hack.

Approved by: Gerry Boland

528. By CI Train Bot Account

Releasing 0.4.8+16.10.20160714-0ubuntu1

529. By Timo Jyrinki

Rebuild against Qt 5.6.

530. By Nick Dedekind

Re-added occlusion detection (LP: #1475678)

Approved by: Daniel d'Andrada

531. By CI Train Bot Account

* Add support for compiler sanitizers via ECM
* Compile with -fsanitize=undefined
* Fix leak in ScreensModelTest (LP: #1585502)
* Fix leak in SessionManager test (LP: #1585498)
* Remove unused m_sessions member
* Add missing breaks
* Initialize m_lastX and m_lastY
* Initialize m_sessionId
* Give the locker a name
* Fix memory leak in QtEventFeederTest (LP: #1585503)
* Fix leaks in application_manager_test (LP: #1585501)
* Improve Session debug logging
* MirSurfaceListModel: prepending a surface always causes
  firstChanged() emission
* Adding ApplicationInfo::surfaceCount property

532. By Daniel d'Andrada

Ensure different cursor names for consecutive custom cursor changes
(LP: #1604701) (LP: #1605078) (LP: #1604701, #1605078)

Approved by: Albert Astals Cid, Unity8 CI Bot

533. By Gerry Boland

Dump core if Mir fails to start in time - dump will help us see where Mir blocked (LP: #1537389)

Approved by: Daniel van Vugt, Unity8 CI Bot

534. By Marco Trevisan (Treviño)

ScreenWindow: handle window activated when exposing it

This will ensure that there's a focused window for the rendered application
(thus we can deliver keyboard events to it) (LP: #1590060)

Approved by: Gerry Boland, Unity8 CI Bot

535. By Albert Astals Cid

Fix memory leak in application_test

Approved by: Daniel d'Andrada, Unity8 CI Bot

536. By Gerry Boland

Tests: AppManTest: use stack instead of heap when possible, better cleanup of resources

Approved by: Andreas Pokorny, Daniel d'Andrada

537. By Daniel d'Andrada

Remove com.canonical.Unity.WindowStack D-Bus service

Nobody knows of anyone using it and the code is outdated
(pre surface-based WM era), so it doesn't even work correctly.

Therefore this is effectively dead code.

Approved by: Gerry Boland

538. By Gerry Boland

AppMan: queue the onProcessStarting slot, as processStarting blocks ubuntu-app-launch from executing the process.

The ProcessStarting signal is fired by a sync dbus call from upstart via ubuntu-app-launch. It is a sync call as AppMan needs to be informed of a new process, before that process can connect through Mir and be authenticated with authoriseSession (it was async before, but we had to make it sync to fix a bug where fast starting processes would connect to Mir before upstart's signal was received).

Instead of reacting immediately in the onProcessStarted - creating the Application & emitting signals to shell (which causes animations) -all blocking upstart launching the app, it is better to push an event onto the event queue and let upstart launch the app.

Note that authoriseSession is a slot connected to with a BlockingQueuedConnection, which also creates an event and pushes it to the event queue. As this will definitely happen after the processStarted signal, we are guaranteed that the slots will be called in the correct order.

This change improves app startup times on Krillin by around 100ms.

Approved by: Daniel d'Andrada

539. By CI Train Bot Account

Releasing 0.4.8+16.10.20160730-0ubuntu1

540. By Daniel d'Andrada

Implement mir::scene::CoordinateTranslator

Unmerged revisions

540. By Daniel d'Andrada

Implement mir::scene::CoordinateTranslator

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/modules/Unity/Application/mirsurface.cpp'
2--- src/modules/Unity/Application/mirsurface.cpp 2016-05-25 13:54:52 +0000
3+++ src/modules/Unity/Application/mirsurface.cpp 2016-06-23 20:33:14 +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@@ -244,6 +245,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@@ -252,6 +257,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-05-24 20:13:10 +0000
37+++ src/modules/Unity/Application/mirsurfaceitem.cpp 2016-06-23 20:33:14 +0000
38@@ -27,6 +27,9 @@
39 // common
40 #include <debughelpers.h>
41
42+// mirserver
43+#include <coordinatetranslator.h>
44+
45 // Qt
46 #include <QDebug>
47 #include <QGuiApplication>
48@@ -641,6 +644,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@@ -649,6 +655,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@@ -735,6 +742,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@@ -746,6 +768,7 @@
89 m_surfaceWidth = value;
90 scheduleMirSurfaceSizeUpdate();
91 Q_EMIT surfaceWidthChanged(value);
92+ updateCoordinateTranslatorRegistration();
93 }
94 }
95
96@@ -765,6 +788,7 @@
97 m_surfaceHeight = value;
98 scheduleMirSurfaceSizeUpdate();
99 Q_EMIT surfaceHeightChanged(value);
100+ updateCoordinateTranslatorRegistration();
101 }
102 }
103
104@@ -781,6 +805,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-05-24 20:13:10 +0000
132+++ src/modules/Unity/Application/mirsurfaceitem.h 2016-06-23 20:33:14 +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@@ -139,6 +143,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-06-14 08:33:55 +0000
173+++ src/platforms/mirserver/CMakeLists.txt 2016-06-23 20:33:14 +0000
174@@ -80,6 +80,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-06-23 20:33:14 +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-06-23 20:33:14 +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-06-23 20:33:14 +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-06-23 20:33:14 +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-06-23 20:33:14 +0000
463@@ -0,0 +1,44 @@
464+set(
465+ COORDINATE_TRANSLATOR_TEST_SOURCES
466+ coordinatetranslator_test.cpp
467+ FakeMirSurfaceItem.cpp
468+ ${CMAKE_SOURCE_DIR}/src/common/debughelpers.cpp
469+ ${CMAKE_SOURCE_DIR}/src/modules/Unity/Application/mirsurfacelistmodel.cpp
470+# We need to run moc on these headers
471+ ${CMAKE_SOURCE_DIR}/src/modules/Unity/Application/mirsurfaceinterface.h
472+ ${CMAKE_SOURCE_DIR}/src/modules/Unity/Application/session_interface.h
473+ ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
474+ ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
475+ ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
476+ ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirFocusControllerInterface.h
477+ ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h
478+ ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceItemInterface.h
479+ ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceListInterface.h
480+# Feed the automoc monster
481+)
482+
483+include_directories(
484+ ${CMAKE_SOURCE_DIR}/src/platforms/mirserver
485+ ${CMAKE_SOURCE_DIR}/src/modules
486+ ${CMAKE_SOURCE_DIR}/src/common
487+ ${CMAKE_SOURCE_DIR}/tests/framework
488+ ${MIRSERVER_INCLUDE_DIRS}
489+)
490+
491+add_executable(QtMirCoordinateTranslatorTest ${COORDINATE_TRANSLATOR_TEST_SOURCES})
492+
493+add_dependencies(QtMirCoordinateTranslatorTest qtmir-test-framework-static)
494+
495+target_link_libraries(
496+ QtMirCoordinateTranslatorTest
497+
498+ qpa-mirserver
499+
500+ -L${CMAKE_BINARY_DIR}/tests/framework
501+ qtmir-test-framework-static
502+
503+ ${GTEST_BOTH_LIBRARIES}
504+ ${GMOCK_LIBRARIES}
505+)
506+
507+add_test(QtMirCoordinateTranslator QtMirCoordinateTranslatorTest)
508
509=== added file 'tests/mirserver/CoordinateTranslator/FakeMirSurfaceItem.cpp'
510--- tests/mirserver/CoordinateTranslator/FakeMirSurfaceItem.cpp 1970-01-01 00:00:00 +0000
511+++ tests/mirserver/CoordinateTranslator/FakeMirSurfaceItem.cpp 2016-06-23 20:33:14 +0000
512@@ -0,0 +1,40 @@
513+/*
514+ * Copyright (C) 2016 Canonical, Ltd.
515+ *
516+ * This program is free software: you can redistribute it and/or modify it under
517+ * the terms of the GNU Lesser General Public License version 3, as published by
518+ * the Free Software Foundation.
519+ *
520+ * This program is distributed in the hope that it will be useful, but WITHOUT
521+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
522+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
523+ * Lesser General Public License for more details.
524+ *
525+ * You should have received a copy of the GNU Lesser General Public License
526+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
527+ */
528+
529+#include "FakeMirSurfaceItem.h"
530+
531+// mirserver
532+#include <coordinatetranslator.h>
533+
534+using namespace qtmir;
535+
536+bool FakeMirSurfaceItem::event(QEvent *ev)
537+{
538+ if (ev->type() == PointMappingEvent::pointMappingEventType()) {
539+ processPointMappingEvent(static_cast<PointMappingEvent*>(ev));
540+ return true;
541+ } else {
542+ return QObject::event(ev);
543+ }
544+}
545+
546+void FakeMirSurfaceItem::processPointMappingEvent(PointMappingEvent* event)
547+{
548+ PointMappingQuery &query = event->query();
549+
550+ query.screenPoint = query.localPoint * 2;
551+ query.semaphore.release();
552+}
553
554=== added file 'tests/mirserver/CoordinateTranslator/FakeMirSurfaceItem.h'
555--- tests/mirserver/CoordinateTranslator/FakeMirSurfaceItem.h 1970-01-01 00:00:00 +0000
556+++ tests/mirserver/CoordinateTranslator/FakeMirSurfaceItem.h 2016-06-23 20:33:14 +0000
557@@ -0,0 +1,37 @@
558+/*
559+ * Copyright (C) 2016 Canonical, Ltd.
560+ *
561+ * This program is free software: you can redistribute it and/or modify it under
562+ * the terms of the GNU Lesser General Public License version 3, as published by
563+ * the Free Software Foundation.
564+ *
565+ * This program is distributed in the hope that it will be useful, but WITHOUT
566+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
567+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
568+ * Lesser General Public License for more details.
569+ *
570+ * You should have received a copy of the GNU Lesser General Public License
571+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
572+ */
573+
574+#ifndef FAKEMIRSURFACEITEM_H
575+#define FAKEMIRSURFACEITEM_H
576+
577+#include <QObject>
578+
579+namespace qtmir {
580+
581+class PointMappingEvent;
582+
583+class FakeMirSurfaceItem : public QObject
584+{
585+ Q_OBJECT
586+public:
587+ bool event(QEvent *e) override;
588+private:
589+ void processPointMappingEvent(PointMappingEvent* event);
590+};
591+
592+} // namespace qtmir
593+
594+#endif // FAKEMIRSURFACEITEM_H
595
596=== added file 'tests/mirserver/CoordinateTranslator/coordinatetranslator_test.cpp'
597--- tests/mirserver/CoordinateTranslator/coordinatetranslator_test.cpp 1970-01-01 00:00:00 +0000
598+++ tests/mirserver/CoordinateTranslator/coordinatetranslator_test.cpp 2016-06-23 20:33:14 +0000
599@@ -0,0 +1,105 @@
600+/*
601+ * Copyright (C) 2016 Canonical, Ltd.
602+ *
603+ * This program is free software: you can redistribute it and/or modify it under
604+ * the terms of the GNU Lesser General Public License version 3, as published by
605+ * the Free Software Foundation.
606+ *
607+ * This program is distributed in the hope that it will be useful, but WITHOUT
608+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
609+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
610+ * Lesser General Public License for more details.
611+ *
612+ * You should have received a copy of the GNU Lesser General Public License
613+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
614+ */
615+
616+#include <gtest/gtest.h>
617+
618+// mirserver
619+#include <coordinatetranslator.h>
620+
621+// tests/framework
622+#include <fake_mirsurface.h>
623+#include <mock_surface.h>
624+
625+// local
626+#include "FakeMirSurfaceItem.h"
627+
628+// Qt
629+#include <QCoreApplication>
630+#include <QMutex>
631+#include <QThread>
632+#include <QWaitCondition>
633+
634+using namespace qtmir;
635+
636+class FakeQtGuiThread : public QThread
637+{
638+ Q_OBJECT
639+
640+public:
641+ std::shared_ptr<mir::scene::MockSurface> mirSurface;
642+
643+ QMutex mutex;
644+ QWaitCondition waitCondition;
645+
646+protected:
647+ void run() override
648+ {
649+ int argc = 0;
650+ char* argv[0];
651+ QCoreApplication qtApp(argc, argv);
652+
653+ qtmir::FakeMirSurfaceItem surfaceItem;
654+ qtmir::FakeMirSurface unitySurface;
655+
656+ CoordinateTranslator::instance()->registerMirSurface(&unitySurface, mirSurface.get());
657+ CoordinateTranslator::instance()->registerMirSurfaceItem(&surfaceItem, &unitySurface);
658+
659+ // sync-point
660+ mutex.lock();
661+ mutex.unlock();
662+ waitCondition.wakeAll();
663+
664+ qtApp.exec();
665+ }
666+};
667+
668+class QtMirCoordinateTranslatorTest : public ::testing::Test
669+{
670+public:
671+ QtMirCoordinateTranslatorTest()
672+ {
673+ }
674+
675+ CoordinateTranslator coordinateTranslator;
676+};
677+
678+TEST_F(QtMirCoordinateTranslatorTest, surface_to_screen)
679+{
680+
681+ auto mirSurface = std::make_shared<mir::scene::MockSurface>();
682+
683+ FakeQtGuiThread fakeQtGuiThread;
684+ fakeQtGuiThread.mirSurface = mirSurface;
685+
686+ fakeQtGuiThread.mutex.lock();
687+ fakeQtGuiThread.start();
688+
689+ // sync-point
690+ fakeQtGuiThread.waitCondition.wait(&fakeQtGuiThread.mutex);
691+ fakeQtGuiThread.mutex.unlock();
692+
693+ // The tests's own thread acts as the Mir thread that calls surface_to_screen()
694+ mir::geometry::Point screenPoint = coordinateTranslator.surface_to_screen(mirSurface, 10, 30);
695+
696+ // FakeMirSurfaceItem will just multiply each coordinate by 2
697+ EXPECT_EQ(screenPoint.x.as_int(), 10*2);
698+ EXPECT_EQ(screenPoint.y.as_int(), 30*2);
699+
700+ QCoreApplication::instance()->quit();
701+ fakeQtGuiThread.wait();
702+}
703+
704+#include "coordinatetranslator_test.moc"

Subscribers

People subscribed via source and target branches