~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to libs/kephal/service/backendconfigurations.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *   Copyright 2008 Aike J Sommer <dev@aikesommer.name>
 
3
 *
 
4
 *   This program is free software; you can redistribute it and/or modify
 
5
 *   it under the terms of the GNU General Public License as
 
6
 *   published by the Free Software Foundation; either version 2,
 
7
 *   or (at your option) any later version.
 
8
 *
 
9
 *   This program is distributed in the hope that it will be useful,
 
10
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 *   GNU General Public License for more details
 
13
 *
 
14
 *   You should have received a copy of the GNU Library General Public
 
15
 *   License along with this program; if not, write to the
 
16
 *   Free Software Foundation, Inc.,
 
17
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
18
 */
 
19
 
 
20
 
 
21
#include "backendconfigurations.h"
 
22
 
 
23
#include "outputs.h"
 
24
#include "backend.h"
 
25
 
 
26
#include <KDebug>
 
27
 
 
28
 
 
29
namespace Kephal {
 
30
 
 
31
    BackendConfigurations * BackendConfigurations::self() {
 
32
        return BackendConfigurations::s_instance;
 
33
    }
 
34
 
 
35
    BackendConfigurations::BackendConfigurations(QObject * parent)
 
36
        : Configurations(parent)/*,
 
37
        m_status(new StatusMessage(this))*/
 
38
    {
 
39
        BackendConfigurations::s_instance = this;
 
40
    }
 
41
 
 
42
    BackendConfigurations::~BackendConfigurations()
 
43
    {
 
44
        BackendConfigurations::s_instance = 0;
 
45
    }
 
46
 
 
47
    BackendConfigurations * BackendConfigurations::s_instance = 0;
 
48
 
 
49
    BackendConfiguration * BackendConfigurations::activeBackendConfiguration() {
 
50
        return (BackendConfiguration *) activeConfiguration();
 
51
    }
 
52
 
 
53
 
 
54
 
 
55
    BackendConfiguration::BackendConfiguration(QObject * parent)
 
56
        : Configuration(parent)
 
57
    {
 
58
    }
 
59
 
 
60
    QMap<int, QRect> BackendConfiguration::realLayout() {
 
61
        QMap<Output *, int> outputScreens;
 
62
        foreach (Output * output, Outputs::self()->outputs()) {
 
63
            int screen = Configurations::self()->screen(output);
 
64
            outputScreens.insert(output, screen);
 
65
        }
 
66
        return realLayout(outputScreens);
 
67
    }
 
68
 
 
69
    QMap<int, QRect> BackendConfiguration::realLayout(const QMap<Output *, int> & outputScreens) {
 
70
        QMap<int, QPoint> simpleLayout = layout();
 
71
        return realLayout(simpleLayout, outputScreens);
 
72
    }
 
73
 
 
74
    QMap<int, QRect> BackendConfiguration::realLayout(const QMap<int, QPoint> & sLayout, const QMap<Output *, int> & outputScreens) {
 
75
        QMap<Output *, QSize> outputSizes;
 
76
        foreach (Output * output, outputScreens.keys()) {
 
77
            outputSizes.insert(output, output->isActivated() ? output->size() : output->preferredSize());
 
78
        }
 
79
        return realLayout(sLayout, outputScreens, outputSizes);
 
80
    }
 
81
 
 
82
    QMap<int, QRect> BackendConfiguration::realLayout(const QMap<int, QPoint> & sLayout, const QMap<Output *, int> & outputScreens, const QMap<Output *, QSize> & outputSizes) {
 
83
        //kDebug() << "calculating real layout for:" << sLayout << outputScreens;
 
84
 
 
85
        QMap<int, QRect> screens;
 
86
        QMap<int, QPoint> simpleLayout = sLayout;
 
87
 
 
88
        QMap<int, QSize> screenSizes;
 
89
        foreach (int screen, simpleLayout.keys()) {
 
90
            screenSizes.insert(screen, QSize());
 
91
        }
 
92
 
 
93
        foreach (Output * output, outputScreens.keys()) {
 
94
            if (outputScreens[output] < 0) {
 
95
                continue;
 
96
            }
 
97
 
 
98
            if (! screenSizes.contains(outputScreens[output])) {
 
99
                INVALID_CONFIGURATION("outputs and configuration don't match");
 
100
                return screens;
 
101
            }
 
102
            screenSizes[outputScreens[output]] = screenSizes[outputScreens[output]].expandedTo(outputSizes[output]);
 
103
        }
 
104
 
 
105
        int begin = simpleLayout.begin().key();
 
106
        screens.insert(begin, QRect(QPoint(0, 0), screenSizes[begin]));
 
107
        simpleToReal(simpleLayout, screenSizes, begin, screens);
 
108
        Configurations::translateOrigin(screens);
 
109
 
 
110
        for (QMap<int, QRect>::const_iterator i = screens.constBegin(); i != screens.constEnd(); ++i) {
 
111
            for (QMap<int, QRect>::const_iterator j = (i + 1); j != screens.constEnd(); ++j) {
 
112
                if (i.value().intersects(j.value())) {
 
113
                    INVALID_CONFIGURATION("overlapping screens");
 
114
                    screens.clear();
 
115
                    return screens;
 
116
                }
 
117
            }
 
118
        }
 
119
 
 
120
        return screens;
 
121
    }
 
122
 
 
123
    void BackendConfiguration::simpleToReal(QMap<int, QPoint> & simpleLayout, const QMap<int, QSize> & screenSizes, int index, QMap<int, QRect> & screens) const {
 
124
        QPoint pos = simpleLayout.take(index);
 
125
 
 
126
        // to the right
 
127
        QPoint nextPos(pos.x() + 1, pos.y());
 
128
        int nextIndex = simpleLayout.key(nextPos, -1);
 
129
        if (nextIndex >= 0) {
 
130
            screens.insert(nextIndex, QRect(screens[index].topRight() + QPoint(1, 0), screenSizes[nextIndex]));
 
131
            simpleToReal(simpleLayout, screenSizes, nextIndex, screens);
 
132
        }
 
133
 
 
134
        // to the left
 
135
        nextPos = QPoint(pos.x() - 1, pos.y());
 
136
        nextIndex = simpleLayout.key(nextPos, -1);
 
137
        if (nextIndex >= 0) {
 
138
            QSize screenSize = screenSizes[nextIndex];
 
139
            screens.insert(nextIndex, QRect(screens[index].topLeft() - QPoint(screenSize.width(), 0), screenSize));
 
140
            simpleToReal(simpleLayout, screenSizes, nextIndex, screens);
 
141
        }
 
142
 
 
143
        // to the bottom
 
144
        nextPos = QPoint(pos.x(), pos.y() + 1);
 
145
        nextIndex = simpleLayout.key(nextPos, -1);
 
146
        if (nextIndex >= 0) {
 
147
            screens.insert(nextIndex, QRect(screens[index].bottomLeft() + QPoint(0, 1), screenSizes[nextIndex]));
 
148
            simpleToReal(simpleLayout, screenSizes, nextIndex, screens);
 
149
        }
 
150
 
 
151
        // to the top
 
152
        nextPos = QPoint(pos.x(), pos.y() - 1);
 
153
        nextIndex = simpleLayout.key(nextPos, -1);
 
154
        if (nextIndex >= 0) {
 
155
            QSize screenSize = screenSizes[nextIndex];
 
156
            screens.insert(nextIndex, QRect(screens[index].topLeft() - QPoint(0, screenSize.height()), screenSize));
 
157
            simpleToReal(simpleLayout, screenSizes, nextIndex, screens);
 
158
        }
 
159
    }
 
160
 
 
161
    QMap<int, QPoint> BackendConfiguration::cloneLayout(int screen) {
 
162
        QSet<QPoint> positions = clonePositions(screen);
 
163
        QMap<int, QPoint> layout;
 
164
        int i = 0;
 
165
        foreach (const QPoint& p, positions) {
 
166
            layout.insert(i, p);
 
167
            ++i;
 
168
        }
 
169
 
 
170
        Configurations::translateOrigin(layout);
 
171
        return layout;
 
172
    }
 
173
 
 
174
    QSet<QPoint> BackendConfiguration::clonePositions(int screen) {
 
175
        QList<QSet<QPoint> > partitions = partition(screen);
 
176
        if (partitions.size() == 1) {
 
177
            return partitions[0];
 
178
        }
 
179
        return QSet<QPoint>();
 
180
    }
 
181
 
 
182
    QSet<QPoint> BackendConfiguration::positions() {
 
183
        QSet<QPoint> result;
 
184
        foreach (const QPoint& p, layout()) {
 
185
            result << p;
 
186
        }
 
187
        return result;
 
188
    }
 
189
 
 
190
    QSet<QPoint> BackendConfiguration::possiblePositions(int screen) const {
 
191
        QList<QSet<QPoint> > partitions = partition(screen);
 
192
        QSet<QPoint> result = border(partitions[0]);
 
193
        foreach (const QSet<QPoint> &partition, partitions) {
 
194
            result.intersect(border(partition));
 
195
        }
 
196
        return result;
 
197
    }
 
198
 
 
199
    /*WILL: used by clonePositions and possiblePositions*/
 
200
    QList<QSet<QPoint> > BackendConfiguration::partition(int screen) const {
 
201
        QHash<QPoint, QSet<QPoint> * > partitions;
 
202
        QMap<int, QPoint> layout = this->layout();
 
203
        bool exclude = layout.contains(screen);
 
204
        QPoint excludePoint;
 
205
        if (exclude) {
 
206
            excludePoint = layout[screen];
 
207
        }
 
208
        foreach (const QPoint& p, layout) {
 
209
            if (exclude && (p == excludePoint)) {
 
210
                continue;
 
211
            }
 
212
            partitions.insert(p, new QSet<QPoint>());
 
213
            partitions[p]->insert(p);
 
214
        }
 
215
 
 
216
        foreach (const QPoint& p, layout) {
 
217
            if (exclude && (p == excludePoint)) {
 
218
                continue;
 
219
            }
 
220
            QList<QPoint> connected;
 
221
            if (partitions.contains(p + QPoint(1, 0))) {
 
222
                connected.append(p + QPoint(1, 0));
 
223
            }
 
224
            if (partitions.contains(p + QPoint(0, 1))) {
 
225
                connected.append(p + QPoint(0, 1));
 
226
            }
 
227
            foreach (const QPoint& c, connected) {
 
228
                if (partitions[p] == partitions[c]) {
 
229
                    continue;
 
230
                }
 
231
                partitions[p]->unite(* (partitions[c]));
 
232
                delete partitions[c];
 
233
                partitions[c] = partitions[p];
 
234
            }
 
235
        }
 
236
 
 
237
        QSet<QSet<QPoint> * > unique;
 
238
        foreach (QSet<QPoint> * partition, partitions) {
 
239
            unique.insert(partition);
 
240
        }
 
241
 
 
242
        QList<QSet<QPoint> > result;
 
243
        foreach (QSet<QPoint> * partition, unique) {
 
244
            result.append(* partition);
 
245
            delete partition;
 
246
        }
 
247
 
 
248
        return result;
 
249
    }
 
250
 
 
251
    QSet<QPoint> BackendConfiguration::border(QSet<QPoint> screens) const {
 
252
        QSet<QPoint> result;
 
253
        QList<QPoint> borders;
 
254
        borders << QPoint(1, 0) << QPoint(0, 1) << QPoint(-1, 0) << QPoint(0, -1);
 
255
        foreach (const QPoint& p, screens) {
 
256
            foreach (const QPoint& border, borders) {
 
257
                if (! screens.contains(p + border)) {
 
258
                    result.insert(p + border);
 
259
                }
 
260
            }
 
261
        }
 
262
 
 
263
        return result;
 
264
    }
 
265
 
 
266
}
 
267
 
 
268
#ifndef NO_KDE
 
269
#include "backendconfigurations.moc"
 
270
#endif
 
271