Merge lp:~unity-team/qtubuntu/DPR2 into lp:qtubuntu

Proposed by Gerry Boland
Status: Work in progress
Proposed branch: lp:~unity-team/qtubuntu/DPR2
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/DPR2
Reviewer Review Type Date Requested Status
Unity8 CI Bot continuous-integration Needs Fixing
Daniel d'Andrada (community) Approve
PS Jenkins bot continuous-integration Approve
Review via email: mp+281664@code.launchpad.net

This proposal supersedes a proposal from 2015-12-17.

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_PIXEL_RATIO=2
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://code.launchpad.net/~unity-team/qtmir/dpr/+merge/257514

 * 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

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

In src/ubuntumirclient/window.cpp

"""
    // Window manager can give us a final size different from what we asked for
    // so let's check what we ended up getting
    {
        MirSurfaceParameters parameters;
        mir_surface_get_parameters(d->surface, &parameters);

        geometry.setWidth(divideAndRoundUp(parameters.width, devicePixelRatio()));
        geometry.setHeight(divideAndRoundUp(parameters.height, devicePixelRatio()));

        DLOG("[ubuntumirclient QPA] created surface has pixel size (%d, %d) and device-pixel size (%d, %d)",
                parameters.width, parameters.height, geometry.width(), geometry.height());
    }

    // 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[...]".

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
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.

Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

In src/ubuntumirclient/window.cpp:

"""
    DLOG("[ubuntumirclient QPA] creating surface at (%d, %d) with pixel size (%d, %d) with title '%s'\n",
            d->bufferSizePx.x(), d->bufferSizePx.y(), d->bufferSizePx.width(), d->bufferSizePx.height(), title.data());
"""

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?

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal

Ok, should be good to go

Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

Looks good to me (didn't test yet).

review: Approve (code)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

And it works fine as well.

review: Approve
Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

Why is that function in src/ubuntumirclient/utils.h inside an anonymous namespace?

review: Needs Information
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal

> Why is that function in src/ubuntumirclient/utils.h inside an anonymous
> namespace?

To stop it polluting the global namespace. The header file is private.

Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

Why did you remove that chunk from UbuntuSurface constructor in src/ubuntumirclient/window.cpp? In any case that removal is unrelated to DPR work.

"""
        auto geom = mWindow->geometry();
        geom.setWidth(parameters.width);
        geom.setHeight(parameters.height);
        if (mWindowState == Qt::WindowFullScreen) {
            geom.setY(0);
        } else {
            geom.setY(panelHeight());
        }
"""

Revision history for this message
Daniel d'Andrada (dandrader) : Posted in a previous version of this proposal
review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

On 17/12/2015 11:52, Daniel d'Andrada wrote:
> Why did you remove that chunk from UbuntuSurface constructor in src/ubuntumirclient/window.cpp? In any case that removal is unrelated to DPR work.
>
> """
> auto geom = mWindow->geometry();
> geom.setWidth(parameters.width);
> geom.setHeight(parameters.height);
> if (mWindowState == Qt::WindowFullScreen) {
> geom.setY(0);
> } else {
> geom.setY(panelHeight());
> }
> """

And so is the panel hack refactoring you're doing.

Revision history for this message
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal

> Why did you remove that chunk from UbuntuSurface constructor in
> src/ubuntumirclient/window.cpp? In any case that removal is unrelated to DPR
> work.
>
> """
> auto geom = mWindow->geometry();
> geom.setWidth(parameters.width);
> geom.setHeight(parameters.height);
> if (mWindowState == Qt::WindowFullScreen) {
> geom.setY(0);
> } else {
> geom.setY(panelHeight());
> }
> """

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.

Revision history for this message
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal

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::WindowFullScreen && geometry().y() != 0) {
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.

Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

Code looks ok

review: Approve (code)
Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

Works fine.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

Still works fine

review: Approve
Revision history for this message
Michał Sawicz (saviq) wrote :

Text conflict in src/ubuntumirclient/input.cpp
Text conflict in src/ubuntumirclient/window.cpp
Text conflict in src/ubuntumirclient/window.h
3 conflicts encountered.

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

Unmerged revisions

307. By Gerry Boland

Fix compile error from bad merge

306. By Gerry Boland

Merge DPI branch

305. By Gerry Boland

lp:~dandrader/qtubuntu/loggingCategory

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2016-01-04 09:38:35 +0000
3+++ debian/changelog 2016-01-06 13:29:28 +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-06 13:29:28 +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-06 13:29:28 +0000
68+++ src/ubuntumirclient/input.cpp 2016-01-06 13:29:28 +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-06 13:29:28 +0000
120+++ src/ubuntumirclient/screen.cpp 2016-01-06 13:29:28 +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-06 13:29:28 +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-06 13:29:28 +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-06 13:29:28 +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-06 13:29:28 +0000
264+++ src/ubuntumirclient/window.cpp 2016-01-06 13:29:28 +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, &parameters);
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-06 13:29:28 +0000
746+++ src/ubuntumirclient/window.h 2016-01-06 13:29:28 +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;

Subscribers

People subscribed via source and target branches