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"
22 #include "kephal/outputs.h"
23 #include "kephal/backend.h"
30 BackendConfigurations
* BackendConfigurations::self() {
31 return BackendConfigurations::m_instance
;
34 BackendConfigurations::BackendConfigurations(QObject
* parent
)
35 : Configurations(parent
)/*,
36 m_status(new StatusMessage(this))*/
38 BackendConfigurations::m_instance
= this;
41 BackendConfigurations::~BackendConfigurations()
43 BackendConfigurations::m_instance
= 0;
46 BackendConfigurations
* BackendConfigurations::m_instance
= 0;
48 BackendConfiguration
* BackendConfigurations::activeBackendConfiguration() {
49 return (BackendConfiguration
*) activeConfiguration();
54 BackendConfiguration::BackendConfiguration(QObject
* parent
)
55 : Configuration(parent
)
59 QMap
<int, QRect
> BackendConfiguration::realLayout() {
60 QMap
<Output
*, int> outputScreens
;
61 foreach (Output
* output
, Outputs::self()->outputs()) {
62 int screen
= Configurations::self()->screen(output
);
63 outputScreens
.insert(output
, screen
);
65 return realLayout(outputScreens
);
68 QMap
<int, QRect
> BackendConfiguration::realLayout(const QMap
<Output
*, int> & outputScreens
) {
69 QMap
<int, QPoint
> simpleLayout
= layout();
70 return realLayout(simpleLayout
, outputScreens
);
73 QMap
<int, QRect
> BackendConfiguration::realLayout(const QMap
<int, QPoint
> & sLayout
, const QMap
<Output
*, int> & outputScreens
) {
74 QMap
<Output
*, QSize
> outputSizes
;
75 foreach (Output
* output
, outputScreens
.keys()) {
76 outputSizes
.insert(output
, output
->isActivated() ? output
->size() : output
->preferredSize());
78 return realLayout(sLayout
, outputScreens
, outputSizes
);
81 QMap
<int, QRect
> BackendConfiguration::realLayout(const QMap
<int, QPoint
> & sLayout
, const QMap
<Output
*, int> & outputScreens
, const QMap
<Output
*, QSize
> & outputSizes
) {
82 //qDebug() << "calculating real layout for:" << sLayout << outputScreens;
84 QMap
<int, QRect
> screens
;
85 QMap
<int, QPoint
> simpleLayout
= sLayout
;
87 QMap
<int, QSize
> screenSizes
;
88 foreach (int screen
, simpleLayout
.keys()) {
89 screenSizes
.insert(screen
, QSize());
92 foreach (Output
* output
, outputScreens
.keys()) {
93 if (outputScreens
[output
] < 0) {
97 if (! screenSizes
.contains(outputScreens
[output
])) {
98 INVALID_CONFIGURATION("outputs and configuration don't match");
101 screenSizes
[outputScreens
[output
]] = screenSizes
[outputScreens
[output
]].expandedTo(outputSizes
[output
]);
104 int begin
= simpleLayout
.begin().key();
105 screens
.insert(begin
, QRect(QPoint(0, 0), screenSizes
[begin
]));
106 simpleToReal(simpleLayout
, screenSizes
, begin
, screens
);
107 Configurations::translateOrigin(screens
);
109 for (QMap
<int, QRect
>::const_iterator i
= screens
.constBegin(); i
!= screens
.constEnd(); ++i
) {
110 for (QMap
<int, QRect
>::const_iterator j
= (i
+ 1); j
!= screens
.constEnd(); ++j
) {
111 if (i
.value().intersects(j
.value())) {
112 INVALID_CONFIGURATION("overlapping screens");
122 void BackendConfiguration::simpleToReal(QMap
<int, QPoint
> & simpleLayout
, const QMap
<int, QSize
> & screenSizes
, int index
, QMap
<int, QRect
> & screens
) {
123 QPoint pos
= simpleLayout
.take(index
);
126 QPoint
nextPos(pos
.x() + 1, pos
.y());
127 int nextIndex
= simpleLayout
.key(nextPos
, -1);
128 if (nextIndex
>= 0) {
129 screens
.insert(nextIndex
, QRect(screens
[index
].topRight() + QPoint(1, 0), screenSizes
[nextIndex
]));
130 simpleToReal(simpleLayout
, screenSizes
, nextIndex
, screens
);
134 nextPos
= QPoint(pos
.x() - 1, pos
.y());
135 nextIndex
= simpleLayout
.key(nextPos
, -1);
136 if (nextIndex
>= 0) {
137 QSize screenSize
= screenSizes
[nextIndex
];
138 screens
.insert(nextIndex
, QRect(screens
[index
].topLeft() - QPoint(screenSize
.width(), 0), screenSize
));
139 simpleToReal(simpleLayout
, screenSizes
, nextIndex
, screens
);
143 nextPos
= QPoint(pos
.x(), pos
.y() + 1);
144 nextIndex
= simpleLayout
.key(nextPos
, -1);
145 if (nextIndex
>= 0) {
146 screens
.insert(nextIndex
, QRect(screens
[index
].bottomLeft() + QPoint(0, 1), screenSizes
[nextIndex
]));
147 simpleToReal(simpleLayout
, screenSizes
, nextIndex
, screens
);
151 nextPos
= QPoint(pos
.x(), pos
.y() - 1);
152 nextIndex
= simpleLayout
.key(nextPos
, -1);
153 if (nextIndex
>= 0) {
154 QSize screenSize
= screenSizes
[nextIndex
];
155 screens
.insert(nextIndex
, QRect(screens
[index
].topLeft() - QPoint(0, screenSize
.height()), screenSize
));
156 simpleToReal(simpleLayout
, screenSizes
, nextIndex
, screens
);
160 QMap
<int, QPoint
> BackendConfiguration::cloneLayout(int screen
) {
161 QSet
<QPoint
> positions
= clonePositions(screen
);
162 QMap
<int, QPoint
> layout
;
164 foreach (const QPoint
& p
, positions
) {
169 Configurations::translateOrigin(layout
);
173 QSet
<QPoint
> BackendConfiguration::clonePositions(int screen
) {
174 QList
<QSet
<QPoint
> > partitions
= partition(screen
);
175 if (partitions
.size() == 1) {
176 return partitions
[0];
178 return QSet
<QPoint
>();
181 QSet
<QPoint
> BackendConfiguration::positions() {
183 foreach (const QPoint
& p
, layout()) {
189 QSet
<QPoint
> BackendConfiguration::possiblePositions(int screen
) {
190 QList
<QSet
<QPoint
> > partitions
= partition(screen
);
191 QSet
<QPoint
> result
= border(partitions
[0]);
192 foreach (QSet
<QPoint
> partition
, partitions
) {
193 result
.intersect(border(partition
));
198 QList
<QSet
<QPoint
> > BackendConfiguration::partition(int screen
) {
199 QHash
<QPoint
, QSet
<QPoint
> * > partitions
;
200 QMap
<int, QPoint
> layout
= this->layout();
201 bool exclude
= layout
.contains(screen
);
204 excludePoint
= layout
[screen
];
206 foreach (const QPoint
& p
, layout
) {
207 if (exclude
&& (p
== excludePoint
)) {
210 partitions
.insert(p
, new QSet
<QPoint
>());
211 partitions
[p
]->insert(p
);
214 foreach (const QPoint
& p
, layout
) {
215 if (exclude
&& (p
== excludePoint
)) {
218 QList
<QPoint
> connected
;
219 if (partitions
.contains(p
+ QPoint(1, 0))) {
220 connected
.append(p
+ QPoint(1, 0));
222 if (partitions
.contains(p
+ QPoint(0, 1))) {
223 connected
.append(p
+ QPoint(0, 1));
225 foreach (const QPoint
& c
, connected
) {
226 if (partitions
[p
] == partitions
[c
]) {
229 partitions
[p
]->unite(* (partitions
[c
]));
230 delete partitions
[c
];
231 partitions
[c
] = partitions
[p
];
235 QSet
<QSet
<QPoint
> * > unique
;
236 foreach (QSet
<QPoint
> * partition
, partitions
) {
237 unique
.insert(partition
);
240 QList
<QSet
<QPoint
> > result
;
241 foreach (QSet
<QPoint
> * partition
, unique
) {
242 result
.append(* partition
);
249 QSet
<QPoint
> BackendConfiguration::border(QSet
<QPoint
> screens
) {
251 QList
<QPoint
> borders
;
252 borders
<< QPoint(1, 0) << QPoint(0, 1) << QPoint(-1, 0) << QPoint(0, -1);
253 foreach (const QPoint
& p
, screens
) {
254 foreach (const QPoint
& border
, borders
) {
255 if (! screens
.contains(p
+ border
)) {
256 result
.insert(p
+ border
);
267 #include "backendconfigurations.moc"