2
* Copyright 2008 Aike J Sommer <dev@aikesommer.name>
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.
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
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.
21
#include "backendconfigurations.h"
31
BackendConfigurations * BackendConfigurations::self() {
32
return BackendConfigurations::s_instance;
35
BackendConfigurations::BackendConfigurations(QObject * parent)
36
: Configurations(parent)/*,
37
m_status(new StatusMessage(this))*/
39
BackendConfigurations::s_instance = this;
42
BackendConfigurations::~BackendConfigurations()
44
BackendConfigurations::s_instance = 0;
47
BackendConfigurations * BackendConfigurations::s_instance = 0;
49
BackendConfiguration * BackendConfigurations::activeBackendConfiguration() {
50
return (BackendConfiguration *) activeConfiguration();
55
BackendConfiguration::BackendConfiguration(QObject * parent)
56
: Configuration(parent)
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);
66
return realLayout(outputScreens);
69
QMap<int, QRect> BackendConfiguration::realLayout(const QMap<Output *, int> & outputScreens) {
70
QMap<int, QPoint> simpleLayout = layout();
71
return realLayout(simpleLayout, outputScreens);
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());
79
return realLayout(sLayout, outputScreens, outputSizes);
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;
85
QMap<int, QRect> screens;
86
QMap<int, QPoint> simpleLayout = sLayout;
88
QMap<int, QSize> screenSizes;
89
foreach (int screen, simpleLayout.keys()) {
90
screenSizes.insert(screen, QSize());
93
foreach (Output * output, outputScreens.keys()) {
94
if (outputScreens[output] < 0) {
98
if (! screenSizes.contains(outputScreens[output])) {
99
INVALID_CONFIGURATION("outputs and configuration don't match");
102
screenSizes[outputScreens[output]] = screenSizes[outputScreens[output]].expandedTo(outputSizes[output]);
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);
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");
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);
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);
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);
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);
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);
161
QMap<int, QPoint> BackendConfiguration::cloneLayout(int screen) {
162
QSet<QPoint> positions = clonePositions(screen);
163
QMap<int, QPoint> layout;
165
foreach (const QPoint& p, positions) {
170
Configurations::translateOrigin(layout);
174
QSet<QPoint> BackendConfiguration::clonePositions(int screen) {
175
QList<QSet<QPoint> > partitions = partition(screen);
176
if (partitions.size() == 1) {
177
return partitions[0];
179
return QSet<QPoint>();
182
QSet<QPoint> BackendConfiguration::positions() {
184
foreach (const QPoint& p, layout()) {
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));
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);
206
excludePoint = layout[screen];
208
foreach (const QPoint& p, layout) {
209
if (exclude && (p == excludePoint)) {
212
partitions.insert(p, new QSet<QPoint>());
213
partitions[p]->insert(p);
216
foreach (const QPoint& p, layout) {
217
if (exclude && (p == excludePoint)) {
220
QList<QPoint> connected;
221
if (partitions.contains(p + QPoint(1, 0))) {
222
connected.append(p + QPoint(1, 0));
224
if (partitions.contains(p + QPoint(0, 1))) {
225
connected.append(p + QPoint(0, 1));
227
foreach (const QPoint& c, connected) {
228
if (partitions[p] == partitions[c]) {
231
partitions[p]->unite(* (partitions[c]));
232
delete partitions[c];
233
partitions[c] = partitions[p];
237
QSet<QSet<QPoint> * > unique;
238
foreach (QSet<QPoint> * partition, partitions) {
239
unique.insert(partition);
242
QList<QSet<QPoint> > result;
243
foreach (QSet<QPoint> * partition, unique) {
244
result.append(* partition);
251
QSet<QPoint> BackendConfiguration::border(QSet<QPoint> screens) const {
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);
269
#include "backendconfigurations.moc"