Status: | Superseded |
---|---|
Proposed branch: | lp:~unity-team/qtubuntu/DPR |
Merge into: | lp:qtubuntu |
Prerequisite: | lp:~dandrader/qtubuntu/loggingCategory |
Diff against target: |
767 lines (+229/-152) 9 files modified
debian/changelog (+6/-0) src/ubuntumirclient/backingstore.cpp (+11/-5) src/ubuntumirclient/input.cpp (+15/-12) src/ubuntumirclient/screen.cpp (+24/-15) src/ubuntumirclient/screen.h (+2/-0) src/ubuntumirclient/ubuntumirclient.pro (+2/-1) src/ubuntumirclient/utils.h (+29/-0) src/ubuntumirclient/window.cpp (+136/-117) src/ubuntumirclient/window.h (+4/-2) |
To merge this branch: | bzr merge lp:~unity-team/qtubuntu/DPR |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel d'Andrada (community) | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Review via email: mp+280820@code.launchpad.net |
This proposal supersedes a proposal from 2015-04-27.
This proposal has been superseded by a proposal from 2016-01-05.
Commit message
Add device pixel ratio support. Small fix for the panel hack.
Description of the change
To test DPR 2:
stop unity8
initctl set-env --global QT_DEVICE_
start unity8
* 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 : Posted in a previous version of this proposal | # |
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:262
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal | # |
In src/ubuntumircl
"""
// Window manager can give us a final size different from what we asked for
// so let's check what we ended up getting
{
}
// Assume that the buffer size matches the surface size at creation time
d->bufferSize = geometry.size();
"""
Here bufferSize will be initialized with a scaled size, but it should have the real size.
So bufferSize initialization should probably moved above the line "// Window manager can give us a final size different[...]".
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:264
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal | # |
@Daniel, you were correct, I had mixed up a case where pixel != devicePixel. Since this is far too easy to screw up, I thought it a good idea to append "Px" to any variable that is in pixels, and so any other geometry is in device pixels. I think it helps distinguish them.
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal | # |
In src/ubuntumircl
"""
DLOG(
"""
bufferSizePx has no x() and y() (as it's a QSize, not a QRect). I think code won't build if you enable debug logging?
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:265
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:266
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:268
http://
Executed test runs:
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:269
http://
Executed test runs:
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:270
http://
Executed test runs:
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:271
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:272
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:273
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:274
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:275
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:276
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:277
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:278
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal | # |
Ok, should be good to go
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal | # |
Looks good to me (didn't test yet).
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:280
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal | # |
And it works fine as well.
Daniel d'Andrada (dandrader) wrote : | # |
Why is that function in src/ubuntumircl
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:290
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Gerry Boland (gerboland) wrote : | # |
> Why is that function in src/ubuntumircl
> namespace?
To stop it polluting the global namespace. The header file is private.
Daniel d'Andrada (dandrader) wrote : | # |
Why did you remove that chunk from UbuntuSurface constructor in src/ubuntumircl
"""
auto geom = mWindow-
if (mWindowState == Qt::WindowFullS
} else {
}
"""
Daniel d'Andrada (dandrader) : | # |
Daniel d'Andrada (dandrader) wrote : | # |
On 17/12/2015 11:52, Daniel d'Andrada wrote:
> Why did you remove that chunk from UbuntuSurface constructor in src/ubuntumircl
>
> """
> auto geom = mWindow-
> geom.setWidth(
> geom.setHeight(
> if (mWindowState == Qt::WindowFullS
> geom.setY(0);
> } else {
> geom.setY(
> }
> """
And so is the panel hack refactoring you're doing.
Gerry Boland (gerboland) wrote : | # |
> Why did you remove that chunk from UbuntuSurface constructor in
> src/ubuntumircl
> work.
>
> """
> auto geom = mWindow-
> geom.setWidth(
> geom.setHeight(
> if (mWindowState == Qt::WindowFullS
> geom.setY(0);
> } else {
> geom.setY(
> }
> """
It was a bit related. I wanted to prevent UbuntuSurface having any knowledge of device-indepedent pixels, I wanted it to be purely pixel based. UbuntuSurface pretty much a wrapper for a MirSurface. So that small refactor allowed me to do that, plus eliminate a small bit of duplicate code.
Gerry Boland (gerboland) wrote : | # |
Panel hack refactoring was to ensure the hack was applied at UbuntuWindow creation in a correct fashion.
The issue I found with the old hack was if window was created in fullscreen state, with y=0, then
if (state == Qt::WindowFullS
was not entered, but
} else if (geometry().y() == 0) {
was. So fullscreen surface got the panel hack applied.
I fixed it here as I was testing widget-based apps which did this.
Daniel d'Andrada (dandrader) wrote : | # |
Code looks ok
Daniel d'Andrada (dandrader) wrote : | # |
Works fine.
- 291. By Gerry Boland
-
Merge loggingCategory with merged trunk
- 292. By Gerry Boland
-
Bump changelog date to suit
Unmerged revisions
- 292. By Gerry Boland
-
Bump changelog date to suit
- 291. By Gerry Boland
-
Merge loggingCategory with merged trunk
- 290. By Gerry Boland
-
Bad merge, fixing
- 289. By Gerry Boland
-
Merge updated loggingCategory
- 288. By Gerry Boland
-
Merge Daniel's categroy logging branch
- 287. By Gerry Boland
-
Fix bug in panel-height hack where fullscreen surface could actually have the hack enabled. Also do little renaming & typo fix
- 286. By Gerry Boland
-
Fix surfaces positioning when going to & from fullscreen
- 285. By Gerry Boland
-
Fix camera app sizing - only tell qt about geometry change after mir replies, do not assume it will occur
- 284. By Gerry Boland
-
Typo making initial surface geometry incorrect
- 283. By Gerry Boland
-
Merge trunk
Preview Diff
1 | === modified file 'debian/changelog' |
2 | --- debian/changelog 2016-01-04 09:38:35 +0000 |
3 | +++ debian/changelog 2016-01-05 16:32:27 +0000 |
4 | @@ -1,3 +1,9 @@ |
5 | +qtubuntu (0.63) UNRELEASED; urgency=medium |
6 | + |
7 | + * Add support for Qt5's devicePixelRatio UI scaling mechanism |
8 | + |
9 | + -- Gerry Boland <gerry.boland@canonical.com> Tue, 05 Jan 2016 16:31:27 +0100 |
10 | + |
11 | qtubuntu (0.62+16.04.20160104-0ubuntu1) xenial; urgency=medium |
12 | |
13 | [ Daniel d'Andrada ] |
14 | |
15 | === modified file 'src/ubuntumirclient/backingstore.cpp' |
16 | --- src/ubuntumirclient/backingstore.cpp 2014-12-04 12:29:39 +0000 |
17 | +++ src/ubuntumirclient/backingstore.cpp 2016-01-05 16:32:27 +0000 |
18 | @@ -1,5 +1,5 @@ |
19 | /* |
20 | - * Copyright (C) 2014 Canonical, Ltd. |
21 | + * Copyright (C) 2014-2015 Canonical, Ltd. |
22 | * |
23 | * This program is free software: you can redistribute it and/or modify it under |
24 | * the terms of the GNU Lesser General Public License version 3, as published by |
25 | @@ -43,8 +43,10 @@ |
26 | { |
27 | Q_UNUSED(region); |
28 | Q_UNUSED(offset); |
29 | + const int dpr = int(window->devicePixelRatio()); |
30 | + |
31 | mContext->makeCurrent(window); |
32 | - glViewport(0, 0, window->width(), window->height()); |
33 | + glViewport(0, 0, window->width() * dpr, window->height() * dpr); |
34 | |
35 | updateTexture(); |
36 | |
37 | @@ -75,12 +77,14 @@ |
38 | |
39 | QRegion fixed; |
40 | QRect imageRect = mImage.rect(); |
41 | + const int dpr = int(window()->devicePixelRatio()); |
42 | |
43 | - /* Following code taken from QEGLPlatformBackingStore under the terms of the Lesser GPL v2.1 licence |
44 | + /* Following code a modified form of that in QEGLPlatformBackingStore, used under the terms of the Lesser GPL v2.1 licence |
45 | * Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). */ |
46 | Q_FOREACH (const QRect &rect, mDirty.rects()) { |
47 | + QRect scaledRect(rect.topLeft() * dpr, rect.size() * dpr); |
48 | // intersect with image rect to be sure |
49 | - QRect r = imageRect & rect; |
50 | + QRect r = imageRect & scaledRect; |
51 | |
52 | // if the rect is wide enough it is cheaper to just extend it instead of doing an image copy |
53 | if (r.width() >= imageRect.width() / 2) { |
54 | @@ -115,7 +119,9 @@ |
55 | |
56 | void UbuntuBackingStore::resize(const QSize& size, const QRegion& /*staticContents*/) |
57 | { |
58 | - mImage = QImage(size, QImage::Format_RGB32); |
59 | + const int dpr = int(window()->devicePixelRatio()); |
60 | + mImage = QImage(size * dpr, QImage::Format_RGB32); |
61 | + mImage.setDevicePixelRatio(dpr); |
62 | |
63 | if (mTexture->isCreated()) |
64 | mTexture->destroy(); |
65 | |
66 | === modified file 'src/ubuntumirclient/input.cpp' |
67 | --- src/ubuntumirclient/input.cpp 2016-01-05 16:32:27 +0000 |
68 | +++ src/ubuntumirclient/input.cpp 2016-01-05 16:32:27 +0000 |
69 | @@ -312,6 +312,7 @@ |
70 | const QRect kWindowGeometry = window->geometry(); |
71 | QList<QWindowSystemInterface::TouchPoint> touchPoints; |
72 | |
73 | + const int dpr = int(window->devicePixelRatio()); |
74 | |
75 | // TODO: Is it worth setting the Qt::TouchPointStationary ones? Currently they are left |
76 | // as Qt::TouchPointMoved |
77 | @@ -319,10 +320,10 @@ |
78 | for (unsigned int i = 0; i < kPointerCount; ++i) { |
79 | QWindowSystemInterface::TouchPoint touchPoint; |
80 | |
81 | - const float kX = mir_touch_event_axis_value(tev, i, mir_touch_axis_x) + kWindowGeometry.x(); |
82 | - const float kY = mir_touch_event_axis_value(tev, i, mir_touch_axis_y) + kWindowGeometry.y(); // see bug lp:1346633 workaround comments elsewhere |
83 | - const float kW = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_major); |
84 | - const float kH = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_minor); |
85 | + const float kX = mir_touch_event_axis_value(tev, i, mir_touch_axis_x) / dpr + kWindowGeometry.x(); |
86 | + const float kY = mir_touch_event_axis_value(tev, i, mir_touch_axis_y) / dpr + kWindowGeometry.y(); // see bug lp:1346633 workaround comments elsewhere |
87 | + const float kW = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_major) / dpr; |
88 | + const float kH = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_minor) / dpr; |
89 | const float kP = mir_touch_event_axis_value(tev, i, mir_touch_axis_pressure); |
90 | touchPoint.id = mir_touch_event_id(tev, i); |
91 | touchPoint.normalPosition = QPointF(kX / kWindowGeometry.width(), kY / kWindowGeometry.height()); |
92 | @@ -449,14 +450,16 @@ |
93 | |
94 | void UbuntuInput::dispatchPointerEvent(UbuntuWindow *platformWindow, const MirInputEvent *ev) |
95 | { |
96 | - auto window = platformWindow->window(); |
97 | - auto timestamp = mir_input_event_get_event_time(ev) / 1000000; |
98 | - |
99 | - auto pev = mir_input_event_get_pointer_event(ev); |
100 | - auto action = mir_pointer_event_action(pev); |
101 | - auto localPoint = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x), |
102 | - mir_pointer_event_axis_value(pev, mir_pointer_axis_y)); |
103 | - auto modifiers = qt_modifiers_from_mir(mir_pointer_event_modifiers(pev)); |
104 | + const int dpr = int(platformWindow->devicePixelRatio()); |
105 | + const auto window = platformWindow->window(); |
106 | + const auto timestamp = mir_input_event_get_event_time(ev) / 1000000; |
107 | + |
108 | + const auto pev = mir_input_event_get_pointer_event(ev); |
109 | + const auto action = mir_pointer_event_action(pev); |
110 | + |
111 | + const auto modifiers = qt_modifiers_from_mir(mir_pointer_event_modifiers(pev)); |
112 | + const auto localPoint = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x) / dpr, |
113 | + mir_pointer_event_axis_value(pev, mir_pointer_axis_y) / dpr); |
114 | |
115 | switch (action) { |
116 | case mir_pointer_action_button_up: |
117 | |
118 | === modified file 'src/ubuntumirclient/screen.cpp' |
119 | --- src/ubuntumirclient/screen.cpp 2016-01-05 16:32:27 +0000 |
120 | +++ src/ubuntumirclient/screen.cpp 2016-01-05 16:32:27 +0000 |
121 | @@ -18,6 +18,7 @@ |
122 | #include "screen.h" |
123 | #include "logging.h" |
124 | #include "orientationchangeevent_p.h" |
125 | +#include "utils.h" |
126 | |
127 | #include <mir_toolkit/mir_client_library.h> |
128 | |
129 | @@ -101,6 +102,14 @@ |
130 | } |
131 | } |
132 | |
133 | +namespace { |
134 | + int qGetEnvIntValue(const char *varName, bool *ok) |
135 | + { |
136 | + return qgetenv(varName).toInt(ok); |
137 | + } |
138 | +} // anonymous namespace |
139 | + |
140 | + |
141 | const QEvent::Type OrientationChangeEvent::mType = |
142 | static_cast<QEvent::Type>(QEvent::registerEventType()); |
143 | |
144 | @@ -164,18 +173,18 @@ |
145 | } |
146 | |
147 | // Set vblank swap interval. |
148 | - int swapInterval = kSwapInterval; |
149 | - QByteArray swapIntervalString = qgetenv("QTUBUNTU_SWAPINTERVAL"); |
150 | - if (!swapIntervalString.isEmpty()) { |
151 | - bool ok; |
152 | - swapInterval = swapIntervalString.toInt(&ok); |
153 | - if (!ok) |
154 | - swapInterval = kSwapInterval; |
155 | - } |
156 | - qCDebug(ubuntumirclient, "setting swap interval to %d", swapInterval); |
157 | + bool ok; |
158 | + int swapInterval = qGetEnvIntValue("QTUBUNTU_SWAPINTERVAL", &ok); |
159 | + if (!ok) |
160 | + swapInterval = kSwapInterval; |
161 | + |
162 | + qCDebug(ubuntumirclient, "Setting swap interval to %d", swapInterval); |
163 | eglSwapInterval(mEglDisplay, swapInterval); |
164 | |
165 | - // Get screen resolution. |
166 | + // Get screen resolution and properties. |
167 | + int dpr = qGetEnvIntValue("QT_DEVICE_PIXEL_RATIO", &ok); |
168 | + mDevicePixelRatio = (ok && dpr > 0) ? dpr : 1.0; |
169 | + |
170 | auto configDeleter = [](MirDisplayConfiguration *config) { mir_display_config_destroy(config); }; |
171 | using configUp = std::unique_ptr<MirDisplayConfiguration, decltype(configDeleter)>; |
172 | configUp displayConfig(mir_connection_create_display_config(connection), configDeleter); |
173 | @@ -187,14 +196,14 @@ |
174 | mOutputId = displayOutput->output_id; |
175 | |
176 | mPhysicalSize = QSizeF(displayOutput->physical_width_mm, displayOutput->physical_height_mm); |
177 | - qCDebug(ubuntumirclient, "screen physical size: %.2fx%.2f", mPhysicalSize.width(), mPhysicalSize.height()); |
178 | + qCDebug(ubuntumirclient, "Screen physical size: %.2fx%.2f mm", mPhysicalSize.width(), mPhysicalSize.height()); |
179 | |
180 | const MirDisplayMode *mode = &displayOutput->modes[displayOutput->current_mode]; |
181 | - const int kScreenWidth = mode->horizontal_resolution; |
182 | - const int kScreenHeight = mode->vertical_resolution; |
183 | - Q_ASSERT(kScreenWidth > 0 && kScreenHeight > 0); |
184 | + const int kScreenWidth = divideAndRoundUp(mode->horizontal_resolution, mDevicePixelRatio); |
185 | + const int kScreenHeight = divideAndRoundUp(mode->vertical_resolution, mDevicePixelRatio); |
186 | + ASSERT(kScreenWidth > 0 && kScreenHeight > 0); |
187 | |
188 | - qCDebug(ubuntumirclient, "screen resolution: %dx%d", kScreenWidth, kScreenHeight); |
189 | + qCDebug(ubuntumirclient, "Screen resolution: %dx%ddp", kScreenWidth, kScreenHeight); |
190 | |
191 | mGeometry = QRect(0, 0, kScreenWidth, kScreenHeight); |
192 | |
193 | |
194 | === modified file 'src/ubuntumirclient/screen.h' |
195 | --- src/ubuntumirclient/screen.h 2015-11-23 11:10:24 +0000 |
196 | +++ src/ubuntumirclient/screen.h 2016-01-05 16:32:27 +0000 |
197 | @@ -38,6 +38,7 @@ |
198 | QRect geometry() const override { return mGeometry; } |
199 | QRect availableGeometry() const override { return mGeometry; } |
200 | QSizeF physicalSize() const override { return mPhysicalSize; } |
201 | + qreal devicePixelRatio() const override { return mDevicePixelRatio; } |
202 | Qt::ScreenOrientation nativeOrientation() const override { return mNativeOrientation; } |
203 | Qt::ScreenOrientation orientation() const override { return mNativeOrientation; } |
204 | QPlatformCursor *cursor() const override { return const_cast<UbuntuCursor*>(&mCursor); } |
205 | @@ -56,6 +57,7 @@ |
206 | private: |
207 | QRect mGeometry; |
208 | QSizeF mPhysicalSize; |
209 | + qreal mDevicePixelRatio; |
210 | Qt::ScreenOrientation mNativeOrientation; |
211 | Qt::ScreenOrientation mCurrentOrientation; |
212 | QImage::Format mFormat; |
213 | |
214 | === modified file 'src/ubuntumirclient/ubuntumirclient.pro' |
215 | --- src/ubuntumirclient/ubuntumirclient.pro 2015-11-10 11:16:14 +0000 |
216 | +++ src/ubuntumirclient/ubuntumirclient.pro 2016-01-05 16:32:27 +0000 |
217 | @@ -42,7 +42,8 @@ |
218 | plugin.h \ |
219 | screen.h \ |
220 | theme.h \ |
221 | - window.h |
222 | + window.h \ |
223 | + utils.h |
224 | |
225 | # Installation path |
226 | target.path += $$[QT_INSTALL_PLUGINS]/platforms |
227 | |
228 | === added file 'src/ubuntumirclient/utils.h' |
229 | --- src/ubuntumirclient/utils.h 1970-01-01 00:00:00 +0000 |
230 | +++ src/ubuntumirclient/utils.h 2016-01-05 16:32:27 +0000 |
231 | @@ -0,0 +1,29 @@ |
232 | +/* |
233 | + * Copyright (C) 2015 Canonical, Ltd. |
234 | + * |
235 | + * This program is free software: you can redistribute it and/or modify it under |
236 | + * the terms of the GNU Lesser General Public License version 3, as published by |
237 | + * the Free Software Foundation. |
238 | + * |
239 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
240 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
241 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
242 | + * Lesser General Public License for more details. |
243 | + * |
244 | + * You should have received a copy of the GNU Lesser General Public License |
245 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
246 | + */ |
247 | + |
248 | +#ifndef UTILS_H |
249 | +#define UTILS_H |
250 | + |
251 | +#include <QtGlobal> |
252 | + |
253 | +namespace { |
254 | + inline int divideAndRoundUp(int numerator, qreal denominator) |
255 | + { |
256 | + return ceil((qreal)numerator / denominator); |
257 | + } |
258 | +} // anonymous namespace |
259 | + |
260 | +#endif // UTILS_H |
261 | |
262 | === modified file 'src/ubuntumirclient/window.cpp' |
263 | --- src/ubuntumirclient/window.cpp 2016-01-05 16:32:27 +0000 |
264 | +++ src/ubuntumirclient/window.cpp 2016-01-05 16:32:27 +0000 |
265 | @@ -19,6 +19,7 @@ |
266 | #include "clipboard.h" |
267 | #include "input.h" |
268 | #include "screen.h" |
269 | +#include "utils.h" |
270 | #include "logging.h" |
271 | |
272 | #include <mir_toolkit/mir_client_library.h> |
273 | @@ -34,6 +35,11 @@ |
274 | |
275 | #include <EGL/egl.h> |
276 | |
277 | + |
278 | +/* |
279 | + * Note: all geometry is in device-independent pixels, except that contained in variables with the |
280 | + * suffix "Px" - whose units are (physical) pixels |
281 | + */ |
282 | Q_LOGGING_CATEGORY(ubuntumirclientBufferSwap, "ubuntumirclient.bufferSwap", QtWarningMsg) |
283 | |
284 | namespace |
285 | @@ -134,13 +140,14 @@ |
286 | Spec makeSurfaceSpec(QWindow *window, UbuntuInput *input, MirConnection *connection) |
287 | { |
288 | const auto geom = window->geometry(); |
289 | - const int width = geom.width() > 0 ? geom.width() : 1; |
290 | - const int height = geom.height() > 0 ? geom.height() : 1; |
291 | + const int dpr = int(window->devicePixelRatio()); |
292 | + const int widthPx = geom.width() > 0 ? geom.width() * dpr : 1; |
293 | + const int heightPx = geom.height() > 0 ? geom.height() * dpr : 1; |
294 | const auto pixelFormat = defaultPixelFormatFor(connection); |
295 | |
296 | if (U_ON_SCREEN_KEYBOARD_ROLE == roleFor(window)) { |
297 | - qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating input method surface (width=%d, height=%d", window, width, height); |
298 | - return Spec{mir_connection_create_spec_for_input_method(connection, width, height, pixelFormat)}; |
299 | + qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating input method surface with size=(%dx%d)px", window, widthPx, heightPx); |
300 | + return Spec{mir_connection_create_spec_for_input_method(connection, widthPx, heightPx, pixelFormat)}; |
301 | } |
302 | |
303 | const Qt::WindowType type = window->type(); |
304 | @@ -153,13 +160,13 @@ |
305 | parent = input->lastFocusedWindow(); |
306 | } |
307 | if (parent) { |
308 | - auto pos = geom.topLeft(); |
309 | - pos -= parent->geometry().topLeft(); |
310 | - MirRectangle location{pos.x(), pos.y(), 0, 0}; |
311 | - qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating menu surface(width:%d, height:%d)", window, width, height); |
312 | + auto posPx = geom.topLeft() * dpr; |
313 | + posPx -= parent->geometry().topLeft() * dpr; |
314 | + MirRectangle location{posPx.x(), posPx.y(), 0, 0}; |
315 | + qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating menu surface with size=(%dx%d)px", window, widthPx, heightPx); |
316 | return Spec{mir_connection_create_spec_for_menu( |
317 | - connection, width, height, pixelFormat, parent->mirSurface(), |
318 | - &location, mir_edge_attachment_any)}; |
319 | + connection, widthPx, heightPx, pixelFormat, parent->mirSurface(), |
320 | + &location, mir_edge_attachment_any)}; |
321 | } else { |
322 | qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - cannot create a menu without a parent!", window); |
323 | } |
324 | @@ -167,33 +174,33 @@ |
325 | auto parent = transientParentFor(window); |
326 | if (parent) { |
327 | // Modal dialog |
328 | - qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating modal dialog (width=%d, height=%d", window, width, height); |
329 | - return Spec{mir_connection_create_spec_for_modal_dialog(connection, width, height, pixelFormat, parent->mirSurface())}; |
330 | + qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating modal dialog with size=(%dx%d)px", window, widthPx, heightPx); |
331 | + return Spec{mir_connection_create_spec_for_modal_dialog(connection, widthPx, heightPx, pixelFormat, parent->mirSurface())}; |
332 | } else { |
333 | // TODO: do Qt parentless dialogs have the same semantics as mir? |
334 | - qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating parentless dialog (width=%d, height=%d)", window, width, height); |
335 | - return Spec{mir_connection_create_spec_for_dialog(connection, width, height, pixelFormat)}; |
336 | + qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating parentless dialog with size=(%dx%d)px", window, widthPx, heightPx); |
337 | + return Spec{mir_connection_create_spec_for_dialog(connection, widthPx, heightPx, pixelFormat)}; |
338 | } |
339 | } |
340 | - qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating normal surface(type=0x%x, width=%d, height=%d)", window, type, width, height); |
341 | - return Spec{mir_connection_create_spec_for_normal_surface(connection, width, height, pixelFormat)}; |
342 | + qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating normal surface(type=0x%x, with size=(%dx%d)px", window, type, widthPx, heightPx); |
343 | + return Spec{mir_connection_create_spec_for_normal_surface(connection, widthPx, heightPx, pixelFormat)}; |
344 | } |
345 | |
346 | -void setSizingConstraints(MirSurfaceSpec *spec, const QSize& minSize, const QSize& maxSize, const QSize& increment) |
347 | +void setSizingConstraints(MirSurfaceSpec *spec, const QSize &minSizePx, const QSize &maxSizePx, const QSize &incrementPx) |
348 | { |
349 | - mir_surface_spec_set_min_width(spec, minSize.width()); |
350 | - mir_surface_spec_set_min_height(spec, minSize.height()); |
351 | - if (maxSize.width() >= minSize.width()) { |
352 | - mir_surface_spec_set_max_width(spec, maxSize.width()); |
353 | - } |
354 | - if (maxSize.height() >= minSize.height()) { |
355 | - mir_surface_spec_set_max_height(spec, maxSize.height()); |
356 | - } |
357 | - if (increment.width() > 0) { |
358 | - mir_surface_spec_set_width_increment(spec, increment.width()); |
359 | - } |
360 | - if (increment.height() > 0) { |
361 | - mir_surface_spec_set_height_increment(spec, increment.height()); |
362 | + mir_surface_spec_set_min_width(spec, minSizePx.width()); |
363 | + mir_surface_spec_set_min_height(spec, minSizePx.height()); |
364 | + if (maxSizePx.width() >= minSizePx.width()) { |
365 | + mir_surface_spec_set_max_width(spec, maxSizePx.width()); |
366 | + } |
367 | + if (maxSizePx.height() >= minSizePx.height()) { |
368 | + mir_surface_spec_set_max_height(spec, maxSizePx.height()); |
369 | + } |
370 | + if (incrementPx.width() > 0) { |
371 | + mir_surface_spec_set_width_increment(spec, incrementPx.width()); |
372 | + } |
373 | + if (incrementPx.height() > 0) { |
374 | + mir_surface_spec_set_height_increment(spec, incrementPx.height()); |
375 | } |
376 | } |
377 | |
378 | @@ -233,6 +240,10 @@ |
379 | |
380 | } //namespace |
381 | |
382 | +/* |
383 | + * UbuntuSurface - wraps a MirSurface |
384 | + * All units are in pixels only (no device pixels). |
385 | + */ |
386 | class UbuntuSurface |
387 | { |
388 | public: |
389 | @@ -248,7 +259,6 @@ |
390 | , mNeedsRepaint(false) |
391 | , mParented(mWindow->transientParent() || mWindow->parent()) |
392 | , mWindowState(mWindow->windowState()) |
393 | - |
394 | { |
395 | mir_surface_set_event_handler(mMirSurface, surfaceEventCallback, this); |
396 | |
397 | @@ -257,22 +267,13 @@ |
398 | MirSurfaceParameters parameters; |
399 | mir_surface_get_parameters(mMirSurface, ¶meters); |
400 | |
401 | - auto geom = mWindow->geometry(); |
402 | - geom.setWidth(parameters.width); |
403 | - geom.setHeight(parameters.height); |
404 | - if (mWindowState == Qt::WindowFullScreen) { |
405 | - geom.setY(0); |
406 | - } else { |
407 | - geom.setY(panelHeight()); |
408 | - } |
409 | - |
410 | // Assume that the buffer size matches the surface size at creation time |
411 | - mBufferSize = geom.size(); |
412 | - platformWindow->QPlatformWindow::setGeometry(geom); |
413 | - QWindowSystemInterface::handleGeometryChange(mWindow, geom); |
414 | + mBufferSizePx.rwidth() = parameters.width; |
415 | + mBufferSizePx.rheight() = parameters.height; |
416 | |
417 | - qCDebug(ubuntumirclient, "created surface at (%d, %d) with size (%d, %d), title '%s', role: '%d'\n", |
418 | - geom.x(), geom.y(), geom.width(), geom.height(), mWindow->title().toUtf8().constData(), roleFor(mWindow)); |
419 | + qCDebug(ubuntumirclient, "created surface with size=(%dx%d)px, title='%s', role=%d", |
420 | + parameters.width, parameters.height, qPrintable(mWindow->title()), roleFor(mWindow)); |
421 | + mPlatformWindow->updateWindowSize(parameters.width, parameters.height); |
422 | } |
423 | |
424 | ~UbuntuSurface() |
425 | @@ -283,24 +284,24 @@ |
426 | mir_surface_release_sync(mMirSurface); |
427 | } |
428 | |
429 | - UbuntuSurface(UbuntuSurface const&) = delete; |
430 | - UbuntuSurface& operator=(UbuntuSurface const&) = delete; |
431 | + UbuntuSurface(const UbuntuSurface &) = delete; |
432 | + UbuntuSurface& operator=(const UbuntuSurface &) = delete; |
433 | |
434 | - void resize(const QSize& newSize); |
435 | + void resize(const QSize &newSizePx); |
436 | void setState(Qt::WindowState newState); |
437 | void setVisible(bool state); |
438 | - void updateTitle(const QString& title); |
439 | - void setSizingConstraints(const QSize& minSize, const QSize& maxSize, const QSize& increment); |
440 | + void updateTitle(const QString &title); |
441 | + void setSizingConstraints(const QSize &minSizePx, const QSize &maxSizePx, const QSize &incrementPx); |
442 | |
443 | void onSwapBuffersDone(); |
444 | - void handleSurfaceResized(int width, int height); |
445 | + void handleSurfaceResized(int widthPx, int heightPx); |
446 | int needsRepaint() const; |
447 | |
448 | EGLSurface eglSurface() const { return mEglSurface; } |
449 | MirSurface *mirSurface() const { return mMirSurface; } |
450 | |
451 | private: |
452 | - static void surfaceEventCallback(MirSurface* surface, const MirEvent *event, void* context); |
453 | + static void surfaceEventCallback(MirSurface *surface, const MirEvent *event, void *context); |
454 | void postEvent(const MirEvent *event); |
455 | void updateSurface(); |
456 | |
457 | @@ -317,29 +318,29 @@ |
458 | bool mNeedsRepaint; |
459 | bool mParented; |
460 | Qt::WindowState mWindowState; |
461 | - QSize mBufferSize; |
462 | + QSize mBufferSizePx; |
463 | |
464 | QMutex mTargetSizeMutex; |
465 | - QSize mTargetSize; |
466 | + QSize mTargetSizePx; |
467 | }; |
468 | |
469 | -void UbuntuSurface::resize(const QSize& size) |
470 | +void UbuntuSurface::resize(const QSize &sizePx) |
471 | { |
472 | - qCDebug(ubuntumirclient,"resize(window=%p, width=%d, height=%d)", mWindow, size.width(), size.height()); |
473 | + qCDebug(ubuntumirclient,"resize(window=%p) to (%dx%d)px", mWindow, sizePx.width(), sizePx.height()); |
474 | |
475 | if (mWindowState == Qt::WindowFullScreen || mWindowState == Qt::WindowMaximized) { |
476 | qCDebug(ubuntumirclient, "resize(window=%p) - not resizing, window is maximized or fullscreen", mWindow); |
477 | return; |
478 | } |
479 | |
480 | - if (size.isEmpty()) { |
481 | + if (sizePx.isEmpty()) { |
482 | qCDebug(ubuntumirclient, "resize(window=%p) - not resizing, size is empty", mWindow); |
483 | return; |
484 | } |
485 | |
486 | Spec spec{mir_connection_create_spec_for_changes(mConnection)}; |
487 | - mir_surface_spec_set_width(spec.get(), size.width()); |
488 | - mir_surface_spec_set_height(spec.get(), size.height()); |
489 | + mir_surface_spec_set_width(spec.get(), sizePx.width()); |
490 | + mir_surface_spec_set_height(spec.get(), sizePx.height()); |
491 | mir_surface_apply_spec(mMirSurface, spec.get()); |
492 | } |
493 | |
494 | @@ -365,7 +366,7 @@ |
495 | mir_wait_for(mir_surface_set_state(mMirSurface, newState)); |
496 | } |
497 | |
498 | -void UbuntuSurface::updateTitle(const QString& newTitle) |
499 | +void UbuntuSurface::updateTitle(const QString &newTitle) |
500 | { |
501 | const auto title = newTitle.toUtf8(); |
502 | Spec spec{mir_connection_create_spec_for_changes(mConnection)}; |
503 | @@ -373,14 +374,14 @@ |
504 | mir_surface_apply_spec(mMirSurface, spec.get()); |
505 | } |
506 | |
507 | -void UbuntuSurface::setSizingConstraints(const QSize& minSize, const QSize& maxSize, const QSize& increment) |
508 | +void UbuntuSurface::setSizingConstraints(const QSize &minSizePx, const QSize &maxSizePx, const QSize &incrementPx) |
509 | { |
510 | Spec spec{mir_connection_create_spec_for_changes(mConnection)}; |
511 | - ::setSizingConstraints(spec.get(), minSize, maxSize, increment); |
512 | + ::setSizingConstraints(spec.get(), minSizePx, maxSizePx, incrementPx); |
513 | mir_surface_apply_spec(mMirSurface, spec.get()); |
514 | } |
515 | |
516 | -void UbuntuSurface::handleSurfaceResized(int width, int height) |
517 | +void UbuntuSurface::handleSurfaceResized(int widthPx, int heightPx) |
518 | { |
519 | QMutexLocker lock(&mTargetSizeMutex); |
520 | |
521 | @@ -390,13 +391,13 @@ |
522 | // see TODO in postEvent as the ideal way we should handle this. |
523 | // The actual buffer size may or may have not changed at this point, so let the rendering |
524 | // thread drive the window geometry updates. |
525 | - mNeedsRepaint = mTargetSize.width() == width && mTargetSize.height() == height; |
526 | + mNeedsRepaint = mTargetSizePx.width() == widthPx && mTargetSizePx.height() == heightPx; |
527 | } |
528 | |
529 | int UbuntuSurface::needsRepaint() const |
530 | { |
531 | if (mNeedsRepaint) { |
532 | - if (mTargetSize != mBufferSize) { |
533 | + if (mTargetSizePx != mBufferSizePx) { |
534 | //If the buffer hasn't changed yet, we need at least two redraws, |
535 | //once to get the new buffer size and propagate the geometry changes |
536 | //and the second to redraw the content at the new size |
537 | @@ -415,29 +416,25 @@ |
538 | static int sFrameNumber = 0; |
539 | ++sFrameNumber; |
540 | |
541 | - EGLint eglSurfaceWidth = -1; |
542 | - EGLint eglSurfaceHeight = -1; |
543 | - eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &eglSurfaceWidth); |
544 | - eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &eglSurfaceHeight); |
545 | - |
546 | - const bool validSize = eglSurfaceWidth > 0 && eglSurfaceHeight > 0; |
547 | - |
548 | - if (validSize && (mBufferSize.width() != eglSurfaceWidth || mBufferSize.height() != eglSurfaceHeight)) { |
549 | - |
550 | - qCDebug(ubuntumirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d] - size changed (%d, %d) => (%d, %d)", |
551 | - mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height(), eglSurfaceWidth, eglSurfaceHeight); |
552 | - |
553 | - mBufferSize.rwidth() = eglSurfaceWidth; |
554 | - mBufferSize.rheight() = eglSurfaceHeight; |
555 | - |
556 | - QRect newGeometry = mPlatformWindow->geometry(); |
557 | - newGeometry.setSize(mBufferSize); |
558 | - |
559 | - mPlatformWindow->QPlatformWindow::setGeometry(newGeometry); |
560 | - QWindowSystemInterface::handleGeometryChange(mWindow, newGeometry); |
561 | + EGLint eglSurfaceWidthPx = -1; |
562 | + EGLint eglSurfaceHeightPx = -1; |
563 | + eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &eglSurfaceWidthPx); |
564 | + eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &eglSurfaceHeightPx); |
565 | + |
566 | + const bool validSize = eglSurfaceWidthPx > 0 && eglSurfaceHeightPx > 0; |
567 | + |
568 | + if (validSize && (mBufferSizePx.width() != eglSurfaceWidthPx || mBufferSizePx.height() != eglSurfaceHeightPx)) { |
569 | + |
570 | + qCDebug(ubuntumirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d] - buffer size changed (%dx%d)px => (%dx%d)px", |
571 | + mWindow, sFrameNumber, mBufferSizePx.width(), mBufferSizePx.height(), eglSurfaceWidthPx, eglSurfaceHeightPx); |
572 | + |
573 | + mBufferSizePx.rwidth() = eglSurfaceWidthPx; |
574 | + mBufferSizePx.rheight() = eglSurfaceHeightPx; |
575 | + |
576 | + mPlatformWindow->updateWindowSize(eglSurfaceWidthPx, eglSurfaceHeightPx); |
577 | } else { |
578 | - qCDebug(ubuntumirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d] - buffer size (%d,%d)", |
579 | - mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height()); |
580 | + qCDebug(ubuntumirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d] - buffer size=(%dx%d)px", |
581 | + mWindow, sFrameNumber, mBufferSizePx.width(), mBufferSizePx.height()); |
582 | } |
583 | } |
584 | |
585 | @@ -458,13 +455,13 @@ |
586 | // As a workaround, we use the width/height as an identifier of this latest event |
587 | // so the event handler (handleSurfaceResized) can discard/ignore old ones. |
588 | const auto resizeEvent = mir_event_get_resize_event(event); |
589 | - const auto width = mir_resize_event_get_width(resizeEvent); |
590 | - const auto height = mir_resize_event_get_height(resizeEvent); |
591 | - qCDebug(ubuntumirclient, "resizeEvent(window=%p, width=%d, height=%d)", mWindow, width, height); |
592 | + const auto widthPx = mir_resize_event_get_width(resizeEvent); |
593 | + const auto heightPx = mir_resize_event_get_height(resizeEvent); |
594 | + qCDebug(ubuntumirclient, "resizeEvent(window=%p, size=(%dx%d)px", mWindow, widthPx, heightPx); |
595 | |
596 | QMutexLocker lock(&mTargetSizeMutex); |
597 | - mTargetSize.rwidth() = width; |
598 | - mTargetSize.rheight() = height; |
599 | + mTargetSizePx.rwidth() = widthPx; |
600 | + mTargetSizePx.rheight() = heightPx; |
601 | } |
602 | |
603 | mInput->postEvent(mPlatformWindow, event); |
604 | @@ -496,7 +493,10 @@ |
605 | , mClipboard(clipboard) |
606 | , mSurface(new UbuntuSurface{this, screen, input, connection}) |
607 | { |
608 | - qCDebug(ubuntumirclient, "UbuntuWindow(window=%p, screen=%p, input=%p, surf=%p)", w, screen, input, mSurface.get()); |
609 | + qCDebug(ubuntumirclient, "UbuntuWindow(window=%p, screen=%p, input=%p, surf=%p) with title '%s', role: '%d'", |
610 | + w, screen, input, mSurface.get(), qPrintable(window()->title()), roleFor(window())); |
611 | + |
612 | + enablePanelHeightHack(w->windowState() != Qt::WindowFullScreen); |
613 | } |
614 | |
615 | UbuntuWindow::~UbuntuWindow() |
616 | @@ -504,12 +504,25 @@ |
617 | qCDebug(ubuntumirclient, "~UbuntuWindow(window=%p)", this); |
618 | } |
619 | |
620 | -void UbuntuWindow::handleSurfaceResized(int width, int height) |
621 | +void UbuntuWindow::updateWindowSize(int widthPx, int heightPx) // after when Mir has resized the surface |
622 | +{ |
623 | + const float dpr = devicePixelRatio(); |
624 | + auto geom = geometry(); |
625 | + geom.setWidth(divideAndRoundUp(widthPx, dpr)); |
626 | + geom.setHeight(divideAndRoundUp(heightPx, dpr)); |
627 | + |
628 | + QPlatformWindow::setGeometry(geom); |
629 | + QWindowSystemInterface::handleGeometryChange(window(), geom); |
630 | + |
631 | + qCDebug(ubuntumirclient) << "Surface geometry updated:" << geom; |
632 | +} |
633 | + |
634 | +void UbuntuWindow::handleSurfaceResized(int widthPx, int heightPx) |
635 | { |
636 | QMutexLocker lock(&mMutex); |
637 | - qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p, width=%d, height=%d)", window(), width, height); |
638 | + qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p, size=(%dx%d)px", window(), widthPx, heightPx); |
639 | |
640 | - mSurface->handleSurfaceResized(width, height); |
641 | + mSurface->handleSurfaceResized(widthPx, heightPx); |
642 | |
643 | // This resize event could have occurred just after the last buffer swap for this window. |
644 | // This means the client may still be holding a buffer with the older size. The first redraw call |
645 | @@ -519,7 +532,7 @@ |
646 | auto const numRepaints = mSurface->needsRepaint(); |
647 | qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p) redraw %d times", window(), numRepaints); |
648 | for (int i = 0; i < numRepaints; i++) { |
649 | - qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p) repainting width=%d, height=%d", window(), geometry().size().width(), geometry().size().height()); |
650 | + qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p) repainting size=(%dx%d)dp", window(), geometry().size().width(), geometry().size().height()); |
651 | QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); |
652 | } |
653 | } |
654 | @@ -543,7 +556,7 @@ |
655 | qCDebug(ubuntumirclient, "setWindowState(window=%p, %s)", this, qtWindowStateToStr(state)); |
656 | mSurface->setState(state); |
657 | |
658 | - updatePanelHeightHack(state); |
659 | + enablePanelHeightHack(state != Qt::WindowFullScreen); |
660 | } |
661 | |
662 | /* |
663 | @@ -552,34 +565,34 @@ |
664 | window is always on the top-left corner, right below the indicators panel if not |
665 | in fullscreen. |
666 | */ |
667 | -void UbuntuWindow::updatePanelHeightHack(Qt::WindowState state) |
668 | +void UbuntuWindow::enablePanelHeightHack(bool enable) |
669 | { |
670 | - if (state == Qt::WindowFullScreen && geometry().y() != 0) { |
671 | - QRect newGeometry = geometry(); |
672 | + QRect newGeometry = geometry(); |
673 | + if (enable) { |
674 | + newGeometry.setY(panelHeight()); |
675 | + } else { |
676 | newGeometry.setY(0); |
677 | - QPlatformWindow::setGeometry(newGeometry); |
678 | - QWindowSystemInterface::handleGeometryChange(window(), newGeometry); |
679 | - } else if (geometry().y() == 0) { |
680 | - QRect newGeometry = geometry(); |
681 | - newGeometry.setY(panelHeight()); |
682 | + } |
683 | + |
684 | + if (newGeometry != geometry()) { |
685 | QPlatformWindow::setGeometry(newGeometry); |
686 | QWindowSystemInterface::handleGeometryChange(window(), newGeometry); |
687 | } |
688 | } |
689 | |
690 | -void UbuntuWindow::setGeometry(const QRect& rect) |
691 | +void UbuntuWindow::setGeometry(const QRect &rect) |
692 | { |
693 | QMutexLocker lock(&mMutex); |
694 | - qCDebug(ubuntumirclient, "setGeometry (window=%p, x=%d, y=%d, width=%d, height=%d)", |
695 | - window(), rect.x(), rect.y(), rect.width(), rect.height()); |
696 | + qCDebug(ubuntumirclient, "setGeometry (window=%p, position=(%d, %d)dp, size=(%dx%d)dp)", |
697 | + window(), rect.x(), rect.y(), rect.width(), rect.height()); |
698 | |
699 | //NOTE: mir surfaces cannot be moved by the client so ignore the topLeft coordinates |
700 | const auto newSize = rect.size(); |
701 | auto newGeometry = geometry(); |
702 | newGeometry.setSize(newSize); |
703 | - QPlatformWindow::setGeometry(newGeometry); |
704 | |
705 | - mSurface->resize(newSize); |
706 | + mSurface->resize(newSize * devicePixelRatio()); |
707 | + // Note: don't call handleGeometryChange here, wait to see what Mir replies with. |
708 | } |
709 | |
710 | void UbuntuWindow::setVisible(bool visible) |
711 | @@ -595,7 +608,7 @@ |
712 | QWindowSystemInterface::flushWindowSystemEvents(); |
713 | } |
714 | |
715 | -void UbuntuWindow::setWindowTitle(const QString& title) |
716 | +void UbuntuWindow::setWindowTitle(const QString &title) |
717 | { |
718 | QMutexLocker lock(&mMutex); |
719 | qCDebug(ubuntumirclient, "setWindowTitle(window=%p) title=%s)", window(), title.toUtf8().constData()); |
720 | @@ -606,11 +619,17 @@ |
721 | { |
722 | QMutexLocker lock(&mMutex); |
723 | const auto win = window(); |
724 | - qCDebug(ubuntumirclient, "propagateSizeHints(window=%p) min(%d,%d), max(%d,%d) increment(%d, %d)", |
725 | - win, win->minimumSize().width(), win->minimumSize().height(), |
726 | - win->maximumSize().width(), win->maximumSize().height(), |
727 | - win->sizeIncrement().width(), win->sizeIncrement().height()); |
728 | - mSurface->setSizingConstraints(win->minimumSize(), win->maximumSize(), win->sizeIncrement()); |
729 | + const float dpr = devicePixelRatio(); |
730 | + qCDebug(ubuntumirclient, "propagateSizeHints(window=%p) min(%dx%d)dp; max(%dx%d)dp; increment(%dx%d)dp", |
731 | + win, win->minimumSize().width(), win->minimumSize().height(), |
732 | + win->maximumSize().width(), win->maximumSize().height(), |
733 | + win->sizeIncrement().width(), win->sizeIncrement().height()); |
734 | + mSurface->setSizingConstraints(win->minimumSize() * dpr, win->maximumSize() * dpr, win->sizeIncrement() * dpr); |
735 | +} |
736 | + |
737 | +qreal UbuntuWindow::devicePixelRatio() const |
738 | +{ |
739 | + return screen() ? screen()->devicePixelRatio() : 1.0; // not impossible a Window has no attached Screen |
740 | } |
741 | |
742 | void* UbuntuWindow::eglSurface() const |
743 | |
744 | === modified file 'src/ubuntumirclient/window.h' |
745 | --- src/ubuntumirclient/window.h 2016-01-05 16:32:27 +0000 |
746 | +++ src/ubuntumirclient/window.h 2016-01-05 16:32:27 +0000 |
747 | @@ -46,16 +46,18 @@ |
748 | void setVisible(bool visible) override; |
749 | void setWindowTitle(const QString &title) override; |
750 | void propagateSizeHints() override; |
751 | + qreal devicePixelRatio() const override; |
752 | |
753 | // New methods. |
754 | void *eglSurface() const; |
755 | MirSurface *mirSurface() const; |
756 | - void handleSurfaceResized(int width, int height); |
757 | + void updateWindowSize(int widthPx, int heightPx); |
758 | + void handleSurfaceResized(int widthPx, int heightPx); |
759 | void handleSurfaceFocused(); |
760 | void onSwapBuffersDone(); |
761 | |
762 | private: |
763 | - void updatePanelHeightHack(Qt::WindowState); |
764 | + void enablePanelHeightHack(bool enable); |
765 | mutable QMutex mMutex; |
766 | const WId mId; |
767 | const QSharedPointer<UbuntuClipboard> mClipboard; |
PASSED: Continuous integration, rev:261 jenkins. qa.ubuntu. com/job/ qtubuntu- ci/204/ jenkins. qa.ubuntu. com/job/ qtubuntu- vivid-armhf- ci/30 jenkins. qa.ubuntu. com/job/ qtubuntu- vivid-armhf- ci/30/artifact/ work/output/ *zip*/output. zip
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/qtubuntu- ci/204/ rebuild
http://