2
* Copyright (C) 2016 Canonical, Ltd.
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.
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.
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/>.
17
#include "qquickscreenwindow.h"
21
#include "screenscontroller.h"
24
#include <QGuiApplication>
26
#include <qpa/qplatformnativeinterface.h>
29
using namespace qtmir;
32
* QQuickScreenWindow - wrapper of QQuickWindow to enable QML to specify destination screen
33
* and read Mir-specific properties of that screen like scale & form factor
37
* Small implementation detail: during construction, the backing qtmir::ScreenWindow/QPlatformScreen
38
* has not been created yet, so handle() returns nullptr there.
40
* The "scale" & "form factor" properties are obtainable only via the QPlatformNativeInterface,
41
* which refers to windows by their backing handles. So need to postpone querying these values
42
* until after QQuickScreenWindow construction. Handiest approach is to only fetch the value
43
* on first read of the property.
45
* There's no problem connecting to QPlatformNativeInterface::windowPropertyChanged in the
46
* constructor however.
48
QQuickScreenWindow::QQuickScreenWindow(QQuickWindow *parent)
49
: QQuickWindow(parent)
50
, m_scale(-1.0) // start with invalid initial state, fetch correct value on first invokation
51
, m_formFactor(FormFactorUnknown)
53
if (qGuiApp->platformName() == QLatin1String("mirserver")) {
54
connect(qGuiApp->platformNativeInterface(), &QPlatformNativeInterface::windowPropertyChanged,
55
this, &QQuickScreenWindow::nativePropertyChanged);
56
//m_scale = getScaleNativeProperty(); DO NOT CALL HERE - see note above
57
//m_formFactor = getFormFactorNativeProperty(); ditto
59
qCritical("Not using 'mirserver' QPA plugin, the Unity.Screens plugin will be useless!");
63
QScreen *QQuickScreenWindow::screen() const
65
return QQuickWindow::screen();
68
void QQuickScreenWindow::setScreen(QScreen *screen)
70
QQuickWindow::setScreen(screen);
72
float scale = getScaleNativeProperty();
73
if (!qFuzzyCompare(m_scale, scale)) {
75
Q_EMIT scaleChanged(m_scale);
78
auto formFactor = getFormFactorNativeProperty();
79
if (formFactor != m_formFactor) {
80
m_formFactor = formFactor;
81
Q_EMIT formFactorChanged(m_formFactor);
85
qreal QQuickScreenWindow::scale()
88
m_scale = getScaleNativeProperty();
90
// am keeping local copy, to avoid emitting changed signal if screen changes but scale doesn't.
94
bool QQuickScreenWindow::setScaleAndFormFactor(const float scale, const FormFactor formFactor)
96
if (qFuzzyCompare(scale, m_scale) && formFactor == m_formFactor) {
100
// Operates through the mirserver ScreensController API
101
auto controller = static_cast<ScreensController*>(qGuiApp->platformNativeInterface()
102
->nativeResourceForIntegration("ScreensController"));
107
auto screenHandle = static_cast<Screen *>(screen()->handle());
112
auto id = screenHandle->outputId();
114
auto configs = controller->configuration();
116
auto config = configs.begin();
117
while (config != configs.end()) {
118
if (config->id == id) {
119
config->scale = scale;
120
config->formFactor = static_cast<MirFormFactor>(formFactor);
125
return controller->setConfiguration(configs);
128
FormFactor QQuickScreenWindow::formFactor()
130
if (m_formFactor == FormFactorUnknown) {
131
m_formFactor = getFormFactorNativeProperty();
136
void QQuickScreenWindow::nativePropertyChanged(QPlatformWindow *window, const QString &propertyName)
138
if (window != handle()) {
142
if (propertyName == QStringLiteral("scale")) {
143
float scale = getScaleNativeProperty();
145
if (qFuzzyCompare(m_scale, scale)) {
149
Q_EMIT scaleChanged(m_scale);
150
} else if (propertyName == QStringLiteral("formFactor")) {
151
auto formFactor = getFormFactorNativeProperty();
153
if (formFactor == m_formFactor) {
156
m_formFactor = formFactor;
157
Q_EMIT formFactorChanged(m_formFactor);
161
float QQuickScreenWindow::getScaleNativeProperty() const
163
QVariant scaleVal = qGuiApp->platformNativeInterface()
164
->windowProperty(handle(), QStringLiteral("scale"));
165
if (!scaleVal.isValid()) {
169
float scale = scaleVal.toFloat(&ok);
170
if (!ok || scale <= 0) {
176
FormFactor QQuickScreenWindow::getFormFactorNativeProperty() const
178
QVariant formFactorVal = qGuiApp->platformNativeInterface()
179
->windowProperty(handle(), QStringLiteral("formFactor"));
180
if (!formFactorVal.isValid()) {
184
return static_cast<FormFactor>(formFactorVal.toInt());