~arjunak234-deactivatedaccount/kde-workspace/fix125114

« back to all changes in this revision

Viewing changes to libs/kephal/service/outputscreens.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 "outputscreens.h"
 
22
 
 
23
#include <QTimer>
 
24
 
 
25
#include <KDebug>
 
26
 
 
27
namespace Kephal {
 
28
 
 
29
    OutputScreens::OutputScreens(QObject * parent)
 
30
        : Screens(parent),
 
31
        m_rebuildTimer(new QTimer(this))
 
32
    {
 
33
        m_rebuildTimer->setSingleShot(true);
 
34
        connect(m_rebuildTimer, SIGNAL(timeout()), this, SLOT(rebuildTimeout()));
 
35
        init();
 
36
    }
 
37
 
 
38
    QList<Screen *> OutputScreens::screens() {
 
39
        QList<Screen *> result;
 
40
        foreach(OutputScreen * screen, m_screens) {
 
41
            result.append(screen);
 
42
        }
 
43
        return result;
 
44
    }
 
45
 
 
46
    int OutputScreens::findId() {
 
47
        for (int i = 0; i < m_screens.size(); ++i) {
 
48
            if (! m_screens.contains(i)) {
 
49
                return i;
 
50
            }
 
51
        }
 
52
        return m_screens.size();
 
53
    }
 
54
 
 
55
    void OutputScreens::init() {
 
56
        buildScreens();
 
57
 
 
58
        connect(Outputs::self(), SIGNAL(outputResized(Kephal::Output *, QSize, QSize)), this, SLOT(outputResized(Kephal::Output *, QSize, QSize)));
 
59
        connect(Outputs::self(), SIGNAL(outputMoved(Kephal::Output *, QPoint, QPoint)), this, SLOT(outputMoved(Kephal::Output *, QPoint, QPoint)));
 
60
        connect(Outputs::self(), SIGNAL(outputActivated(Kephal::Output *)), this, SLOT(outputActivated(Kephal::Output *)));
 
61
        connect(Outputs::self(), SIGNAL(outputDeactivated(Kephal::Output *)), this, SLOT(outputDeactivated(Kephal::Output *)));
 
62
    }
 
63
 
 
64
    void OutputScreens::outputActivated(Kephal::Output * o) {
 
65
        Q_UNUSED(o)
 
66
        kDebug();
 
67
        triggerRebuildScreens();
 
68
    }
 
69
 
 
70
    void OutputScreens::outputDeactivated(Kephal::Output * o) {
 
71
        Q_UNUSED(o)
 
72
        kDebug();
 
73
        triggerRebuildScreens();
 
74
    }
 
75
 
 
76
    void OutputScreens::outputMoved(Kephal::Output * o, QPoint oldPosition, QPoint newPosition) {
 
77
        Q_UNUSED(o)
 
78
        Q_UNUSED(oldPosition)
 
79
        Q_UNUSED(newPosition)
 
80
        kDebug();
 
81
        triggerRebuildScreens();
 
82
    }
 
83
 
 
84
    void OutputScreens::outputResized(Kephal::Output * o, QSize oldSize, QSize newSize) {
 
85
        Q_UNUSED(o)
 
86
        Q_UNUSED(oldSize)
 
87
        Q_UNUSED(newSize)
 
88
        kDebug();
 
89
        triggerRebuildScreens();
 
90
    }
 
91
 
 
92
    void OutputScreens::buildScreens() {
 
93
        foreach (Output * output, Outputs::self()->outputs()) {
 
94
            // for each connected and active output,
 
95
            if (! output->isConnected() || ! output->isActivated()) {
 
96
                continue;
 
97
            }
 
98
 
 
99
            // look for any screen which intersects this output, and add it to the screen
 
100
            bool found = false;
 
101
            foreach (OutputScreen * screen, m_screens) {
 
102
                if (screen->geom().intersects(output->geom())) {
 
103
                    screen->add(output);
 
104
                    found = true;
 
105
                    break;
 
106
                }
 
107
            }
 
108
            // if the output did not intersect, add it to the first empty screen found
 
109
            if (! found) {
 
110
                foreach (OutputScreen * screen, m_screens) {
 
111
                    if (screen->outputs().empty()) {
 
112
                        screen->add(output);
 
113
                        found = true;
 
114
                        break;
 
115
                    }
 
116
                }
 
117
            }
 
118
            // if no empty screen found, generate one and add this output to it.
 
119
            if (! found) {
 
120
                OutputScreen * screen = new OutputScreen(this);
 
121
                screen->_setId(findId());
 
122
                screen->add(output);
 
123
                m_screens.insert(screen->id(), screen);
 
124
            }
 
125
        }
 
126
 
 
127
        // remove any remaining empty screens 
 
128
        for (QMap<int, OutputScreen *>::iterator i = m_screens.begin(); i != m_screens.end();) {
 
129
            if (i.value()->outputs().empty()) {
 
130
                i = m_screens.erase(i);
 
131
            } else {
 
132
                ++i;
 
133
            }
 
134
        }
 
135
 
 
136
        // remove any intersecting Screens and add removed Screens' Outputs to the intersected Screen
 
137
        bool changed;
 
138
        do {
 
139
            changed = false;
 
140
            for (QMap<int, OutputScreen *>::iterator i = m_screens.begin(); i != m_screens.end(); ++i) {
 
141
                bool deleted = false;
 
142
                for (QMap<int, OutputScreen *>::iterator j = i + 1; j != m_screens.end(); ++j) {
 
143
                    if (i.value()->geom().intersects(j.value()->geom())) {
 
144
                        OutputScreen * to = i.value();
 
145
                        OutputScreen * from = j.value();
 
146
 
 
147
                        foreach (Output * output, from->outputs()) {
 
148
                            to->add(output);
 
149
                        }
 
150
 
 
151
                        changed = true;
 
152
                        deleted = true;
 
153
                        m_screens.erase(j);
 
154
                        delete from;
 
155
                        break;
 
156
                    }
 
157
                }
 
158
                if (deleted) {
 
159
                    break;
 
160
                }
 
161
            }
 
162
        } while (changed);
 
163
 
 
164
        // I think this tries to renumber m_screens from 0, removing any gaps due to removed
 
165
        // intersecting screens
 
166
        for (int i = 0; i < m_screens.size(); ++i) {
 
167
            if (! m_screens.contains(i)) {
 
168
                // get the lowest numbered screen in m_screens
 
169
                int min = -1;
 
170
                for (QMap<int, OutputScreen *>::iterator it = m_screens.begin(); it != m_screens.end(); ++it) {
 
171
                    if ((min == -1) || (it.key() < min)) {
 
172
                        min = it.key();
 
173
                    }
 
174
                }
 
175
                OutputScreen * screen = m_screens.take(min);
 
176
                screen->_setId(i);
 
177
                m_screens.insert(i, screen);
 
178
            }
 
179
        }
 
180
    }
 
181
 
 
182
    void OutputScreens::triggerRebuildScreens() {
 
183
        kDebug();
 
184
        m_rebuildTimer->start(200);
 
185
    }
 
186
 
 
187
    void OutputScreens::rebuildTimeout() {
 
188
        rebuildScreens();
 
189
    }
 
190
 
 
191
    void OutputScreens::rebuildScreens() {
 
192
        kDebug();
 
193
 
 
194
        QMap<int, QRect> geoms;
 
195
        for (QMap<int, OutputScreen *>::const_iterator i = m_screens.constBegin(); i != m_screens.constEnd(); ++i) {
 
196
            geoms.insert(i.key(), i.value()->geom());
 
197
            i.value()->clearOutputs();
 
198
        }
 
199
 
 
200
        prepareScreens(m_screens);
 
201
        buildScreens();
 
202
 
 
203
        for (QMap<int, OutputScreen *>::const_iterator i = m_screens.constBegin(); i != m_screens.constEnd(); ++i) {
 
204
            if (! geoms.contains(i.key())) {
 
205
                emit screenAdded(i.value());
 
206
                kDebug() << "emitted screenAdded " << i.key();
 
207
            } else if (geoms[i.key()] != i.value()->geom()) {
 
208
                if (geoms[i.key()].topLeft() != i.value()->geom().topLeft()) {
 
209
                    emit screenMoved(i.value(), geoms[i.key()].topLeft(), i.value()->geom().topLeft());
 
210
                    kDebug() << "emitted screenMoved " << i.key() << " - old " << geoms[i.key()] << " - new " << i.value()->geom();
 
211
                }
 
212
                if (geoms[i.key()].size() != i.value()->geom().size()) {
 
213
                    emit screenResized(i.value(), geoms[i.key()].size(), i.value()->geom().size());
 
214
                    kDebug() << "emitted screenResized " << i.key() << " - old " << geoms[i.key()] << " - new " << i.value()->geom();
 
215
                }
 
216
            }
 
217
        }
 
218
 
 
219
        for (QMap<int, QRect>::const_iterator i = geoms.constBegin(); i != geoms.constEnd(); ++i) {
 
220
            if (! m_screens.contains(i.key())) {
 
221
                emit screenRemoved(i.key());
 
222
                kDebug() << "emitted screenRemoved " << i.key();
 
223
            }
 
224
        }
 
225
    }
 
226
 
 
227
    void OutputScreens::prepareScreens(QMap<int, OutputScreen *> & screens) {
 
228
        Q_UNUSED(screens)
 
229
    }
 
230
 
 
231
 
 
232
 
 
233
    OutputScreen::OutputScreen(QObject * parent)
 
234
        : SimpleScreen(parent)
 
235
    {
 
236
    }
 
237
 
 
238
    void OutputScreen::add(Output * output) {
 
239
        m_outputs.append(output);
 
240
 
 
241
        QRect geom = this->geom();
 
242
        if (geom.isEmpty()) {
 
243
            geom = output->geom();
 
244
        } else {
 
245
            geom = geom.unite(output->geom());
 
246
        }
 
247
 
 
248
        _setSize(geom.size());
 
249
        _setPosition(geom.topLeft());
 
250
    }
 
251
 
 
252
    QList<Output *> OutputScreen::outputs() {
 
253
        return m_outputs;
 
254
    }
 
255
 
 
256
    void OutputScreen::remove(Output * output) {
 
257
        m_outputs.removeAll(output);
 
258
    }
 
259
 
 
260
    void OutputScreen::clearOutputs() {
 
261
        m_outputs.clear();
 
262
        _setSize(QSize(0, 0));
 
263
        _setPosition(QPoint(0, 0));
 
264
    }
 
265
 
 
266
}
 
267
 
 
268
#ifndef NO_KDE
 
269
#include "outputscreens.moc"
 
270
#endif