~ci-train-bot/qtubuntu/qtubuntu-ubuntu-xenial-landing-057

« back to all changes in this revision

Viewing changes to src/ubuntumirclient/screenobserver.cpp

  • Committer: CI Train Bot
  • Author(s): Gerry Boland, Nick Dedekind
  • Date: 2016-02-05 11:55:35 UTC
  • mfrom: (310.1.4 qtubuntu-clean)
  • Revision ID: ci-train-bot@canonical.com-20160205115535-99xvn26a75cr399q
React to formFactor and window flag changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2016 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
#include "screenobserver.h"
 
18
#include "screen.h"
 
19
#include "window.h"
 
20
#include "logging.h"
 
21
 
 
22
// Qt
 
23
#include <QMetaObject>
 
24
#include <QPointer>
 
25
#include <private/qwindow_p.h>
 
26
 
 
27
// Mir
 
28
#include <mirclient/mir_toolkit/mir_connection.h>
 
29
 
 
30
#include <memory>
 
31
 
 
32
namespace {
 
33
    static void displayConfigurationChangedCallback(MirConnection */*connection*/, void* context)
 
34
    {
 
35
        ASSERT(context != NULL);
 
36
        UbuntuScreenObserver *observer = static_cast<UbuntuScreenObserver *>(context);
 
37
        QMetaObject::invokeMethod(observer, "update");
 
38
    }
 
39
} // anonymous namespace
 
40
 
 
41
UbuntuScreenObserver::UbuntuScreenObserver(MirConnection *mirConnection)
 
42
    : mMirConnection(mirConnection)
 
43
{
 
44
    mir_connection_set_display_config_change_callback(mirConnection, ::displayConfigurationChangedCallback, this);
 
45
    update();
 
46
}
 
47
 
 
48
void UbuntuScreenObserver::update()
 
49
{
 
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);
 
54
 
 
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;
 
58
    mScreenList.clear();
 
59
 
 
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);
 
67
            } else {
 
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();
 
72
            }
 
73
            mScreenList.append(screen);
 
74
        }
 
75
    }
 
76
 
 
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.
 
81
        delete screen;
 
82
    }
 
83
 
 
84
    /*
 
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
 
89
     */
 
90
    Q_FOREACH (const auto screen, newScreenList) {
 
91
        Q_EMIT screenAdded(screen);
 
92
    }
 
93
 
 
94
    qDebug() << "=======================================";
 
95
    for (auto screen: mScreenList) {
 
96
        qDebug() << screen << "- id:" << screen->outputId()
 
97
                           << "geometry:" << screen->geometry()
 
98
                           << "form factor:" << screen->formFactor();
 
99
    }
 
100
    qDebug() << "=======================================";
 
101
}
 
102
 
 
103
UbuntuScreen *UbuntuScreenObserver::findScreenWithId(uint32_t id)
 
104
{
 
105
    return findScreenWithId(mScreenList, id);
 
106
}
 
107
 
 
108
UbuntuScreen *UbuntuScreenObserver::findScreenWithId(const QList<UbuntuScreen *> &list, uint32_t id)
 
109
{
 
110
    Q_FOREACH (const auto screen, list) {
 
111
        if (screen->outputId() == id) {
 
112
            return screen;
 
113
        }
 
114
    }
 
115
    return nullptr;
 
116
}
 
117
 
 
118
void UbuntuScreenObserver::handleScreenPropertiesChange(UbuntuScreen *screen, MirFormFactor formFactor)
 
119
{
 
120
    screen->setAdditionalMirDisplayProperties(formFactor);
 
121
 
 
122
    qDebug() << "=======================================";
 
123
    for (auto screen: mScreenList) {
 
124
        qDebug() << screen << "- id:" << screen->outputId()
 
125
                           << "geometry:" << screen->geometry()
 
126
                           << "form factor:" << screen->formFactor();
 
127
    }
 
128
    qDebug() << "=======================================";
 
129
}
 
130