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>
27
#include <mirclient/mir_toolkit/mir_connection.h>
28
#include <mirclient/mir_toolkit/mir_display_configuration.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");
40
const char *mirFormFactorToStr(MirFormFactor formFactor)
43
case mir_form_factor_unknown: return "unknown";
44
case mir_form_factor_phone: return "phone";
45
case mir_form_factor_tablet: return "tablet";
46
case mir_form_factor_monitor: return "monitor";
47
case mir_form_factor_tv: return "tv";
48
case mir_form_factor_projector: return "projector";
52
} // anonymous namespace
54
UbuntuScreenObserver::UbuntuScreenObserver(MirConnection *mirConnection)
55
: mMirConnection(mirConnection)
57
mir_connection_set_display_config_change_callback(mirConnection, ::displayConfigurationChangedCallback, this);
61
void UbuntuScreenObserver::update()
63
// Wrap MirDisplayConfiguration to always delete when out of scope
64
auto configDeleter = [](MirDisplayConfig *config) { mir_display_config_release(config); };
65
using configUp = std::unique_ptr<MirDisplayConfig, decltype(configDeleter)>;
66
configUp displayConfig(mir_connection_create_display_configuration(mMirConnection), configDeleter);
68
// Mir only tells us something changed, it is up to us to figure out what.
69
QList<UbuntuScreen*> newScreenList;
70
QList<UbuntuScreen*> oldScreenList = mScreenList;
73
for (int i = 0; i < mir_display_config_get_num_outputs(displayConfig.get()); i++) {
74
const MirOutput *output = mir_display_config_get_output(displayConfig.get(), i);
75
if (mir_output_is_enabled(output)) {
76
UbuntuScreen *screen = findScreenWithId(oldScreenList, mir_output_get_id(output));
77
if (screen) { // we've already set up this display before
78
screen->updateMirOutput(output);
79
oldScreenList.removeAll(screen);
81
// new display, so create UbuntuScreen for it
82
screen = new UbuntuScreen(output, mMirConnection);
83
newScreenList.append(screen);
84
qCDebug(ubuntumirclient) << "Added Screen with id" << mir_output_get_id(output)
85
<< "and geometry" << screen->geometry();
87
mScreenList.append(screen);
91
// Announce old & unused Screens, should be deleted by the slot
92
Q_FOREACH (const auto screen, oldScreenList) {
93
Q_EMIT screenRemoved(screen);
97
* Mir's MirDisplayOutput does not include formFactor or scale for some reason, but Qt
98
* will want that information on creating the QScreen. Only way we get that info is when
99
* Mir positions a Window on that Screen. See "handleScreenPropertiesChange" method
102
// Announce new Screens
103
Q_FOREACH (const auto screen, newScreenList) {
104
Q_EMIT screenAdded(screen);
107
qCDebug(ubuntumirclient) << "=======================================";
108
for (auto screen: mScreenList) {
109
qCDebug(ubuntumirclient) << screen << "- id:" << screen->mirOutputId()
110
<< "geometry:" << screen->geometry()
111
<< "form factor:" << mirFormFactorToStr(screen->formFactor())
112
<< "scale:" << screen->scale();
114
qCDebug(ubuntumirclient) << "=======================================";
117
UbuntuScreen *UbuntuScreenObserver::findScreenWithId(int id)
119
return findScreenWithId(mScreenList, id);
122
UbuntuScreen *UbuntuScreenObserver::findScreenWithId(const QList<UbuntuScreen *> &list, int id)
124
Q_FOREACH (const auto screen, list) {
125
if (screen->mirOutputId() == id) {
132
void UbuntuScreenObserver::handleScreenPropertiesChange(UbuntuScreen *screen, int dpi,
133
MirFormFactor formFactor, float scale)
135
screen->setAdditionalMirDisplayProperties(scale, formFactor, dpi);