Status: | Work in progress |
---|---|
Proposed branch: | lp:~unity-team/qtmir/dpr |
Merge into: | lp:qtmir |
Diff against target: |
722 lines (+187/-116) (has conflicts) 14 files modified
debian/changelog (+9/-0) src/modules/Unity/Application/mirsurface.cpp (+63/-61) src/modules/Unity/Application/mirsurface.h (+8/-8) src/modules/Unity/Application/mirsurfaceinterface.h (+8/-8) src/modules/Unity/Application/mirsurfaceitem.cpp (+36/-16) src/modules/Unity/Application/mirsurfaceitem.h (+1/-0) src/platforms/mirserver/qteventfeeder.cpp (+13/-6) src/platforms/mirserver/qteventfeeder.h (+1/-0) src/platforms/mirserver/screen.cpp (+26/-5) src/platforms/mirserver/screen.h (+5/-2) src/platforms/mirserver/screencontroller.cpp (+2/-2) src/platforms/mirserver/screenwindow.cpp (+5/-0) src/platforms/mirserver/screenwindow.h (+2/-0) tests/modules/common/fake_mirsurface.h (+8/-8) Text conflict in debian/changelog |
To merge this branch: | bzr merge lp:~unity-team/qtmir/dpr |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity8 CI Bot (community) | continuous-integration | Needs Fixing | |
Daniel d'Andrada (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Review via email: mp+257514@code.launchpad.net |
Commit message
Add device pixel ratio support
Description of the change
* Are there any related MPs required for this MP to build/function as expected? Please list.
Nothing depends on this directly, but to do a full test, you'll need:
https:/
* Did you perform an exploratory manual test run of your code change and any related functionality?
Y
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:326
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Gerry Boland (gerboland) wrote : | # |
* Are there any related MPs required for this MP to build/function as expected? Please list.
Nothing depends on this directly, but to do a full test, you'll need:
https:/
https:/
https:/
* Did you perform an exploratory manual test run of your code change and any related functionality?
Y
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:326
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Daniel d'Andrada (dandrader) wrote : | # |
In src/modules/
"""
- int qmlWidth = (int)width();
- int qmlHeight = (int)height();
+ const qreal dpr = devicePixelRatio();
+ int qmlWidth = (int)width() * dpr;
+ int qmlHeight = (int)height() * dpr;
"""
Now they're no longer representing the qml width and height, thus the naming is misleading.
Better calling them something like newMirWidth and newMirHeight.
Also it would be more correct to cast to int *after* the dpr multiplication: (int)(width() * dpr)
Daniel d'Andrada (dandrader) wrote : | # |
In src/modules/
"""
- mir::geometry::Size newMirSize(
+ mir::geometry::Size newMirSize(
- setImplicitSize
+ setImplicitSize
}
}
"""
The implicit size should not be scaled.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:330
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:331
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:333
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:334
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:335
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:336
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:337
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:338
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Daniel d'Andrada (dandrader) wrote : | # |
The debian/changelog entry is misplaced. Likely the result of a bad merge with trunk.
Daniel d'Andrada (dandrader) wrote : | # |
The only way I see of saving MirSurface from knowing about DPR is passing it the event data directly as parameters instead of giving it the whole QEvent.
Eg:
MirSurface:
Would be:
MirSurface:
Which is actually not a bad thing.
Gerry Boland (gerboland) wrote : | # |
> The only way I see of saving MirSurface from knowing about DPR is passing it
> the event data directly as parameters instead of giving it the whole QEvent.
>
> Eg:
>
> MirSurface:
>
> Would be:
>
> MirSurface:
> Qt::KeyboardMod
>
> Which is actually not a bad thing.
For touch events too?
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:340
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Daniel d'Andrada (dandrader) wrote : | # |
On 18/09/15 08:44, Gerry Boland wrote:
>> The only way I see of saving MirSurface from knowing about DPR is passing it
>> the event data directly as parameters instead of giving it the whole QEvent.
>>
>> Eg:
>>
>> MirSurface:
>>
>> Would be:
>>
>> MirSurface:
>> Qt::KeyboardMod
>>
>> Which is actually not a bad thing.
> For touch events too?
You'll have to to copy the QList<QTouchEve
you can transform the points. Is that what you're afraid of (performance
hit)?
Gerry Boland (gerboland) wrote : | # |
> On 18/09/15 08:44, Gerry Boland wrote:
> >> The only way I see of saving MirSurface from knowing about DPR is passing
> it
> >> the event data directly as parameters instead of giving it the whole
> QEvent.
> >>
> >> Eg:
> >>
> >> MirSurface:
> >>
> >> Would be:
> >>
> >> MirSurface:
> >> Qt::KeyboardMod
> >>
> >> Which is actually not a bad thing.
> > For touch events too?
>
> You'll have to to copy the QList<QTouchEve
> you can transform the points. Is that what you're afraid of (performance
> hit)?
Well more generally, it seems to be so much work just for a multiplication. Is why I'm hesitating.
Daniel d'Andrada (dandrader) wrote : | # |
In mirsurfaceitem.cpp:
"""
m_lastTouchEven
"""
????
Daniel d'Andrada (dandrader) wrote : | # |
In mirsurfceitem.cpp:
"""
Note: all geometry is in device-pixels, except that contained in variables with the
"""
s/device-
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:341
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Daniel d'Andrada (dandrader) wrote : | # |
"""
const float kP = mir_touch_
"""
Not sure if the pressure axis has any relationship with x & y dimensions to deserve the dpr conversion.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:343
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Daniel d'Andrada (dandrader) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:344
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:345
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:347
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:348
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:350
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:351
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:352
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:354
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:355
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Daniel d'Andrada (dandrader) wrote : | # |
In MirSurfaceItem:
Daniel d'Andrada (dandrader) wrote : | # |
Still in MirSurfaceItem:
"""
qreal u = targetRect.width() / textureSize.width() * dpr;
"""
Would be better expressed as:
"""
qreal u = (targetRect.width() * dpr) / textureSize.
"""
To make it obvious that your're converting targetRect.width() from DIP (or layout pixels) to actual/physical pixels, which is the unit of textureSize.
Likewise for the v coordinate.
Daniel d'Andrada (dandrader) wrote : | # |
In src/platforms/
"""
qreal getDevicePixelR
{
return qGuiApp-
}
"""
Qt coding style doesn't use the "get" prefix for getters. I think we should stick to it unless there's a good reason to deviate.
Daniel d'Andrada (dandrader) wrote : | # |
In QtEventFeeder:
"""
auto movement = QPointF(
"""
I think you meant:
"""
auto movement = QPointF(
"""
Daniel d'Andrada (dandrader) wrote : | # |
Nitpick in Screen::Screen
"""
bool ok;
const int dpr = qGetEnvIntValue
m_devicePix
"""
You would be better off moving this whole snippet into a separate function instead of just the qGetEnvIntValue part (as it's used only once anyway). That would spare the constructor namespace from getting polluted with those helper variables ok and dpr.
PS: That's what happens when you re-review something. You start to nitpick :)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:358
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Gerry Boland (gerboland) wrote : | # |
I can merge this into trunk just fine. LP confused?
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:360
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:360
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Daniel d'Andrada (dandrader) wrote : | # |
Code looks fine. Didn't test yet.
Daniel d'Andrada (dandrader) wrote : | # |
And works fine as well.
Michał Sawicz (saviq) wrote : | # |
Text conflict in debian/changelog
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:360
https:/
Executed test runs:
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Michał Sawicz (saviq) wrote : | # |
Text conflict in src/modules/
Text conflict in src/platforms/
Text conflict in tests/framework
3 conflicts encountered.
Gerry Boland (gerboland) wrote : | # |
Marking WIP, needs rebasing on top of DGU work
Unmerged revisions
- 360. By Gerry Boland
-
Move DPR env var reading into dedicated function
- 359. By Gerry Boland
-
Typo in DPR calculation
- 358. By Gerry Boland
-
getDevicePixelRatio -> devicePixelRatio
- 357. By Gerry Boland
-
MirSurfaceItem:
:updatePaintNod e - move calculation around to clarify intention - 356. By Gerry Boland
-
MirSurfaceItem:
:updatePaintNod e Move dpr inside block where it is used - 355. By Gerry Boland
-
Merge trunk
- 354. By Gerry Boland
-
Fix scaling to render app surface correctly
- 353. By Gerry Boland
-
Add units to debug message
- 352. By Gerry Boland
-
Merge trunk
- 351. By Gerry Boland
-
Merge trunk
Preview Diff
1 | === modified file 'debian/changelog' | |||
2 | --- debian/changelog 2016-01-04 09:38:12 +0000 | |||
3 | +++ debian/changelog 2016-01-07 17:03:26 +0000 | |||
4 | @@ -1,3 +1,4 @@ | |||
5 | 1 | <<<<<<< TREE | ||
6 | 1 | qtmir (0.4.7+16.04.20160104-0ubuntu1) xenial; urgency=medium | 2 | qtmir (0.4.7+16.04.20160104-0ubuntu1) xenial; urgency=medium |
7 | 2 | 3 | ||
8 | 3 | [ Daniel d'Andrada ] | 4 | [ Daniel d'Andrada ] |
9 | @@ -6,6 +7,14 @@ | |||
10 | 6 | 7 | ||
11 | 7 | -- Michał Sawicz <michal.sawicz@canonical.com> Mon, 04 Jan 2016 09:38:12 +0000 | 8 | -- Michał Sawicz <michal.sawicz@canonical.com> Mon, 04 Jan 2016 09:38:12 +0000 |
12 | 8 | 9 | ||
13 | 10 | ======= | ||
14 | 11 | qtmir (0.4.8) UNRELEASED; urgency=medium | ||
15 | 12 | |||
16 | 13 | * Add support for devicePixelRatio, the Qt5.4 UI scaling system | ||
17 | 14 | |||
18 | 15 | -- Gerry Boland <gerry.boland@canonical.com> Mon, 04 Jan 2016 12:30:00 +0100 | ||
19 | 16 | |||
20 | 17 | >>>>>>> MERGE-SOURCE | ||
21 | 9 | qtmir (0.4.7+16.04.20151222-0ubuntu1) xenial; urgency=medium | 18 | qtmir (0.4.7+16.04.20151222-0ubuntu1) xenial; urgency=medium |
22 | 10 | 19 | ||
23 | 11 | * No-change rebuild to get -gles in sync | 20 | * No-change rebuild to get -gles in sync |
24 | 12 | 21 | ||
25 | === modified file 'src/modules/Unity/Application/mirsurface.cpp' | |||
26 | --- src/modules/Unity/Application/mirsurface.cpp 2015-12-10 13:08:43 +0000 | |||
27 | +++ src/modules/Unity/Application/mirsurface.cpp 2016-01-07 17:03:26 +0000 | |||
28 | @@ -73,34 +73,34 @@ | |||
29 | 73 | return result; | 73 | return result; |
30 | 74 | } | 74 | } |
31 | 75 | 75 | ||
33 | 76 | mir::EventUPtr makeMirEvent(QMouseEvent *qtEvent, MirPointerAction action) | 76 | mir::EventUPtr makeMirEvent(QMouseEvent *qtEvent, MirPointerAction action, qreal dpr) |
34 | 77 | { | 77 | { |
35 | 78 | auto timestamp = uncompressTimestamp<qtmir::Timestamp>(qtmir::Timestamp(qtEvent->timestamp())); | 78 | auto timestamp = uncompressTimestamp<qtmir::Timestamp>(qtmir::Timestamp(qtEvent->timestamp())); |
36 | 79 | auto modifiers = getMirModifiersFromQt(qtEvent->modifiers()); | 79 | auto modifiers = getMirModifiersFromQt(qtEvent->modifiers()); |
37 | 80 | auto buttons = getMirButtonsFromQt(qtEvent->buttons()); | 80 | auto buttons = getMirButtonsFromQt(qtEvent->buttons()); |
38 | 81 | 81 | ||
39 | 82 | return mir::events::make_event(0 /*DeviceID */, timestamp, 0 /* mac */, modifiers, action, | 82 | return mir::events::make_event(0 /*DeviceID */, timestamp, 0 /* mac */, modifiers, action, |
41 | 83 | buttons, qtEvent->x(), qtEvent->y(), 0, 0, 0, 0); | 83 | buttons, qtEvent->x() * dpr, qtEvent->y() * dpr, 0, 0, 0, 0); |
42 | 84 | } | 84 | } |
43 | 85 | 85 | ||
45 | 86 | mir::EventUPtr makeMirEvent(QHoverEvent *qtEvent, MirPointerAction action) | 86 | mir::EventUPtr makeMirEvent(QHoverEvent *qtEvent, MirPointerAction action, qreal dpr) |
46 | 87 | { | 87 | { |
47 | 88 | auto timestamp = uncompressTimestamp<qtmir::Timestamp>(qtmir::Timestamp(qtEvent->timestamp())); | 88 | auto timestamp = uncompressTimestamp<qtmir::Timestamp>(qtmir::Timestamp(qtEvent->timestamp())); |
48 | 89 | 89 | ||
49 | 90 | MirPointerButtons buttons = 0; | 90 | MirPointerButtons buttons = 0; |
50 | 91 | 91 | ||
51 | 92 | return mir::events::make_event(0 /*DeviceID */, timestamp, 0 /* mac */, mir_input_event_modifier_none, action, | 92 | return mir::events::make_event(0 /*DeviceID */, timestamp, 0 /* mac */, mir_input_event_modifier_none, action, |
53 | 93 | buttons, qtEvent->posF().x(), qtEvent->posF().y(), 0, 0, 0, 0); | 93 | buttons, qtEvent->posF().x() * dpr, qtEvent->posF().y() * dpr, 0, 0, 0, 0); |
54 | 94 | } | 94 | } |
55 | 95 | 95 | ||
57 | 96 | mir::EventUPtr makeMirEvent(QWheelEvent *qtEvent) | 96 | mir::EventUPtr makeMirEvent(QWheelEvent *qtEvent, qreal dpr) |
58 | 97 | { | 97 | { |
59 | 98 | auto timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::milliseconds(qtEvent->timestamp())); | 98 | auto timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::milliseconds(qtEvent->timestamp())); |
60 | 99 | auto modifiers = getMirModifiersFromQt(qtEvent->modifiers()); | 99 | auto modifiers = getMirModifiersFromQt(qtEvent->modifiers()); |
61 | 100 | auto buttons = getMirButtonsFromQt(qtEvent->buttons()); | 100 | auto buttons = getMirButtonsFromQt(qtEvent->buttons()); |
62 | 101 | 101 | ||
63 | 102 | return mir::events::make_event(0 /*DeviceID */, timestamp, 0 /* mac */, modifiers, mir_pointer_action_motion, | 102 | return mir::events::make_event(0 /*DeviceID */, timestamp, 0 /* mac */, modifiers, mir_pointer_action_motion, |
65 | 103 | buttons, qtEvent->x(), qtEvent->y(), | 103 | buttons, qtEvent->x() * dpr, qtEvent->y() * dpr, |
66 | 104 | qtEvent->angleDelta().x(), qtEvent->angleDelta().y(), | 104 | qtEvent->angleDelta().x(), qtEvent->angleDelta().y(), |
67 | 105 | 0, 0); | 105 | 0, 0); |
68 | 106 | } | 106 | } |
69 | @@ -131,7 +131,8 @@ | |||
70 | 131 | mir::EventUPtr makeMirEvent(Qt::KeyboardModifiers qmods, | 131 | mir::EventUPtr makeMirEvent(Qt::KeyboardModifiers qmods, |
71 | 132 | const QList<QTouchEvent::TouchPoint> &qtTouchPoints, | 132 | const QList<QTouchEvent::TouchPoint> &qtTouchPoints, |
72 | 133 | Qt::TouchPointStates /* qtTouchPointStates */, | 133 | Qt::TouchPointStates /* qtTouchPointStates */, |
74 | 134 | ulong qtTimestamp) | 134 | ulong qtTimestamp, |
75 | 135 | qreal dpr) | ||
76 | 135 | { | 136 | { |
77 | 136 | auto modifiers = getMirModifiersFromQt(qmods); | 137 | auto modifiers = getMirModifiersFromQt(qmods); |
78 | 137 | auto ev = mir::events::make_event(0, uncompressTimestamp<qtmir::Timestamp>(qtmir::Timestamp(qtTimestamp)), | 138 | auto ev = mir::events::make_event(0, uncompressTimestamp<qtmir::Timestamp>(qtmir::Timestamp(qtTimestamp)), |
79 | @@ -156,10 +157,10 @@ | |||
80 | 156 | tooltype = mir_touch_tooltype_stylus; | 157 | tooltype = mir_touch_tooltype_stylus; |
81 | 157 | 158 | ||
82 | 158 | mir::events::add_touch(*ev, id, action, tooltype, | 159 | mir::events::add_touch(*ev, id, action, tooltype, |
84 | 159 | touchPoint.pos().x(), touchPoint.pos().y(), | 160 | touchPoint.pos().x() * dpr, touchPoint.pos().y() * dpr, |
85 | 160 | touchPoint.pressure(), | 161 | touchPoint.pressure(), |
88 | 161 | touchPoint.rect().width(), | 162 | touchPoint.rect().width() * dpr, |
89 | 162 | touchPoint.rect().height(), | 163 | touchPoint.rect().height() * dpr, |
90 | 163 | 0 /* size */); | 164 | 0 /* size */); |
91 | 164 | } | 165 | } |
92 | 165 | 166 | ||
93 | @@ -429,16 +430,16 @@ | |||
94 | 429 | 430 | ||
95 | 430 | void MirSurface::resize(int width, int height) | 431 | void MirSurface::resize(int width, int height) |
96 | 431 | { | 432 | { |
99 | 432 | int mirWidth = m_surface->size().width.as_int(); | 433 | const int mirWidth = m_surface->size().width.as_int(); |
100 | 433 | int mirHeight = m_surface->size().height.as_int(); | 434 | const int mirHeight = m_surface->size().height.as_int(); |
101 | 434 | 435 | ||
102 | 435 | bool mirSizeIsDifferent = width != mirWidth || height != mirHeight; | 436 | bool mirSizeIsDifferent = width != mirWidth || height != mirHeight; |
103 | 436 | 437 | ||
104 | 437 | if (clientIsRunning() && mirSizeIsDifferent) { | 438 | if (clientIsRunning() && mirSizeIsDifferent) { |
105 | 438 | mir::geometry::Size newMirSize(width, height); | 439 | mir::geometry::Size newMirSize(width, height); |
106 | 439 | m_surface->resize(newMirSize); | 440 | m_surface->resize(newMirSize); |
109 | 440 | DEBUG_MSG << " old (" << mirWidth << "," << mirHeight << ")" | 441 | DEBUG_MSG << " old (" << mirWidth << "," << mirHeight << ")px" |
110 | 441 | << ", new (" << width << "," << height << ")"; | 442 | << ", new (" << width << "," << height << ")px"; |
111 | 442 | } | 443 | } |
112 | 443 | } | 444 | } |
113 | 444 | 445 | ||
114 | @@ -576,51 +577,51 @@ | |||
115 | 576 | return m_surface->query(mir_surface_attrib_visibility) == mir_surface_visibility_exposed; | 577 | return m_surface->query(mir_surface_attrib_visibility) == mir_surface_visibility_exposed; |
116 | 577 | } | 578 | } |
117 | 578 | 579 | ||
163 | 579 | void MirSurface::mousePressEvent(QMouseEvent *event) | 580 | void MirSurface::mousePressEvent(QMouseEvent *event, qreal dpr) |
164 | 580 | { | 581 | { |
165 | 581 | auto ev = makeMirEvent(event, mir_pointer_action_button_down); | 582 | auto ev = makeMirEvent(event, mir_pointer_action_button_down, dpr); |
166 | 582 | m_surface->consume(*ev); | 583 | m_surface->consume(*ev); |
167 | 583 | event->accept(); | 584 | event->accept(); |
168 | 584 | } | 585 | } |
169 | 585 | 586 | ||
170 | 586 | void MirSurface::mouseMoveEvent(QMouseEvent *event) | 587 | void MirSurface::mouseMoveEvent(QMouseEvent *event, qreal dpr) |
171 | 587 | { | 588 | { |
172 | 588 | auto ev = makeMirEvent(event, mir_pointer_action_motion); | 589 | auto ev = makeMirEvent(event, mir_pointer_action_motion, dpr); |
173 | 589 | m_surface->consume(*ev); | 590 | m_surface->consume(*ev); |
174 | 590 | event->accept(); | 591 | event->accept(); |
175 | 591 | } | 592 | } |
176 | 592 | 593 | ||
177 | 593 | void MirSurface::mouseReleaseEvent(QMouseEvent *event) | 594 | void MirSurface::mouseReleaseEvent(QMouseEvent *event, qreal dpr) |
178 | 594 | { | 595 | { |
179 | 595 | auto ev = makeMirEvent(event, mir_pointer_action_button_up); | 596 | auto ev = makeMirEvent(event, mir_pointer_action_button_up, dpr); |
180 | 596 | m_surface->consume(*ev); | 597 | m_surface->consume(*ev); |
181 | 597 | event->accept(); | 598 | event->accept(); |
182 | 598 | } | 599 | } |
183 | 599 | 600 | ||
184 | 600 | void MirSurface::hoverEnterEvent(QHoverEvent *event) | 601 | void MirSurface::hoverEnterEvent(QHoverEvent *event, qreal dpr) |
185 | 601 | { | 602 | { |
186 | 602 | auto ev = makeMirEvent(event, mir_pointer_action_enter); | 603 | auto ev = makeMirEvent(event, mir_pointer_action_enter, dpr); |
187 | 603 | m_surface->consume(*ev); | 604 | m_surface->consume(*ev); |
188 | 604 | event->accept(); | 605 | event->accept(); |
189 | 605 | } | 606 | } |
190 | 606 | 607 | ||
191 | 607 | void MirSurface::hoverLeaveEvent(QHoverEvent *event) | 608 | void MirSurface::hoverLeaveEvent(QHoverEvent *event, qreal dpr) |
192 | 608 | { | 609 | { |
193 | 609 | auto ev = makeMirEvent(event, mir_pointer_action_leave); | 610 | auto ev = makeMirEvent(event, mir_pointer_action_leave, dpr); |
194 | 610 | m_surface->consume(*ev); | 611 | m_surface->consume(*ev); |
195 | 611 | event->accept(); | 612 | event->accept(); |
196 | 612 | } | 613 | } |
197 | 613 | 614 | ||
198 | 614 | void MirSurface::hoverMoveEvent(QHoverEvent *event) | 615 | void MirSurface::hoverMoveEvent(QHoverEvent *event, qreal dpr) |
199 | 615 | { | 616 | { |
200 | 616 | auto ev = makeMirEvent(event, mir_pointer_action_motion); | 617 | auto ev = makeMirEvent(event, mir_pointer_action_motion, dpr); |
201 | 617 | m_surface->consume(*ev); | 618 | m_surface->consume(*ev); |
202 | 618 | event->accept(); | 619 | event->accept(); |
203 | 619 | } | 620 | } |
204 | 620 | 621 | ||
205 | 621 | void MirSurface::wheelEvent(QWheelEvent *event) | 622 | void MirSurface::wheelEvent(QWheelEvent *event, qreal dpr) |
206 | 622 | { | 623 | { |
207 | 623 | auto ev = makeMirEvent(event); | 624 | auto ev = makeMirEvent(event, dpr); |
208 | 624 | m_surface->consume(*ev); | 625 | m_surface->consume(*ev); |
209 | 625 | event->accept(); | 626 | event->accept(); |
210 | 626 | } | 627 | } |
211 | @@ -642,9 +643,10 @@ | |||
212 | 642 | void MirSurface::touchEvent(Qt::KeyboardModifiers mods, | 643 | void MirSurface::touchEvent(Qt::KeyboardModifiers mods, |
213 | 643 | const QList<QTouchEvent::TouchPoint> &touchPoints, | 644 | const QList<QTouchEvent::TouchPoint> &touchPoints, |
214 | 644 | Qt::TouchPointStates touchPointStates, | 645 | Qt::TouchPointStates touchPointStates, |
216 | 645 | ulong timestamp) | 646 | ulong timestamp, |
217 | 647 | qreal dpr) | ||
218 | 646 | { | 648 | { |
220 | 647 | auto ev = makeMirEvent(mods, touchPoints, touchPointStates, timestamp); | 649 | auto ev = makeMirEvent(mods, touchPoints, touchPointStates, timestamp, dpr); |
221 | 648 | m_surface->consume(*ev); | 650 | m_surface->consume(*ev); |
222 | 649 | } | 651 | } |
223 | 650 | 652 | ||
224 | 651 | 653 | ||
225 | === modified file 'src/modules/Unity/Application/mirsurface.h' | |||
226 | --- src/modules/Unity/Application/mirsurface.h 2015-12-10 13:08:43 +0000 | |||
227 | +++ src/modules/Unity/Application/mirsurface.h 2016-01-07 17:03:26 +0000 | |||
228 | @@ -101,13 +101,13 @@ | |||
229 | 101 | 101 | ||
230 | 102 | void close() override; | 102 | void close() override; |
231 | 103 | 103 | ||
239 | 104 | void mousePressEvent(QMouseEvent *event) override; | 104 | void mousePressEvent(QMouseEvent *event, qreal dpr) override; |
240 | 105 | void mouseMoveEvent(QMouseEvent *event) override; | 105 | void mouseMoveEvent(QMouseEvent *event, qreal dpr) override; |
241 | 106 | void mouseReleaseEvent(QMouseEvent *event) override; | 106 | void mouseReleaseEvent(QMouseEvent *event, qreal dpr) override; |
242 | 107 | void hoverEnterEvent(QHoverEvent *event) override; | 107 | void hoverEnterEvent(QHoverEvent *event, qreal dpr) override; |
243 | 108 | void hoverLeaveEvent(QHoverEvent *event) override; | 108 | void hoverLeaveEvent(QHoverEvent *event, qreal dpr) override; |
244 | 109 | void hoverMoveEvent(QHoverEvent *event) override; | 109 | void hoverMoveEvent(QHoverEvent *event, qreal dpr) override; |
245 | 110 | void wheelEvent(QWheelEvent *event) override; | 110 | void wheelEvent(QWheelEvent *event, qreal dpr) override; |
246 | 111 | 111 | ||
247 | 112 | void keyPressEvent(QKeyEvent *event) override; | 112 | void keyPressEvent(QKeyEvent *event) override; |
248 | 113 | void keyReleaseEvent(QKeyEvent *event) override; | 113 | void keyReleaseEvent(QKeyEvent *event) override; |
249 | @@ -115,7 +115,7 @@ | |||
250 | 115 | void touchEvent(Qt::KeyboardModifiers qmods, | 115 | void touchEvent(Qt::KeyboardModifiers qmods, |
251 | 116 | const QList<QTouchEvent::TouchPoint> &qtTouchPoints, | 116 | const QList<QTouchEvent::TouchPoint> &qtTouchPoints, |
252 | 117 | Qt::TouchPointStates qtTouchPointStates, | 117 | Qt::TouchPointStates qtTouchPointStates, |
254 | 118 | ulong qtTimestamp) override; | 118 | ulong qtTimestamp, qreal dpr) override; |
255 | 119 | 119 | ||
256 | 120 | QString appId() const override; | 120 | QString appId() const override; |
257 | 121 | 121 | ||
258 | 122 | 122 | ||
259 | === modified file 'src/modules/Unity/Application/mirsurfaceinterface.h' | |||
260 | --- src/modules/Unity/Application/mirsurfaceinterface.h 2015-12-10 13:08:43 +0000 | |||
261 | +++ src/modules/Unity/Application/mirsurfaceinterface.h 2016-01-07 17:03:26 +0000 | |||
262 | @@ -66,13 +66,13 @@ | |||
263 | 66 | 66 | ||
264 | 67 | virtual void close() = 0; | 67 | virtual void close() = 0; |
265 | 68 | 68 | ||
273 | 69 | virtual void mousePressEvent(QMouseEvent *event) = 0; | 69 | virtual void mousePressEvent(QMouseEvent *event, qreal dpr = 1.0) = 0; |
274 | 70 | virtual void mouseMoveEvent(QMouseEvent *event) = 0; | 70 | virtual void mouseMoveEvent(QMouseEvent *event, qreal dpr = 1.0) = 0; |
275 | 71 | virtual void mouseReleaseEvent(QMouseEvent *event) = 0; | 71 | virtual void mouseReleaseEvent(QMouseEvent *event, qreal dpr = 1.0) = 0; |
276 | 72 | virtual void hoverEnterEvent(QHoverEvent *event) = 0; | 72 | virtual void hoverEnterEvent(QHoverEvent *event, qreal dpr = 1.0) = 0; |
277 | 73 | virtual void hoverLeaveEvent(QHoverEvent *event) = 0; | 73 | virtual void hoverLeaveEvent(QHoverEvent *event, qreal dpr = 1.0) = 0; |
278 | 74 | virtual void hoverMoveEvent(QHoverEvent *event) = 0; | 74 | virtual void hoverMoveEvent(QHoverEvent *event, qreal dpr = 1.0) = 0; |
279 | 75 | virtual void wheelEvent(QWheelEvent *event) = 0; | 75 | virtual void wheelEvent(QWheelEvent *event, qreal dpr = 1.0) = 0; |
280 | 76 | 76 | ||
281 | 77 | virtual void keyPressEvent(QKeyEvent *event) = 0; | 77 | virtual void keyPressEvent(QKeyEvent *event) = 0; |
282 | 78 | virtual void keyReleaseEvent(QKeyEvent *event) = 0; | 78 | virtual void keyReleaseEvent(QKeyEvent *event) = 0; |
283 | @@ -80,7 +80,7 @@ | |||
284 | 80 | virtual void touchEvent(Qt::KeyboardModifiers qmods, | 80 | virtual void touchEvent(Qt::KeyboardModifiers qmods, |
285 | 81 | const QList<QTouchEvent::TouchPoint> &qtTouchPoints, | 81 | const QList<QTouchEvent::TouchPoint> &qtTouchPoints, |
286 | 82 | Qt::TouchPointStates qtTouchPointStates, | 82 | Qt::TouchPointStates qtTouchPointStates, |
288 | 83 | ulong qtTimestamp) = 0; | 83 | ulong qtTimestamp, qreal dpr = 1.0) = 0; |
289 | 84 | 84 | ||
290 | 85 | virtual QString appId() const = 0; | 85 | virtual QString appId() const = 0; |
291 | 86 | 86 | ||
292 | 87 | 87 | ||
293 | === modified file 'src/modules/Unity/Application/mirsurfaceitem.cpp' | |||
294 | --- src/modules/Unity/Application/mirsurfaceitem.cpp 2015-12-10 13:08:43 +0000 | |||
295 | +++ src/modules/Unity/Application/mirsurfaceitem.cpp 2016-01-07 17:03:26 +0000 | |||
296 | @@ -54,6 +54,11 @@ | |||
297 | 54 | QObject *textureProvider; | 54 | QObject *textureProvider; |
298 | 55 | }; | 55 | }; |
299 | 56 | 56 | ||
300 | 57 | inline int divideAndRoundUp(int numerator, qreal denominator) | ||
301 | 58 | { | ||
302 | 59 | return ceil((qreal)numerator / denominator); | ||
303 | 60 | } | ||
304 | 61 | |||
305 | 57 | } // namespace { | 62 | } // namespace { |
306 | 58 | 63 | ||
307 | 59 | class MirTextureProvider : public QSGTextureProvider | 64 | class MirTextureProvider : public QSGTextureProvider |
308 | @@ -81,6 +86,11 @@ | |||
309 | 81 | QSharedPointer<QSGTexture> t; | 86 | QSharedPointer<QSGTexture> t; |
310 | 82 | }; | 87 | }; |
311 | 83 | 88 | ||
312 | 89 | /* | ||
313 | 90 | * Note: all geometry is in device-independent pixels, except that contained in variables with the | ||
314 | 91 | * suffix "Px" - whose units are physical pixels | ||
315 | 92 | */ | ||
316 | 93 | |||
317 | 84 | MirSurfaceItem::MirSurfaceItem(QQuickItem *parent) | 94 | MirSurfaceItem::MirSurfaceItem(QQuickItem *parent) |
318 | 85 | : MirSurfaceItemInterface(parent) | 95 | : MirSurfaceItemInterface(parent) |
319 | 86 | , m_surface(nullptr) | 96 | , m_surface(nullptr) |
320 | @@ -248,13 +258,14 @@ | |||
321 | 248 | 258 | ||
322 | 249 | if (m_fillMode == PadOrCrop) { | 259 | if (m_fillMode == PadOrCrop) { |
323 | 250 | const QSize &textureSize = m_textureProvider->texture()->textureSize(); | 260 | const QSize &textureSize = m_textureProvider->texture()->textureSize(); |
324 | 261 | const qreal dpr = devicePixelRatio(); | ||
325 | 251 | 262 | ||
326 | 252 | QRectF targetRect; | 263 | QRectF targetRect; |
327 | 253 | targetRect.setWidth(qMin(width(), static_cast<qreal>(textureSize.width()))); | 264 | targetRect.setWidth(qMin(width(), static_cast<qreal>(textureSize.width()))); |
328 | 254 | targetRect.setHeight(qMin(height(), static_cast<qreal>(textureSize.height()))); | 265 | targetRect.setHeight(qMin(height(), static_cast<qreal>(textureSize.height()))); |
329 | 255 | 266 | ||
332 | 256 | qreal u = targetRect.width() / textureSize.width(); | 267 | qreal u = (targetRect.width() * dpr) / textureSize.width(); |
333 | 257 | qreal v = targetRect.height() / textureSize.height(); | 268 | qreal v = (targetRect.height() * dpr) / textureSize.height(); |
334 | 258 | node->setSubSourceRect(QRectF(0, 0, u, v)); | 269 | node->setSubSourceRect(QRectF(0, 0, u, v)); |
335 | 259 | 270 | ||
336 | 260 | node->setTargetRect(targetRect); | 271 | node->setTargetRect(targetRect); |
337 | @@ -285,12 +296,12 @@ | |||
338 | 285 | if (type() == Mir::InputMethodType) { | 296 | if (type() == Mir::InputMethodType) { |
339 | 286 | // FIXME: Hack to get the VKB use case working while we don't have the proper solution in place. | 297 | // FIXME: Hack to get the VKB use case working while we don't have the proper solution in place. |
340 | 287 | if (isMouseInsideUbuntuKeyboard(event)) { | 298 | if (isMouseInsideUbuntuKeyboard(event)) { |
342 | 288 | m_surface->mousePressEvent(event); | 299 | m_surface->mousePressEvent(event, devicePixelRatio()); |
343 | 289 | } else { | 300 | } else { |
344 | 290 | event->ignore(); | 301 | event->ignore(); |
345 | 291 | } | 302 | } |
346 | 292 | } else { | 303 | } else { |
348 | 293 | m_surface->mousePressEvent(event); | 304 | m_surface->mousePressEvent(event, devicePixelRatio()); |
349 | 294 | } | 305 | } |
350 | 295 | } else { | 306 | } else { |
351 | 296 | event->ignore(); | 307 | event->ignore(); |
352 | @@ -300,7 +311,7 @@ | |||
353 | 300 | void MirSurfaceItem::mouseMoveEvent(QMouseEvent *event) | 311 | void MirSurfaceItem::mouseMoveEvent(QMouseEvent *event) |
354 | 301 | { | 312 | { |
355 | 302 | if (m_consumesInput && m_surface && m_surface->live()) { | 313 | if (m_consumesInput && m_surface && m_surface->live()) { |
357 | 303 | m_surface->mouseMoveEvent(event); | 314 | m_surface->mouseMoveEvent(event, devicePixelRatio()); |
358 | 304 | } else { | 315 | } else { |
359 | 305 | event->ignore(); | 316 | event->ignore(); |
360 | 306 | } | 317 | } |
361 | @@ -309,7 +320,7 @@ | |||
362 | 309 | void MirSurfaceItem::mouseReleaseEvent(QMouseEvent *event) | 320 | void MirSurfaceItem::mouseReleaseEvent(QMouseEvent *event) |
363 | 310 | { | 321 | { |
364 | 311 | if (m_consumesInput && m_surface && m_surface->live()) { | 322 | if (m_consumesInput && m_surface && m_surface->live()) { |
366 | 312 | m_surface->mouseReleaseEvent(event); | 323 | m_surface->mouseReleaseEvent(event, devicePixelRatio()); |
367 | 313 | } else { | 324 | } else { |
368 | 314 | event->ignore(); | 325 | event->ignore(); |
369 | 315 | } | 326 | } |
370 | @@ -327,7 +338,7 @@ | |||
371 | 327 | void MirSurfaceItem::hoverEnterEvent(QHoverEvent *event) | 338 | void MirSurfaceItem::hoverEnterEvent(QHoverEvent *event) |
372 | 328 | { | 339 | { |
373 | 329 | if (m_consumesInput && m_surface && m_surface->live()) { | 340 | if (m_consumesInput && m_surface && m_surface->live()) { |
375 | 330 | m_surface->hoverEnterEvent(event); | 341 | m_surface->hoverEnterEvent(event, devicePixelRatio()); |
376 | 331 | } else { | 342 | } else { |
377 | 332 | event->ignore(); | 343 | event->ignore(); |
378 | 333 | } | 344 | } |
379 | @@ -336,7 +347,7 @@ | |||
380 | 336 | void MirSurfaceItem::hoverLeaveEvent(QHoverEvent *event) | 347 | void MirSurfaceItem::hoverLeaveEvent(QHoverEvent *event) |
381 | 337 | { | 348 | { |
382 | 338 | if (m_consumesInput && m_surface && m_surface->live()) { | 349 | if (m_consumesInput && m_surface && m_surface->live()) { |
384 | 339 | m_surface->hoverLeaveEvent(event); | 350 | m_surface->hoverLeaveEvent(event, devicePixelRatio()); |
385 | 340 | } else { | 351 | } else { |
386 | 341 | event->ignore(); | 352 | event->ignore(); |
387 | 342 | } | 353 | } |
388 | @@ -345,7 +356,7 @@ | |||
389 | 345 | void MirSurfaceItem::hoverMoveEvent(QHoverEvent *event) | 356 | void MirSurfaceItem::hoverMoveEvent(QHoverEvent *event) |
390 | 346 | { | 357 | { |
391 | 347 | if (m_consumesInput && m_surface && m_surface->live()) { | 358 | if (m_consumesInput && m_surface && m_surface->live()) { |
393 | 348 | m_surface->hoverMoveEvent(event); | 359 | m_surface->hoverMoveEvent(event, devicePixelRatio()); |
394 | 349 | } else { | 360 | } else { |
395 | 350 | event->ignore(); | 361 | event->ignore(); |
396 | 351 | } | 362 | } |
397 | @@ -404,7 +415,7 @@ | |||
398 | 404 | touchEvent.updateTouchPointStatesAndType(); | 415 | touchEvent.updateTouchPointStatesAndType(); |
399 | 405 | 416 | ||
400 | 406 | m_surface->touchEvent(touchEvent.modifiers, touchEvent.touchPoints, | 417 | m_surface->touchEvent(touchEvent.modifiers, touchEvent.touchPoints, |
402 | 407 | touchEvent.touchPointStates, touchEvent.timestamp); | 418 | touchEvent.touchPointStates, touchEvent.timestamp, devicePixelRatio()); |
403 | 408 | 419 | ||
404 | 409 | *m_lastTouchEvent = touchEvent; | 420 | *m_lastTouchEvent = touchEvent; |
405 | 410 | 421 | ||
406 | @@ -425,7 +436,7 @@ | |||
407 | 425 | endCurrentTouchSequence(timestamp); | 436 | endCurrentTouchSequence(timestamp); |
408 | 426 | } | 437 | } |
409 | 427 | 438 | ||
411 | 428 | m_surface->touchEvent(mods, touchPoints, touchPointStates, timestamp); | 439 | m_surface->touchEvent(mods, touchPoints, touchPointStates, timestamp, devicePixelRatio()); |
412 | 429 | 440 | ||
413 | 430 | if (!m_lastTouchEvent) { | 441 | if (!m_lastTouchEvent) { |
414 | 431 | m_lastTouchEvent = new TouchEvent; | 442 | m_lastTouchEvent = new TouchEvent; |
415 | @@ -537,10 +548,12 @@ | |||
416 | 537 | } | 548 | } |
417 | 538 | 549 | ||
418 | 539 | // If one dimension is not set, fallback to the current value | 550 | // If one dimension is not set, fallback to the current value |
421 | 540 | int width = m_surfaceWidth > 0 ? m_surfaceWidth : m_surface->size().width(); | 551 | const int width = m_surfaceWidth > 0 ? m_surfaceWidth : m_surface->size().width(); |
422 | 541 | int height = m_surfaceHeight > 0 ? m_surfaceHeight : m_surface->size().height(); | 552 | const int height = m_surfaceHeight > 0 ? m_surfaceHeight : m_surface->size().height(); |
423 | 553 | const int widthPx = width * devicePixelRatio(); | ||
424 | 554 | const int heightPx = height * devicePixelRatio(); | ||
425 | 542 | 555 | ||
427 | 543 | m_surface->resize(width, height); | 556 | m_surface->resize(widthPx, heightPx); |
428 | 544 | } | 557 | } |
429 | 545 | 558 | ||
430 | 546 | void MirSurfaceItem::updateMirSurfaceVisibility() | 559 | void MirSurfaceItem::updateMirSurfaceVisibility() |
431 | @@ -565,6 +578,11 @@ | |||
432 | 565 | m_textureProvider = nullptr; | 578 | m_textureProvider = nullptr; |
433 | 566 | } | 579 | } |
434 | 567 | 580 | ||
435 | 581 | qreal MirSurfaceItem::devicePixelRatio() const | ||
436 | 582 | { | ||
437 | 583 | return window() ? window()->devicePixelRatio() : 1.0; | ||
438 | 584 | } | ||
439 | 585 | |||
440 | 568 | void MirSurfaceItem::TouchEvent::updateTouchPointStatesAndType() | 586 | void MirSurfaceItem::TouchEvent::updateTouchPointStatesAndType() |
441 | 569 | { | 587 | { |
442 | 570 | touchPointStates = 0; | 588 | touchPointStates = 0; |
443 | @@ -654,7 +672,8 @@ | |||
444 | 654 | Q_EMIT surfaceStateChanged(m_surface->state()); | 672 | Q_EMIT surfaceStateChanged(m_surface->state()); |
445 | 655 | 673 | ||
446 | 656 | updateMirSurfaceSize(); | 674 | updateMirSurfaceSize(); |
448 | 657 | setImplicitSize(m_surface->size().width(), m_surface->size().height()); | 675 | setImplicitSize(divideAndRoundUp(m_surface->size().width(), devicePixelRatio()), |
449 | 676 | divideAndRoundUp(m_surface->size().height(), devicePixelRatio())); | ||
450 | 658 | updateMirSurfaceVisibility(); | 677 | updateMirSurfaceVisibility(); |
451 | 659 | 678 | ||
452 | 660 | // Qt::ArrowCursor is the default when no cursor has been explicitly set, so no point forwarding it. | 679 | // Qt::ArrowCursor is the default when no cursor has been explicitly set, so no point forwarding it. |
453 | @@ -729,7 +748,8 @@ | |||
454 | 729 | 748 | ||
455 | 730 | void MirSurfaceItem::onActualSurfaceSizeChanged(const QSize &size) | 749 | void MirSurfaceItem::onActualSurfaceSizeChanged(const QSize &size) |
456 | 731 | { | 750 | { |
458 | 732 | setImplicitSize(size.width(), size.height()); | 751 | setImplicitSize(divideAndRoundUp(size.width(), devicePixelRatio()), |
459 | 752 | divideAndRoundUp(size.height(), devicePixelRatio())); | ||
460 | 733 | } | 753 | } |
461 | 734 | 754 | ||
462 | 735 | int MirSurfaceItem::surfaceHeight() const | 755 | int MirSurfaceItem::surfaceHeight() const |
463 | 736 | 756 | ||
464 | === modified file 'src/modules/Unity/Application/mirsurfaceitem.h' | |||
465 | --- src/modules/Unity/Application/mirsurfaceitem.h 2015-12-10 13:08:43 +0000 | |||
466 | +++ src/modules/Unity/Application/mirsurfaceitem.h 2016-01-07 17:03:26 +0000 | |||
467 | @@ -123,6 +123,7 @@ | |||
468 | 123 | void onWindowChanged(QQuickWindow *window); | 123 | void onWindowChanged(QQuickWindow *window); |
469 | 124 | 124 | ||
470 | 125 | private: | 125 | private: |
471 | 126 | qreal devicePixelRatio() const; | ||
472 | 126 | void ensureTextureProvider(); | 127 | void ensureTextureProvider(); |
473 | 127 | 128 | ||
474 | 128 | bool hasTouchInsideUbuntuKeyboard(const QList<QTouchEvent::TouchPoint> &touchPoints); | 129 | bool hasTouchInsideUbuntuKeyboard(const QList<QTouchEvent::TouchPoint> &touchPoints); |
475 | 129 | 130 | ||
476 | === modified file 'src/platforms/mirserver/qteventfeeder.cpp' | |||
477 | --- src/platforms/mirserver/qteventfeeder.cpp 2015-12-07 08:06:16 +0000 | |||
478 | +++ src/platforms/mirserver/qteventfeeder.cpp 2016-01-07 17:03:26 +0000 | |||
479 | @@ -395,6 +395,11 @@ | |||
480 | 395 | return m_screenController->getWindowForPoint(point); | 395 | return m_screenController->getWindowForPoint(point); |
481 | 396 | } | 396 | } |
482 | 397 | 397 | ||
483 | 398 | qreal devicePixelRatio() override | ||
484 | 399 | { | ||
485 | 400 | return qGuiApp->devicePixelRatio(); // FIXME: make per-screen. | ||
486 | 401 | } | ||
487 | 402 | |||
488 | 398 | void registerTouchDevice(QTouchDevice *device) override | 403 | void registerTouchDevice(QTouchDevice *device) override |
489 | 399 | { | 404 | { |
490 | 400 | QWindowSystemInterface::registerTouchDevice(device); | 405 | QWindowSystemInterface::registerTouchDevice(device); |
491 | @@ -558,8 +563,9 @@ | |||
492 | 558 | 563 | ||
493 | 559 | auto modifiers = getQtModifiersFromMir(mir_pointer_event_modifiers(pev)); | 564 | auto modifiers = getQtModifiersFromMir(mir_pointer_event_modifiers(pev)); |
494 | 560 | 565 | ||
497 | 561 | auto movement = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_relative_x), | 566 | const qreal dpr = mQtWindowSystem->devicePixelRatio(); |
498 | 562 | mir_pointer_event_axis_value(pev, mir_pointer_axis_relative_y)); | 567 | auto movement = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_relative_x) / dpr, |
499 | 568 | mir_pointer_event_axis_value(pev, mir_pointer_axis_relative_y) / dpr); | ||
500 | 563 | 569 | ||
501 | 564 | switch (action) { | 570 | switch (action) { |
502 | 565 | case mir_pointer_action_button_up: | 571 | case mir_pointer_action_button_up: |
503 | @@ -653,6 +659,7 @@ | |||
504 | 653 | // FIXME(loicm) Max pressure is device specific. That one is for the Samsung Galaxy Nexus. That | 659 | // FIXME(loicm) Max pressure is device specific. That one is for the Samsung Galaxy Nexus. That |
505 | 654 | // needs to be fixed as soon as the compat input lib adds query support. | 660 | // needs to be fixed as soon as the compat input lib adds query support. |
506 | 655 | const float kMaxPressure = 1.28; | 661 | const float kMaxPressure = 1.28; |
507 | 662 | const qreal dpr = mQtWindowSystem->devicePixelRatio(); | ||
508 | 656 | const int kPointerCount = mir_touch_event_point_count(tev); | 663 | const int kPointerCount = mir_touch_event_point_count(tev); |
509 | 657 | QList<QWindowSystemInterface::TouchPoint> touchPoints; | 664 | QList<QWindowSystemInterface::TouchPoint> touchPoints; |
510 | 658 | QWindow *window = nullptr; | 665 | QWindow *window = nullptr; |
511 | @@ -674,10 +681,10 @@ | |||
512 | 674 | for (int i = 0; i < kPointerCount; ++i) { | 681 | for (int i = 0; i < kPointerCount; ++i) { |
513 | 675 | QWindowSystemInterface::TouchPoint touchPoint; | 682 | QWindowSystemInterface::TouchPoint touchPoint; |
514 | 676 | 683 | ||
519 | 677 | const float kX = mir_touch_event_axis_value(tev, i, mir_touch_axis_x); | 684 | const float kX = mir_touch_event_axis_value(tev, i, mir_touch_axis_x) / dpr; |
520 | 678 | const float kY = mir_touch_event_axis_value(tev, i, mir_touch_axis_y); | 685 | const float kY = mir_touch_event_axis_value(tev, i, mir_touch_axis_y) / dpr; |
521 | 679 | const float kW = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_major); | 686 | const float kW = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_major) / dpr; |
522 | 680 | const float kH = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_minor); | 687 | const float kH = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_minor) / dpr; |
523 | 681 | const float kP = mir_touch_event_axis_value(tev, i, mir_touch_axis_pressure); | 688 | const float kP = mir_touch_event_axis_value(tev, i, mir_touch_axis_pressure); |
524 | 682 | touchPoint.id = mir_touch_event_id(tev, i); | 689 | touchPoint.id = mir_touch_event_id(tev, i); |
525 | 683 | 690 | ||
526 | 684 | 691 | ||
527 | === modified file 'src/platforms/mirserver/qteventfeeder.h' | |||
528 | --- src/platforms/mirserver/qteventfeeder.h 2015-11-19 14:17:54 +0000 | |||
529 | +++ src/platforms/mirserver/qteventfeeder.h 2016-01-07 17:03:26 +0000 | |||
530 | @@ -39,6 +39,7 @@ | |||
531 | 39 | virtual ~QtWindowSystemInterface() {} | 39 | virtual ~QtWindowSystemInterface() {} |
532 | 40 | virtual void setScreenController(const QSharedPointer<ScreenController> &sc) = 0; | 40 | virtual void setScreenController(const QSharedPointer<ScreenController> &sc) = 0; |
533 | 41 | virtual QWindow* getWindowForTouchPoint(const QPoint &point) = 0; | 41 | virtual QWindow* getWindowForTouchPoint(const QPoint &point) = 0; |
534 | 42 | virtual qreal devicePixelRatio() { return 1.0; } | ||
535 | 42 | virtual QWindow* focusedWindow() = 0; | 43 | virtual QWindow* focusedWindow() = 0; |
536 | 43 | virtual void registerTouchDevice(QTouchDevice *device) = 0; | 44 | virtual void registerTouchDevice(QTouchDevice *device) = 0; |
537 | 44 | virtual void handleExtendedKeyEvent(QWindow *window, ulong timestamp, QEvent::Type type, int key, | 45 | virtual void handleExtendedKeyEvent(QWindow *window, ulong timestamp, QEvent::Type type, int key, |
538 | 45 | 46 | ||
539 | === modified file 'src/platforms/mirserver/screen.cpp' | |||
540 | --- src/platforms/mirserver/screen.cpp 2015-10-14 22:59:04 +0000 | |||
541 | +++ src/platforms/mirserver/screen.cpp 2016-01-07 17:03:26 +0000 | |||
542 | @@ -44,6 +44,7 @@ | |||
543 | 44 | char *c = (char*)&i; | 44 | char *c = (char*)&i; |
544 | 45 | return *c == 1; | 45 | return *c == 1; |
545 | 46 | } | 46 | } |
546 | 47 | |||
547 | 47 | static mir::renderer::gl::RenderTarget *as_render_target( | 48 | static mir::renderer::gl::RenderTarget *as_render_target( |
548 | 48 | mir::graphics::DisplayBuffer *displayBuffer) | 49 | mir::graphics::DisplayBuffer *displayBuffer) |
549 | 49 | { | 50 | { |
550 | @@ -56,6 +57,17 @@ | |||
551 | 56 | return render_target; | 57 | return render_target; |
552 | 57 | } | 58 | } |
553 | 58 | 59 | ||
554 | 60 | qreal readDevicePixelRatioEnvVar() | ||
555 | 61 | { | ||
556 | 62 | bool ok; | ||
557 | 63 | const int dpr = qgetenv("QT_DEVICE_PIXEL_RATIO").toInt(&ok); | ||
558 | 64 | if (ok && dpr > 0) { | ||
559 | 65 | return (qreal) dpr; | ||
560 | 66 | } else { | ||
561 | 67 | return 1.0; // fallback value | ||
562 | 68 | } | ||
563 | 69 | } | ||
564 | 70 | |||
565 | 59 | enum QImage::Format qImageFormatFromMirPixelFormat(MirPixelFormat mirPixelFormat) { | 71 | enum QImage::Format qImageFormatFromMirPixelFormat(MirPixelFormat mirPixelFormat) { |
566 | 60 | switch (mirPixelFormat) { | 72 | switch (mirPixelFormat) { |
567 | 61 | case mir_pixel_format_abgr_8888: | 73 | case mir_pixel_format_abgr_8888: |
568 | @@ -123,6 +135,9 @@ | |||
569 | 123 | , m_screenWindow(nullptr) | 135 | , m_screenWindow(nullptr) |
570 | 124 | , m_unityScreen(nullptr) | 136 | , m_unityScreen(nullptr) |
571 | 125 | { | 137 | { |
572 | 138 | // Get screen resolution and properties. | ||
573 | 139 | m_devicePixelRatio = readDevicePixelRatioEnvVar(); | ||
574 | 140 | |||
575 | 126 | setMirDisplayConfiguration(screen); | 141 | setMirDisplayConfiguration(screen); |
576 | 127 | 142 | ||
577 | 128 | // Set the default orientation based on the initial screen dimmensions. | 143 | // Set the default orientation based on the initial screen dimmensions. |
578 | @@ -197,14 +212,20 @@ | |||
579 | 197 | m_powerMode = screen.power_mode; | 212 | m_powerMode = screen.power_mode; |
580 | 198 | 213 | ||
581 | 199 | QRect oldGeometry = m_geometry; | 214 | QRect oldGeometry = m_geometry; |
585 | 200 | // Position of screen in virtual desktop coordinate space | 215 | // Position of screen in virtual desktop coordinate space (physical pixels) |
586 | 201 | m_geometry.setTop(screen.top_left.y.as_int()); | 216 | m_nativeGeometry.setTop(screen.top_left.y.as_int()); |
587 | 202 | m_geometry.setLeft(screen.top_left.x.as_int()); | 217 | m_nativeGeometry.setLeft(screen.top_left.x.as_int()); |
588 | 203 | 218 | ||
589 | 204 | // Mode = current resolution & refresh rate | 219 | // Mode = current resolution & refresh rate |
590 | 205 | mir::graphics::DisplayConfigurationMode mode = screen.modes.at(screen.current_mode_index); | 220 | mir::graphics::DisplayConfigurationMode mode = screen.modes.at(screen.current_mode_index); |
593 | 206 | m_geometry.setWidth(mode.size.width.as_int()); | 221 | m_nativeGeometry.setWidth(mode.size.width.as_int()); |
594 | 207 | m_geometry.setHeight(mode.size.height.as_int()); | 222 | m_nativeGeometry.setHeight(mode.size.height.as_int()); |
595 | 223 | |||
596 | 224 | // Geometry is in terms of device-independent pixels | ||
597 | 225 | m_geometry.setTop(m_nativeGeometry.top() / m_devicePixelRatio); | ||
598 | 226 | m_geometry.setLeft(m_nativeGeometry.left() / m_devicePixelRatio); | ||
599 | 227 | m_geometry.setWidth(m_nativeGeometry.width() / m_devicePixelRatio); | ||
600 | 228 | m_geometry.setHeight(m_nativeGeometry.height() / m_devicePixelRatio); | ||
601 | 208 | 229 | ||
602 | 209 | // DPI - unnecessary to calculate, default implementation in QPlatformScreen is sufficient | 230 | // DPI - unnecessary to calculate, default implementation in QPlatformScreen is sufficient |
603 | 210 | 231 | ||
604 | 211 | 232 | ||
605 | === modified file 'src/platforms/mirserver/screen.h' | |||
606 | --- src/platforms/mirserver/screen.h 2015-10-14 22:59:04 +0000 | |||
607 | +++ src/platforms/mirserver/screen.h 2016-01-07 17:03:26 +0000 | |||
608 | @@ -44,13 +44,15 @@ | |||
609 | 44 | ~Screen(); | 44 | ~Screen(); |
610 | 45 | 45 | ||
611 | 46 | // QPlatformScreen methods. | 46 | // QPlatformScreen methods. |
613 | 47 | QRect geometry() const override { return m_geometry; } | 47 | QRect geometry() const override { return m_geometry; } // in device-independent pixels |
614 | 48 | QRect nativeGeometry() const { return m_nativeGeometry; } // in physical pixels | ||
615 | 48 | int depth() const override { return m_depth; } | 49 | int depth() const override { return m_depth; } |
616 | 49 | QImage::Format format() const override { return m_format; } | 50 | QImage::Format format() const override { return m_format; } |
617 | 50 | QSizeF physicalSize() const override { return m_physicalSize; } | 51 | QSizeF physicalSize() const override { return m_physicalSize; } |
618 | 51 | qreal refreshRate() const override { return m_refreshRate; } | 52 | qreal refreshRate() const override { return m_refreshRate; } |
619 | 52 | Qt::ScreenOrientation nativeOrientation() const override { return m_nativeOrientation; } | 53 | Qt::ScreenOrientation nativeOrientation() const override { return m_nativeOrientation; } |
620 | 53 | Qt::ScreenOrientation orientation() const override { return m_currentOrientation; } | 54 | Qt::ScreenOrientation orientation() const override { return m_currentOrientation; } |
621 | 55 | qreal devicePixelRatio() const override { return m_devicePixelRatio; } | ||
622 | 54 | QPlatformCursor *cursor() const override; | 56 | QPlatformCursor *cursor() const override; |
623 | 55 | 57 | ||
624 | 56 | void toggleSensors(const bool enable) const; | 58 | void toggleSensors(const bool enable) const; |
625 | @@ -79,11 +81,12 @@ | |||
626 | 79 | void doneCurrent(); | 81 | void doneCurrent(); |
627 | 80 | 82 | ||
628 | 81 | private: | 83 | private: |
630 | 82 | QRect m_geometry; | 84 | QRect m_geometry, m_nativeGeometry; |
631 | 83 | int m_depth; | 85 | int m_depth; |
632 | 84 | QImage::Format m_format; | 86 | QImage::Format m_format; |
633 | 85 | QSizeF m_physicalSize; | 87 | QSizeF m_physicalSize; |
634 | 86 | qreal m_refreshRate; | 88 | qreal m_refreshRate; |
635 | 89 | qreal m_devicePixelRatio; | ||
636 | 87 | 90 | ||
637 | 88 | mir::renderer::gl::RenderTarget *m_renderTarget; | 91 | mir::renderer::gl::RenderTarget *m_renderTarget; |
638 | 89 | mir::graphics::DisplaySyncGroup *m_displayGroup; | 92 | mir::graphics::DisplaySyncGroup *m_displayGroup; |
639 | 90 | 93 | ||
640 | === modified file 'src/platforms/mirserver/screencontroller.cpp' | |||
641 | --- src/platforms/mirserver/screencontroller.cpp 2015-10-21 11:34:56 +0000 | |||
642 | +++ src/platforms/mirserver/screencontroller.cpp 2016-01-07 17:03:26 +0000 | |||
643 | @@ -163,7 +163,7 @@ | |||
644 | 163 | buffer.view_area().size.height.as_int()); | 163 | buffer.view_area().size.height.as_int()); |
645 | 164 | 164 | ||
646 | 165 | for (auto screen : m_screenList) { | 165 | for (auto screen : m_screenList) { |
648 | 166 | if (dbGeom == screen->geometry()) { | 166 | if (dbGeom == screen->nativeGeometry()) { |
649 | 167 | screen->setMirDisplayBuffer(&buffer, &group); | 167 | screen->setMirDisplayBuffer(&buffer, &group); |
650 | 168 | break; | 168 | break; |
651 | 169 | } | 169 | } |
652 | @@ -174,7 +174,7 @@ | |||
653 | 174 | qCDebug(QTMIR_SCREENS) << "======================================="; | 174 | qCDebug(QTMIR_SCREENS) << "======================================="; |
654 | 175 | for (auto screen: m_screenList) { | 175 | for (auto screen: m_screenList) { |
655 | 176 | qCDebug(QTMIR_SCREENS) << screen << "- id:" << screen->m_outputId.as_value() | 176 | qCDebug(QTMIR_SCREENS) << screen << "- id:" << screen->m_outputId.as_value() |
657 | 177 | << "geometry:" << screen->geometry() | 177 | << "geometry (px):" << screen->nativeGeometry() |
658 | 178 | << "window:" << screen->window() | 178 | << "window:" << screen->window() |
659 | 179 | << "type" << static_cast<int>(screen->outputType()); | 179 | << "type" << static_cast<int>(screen->outputType()); |
660 | 180 | } | 180 | } |
661 | 181 | 181 | ||
662 | === modified file 'src/platforms/mirserver/screenwindow.cpp' | |||
663 | --- src/platforms/mirserver/screenwindow.cpp 2015-10-15 07:05:16 +0000 | |||
664 | +++ src/platforms/mirserver/screenwindow.cpp 2016-01-07 17:03:26 +0000 | |||
665 | @@ -60,6 +60,11 @@ | |||
666 | 60 | window->setSurfaceType(QSurface::OpenGLSurface); | 60 | window->setSurfaceType(QSurface::OpenGLSurface); |
667 | 61 | } | 61 | } |
668 | 62 | 62 | ||
669 | 63 | qreal ScreenWindow::devicePixelRatio() const | ||
670 | 64 | { | ||
671 | 65 | return screen()->devicePixelRatio(); | ||
672 | 66 | } | ||
673 | 67 | |||
674 | 63 | ScreenWindow::~ScreenWindow() | 68 | ScreenWindow::~ScreenWindow() |
675 | 64 | { | 69 | { |
676 | 65 | qCDebug(QTMIR_SCREENS) << "Destroying ScreenWindow" << this; | 70 | qCDebug(QTMIR_SCREENS) << "Destroying ScreenWindow" << this; |
677 | 66 | 71 | ||
678 | === modified file 'src/platforms/mirserver/screenwindow.h' | |||
679 | --- src/platforms/mirserver/screenwindow.h 2015-10-14 22:59:04 +0000 | |||
680 | +++ src/platforms/mirserver/screenwindow.h 2016-01-07 17:03:26 +0000 | |||
681 | @@ -29,6 +29,8 @@ | |||
682 | 29 | explicit ScreenWindow(QWindow *window); | 29 | explicit ScreenWindow(QWindow *window); |
683 | 30 | virtual ~ScreenWindow(); | 30 | virtual ~ScreenWindow(); |
684 | 31 | 31 | ||
685 | 32 | qreal devicePixelRatio() const override; | ||
686 | 33 | |||
687 | 32 | bool isExposed() const override; | 34 | bool isExposed() const override; |
688 | 33 | void setExposed(const bool exposed); | 35 | void setExposed(const bool exposed); |
689 | 34 | 36 | ||
690 | 35 | 37 | ||
691 | === modified file 'tests/modules/common/fake_mirsurface.h' | |||
692 | --- tests/modules/common/fake_mirsurface.h 2015-12-10 13:08:43 +0000 | |||
693 | +++ tests/modules/common/fake_mirsurface.h 2016-01-07 17:03:26 +0000 | |||
694 | @@ -152,13 +152,13 @@ | |||
695 | 152 | 152 | ||
696 | 153 | void setFocus(bool focus) override { m_focused = focus; } | 153 | void setFocus(bool focus) override { m_focused = focus; } |
697 | 154 | 154 | ||
705 | 155 | void mousePressEvent(QMouseEvent *) override {} | 155 | void mousePressEvent(QMouseEvent *, qreal) override {} |
706 | 156 | void mouseMoveEvent(QMouseEvent *) override {} | 156 | void mouseMoveEvent(QMouseEvent *, qreal) override {} |
707 | 157 | void mouseReleaseEvent(QMouseEvent *) override {} | 157 | void mouseReleaseEvent(QMouseEvent *, qreal) override {} |
708 | 158 | void hoverEnterEvent(QHoverEvent *) override {} | 158 | void hoverEnterEvent(QHoverEvent *, qreal) override {} |
709 | 159 | void hoverLeaveEvent(QHoverEvent *) override {} | 159 | void hoverLeaveEvent(QHoverEvent *, qreal) override {} |
710 | 160 | void hoverMoveEvent(QHoverEvent *) override {} | 160 | void hoverMoveEvent(QHoverEvent *, qreal) override {} |
711 | 161 | void wheelEvent(QWheelEvent *) override {} | 161 | void wheelEvent(QWheelEvent *, qreal) override {} |
712 | 162 | 162 | ||
713 | 163 | void keyPressEvent(QKeyEvent *) override {} | 163 | void keyPressEvent(QKeyEvent *) override {} |
714 | 164 | void keyReleaseEvent(QKeyEvent *) override {} | 164 | void keyReleaseEvent(QKeyEvent *) override {} |
715 | @@ -166,7 +166,7 @@ | |||
716 | 166 | void touchEvent(Qt::KeyboardModifiers mods, | 166 | void touchEvent(Qt::KeyboardModifiers mods, |
717 | 167 | const QList<QTouchEvent::TouchPoint> &points, | 167 | const QList<QTouchEvent::TouchPoint> &points, |
718 | 168 | Qt::TouchPointStates states, | 168 | Qt::TouchPointStates states, |
720 | 169 | ulong timestamp) override { | 169 | ulong timestamp, qreal) override { |
721 | 170 | m_touchesReceived.append(TouchEvent(mods, points, states, timestamp)); | 170 | m_touchesReceived.append(TouchEvent(mods, points, states, timestamp)); |
722 | 171 | } | 171 | } |
723 | 172 | 172 |
FAILED: Continuous integration, rev:326 jenkins. qa.ubuntu. com/job/ qtmir-ci/ 252/ jenkins. qa.ubuntu. com/job/ qtmir-vivid- amd64-ci/ 103/console jenkins. qa.ubuntu. com/job/ qtmir-vivid- armhf-ci/ 103 jenkins. qa.ubuntu. com/job/ qtmir-vivid- armhf-ci/ 103/artifact/ work/output/ *zip*/output. zip
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/qtmir- ci/252/ rebuild
http://