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 "screenobserver.h"
23
#include <QMetaObject>
25
#include <private/qwindow_p.h>
28
#include <mirclient/mir_toolkit/mir_connection.h>
33
static void displayConfigurationChangedCallback(MirConnection */*connection*/, void* context)
35
ASSERT(context != NULL);
36
UbuntuScreenObserver *observer = static_cast<UbuntuScreenObserver *>(context);
37
QMetaObject::invokeMethod(observer, "update");
39
} // anonymous namespace
41
UbuntuScreenObserver::UbuntuScreenObserver(MirConnection *mirConnection)
42
: mMirConnection(mirConnection)
44
mir_connection_set_display_config_change_callback(mirConnection, ::displayConfigurationChangedCallback, this);
48
void UbuntuScreenObserver::update()
50
// Wrap MirDisplayConfiguration to always delete when out of scope
51
auto configDeleter = [](MirDisplayConfiguration *config) { mir_display_config_destroy(config); };
52
using configUp = std::unique_ptr<MirDisplayConfiguration, decltype(configDeleter)>;
53
configUp displayConfig(mir_connection_create_display_config(mMirConnection), configDeleter);
55
// Mir only tells us something changed, it is up to us to figure out what.
56
QList<UbuntuScreen*> newScreenList;
57
QList<UbuntuScreen*> oldScreenList = mScreenList;
60
for (uint32_t i=0; i<displayConfig->num_outputs; i++) {
61
MirDisplayOutput output = displayConfig->outputs[i];
62
if (output.used && output.connected) {
63
UbuntuScreen *screen = findScreenWithId(oldScreenList, output.output_id);
64
if (screen) { // we've already set up this display before, refresh its internals
65
screen->setMirDisplayOutput(output);
66
oldScreenList.removeAll(screen);
68
// new display, so create UbuntuScreen for it
69
screen = new UbuntuScreen(output, mMirConnection);
70
newScreenList.append(screen);
71
qDebug() << "Added Screen with id" << output.output_id << "and geometry" << screen->geometry();
73
mScreenList.append(screen);
77
// Delete any old & unused Screens
78
Q_FOREACH (const auto screen, oldScreenList) {
79
qDebug() << "Removed Screen with id" << screen->outputId() << "and geometry" << screen->geometry();
80
// The screen is automatically removed from Qt's internal list by the QPlatformScreen destructor.
85
* Mir's MirDisplayOutput does not include formFactor or scale for some reason, but Qt
86
* will want that information on creating the QScreen. Only way we get that info is when
87
* Mir positions a Window on that Screen. It's ugly, but will have to re-create the window
88
* again, after that happens. See "handleScreenPropertiesChange" method
90
Q_FOREACH (const auto screen, newScreenList) {
91
Q_EMIT screenAdded(screen);
94
qDebug() << "=======================================";
95
for (auto screen: mScreenList) {
96
qDebug() << screen << "- id:" << screen->outputId()
97
<< "geometry:" << screen->geometry()
98
<< "form factor:" << screen->formFactor();
100
qDebug() << "=======================================";
103
UbuntuScreen *UbuntuScreenObserver::findScreenWithId(uint32_t id)
105
return findScreenWithId(mScreenList, id);
108
UbuntuScreen *UbuntuScreenObserver::findScreenWithId(const QList<UbuntuScreen *> &list, uint32_t id)
110
Q_FOREACH (const auto screen, list) {
111
if (screen->outputId() == id) {
118
void UbuntuScreenObserver::handleScreenPropertiesChange(UbuntuScreen *screen, MirFormFactor formFactor)
120
screen->setAdditionalMirDisplayProperties(formFactor);
122
qDebug() << "=======================================";
123
for (auto screen: mScreenList) {
124
qDebug() << screen << "- id:" << screen->outputId()
125
<< "geometry:" << screen->geometry()
126
<< "form factor:" << screen->formFactor();
128
qDebug() << "=======================================";