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
=== modified file 'debian/changelog'
--- debian/changelog 2016-01-04 09:38:35 +0000
+++ debian/changelog 2016-01-06 13:29:28 +0000
@@ -1,3 +1,9 @@
1qtubuntu (0.63) UNRELEASED; urgency=medium
2
3 * Add support for Qt5's devicePixelRatio UI scaling mechanism
4
5 -- Gerry Boland <gerry.boland@canonical.com> Tue, 05 Jan 2016 16:31:27 +0100
6
1qtubuntu (0.62+16.04.20160104-0ubuntu1) xenial; urgency=medium7qtubuntu (0.62+16.04.20160104-0ubuntu1) xenial; urgency=medium
28
3 [ Daniel d'Andrada ]9 [ Daniel d'Andrada ]
410
=== modified file 'src/ubuntumirclient/backingstore.cpp'
--- src/ubuntumirclient/backingstore.cpp 2014-12-04 12:29:39 +0000
+++ src/ubuntumirclient/backingstore.cpp 2016-01-06 13:29:28 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (C) 2014 Canonical, Ltd.2 * Copyright (C) 2014-2015 Canonical, Ltd.
3 *3 *
4 * This program is free software: you can redistribute it and/or modify it under4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by5 * the terms of the GNU Lesser General Public License version 3, as published by
@@ -43,8 +43,10 @@
43{43{
44 Q_UNUSED(region);44 Q_UNUSED(region);
45 Q_UNUSED(offset);45 Q_UNUSED(offset);
46 const int dpr = int(window->devicePixelRatio());
47
46 mContext->makeCurrent(window);48 mContext->makeCurrent(window);
47 glViewport(0, 0, window->width(), window->height());49 glViewport(0, 0, window->width() * dpr, window->height() * dpr);
4850
49 updateTexture();51 updateTexture();
5052
@@ -75,12 +77,14 @@
7577
76 QRegion fixed;78 QRegion fixed;
77 QRect imageRect = mImage.rect();79 QRect imageRect = mImage.rect();
80 const int dpr = int(window()->devicePixelRatio());
7881
79 /* Following code taken from QEGLPlatformBackingStore under the terms of the Lesser GPL v2.1 licence82 /* Following code a modified form of that in QEGLPlatformBackingStore, used under the terms of the Lesser GPL v2.1 licence
80 * Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). */83 * Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). */
81 Q_FOREACH (const QRect &rect, mDirty.rects()) {84 Q_FOREACH (const QRect &rect, mDirty.rects()) {
85 QRect scaledRect(rect.topLeft() * dpr, rect.size() * dpr);
82 // intersect with image rect to be sure86 // intersect with image rect to be sure
83 QRect r = imageRect & rect;87 QRect r = imageRect & scaledRect;
8488
85 // if the rect is wide enough it is cheaper to just extend it instead of doing an image copy89 // if the rect is wide enough it is cheaper to just extend it instead of doing an image copy
86 if (r.width() >= imageRect.width() / 2) {90 if (r.width() >= imageRect.width() / 2) {
@@ -115,7 +119,9 @@
115119
116void UbuntuBackingStore::resize(const QSize& size, const QRegion& /*staticContents*/)120void UbuntuBackingStore::resize(const QSize& size, const QRegion& /*staticContents*/)
117{121{
118 mImage = QImage(size, QImage::Format_RGB32);122 const int dpr = int(window()->devicePixelRatio());
123 mImage = QImage(size * dpr, QImage::Format_RGB32);
124 mImage.setDevicePixelRatio(dpr);
119125
120 if (mTexture->isCreated())126 if (mTexture->isCreated())
121 mTexture->destroy();127 mTexture->destroy();
122128
=== modified file 'src/ubuntumirclient/input.cpp'
--- src/ubuntumirclient/input.cpp 2016-01-06 13:29:28 +0000
+++ src/ubuntumirclient/input.cpp 2016-01-06 13:29:28 +0000
@@ -312,6 +312,7 @@
312 const QRect kWindowGeometry = window->geometry();312 const QRect kWindowGeometry = window->geometry();
313 QList<QWindowSystemInterface::TouchPoint> touchPoints;313 QList<QWindowSystemInterface::TouchPoint> touchPoints;
314314
315 const int dpr = int(window->devicePixelRatio());
315316
316 // TODO: Is it worth setting the Qt::TouchPointStationary ones? Currently they are left317 // TODO: Is it worth setting the Qt::TouchPointStationary ones? Currently they are left
317 // as Qt::TouchPointMoved318 // as Qt::TouchPointMoved
@@ -319,10 +320,10 @@
319 for (unsigned int i = 0; i < kPointerCount; ++i) {320 for (unsigned int i = 0; i < kPointerCount; ++i) {
320 QWindowSystemInterface::TouchPoint touchPoint;321 QWindowSystemInterface::TouchPoint touchPoint;
321322
322 const float kX = mir_touch_event_axis_value(tev, i, mir_touch_axis_x) + kWindowGeometry.x();323 const float kX = mir_touch_event_axis_value(tev, i, mir_touch_axis_x) / dpr + kWindowGeometry.x();
323 const float kY = mir_touch_event_axis_value(tev, i, mir_touch_axis_y) + kWindowGeometry.y(); // see bug lp:1346633 workaround comments elsewhere324 const float kY = mir_touch_event_axis_value(tev, i, mir_touch_axis_y) / dpr + kWindowGeometry.y(); // see bug lp:1346633 workaround comments elsewhere
324 const float kW = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_major);325 const float kW = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_major) / dpr;
325 const float kH = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_minor);326 const float kH = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_minor) / dpr;
326 const float kP = mir_touch_event_axis_value(tev, i, mir_touch_axis_pressure);327 const float kP = mir_touch_event_axis_value(tev, i, mir_touch_axis_pressure);
327 touchPoint.id = mir_touch_event_id(tev, i);328 touchPoint.id = mir_touch_event_id(tev, i);
328 touchPoint.normalPosition = QPointF(kX / kWindowGeometry.width(), kY / kWindowGeometry.height());329 touchPoint.normalPosition = QPointF(kX / kWindowGeometry.width(), kY / kWindowGeometry.height());
@@ -449,14 +450,16 @@
449450
450void UbuntuInput::dispatchPointerEvent(UbuntuWindow *platformWindow, const MirInputEvent *ev)451void UbuntuInput::dispatchPointerEvent(UbuntuWindow *platformWindow, const MirInputEvent *ev)
451{452{
452 auto window = platformWindow->window();453 const int dpr = int(platformWindow->devicePixelRatio());
453 auto timestamp = mir_input_event_get_event_time(ev) / 1000000;454 const auto window = platformWindow->window();
454455 const auto timestamp = mir_input_event_get_event_time(ev) / 1000000;
455 auto pev = mir_input_event_get_pointer_event(ev);456
456 auto action = mir_pointer_event_action(pev);457 const auto pev = mir_input_event_get_pointer_event(ev);
457 auto localPoint = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x),458 const auto action = mir_pointer_event_action(pev);
458 mir_pointer_event_axis_value(pev, mir_pointer_axis_y));459
459 auto modifiers = qt_modifiers_from_mir(mir_pointer_event_modifiers(pev));460 const auto modifiers = qt_modifiers_from_mir(mir_pointer_event_modifiers(pev));
461 const auto localPoint = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x) / dpr,
462 mir_pointer_event_axis_value(pev, mir_pointer_axis_y) / dpr);
460463
461 switch (action) {464 switch (action) {
462 case mir_pointer_action_button_up:465 case mir_pointer_action_button_up:
463466
=== modified file 'src/ubuntumirclient/screen.cpp'
--- src/ubuntumirclient/screen.cpp 2016-01-06 13:29:28 +0000
+++ src/ubuntumirclient/screen.cpp 2016-01-06 13:29:28 +0000
@@ -18,6 +18,7 @@
18#include "screen.h"18#include "screen.h"
19#include "logging.h"19#include "logging.h"
20#include "orientationchangeevent_p.h"20#include "orientationchangeevent_p.h"
21#include "utils.h"
2122
22#include <mir_toolkit/mir_client_library.h>23#include <mir_toolkit/mir_client_library.h>
2324
@@ -101,6 +102,14 @@
101 }102 }
102}103}
103104
105namespace {
106 int qGetEnvIntValue(const char *varName, bool *ok)
107 {
108 return qgetenv(varName).toInt(ok);
109 }
110} // anonymous namespace
111
112
104const QEvent::Type OrientationChangeEvent::mType =113const QEvent::Type OrientationChangeEvent::mType =
105 static_cast<QEvent::Type>(QEvent::registerEventType());114 static_cast<QEvent::Type>(QEvent::registerEventType());
106115
@@ -164,18 +173,18 @@
164 }173 }
165174
166 // Set vblank swap interval.175 // Set vblank swap interval.
167 int swapInterval = kSwapInterval;176 bool ok;
168 QByteArray swapIntervalString = qgetenv("QTUBUNTU_SWAPINTERVAL");177 int swapInterval = qGetEnvIntValue("QTUBUNTU_SWAPINTERVAL", &ok);
169 if (!swapIntervalString.isEmpty()) {178 if (!ok)
170 bool ok;179 swapInterval = kSwapInterval;
171 swapInterval = swapIntervalString.toInt(&ok);180
172 if (!ok)181 qCDebug(ubuntumirclient, "Setting swap interval to %d", swapInterval);
173 swapInterval = kSwapInterval;
174 }
175 qCDebug(ubuntumirclient, "setting swap interval to %d", swapInterval);
176 eglSwapInterval(mEglDisplay, swapInterval);182 eglSwapInterval(mEglDisplay, swapInterval);
177183
178 // Get screen resolution.184 // Get screen resolution and properties.
185 int dpr = qGetEnvIntValue("QT_DEVICE_PIXEL_RATIO", &ok);
186 mDevicePixelRatio = (ok && dpr > 0) ? dpr : 1.0;
187
179 auto configDeleter = [](MirDisplayConfiguration *config) { mir_display_config_destroy(config); };188 auto configDeleter = [](MirDisplayConfiguration *config) { mir_display_config_destroy(config); };
180 using configUp = std::unique_ptr<MirDisplayConfiguration, decltype(configDeleter)>;189 using configUp = std::unique_ptr<MirDisplayConfiguration, decltype(configDeleter)>;
181 configUp displayConfig(mir_connection_create_display_config(connection), configDeleter);190 configUp displayConfig(mir_connection_create_display_config(connection), configDeleter);
@@ -187,14 +196,14 @@
187 mOutputId = displayOutput->output_id;196 mOutputId = displayOutput->output_id;
188197
189 mPhysicalSize = QSizeF(displayOutput->physical_width_mm, displayOutput->physical_height_mm);198 mPhysicalSize = QSizeF(displayOutput->physical_width_mm, displayOutput->physical_height_mm);
190 qCDebug(ubuntumirclient, "screen physical size: %.2fx%.2f", mPhysicalSize.width(), mPhysicalSize.height());199 qCDebug(ubuntumirclient, "Screen physical size: %.2fx%.2f mm", mPhysicalSize.width(), mPhysicalSize.height());
191200
192 const MirDisplayMode *mode = &displayOutput->modes[displayOutput->current_mode];201 const MirDisplayMode *mode = &displayOutput->modes[displayOutput->current_mode];
193 const int kScreenWidth = mode->horizontal_resolution;202 const int kScreenWidth = divideAndRoundUp(mode->horizontal_resolution, mDevicePixelRatio);
194 const int kScreenHeight = mode->vertical_resolution;203 const int kScreenHeight = divideAndRoundUp(mode->vertical_resolution, mDevicePixelRatio);
195 Q_ASSERT(kScreenWidth > 0 && kScreenHeight > 0);204 ASSERT(kScreenWidth > 0 && kScreenHeight > 0);
196205
197 qCDebug(ubuntumirclient, "screen resolution: %dx%d", kScreenWidth, kScreenHeight);206 qCDebug(ubuntumirclient, "Screen resolution: %dx%ddp", kScreenWidth, kScreenHeight);
198207
199 mGeometry = QRect(0, 0, kScreenWidth, kScreenHeight);208 mGeometry = QRect(0, 0, kScreenWidth, kScreenHeight);
200209
201210
=== modified file 'src/ubuntumirclient/screen.h'
--- src/ubuntumirclient/screen.h 2015-11-23 11:10:24 +0000
+++ src/ubuntumirclient/screen.h 2016-01-06 13:29:28 +0000
@@ -38,6 +38,7 @@
38 QRect geometry() const override { return mGeometry; }38 QRect geometry() const override { return mGeometry; }
39 QRect availableGeometry() const override { return mGeometry; }39 QRect availableGeometry() const override { return mGeometry; }
40 QSizeF physicalSize() const override { return mPhysicalSize; }40 QSizeF physicalSize() const override { return mPhysicalSize; }
41 qreal devicePixelRatio() const override { return mDevicePixelRatio; }
41 Qt::ScreenOrientation nativeOrientation() const override { return mNativeOrientation; }42 Qt::ScreenOrientation nativeOrientation() const override { return mNativeOrientation; }
42 Qt::ScreenOrientation orientation() const override { return mNativeOrientation; }43 Qt::ScreenOrientation orientation() const override { return mNativeOrientation; }
43 QPlatformCursor *cursor() const override { return const_cast<UbuntuCursor*>(&mCursor); }44 QPlatformCursor *cursor() const override { return const_cast<UbuntuCursor*>(&mCursor); }
@@ -56,6 +57,7 @@
56private:57private:
57 QRect mGeometry;58 QRect mGeometry;
58 QSizeF mPhysicalSize;59 QSizeF mPhysicalSize;
60 qreal mDevicePixelRatio;
59 Qt::ScreenOrientation mNativeOrientation;61 Qt::ScreenOrientation mNativeOrientation;
60 Qt::ScreenOrientation mCurrentOrientation;62 Qt::ScreenOrientation mCurrentOrientation;
61 QImage::Format mFormat;63 QImage::Format mFormat;
6264
=== modified file 'src/ubuntumirclient/ubuntumirclient.pro'
--- src/ubuntumirclient/ubuntumirclient.pro 2015-11-10 11:16:14 +0000
+++ src/ubuntumirclient/ubuntumirclient.pro 2016-01-06 13:29:28 +0000
@@ -42,7 +42,8 @@
42 plugin.h \42 plugin.h \
43 screen.h \43 screen.h \
44 theme.h \44 theme.h \
45 window.h45 window.h \
46 utils.h
4647
47# Installation path48# Installation path
48target.path += $$[QT_INSTALL_PLUGINS]/platforms49target.path += $$[QT_INSTALL_PLUGINS]/platforms
4950
=== added file 'src/ubuntumirclient/utils.h'
--- src/ubuntumirclient/utils.h 1970-01-01 00:00:00 +0000
+++ src/ubuntumirclient/utils.h 2016-01-06 13:29:28 +0000
@@ -0,0 +1,29 @@
1/*
2 * Copyright (C) 2015 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef UTILS_H
18#define UTILS_H
19
20#include <QtGlobal>
21
22namespace {
23 inline int divideAndRoundUp(int numerator, qreal denominator)
24 {
25 return ceil((qreal)numerator / denominator);
26 }
27} // anonymous namespace
28
29#endif // UTILS_H
030
=== modified file 'src/ubuntumirclient/window.cpp'
--- src/ubuntumirclient/window.cpp 2016-01-06 13:29:28 +0000
+++ src/ubuntumirclient/window.cpp 2016-01-06 13:29:28 +0000
@@ -19,6 +19,7 @@
19#include "clipboard.h"19#include "clipboard.h"
20#include "input.h"20#include "input.h"
21#include "screen.h"21#include "screen.h"
22#include "utils.h"
22#include "logging.h"23#include "logging.h"
2324
24#include <mir_toolkit/mir_client_library.h>25#include <mir_toolkit/mir_client_library.h>
@@ -34,6 +35,11 @@
3435
35#include <EGL/egl.h>36#include <EGL/egl.h>
3637
38
39/*
40 * Note: all geometry is in device-independent pixels, except that contained in variables with the
41 * suffix "Px" - whose units are (physical) pixels
42 */
37Q_LOGGING_CATEGORY(ubuntumirclientBufferSwap, "ubuntumirclient.bufferSwap", QtWarningMsg)43Q_LOGGING_CATEGORY(ubuntumirclientBufferSwap, "ubuntumirclient.bufferSwap", QtWarningMsg)
3844
39namespace45namespace
@@ -134,13 +140,14 @@
134Spec makeSurfaceSpec(QWindow *window, UbuntuInput *input, MirConnection *connection)140Spec makeSurfaceSpec(QWindow *window, UbuntuInput *input, MirConnection *connection)
135{141{
136 const auto geom = window->geometry();142 const auto geom = window->geometry();
137 const int width = geom.width() > 0 ? geom.width() : 1;143 const int dpr = int(window->devicePixelRatio());
138 const int height = geom.height() > 0 ? geom.height() : 1;144 const int widthPx = geom.width() > 0 ? geom.width() * dpr : 1;
145 const int heightPx = geom.height() > 0 ? geom.height() * dpr : 1;
139 const auto pixelFormat = defaultPixelFormatFor(connection);146 const auto pixelFormat = defaultPixelFormatFor(connection);
140147
141 if (U_ON_SCREEN_KEYBOARD_ROLE == roleFor(window)) {148 if (U_ON_SCREEN_KEYBOARD_ROLE == roleFor(window)) {
142 qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating input method surface (width=%d, height=%d", window, width, height);149 qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating input method surface with size=(%dx%d)px", window, widthPx, heightPx);
143 return Spec{mir_connection_create_spec_for_input_method(connection, width, height, pixelFormat)};150 return Spec{mir_connection_create_spec_for_input_method(connection, widthPx, heightPx, pixelFormat)};
144 }151 }
145152
146 const Qt::WindowType type = window->type();153 const Qt::WindowType type = window->type();
@@ -153,13 +160,13 @@
153 parent = input->lastFocusedWindow();160 parent = input->lastFocusedWindow();
154 }161 }
155 if (parent) {162 if (parent) {
156 auto pos = geom.topLeft();163 auto posPx = geom.topLeft() * dpr;
157 pos -= parent->geometry().topLeft();164 posPx -= parent->geometry().topLeft() * dpr;
158 MirRectangle location{pos.x(), pos.y(), 0, 0};165 MirRectangle location{posPx.x(), posPx.y(), 0, 0};
159 qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating menu surface(width:%d, height:%d)", window, width, height);166 qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating menu surface with size=(%dx%d)px", window, widthPx, heightPx);
160 return Spec{mir_connection_create_spec_for_menu(167 return Spec{mir_connection_create_spec_for_menu(
161 connection, width, height, pixelFormat, parent->mirSurface(),168 connection, widthPx, heightPx, pixelFormat, parent->mirSurface(),
162 &location, mir_edge_attachment_any)};169 &location, mir_edge_attachment_any)};
163 } else {170 } else {
164 qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - cannot create a menu without a parent!", window);171 qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - cannot create a menu without a parent!", window);
165 }172 }
@@ -167,33 +174,33 @@
167 auto parent = transientParentFor(window);174 auto parent = transientParentFor(window);
168 if (parent) {175 if (parent) {
169 // Modal dialog176 // Modal dialog
170 qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating modal dialog (width=%d, height=%d", window, width, height);177 qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating modal dialog with size=(%dx%d)px", window, widthPx, heightPx);
171 return Spec{mir_connection_create_spec_for_modal_dialog(connection, width, height, pixelFormat, parent->mirSurface())};178 return Spec{mir_connection_create_spec_for_modal_dialog(connection, widthPx, heightPx, pixelFormat, parent->mirSurface())};
172 } else {179 } else {
173 // TODO: do Qt parentless dialogs have the same semantics as mir?180 // TODO: do Qt parentless dialogs have the same semantics as mir?
174 qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating parentless dialog (width=%d, height=%d)", window, width, height);181 qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating parentless dialog with size=(%dx%d)px", window, widthPx, heightPx);
175 return Spec{mir_connection_create_spec_for_dialog(connection, width, height, pixelFormat)};182 return Spec{mir_connection_create_spec_for_dialog(connection, widthPx, heightPx, pixelFormat)};
176 }183 }
177 }184 }
178 qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating normal surface(type=0x%x, width=%d, height=%d)", window, type, width, height);185 qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating normal surface(type=0x%x, with size=(%dx%d)px", window, type, widthPx, heightPx);
179 return Spec{mir_connection_create_spec_for_normal_surface(connection, width, height, pixelFormat)};186 return Spec{mir_connection_create_spec_for_normal_surface(connection, widthPx, heightPx, pixelFormat)};
180}187}
181188
182void setSizingConstraints(MirSurfaceSpec *spec, const QSize& minSize, const QSize& maxSize, const QSize& increment)189void setSizingConstraints(MirSurfaceSpec *spec, const QSize &minSizePx, const QSize &maxSizePx, const QSize &incrementPx)
183{190{
184 mir_surface_spec_set_min_width(spec, minSize.width());191 mir_surface_spec_set_min_width(spec, minSizePx.width());
185 mir_surface_spec_set_min_height(spec, minSize.height());192 mir_surface_spec_set_min_height(spec, minSizePx.height());
186 if (maxSize.width() >= minSize.width()) {193 if (maxSizePx.width() >= minSizePx.width()) {
187 mir_surface_spec_set_max_width(spec, maxSize.width());194 mir_surface_spec_set_max_width(spec, maxSizePx.width());
188 }195 }
189 if (maxSize.height() >= minSize.height()) {196 if (maxSizePx.height() >= minSizePx.height()) {
190 mir_surface_spec_set_max_height(spec, maxSize.height());197 mir_surface_spec_set_max_height(spec, maxSizePx.height());
191 }198 }
192 if (increment.width() > 0) {199 if (incrementPx.width() > 0) {
193 mir_surface_spec_set_width_increment(spec, increment.width());200 mir_surface_spec_set_width_increment(spec, incrementPx.width());
194 }201 }
195 if (increment.height() > 0) {202 if (incrementPx.height() > 0) {
196 mir_surface_spec_set_height_increment(spec, increment.height());203 mir_surface_spec_set_height_increment(spec, incrementPx.height());
197 }204 }
198}205}
199206
@@ -233,6 +240,10 @@
233240
234} //namespace241} //namespace
235242
243/*
244 * UbuntuSurface - wraps a MirSurface
245 * All units are in pixels only (no device pixels).
246 */
236class UbuntuSurface247class UbuntuSurface
237{248{
238public:249public:
@@ -248,7 +259,6 @@
248 , mNeedsRepaint(false)259 , mNeedsRepaint(false)
249 , mParented(mWindow->transientParent() || mWindow->parent())260 , mParented(mWindow->transientParent() || mWindow->parent())
250 , mWindowState(mWindow->windowState())261 , mWindowState(mWindow->windowState())
251
252 {262 {
253 mir_surface_set_event_handler(mMirSurface, surfaceEventCallback, this);263 mir_surface_set_event_handler(mMirSurface, surfaceEventCallback, this);
254264
@@ -257,22 +267,13 @@
257 MirSurfaceParameters parameters;267 MirSurfaceParameters parameters;
258 mir_surface_get_parameters(mMirSurface, &parameters);268 mir_surface_get_parameters(mMirSurface, &parameters);
259269
260 auto geom = mWindow->geometry();
261 geom.setWidth(parameters.width);
262 geom.setHeight(parameters.height);
263 if (mWindowState == Qt::WindowFullScreen) {
264 geom.setY(0);
265 } else {
266 geom.setY(panelHeight());
267 }
268
269 // Assume that the buffer size matches the surface size at creation time270 // Assume that the buffer size matches the surface size at creation time
270 mBufferSize = geom.size();271 mBufferSizePx.rwidth() = parameters.width;
271 platformWindow->QPlatformWindow::setGeometry(geom);272 mBufferSizePx.rheight() = parameters.height;
272 QWindowSystemInterface::handleGeometryChange(mWindow, geom);
273273
274 qCDebug(ubuntumirclient, "created surface at (%d, %d) with size (%d, %d), title '%s', role: '%d'\n",274 qCDebug(ubuntumirclient, "created surface with size=(%dx%d)px, title='%s', role=%d",
275 geom.x(), geom.y(), geom.width(), geom.height(), mWindow->title().toUtf8().constData(), roleFor(mWindow));275 parameters.width, parameters.height, qPrintable(mWindow->title()), roleFor(mWindow));
276 mPlatformWindow->updateWindowSize(parameters.width, parameters.height);
276 }277 }
277278
278 ~UbuntuSurface()279 ~UbuntuSurface()
@@ -283,24 +284,24 @@
283 mir_surface_release_sync(mMirSurface);284 mir_surface_release_sync(mMirSurface);
284 }285 }
285286
286 UbuntuSurface(UbuntuSurface const&) = delete;287 UbuntuSurface(const UbuntuSurface &) = delete;
287 UbuntuSurface& operator=(UbuntuSurface const&) = delete;288 UbuntuSurface& operator=(const UbuntuSurface &) = delete;
288289
289 void resize(const QSize& newSize);290 void resize(const QSize &newSizePx);
290 void setState(Qt::WindowState newState);291 void setState(Qt::WindowState newState);
291 void setVisible(bool state);292 void setVisible(bool state);
292 void updateTitle(const QString& title);293 void updateTitle(const QString &title);
293 void setSizingConstraints(const QSize& minSize, const QSize& maxSize, const QSize& increment);294 void setSizingConstraints(const QSize &minSizePx, const QSize &maxSizePx, const QSize &incrementPx);
294295
295 void onSwapBuffersDone();296 void onSwapBuffersDone();
296 void handleSurfaceResized(int width, int height);297 void handleSurfaceResized(int widthPx, int heightPx);
297 int needsRepaint() const;298 int needsRepaint() const;
298299
299 EGLSurface eglSurface() const { return mEglSurface; }300 EGLSurface eglSurface() const { return mEglSurface; }
300 MirSurface *mirSurface() const { return mMirSurface; }301 MirSurface *mirSurface() const { return mMirSurface; }
301302
302private:303private:
303 static void surfaceEventCallback(MirSurface* surface, const MirEvent *event, void* context);304 static void surfaceEventCallback(MirSurface *surface, const MirEvent *event, void *context);
304 void postEvent(const MirEvent *event);305 void postEvent(const MirEvent *event);
305 void updateSurface();306 void updateSurface();
306307
@@ -317,29 +318,29 @@
317 bool mNeedsRepaint;318 bool mNeedsRepaint;
318 bool mParented;319 bool mParented;
319 Qt::WindowState mWindowState;320 Qt::WindowState mWindowState;
320 QSize mBufferSize;321 QSize mBufferSizePx;
321322
322 QMutex mTargetSizeMutex;323 QMutex mTargetSizeMutex;
323 QSize mTargetSize;324 QSize mTargetSizePx;
324};325};
325326
326void UbuntuSurface::resize(const QSize& size)327void UbuntuSurface::resize(const QSize &sizePx)
327{328{
328 qCDebug(ubuntumirclient,"resize(window=%p, width=%d, height=%d)", mWindow, size.width(), size.height());329 qCDebug(ubuntumirclient,"resize(window=%p) to (%dx%d)px", mWindow, sizePx.width(), sizePx.height());
329330
330 if (mWindowState == Qt::WindowFullScreen || mWindowState == Qt::WindowMaximized) {331 if (mWindowState == Qt::WindowFullScreen || mWindowState == Qt::WindowMaximized) {
331 qCDebug(ubuntumirclient, "resize(window=%p) - not resizing, window is maximized or fullscreen", mWindow);332 qCDebug(ubuntumirclient, "resize(window=%p) - not resizing, window is maximized or fullscreen", mWindow);
332 return;333 return;
333 }334 }
334335
335 if (size.isEmpty()) {336 if (sizePx.isEmpty()) {
336 qCDebug(ubuntumirclient, "resize(window=%p) - not resizing, size is empty", mWindow);337 qCDebug(ubuntumirclient, "resize(window=%p) - not resizing, size is empty", mWindow);
337 return;338 return;
338 }339 }
339340
340 Spec spec{mir_connection_create_spec_for_changes(mConnection)};341 Spec spec{mir_connection_create_spec_for_changes(mConnection)};
341 mir_surface_spec_set_width(spec.get(), size.width());342 mir_surface_spec_set_width(spec.get(), sizePx.width());
342 mir_surface_spec_set_height(spec.get(), size.height());343 mir_surface_spec_set_height(spec.get(), sizePx.height());
343 mir_surface_apply_spec(mMirSurface, spec.get());344 mir_surface_apply_spec(mMirSurface, spec.get());
344}345}
345346
@@ -365,7 +366,7 @@
365 mir_wait_for(mir_surface_set_state(mMirSurface, newState));366 mir_wait_for(mir_surface_set_state(mMirSurface, newState));
366}367}
367368
368void UbuntuSurface::updateTitle(const QString& newTitle)369void UbuntuSurface::updateTitle(const QString &newTitle)
369{370{
370 const auto title = newTitle.toUtf8();371 const auto title = newTitle.toUtf8();
371 Spec spec{mir_connection_create_spec_for_changes(mConnection)};372 Spec spec{mir_connection_create_spec_for_changes(mConnection)};
@@ -373,14 +374,14 @@
373 mir_surface_apply_spec(mMirSurface, spec.get());374 mir_surface_apply_spec(mMirSurface, spec.get());
374}375}
375376
376void UbuntuSurface::setSizingConstraints(const QSize& minSize, const QSize& maxSize, const QSize& increment)377void UbuntuSurface::setSizingConstraints(const QSize &minSizePx, const QSize &maxSizePx, const QSize &incrementPx)
377{378{
378 Spec spec{mir_connection_create_spec_for_changes(mConnection)};379 Spec spec{mir_connection_create_spec_for_changes(mConnection)};
379 ::setSizingConstraints(spec.get(), minSize, maxSize, increment);380 ::setSizingConstraints(spec.get(), minSizePx, maxSizePx, incrementPx);
380 mir_surface_apply_spec(mMirSurface, spec.get());381 mir_surface_apply_spec(mMirSurface, spec.get());
381}382}
382383
383void UbuntuSurface::handleSurfaceResized(int width, int height)384void UbuntuSurface::handleSurfaceResized(int widthPx, int heightPx)
384{385{
385 QMutexLocker lock(&mTargetSizeMutex);386 QMutexLocker lock(&mTargetSizeMutex);
386387
@@ -390,13 +391,13 @@
390 // see TODO in postEvent as the ideal way we should handle this.391 // see TODO in postEvent as the ideal way we should handle this.
391 // The actual buffer size may or may have not changed at this point, so let the rendering392 // The actual buffer size may or may have not changed at this point, so let the rendering
392 // thread drive the window geometry updates.393 // thread drive the window geometry updates.
393 mNeedsRepaint = mTargetSize.width() == width && mTargetSize.height() == height;394 mNeedsRepaint = mTargetSizePx.width() == widthPx && mTargetSizePx.height() == heightPx;
394}395}
395396
396int UbuntuSurface::needsRepaint() const397int UbuntuSurface::needsRepaint() const
397{398{
398 if (mNeedsRepaint) {399 if (mNeedsRepaint) {
399 if (mTargetSize != mBufferSize) {400 if (mTargetSizePx != mBufferSizePx) {
400 //If the buffer hasn't changed yet, we need at least two redraws,401 //If the buffer hasn't changed yet, we need at least two redraws,
401 //once to get the new buffer size and propagate the geometry changes402 //once to get the new buffer size and propagate the geometry changes
402 //and the second to redraw the content at the new size403 //and the second to redraw the content at the new size
@@ -415,29 +416,25 @@
415 static int sFrameNumber = 0;416 static int sFrameNumber = 0;
416 ++sFrameNumber;417 ++sFrameNumber;
417418
418 EGLint eglSurfaceWidth = -1;419 EGLint eglSurfaceWidthPx = -1;
419 EGLint eglSurfaceHeight = -1;420 EGLint eglSurfaceHeightPx = -1;
420 eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &eglSurfaceWidth);421 eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &eglSurfaceWidthPx);
421 eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &eglSurfaceHeight);422 eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &eglSurfaceHeightPx);
422423
423 const bool validSize = eglSurfaceWidth > 0 && eglSurfaceHeight > 0;424 const bool validSize = eglSurfaceWidthPx > 0 && eglSurfaceHeightPx > 0;
424425
425 if (validSize && (mBufferSize.width() != eglSurfaceWidth || mBufferSize.height() != eglSurfaceHeight)) {426 if (validSize && (mBufferSizePx.width() != eglSurfaceWidthPx || mBufferSizePx.height() != eglSurfaceHeightPx)) {
426427
427 qCDebug(ubuntumirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d] - size changed (%d, %d) => (%d, %d)",428 qCDebug(ubuntumirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d] - buffer size changed (%dx%d)px => (%dx%d)px",
428 mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height(), eglSurfaceWidth, eglSurfaceHeight);429 mWindow, sFrameNumber, mBufferSizePx.width(), mBufferSizePx.height(), eglSurfaceWidthPx, eglSurfaceHeightPx);
429430
430 mBufferSize.rwidth() = eglSurfaceWidth;431 mBufferSizePx.rwidth() = eglSurfaceWidthPx;
431 mBufferSize.rheight() = eglSurfaceHeight;432 mBufferSizePx.rheight() = eglSurfaceHeightPx;
432433
433 QRect newGeometry = mPlatformWindow->geometry();434 mPlatformWindow->updateWindowSize(eglSurfaceWidthPx, eglSurfaceHeightPx);
434 newGeometry.setSize(mBufferSize);
435
436 mPlatformWindow->QPlatformWindow::setGeometry(newGeometry);
437 QWindowSystemInterface::handleGeometryChange(mWindow, newGeometry);
438 } else {435 } else {
439 qCDebug(ubuntumirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d] - buffer size (%d,%d)",436 qCDebug(ubuntumirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d] - buffer size=(%dx%d)px",
440 mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height());437 mWindow, sFrameNumber, mBufferSizePx.width(), mBufferSizePx.height());
441 }438 }
442}439}
443440
@@ -458,13 +455,13 @@
458 // As a workaround, we use the width/height as an identifier of this latest event455 // As a workaround, we use the width/height as an identifier of this latest event
459 // so the event handler (handleSurfaceResized) can discard/ignore old ones.456 // so the event handler (handleSurfaceResized) can discard/ignore old ones.
460 const auto resizeEvent = mir_event_get_resize_event(event);457 const auto resizeEvent = mir_event_get_resize_event(event);
461 const auto width = mir_resize_event_get_width(resizeEvent);458 const auto widthPx = mir_resize_event_get_width(resizeEvent);
462 const auto height = mir_resize_event_get_height(resizeEvent);459 const auto heightPx = mir_resize_event_get_height(resizeEvent);
463 qCDebug(ubuntumirclient, "resizeEvent(window=%p, width=%d, height=%d)", mWindow, width, height);460 qCDebug(ubuntumirclient, "resizeEvent(window=%p, size=(%dx%d)px", mWindow, widthPx, heightPx);
464461
465 QMutexLocker lock(&mTargetSizeMutex);462 QMutexLocker lock(&mTargetSizeMutex);
466 mTargetSize.rwidth() = width;463 mTargetSizePx.rwidth() = widthPx;
467 mTargetSize.rheight() = height;464 mTargetSizePx.rheight() = heightPx;
468 }465 }
469466
470 mInput->postEvent(mPlatformWindow, event);467 mInput->postEvent(mPlatformWindow, event);
@@ -496,7 +493,10 @@
496 , mClipboard(clipboard)493 , mClipboard(clipboard)
497 , mSurface(new UbuntuSurface{this, screen, input, connection})494 , mSurface(new UbuntuSurface{this, screen, input, connection})
498{495{
499 qCDebug(ubuntumirclient, "UbuntuWindow(window=%p, screen=%p, input=%p, surf=%p)", w, screen, input, mSurface.get());496 qCDebug(ubuntumirclient, "UbuntuWindow(window=%p, screen=%p, input=%p, surf=%p) with title '%s', role: '%d'",
497 w, screen, input, mSurface.get(), qPrintable(window()->title()), roleFor(window()));
498
499 enablePanelHeightHack(w->windowState() != Qt::WindowFullScreen);
500}500}
501501
502UbuntuWindow::~UbuntuWindow()502UbuntuWindow::~UbuntuWindow()
@@ -504,12 +504,25 @@
504 qCDebug(ubuntumirclient, "~UbuntuWindow(window=%p)", this);504 qCDebug(ubuntumirclient, "~UbuntuWindow(window=%p)", this);
505}505}
506506
507void UbuntuWindow::handleSurfaceResized(int width, int height)507void UbuntuWindow::updateWindowSize(int widthPx, int heightPx) // after when Mir has resized the surface
508{
509 const float dpr = devicePixelRatio();
510 auto geom = geometry();
511 geom.setWidth(divideAndRoundUp(widthPx, dpr));
512 geom.setHeight(divideAndRoundUp(heightPx, dpr));
513
514 QPlatformWindow::setGeometry(geom);
515 QWindowSystemInterface::handleGeometryChange(window(), geom);
516
517 qCDebug(ubuntumirclient) << "Surface geometry updated:" << geom;
518}
519
520void UbuntuWindow::handleSurfaceResized(int widthPx, int heightPx)
508{521{
509 QMutexLocker lock(&mMutex);522 QMutexLocker lock(&mMutex);
510 qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p, width=%d, height=%d)", window(), width, height);523 qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p, size=(%dx%d)px", window(), widthPx, heightPx);
511524
512 mSurface->handleSurfaceResized(width, height);525 mSurface->handleSurfaceResized(widthPx, heightPx);
513526
514 // This resize event could have occurred just after the last buffer swap for this window.527 // This resize event could have occurred just after the last buffer swap for this window.
515 // This means the client may still be holding a buffer with the older size. The first redraw call528 // This means the client may still be holding a buffer with the older size. The first redraw call
@@ -519,7 +532,7 @@
519 auto const numRepaints = mSurface->needsRepaint();532 auto const numRepaints = mSurface->needsRepaint();
520 qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p) redraw %d times", window(), numRepaints);533 qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p) redraw %d times", window(), numRepaints);
521 for (int i = 0; i < numRepaints; i++) {534 for (int i = 0; i < numRepaints; i++) {
522 qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p) repainting width=%d, height=%d", window(), geometry().size().width(), geometry().size().height());535 qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p) repainting size=(%dx%d)dp", window(), geometry().size().width(), geometry().size().height());
523 QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));536 QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
524 }537 }
525}538}
@@ -543,7 +556,7 @@
543 qCDebug(ubuntumirclient, "setWindowState(window=%p, %s)", this, qtWindowStateToStr(state));556 qCDebug(ubuntumirclient, "setWindowState(window=%p, %s)", this, qtWindowStateToStr(state));
544 mSurface->setState(state);557 mSurface->setState(state);
545558
546 updatePanelHeightHack(state);559 enablePanelHeightHack(state != Qt::WindowFullScreen);
547}560}
548561
549/*562/*
@@ -552,34 +565,34 @@
552 window is always on the top-left corner, right below the indicators panel if not565 window is always on the top-left corner, right below the indicators panel if not
553 in fullscreen.566 in fullscreen.
554 */567 */
555void UbuntuWindow::updatePanelHeightHack(Qt::WindowState state)568void UbuntuWindow::enablePanelHeightHack(bool enable)
556{569{
557 if (state == Qt::WindowFullScreen && geometry().y() != 0) {570 QRect newGeometry = geometry();
558 QRect newGeometry = geometry();571 if (enable) {
572 newGeometry.setY(::panelHeight());
573 } else {
559 newGeometry.setY(0);574 newGeometry.setY(0);
560 QPlatformWindow::setGeometry(newGeometry);575 }
561 QWindowSystemInterface::handleGeometryChange(window(), newGeometry);576
562 } else if (geometry().y() == 0) {577 if (newGeometry != geometry()) {
563 QRect newGeometry = geometry();
564 newGeometry.setY(panelHeight());
565 QPlatformWindow::setGeometry(newGeometry);578 QPlatformWindow::setGeometry(newGeometry);
566 QWindowSystemInterface::handleGeometryChange(window(), newGeometry);579 QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
567 }580 }
568}581}
569582
570void UbuntuWindow::setGeometry(const QRect& rect)583void UbuntuWindow::setGeometry(const QRect &rect)
571{584{
572 QMutexLocker lock(&mMutex);585 QMutexLocker lock(&mMutex);
573 qCDebug(ubuntumirclient, "setGeometry (window=%p, x=%d, y=%d, width=%d, height=%d)",586 qCDebug(ubuntumirclient, "setGeometry (window=%p, position=(%d, %d)dp, size=(%dx%d)dp)",
574 window(), rect.x(), rect.y(), rect.width(), rect.height());587 window(), rect.x(), rect.y(), rect.width(), rect.height());
575588
576 //NOTE: mir surfaces cannot be moved by the client so ignore the topLeft coordinates589 //NOTE: mir surfaces cannot be moved by the client so ignore the topLeft coordinates
577 const auto newSize = rect.size();590 const auto newSize = rect.size();
578 auto newGeometry = geometry();591 auto newGeometry = geometry();
579 newGeometry.setSize(newSize);592 newGeometry.setSize(newSize);
580 QPlatformWindow::setGeometry(newGeometry);
581593
582 mSurface->resize(newSize);594 mSurface->resize(newSize * devicePixelRatio());
595 // Note: don't call handleGeometryChange here, wait to see what Mir replies with.
583}596}
584597
585void UbuntuWindow::setVisible(bool visible)598void UbuntuWindow::setVisible(bool visible)
@@ -595,7 +608,7 @@
595 QWindowSystemInterface::flushWindowSystemEvents();608 QWindowSystemInterface::flushWindowSystemEvents();
596}609}
597610
598void UbuntuWindow::setWindowTitle(const QString& title)611void UbuntuWindow::setWindowTitle(const QString &title)
599{612{
600 QMutexLocker lock(&mMutex);613 QMutexLocker lock(&mMutex);
601 qCDebug(ubuntumirclient, "setWindowTitle(window=%p) title=%s)", window(), title.toUtf8().constData());614 qCDebug(ubuntumirclient, "setWindowTitle(window=%p) title=%s)", window(), title.toUtf8().constData());
@@ -606,11 +619,17 @@
606{619{
607 QMutexLocker lock(&mMutex);620 QMutexLocker lock(&mMutex);
608 const auto win = window();621 const auto win = window();
609 qCDebug(ubuntumirclient, "propagateSizeHints(window=%p) min(%d,%d), max(%d,%d) increment(%d, %d)",622 const float dpr = devicePixelRatio();
610 win, win->minimumSize().width(), win->minimumSize().height(),623 qCDebug(ubuntumirclient, "propagateSizeHints(window=%p) min(%dx%d)dp; max(%dx%d)dp; increment(%dx%d)dp",
611 win->maximumSize().width(), win->maximumSize().height(),624 win, win->minimumSize().width(), win->minimumSize().height(),
612 win->sizeIncrement().width(), win->sizeIncrement().height());625 win->maximumSize().width(), win->maximumSize().height(),
613 mSurface->setSizingConstraints(win->minimumSize(), win->maximumSize(), win->sizeIncrement());626 win->sizeIncrement().width(), win->sizeIncrement().height());
627 mSurface->setSizingConstraints(win->minimumSize() * dpr, win->maximumSize() * dpr, win->sizeIncrement() * dpr);
628}
629
630qreal UbuntuWindow::devicePixelRatio() const
631{
632 return screen() ? screen()->devicePixelRatio() : 1.0; // not impossible a Window has no attached Screen
614}633}
615634
616void* UbuntuWindow::eglSurface() const635void* UbuntuWindow::eglSurface() const
617636
=== modified file 'src/ubuntumirclient/window.h'
--- src/ubuntumirclient/window.h 2016-01-06 13:29:28 +0000
+++ src/ubuntumirclient/window.h 2016-01-06 13:29:28 +0000
@@ -46,16 +46,18 @@
46 void setVisible(bool visible) override;46 void setVisible(bool visible) override;
47 void setWindowTitle(const QString &title) override;47 void setWindowTitle(const QString &title) override;
48 void propagateSizeHints() override;48 void propagateSizeHints() override;
49 qreal devicePixelRatio() const override;
4950
50 // New methods.51 // New methods.
51 void *eglSurface() const;52 void *eglSurface() const;
52 MirSurface *mirSurface() const;53 MirSurface *mirSurface() const;
53 void handleSurfaceResized(int width, int height);54 void updateWindowSize(int widthPx, int heightPx);
55 void handleSurfaceResized(int widthPx, int heightPx);
54 void handleSurfaceFocused();56 void handleSurfaceFocused();
55 void onSwapBuffersDone();57 void onSwapBuffersDone();
5658
57private:59private:
58 void updatePanelHeightHack(Qt::WindowState);60 void enablePanelHeightHack(bool enable);
59 mutable QMutex mMutex;61 mutable QMutex mMutex;
60 const WId mId;62 const WId mId;
61 const QSharedPointer<UbuntuClipboard> mClipboard;63 const QSharedPointer<UbuntuClipboard> mClipboard;

Subscribers

People subscribed via source and target branches