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

« back to all changes in this revision

Viewing changes to kcontrol/randr/randrdisplay.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 (c) 2008      Harry Bock <hbock@providence.edu>
 
3
 * Copyright (c) 2007      Gustavo Pichorim Boiko <gustavo.boiko@kdemail.net>
 
4
 * Copyright (c) 2002,2003 Hamish Rodda <rodda@kde.org>
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
19
 */
 
20
 
 
21
#include <KLocale>
 
22
#include <KConfigGroup>
 
23
#include <KDebug>
 
24
#include <QApplication>
 
25
#include <QDesktopWidget>
 
26
#include <QX11Info>
 
27
 
 
28
#include "randrdisplay.h"
 
29
#ifdef HAS_RANDR_1_2 
 
30
#include "randrscreen.h"
 
31
#endif
 
32
#include "legacyrandrscreen.h"
 
33
#include <config-randr.h>
 
34
 
 
35
RandRDisplay::RandRDisplay()
 
36
        : m_valid(true)
 
37
{
 
38
        m_dpy = QX11Info::display();
 
39
        
 
40
        // Check extension
 
41
        if(XRRQueryExtension(m_dpy, &m_eventBase, &m_errorBase) == False) {
 
42
                m_valid = false;
 
43
                return;
 
44
        }
 
45
 
 
46
        int major_version, minor_version;
 
47
        XRRQueryVersion(m_dpy, &major_version, &minor_version);
 
48
 
 
49
        m_version = i18n("X Resize and Rotate extension version %1.%2",
 
50
                         major_version,minor_version);
 
51
 
 
52
        // check if we have the new version of the XRandR extension
 
53
        RandR::has_1_2 = (major_version > 1 || (major_version == 1 && minor_version >= 2));
 
54
        RandR::has_1_3 = (major_version > 1 || (major_version == 1 && minor_version >= 3));
 
55
        
 
56
        if(RandR::has_1_3)
 
57
                kDebug() << "Using XRANDR extension 1.3 or greater.";
 
58
        else if(RandR::has_1_2)
 
59
                kDebug() << "Using XRANDR extension 1.2.";
 
60
        else kDebug() << "Using legacy XRANDR extension (1.1 or earlier).";
 
61
        
 
62
        kDebug() << "XRANDR error base: " << m_errorBase;
 
63
        m_numScreens = ScreenCount(m_dpy);
 
64
        m_currentScreenIndex = 0;
 
65
 
 
66
        // set the timestamp to 0
 
67
        RandR::timestamp = 0;
 
68
 
 
69
        // This assumption is WRONG with Xinerama
 
70
        // Q_ASSERT(QApplication::desktop()->numScreens() == ScreenCount(QX11Info::display()));
 
71
 
 
72
        for (int i = 0; i < m_numScreens; i++) {
 
73
#ifdef HAS_RANDR_1_2
 
74
                if (RandR::has_1_2)
 
75
                        m_screens.append(new RandRScreen(i));
 
76
                else
 
77
#endif
 
78
                        m_legacyScreens.append(new LegacyRandRScreen(i));
 
79
        }
 
80
 
 
81
#if 0
 
82
//#ifdef HAS_RANDR_1_2
 
83
        // check if we have more than one output, if no, revert to the legacy behavior
 
84
        if (RandR::has_1_2)
 
85
        {
 
86
                int count = 0;
 
87
                foreach(RandRScreen *screen, m_screens)
 
88
                        count += screen->outputs().count();
 
89
 
 
90
                if (count < 2)
 
91
                {
 
92
                        RandR::has_1_2 = false;
 
93
                        for (int i = 0; i < m_numScreens; ++i)
 
94
                        {
 
95
                                delete m_screens[i];
 
96
                                m_legacyScreens.append(new LegacyRandRScreen(i));
 
97
                        }
 
98
                        m_screens.clear();
 
99
                }
 
100
        }
 
101
#endif
 
102
        setCurrentScreen(DefaultScreen(QX11Info::display()));
 
103
}
 
104
 
 
105
RandRDisplay::~RandRDisplay()
 
106
{
 
107
                qDeleteAll(m_legacyScreens);
 
108
#ifdef HAS_RANDR_1_2
 
109
                qDeleteAll(m_screens);
 
110
#endif
 
111
}
 
112
 
 
113
bool RandRDisplay::isValid() const
 
114
{
 
115
        return m_valid;
 
116
}
 
117
 
 
118
const QString& RandRDisplay::errorCode() const
 
119
{
 
120
        return m_errorCode;
 
121
}
 
122
 
 
123
int RandRDisplay::eventBase() const
 
124
{
 
125
        return m_eventBase;
 
126
}
 
127
 
 
128
int RandRDisplay::errorBase() const
 
129
{
 
130
        return m_errorBase;
 
131
}
 
132
 
 
133
const QString& RandRDisplay::version() const
 
134
{
 
135
        return m_version;
 
136
}
 
137
 
 
138
void RandRDisplay::setCurrentScreen(int index)
 
139
{
 
140
        Q_ASSERT(index < ScreenCount(m_dpy));
 
141
        m_currentScreenIndex = index;
 
142
}
 
143
 
 
144
int RandRDisplay::screenIndexOfWidget(QWidget* widget)
 
145
{
 
146
        //int ret = QApplication::desktop()->screenNumber(widget);
 
147
        //return ret != -1 ? ret : QApplication::desktop()->primaryScreen();
 
148
        
 
149
        // get info from Qt's X11 info directly; QDesktopWidget seems to use
 
150
        // Xinerama by default, which doesn't work properly with randr.
 
151
        // It will return more screens than exist for the display, causing
 
152
        // a crash in the screen/currentScreen methods.
 
153
        if(widget)
 
154
                return widget->x11Info().screen();
 
155
 
 
156
        return -1;
 
157
}
 
158
 
 
159
int RandRDisplay::currentScreenIndex() const
 
160
{
 
161
        return m_currentScreenIndex;
 
162
}
 
163
 
 
164
bool RandRDisplay::needsRefresh() const
 
165
{
 
166
        Time time, config_timestamp;
 
167
        time = XRRTimes(m_dpy, m_currentScreenIndex, &config_timestamp);
 
168
        
 
169
        kDebug() << "Cache:" << RandR::timestamp << "Server:" << time << "Config:" << config_timestamp;
 
170
        return (RandR::timestamp < time);
 
171
}
 
172
 
 
173
void RandRDisplay::refresh()
 
174
{
 
175
#ifdef HAS_RANDR_1_2
 
176
        if (RandR::has_1_2) {
 
177
                for (int i = 0; i < m_screens.count(); ++i) {
 
178
                        RandRScreen* s = m_screens.at(i);
 
179
                        s->loadSettings();
 
180
                }
 
181
        }
 
182
        else
 
183
#endif
 
184
        {
 
185
                for (int i = 0; i < m_legacyScreens.size(); ++i) {
 
186
                        LegacyRandRScreen* s = m_legacyScreens.at(i);
 
187
                        s->loadSettings();
 
188
                }
 
189
        }
 
190
}
 
191
 
 
192
bool RandRDisplay::canHandle(const XEvent *e) const 
 
193
{
 
194
        if (e->type == m_eventBase + RRScreenChangeNotify)
 
195
                return true;
 
196
#ifdef HAS_RANDR_1_2
 
197
        else if (e->type == m_eventBase + RRNotify)
 
198
                return true;
 
199
#endif
 
200
        return false;
 
201
}
 
202
 
 
203
 
 
204
void RandRDisplay::handleEvent(XEvent *e)
 
205
{
 
206
        if (e->type == m_eventBase + RRScreenChangeNotify) {
 
207
#ifdef HAS_RANDR_1_2
 
208
                if (RandR::has_1_2) {
 
209
                        XRRScreenChangeNotifyEvent *event = (XRRScreenChangeNotifyEvent*)(e);
 
210
                        for (int i=0; i < m_screens.count(); ++i) {
 
211
                                RandRScreen *screen = m_screens.at(i);
 
212
                                if (screen->rootWindow() == event->root)
 
213
                                        screen->handleEvent(event);
 
214
                        }
 
215
                        
 
216
                }
 
217
                else
 
218
#endif
 
219
                {
 
220
                        // handle the event
 
221
                }
 
222
        }
 
223
#ifdef HAS_RANDR_1_2
 
224
        else if (e->type == m_eventBase + RRNotify) {
 
225
                //forward the event to the right screen
 
226
                XRRNotifyEvent *event = (XRRNotifyEvent*)e;
 
227
                for (int i=0; i < m_screens.count(); ++i) {
 
228
                        RandRScreen *screen = m_screens.at(i);
 
229
                        if ( screen->rootWindow() == event->window ) {
 
230
                                screen->handleRandREvent(event);
 
231
                        }
 
232
                }
 
233
        }
 
234
#endif
 
235
}
 
236
 
 
237
int RandRDisplay::numScreens() const
 
238
{
 
239
        Q_ASSERT(ScreenCount(QX11Info::display()) == m_numScreens);
 
240
        return m_numScreens;
 
241
}
 
242
 
 
243
LegacyRandRScreen* RandRDisplay::legacyScreen(int index)
 
244
{
 
245
        return m_legacyScreens.at(index);
 
246
}
 
247
 
 
248
LegacyRandRScreen* RandRDisplay::currentLegacyScreen()
 
249
{
 
250
        return m_legacyScreens.at(m_currentScreenIndex);
 
251
}
 
252
 
 
253
#ifdef HAS_RANDR_1_2
 
254
RandRScreen* RandRDisplay::screen(int index)
 
255
{
 
256
        return m_screens.at(index);
 
257
}
 
258
 
 
259
RandRScreen* RandRDisplay::currentScreen()
 
260
{
 
261
        return m_screens.at(m_currentScreenIndex);
 
262
}
 
263
#endif
 
264
 
 
265
bool RandRDisplay::loadDisplay(KConfig& config, bool loadScreens)
 
266
{
 
267
        if (loadScreens)
 
268
        {
 
269
#ifdef HAS_RANDR_1_2
 
270
                if (RandR::has_1_2)
 
271
                {
 
272
                        foreach(RandRScreen *s, m_screens)
 
273
                                s->load(config);
 
274
 
 
275
                }
 
276
                else
 
277
#endif
 
278
                {
 
279
                        foreach(LegacyRandRScreen* s, m_legacyScreens)
 
280
                                s->load(config);
 
281
                }
 
282
        }
 
283
        return applyOnStartup(config);
 
284
}
 
285
 
 
286
bool RandRDisplay::applyOnStartup(KConfig& config)
 
287
{
 
288
        return config.group("Display").readEntry("ApplyOnStartup", false);
 
289
}
 
290
 
 
291
bool RandRDisplay::syncTrayApp(KConfig& config)
 
292
{
 
293
        return config.group("Display").readEntry("SyncTrayApp", false);
 
294
}
 
295
 
 
296
void RandRDisplay::saveDisplay(KConfig& config, bool syncTrayApp)
 
297
{
 
298
        KConfigGroup group = config.group("Display");
 
299
        group.writeEntry("SyncTrayApp", syncTrayApp);
 
300
 
 
301
#ifdef HAS_RANDR_1_2
 
302
        if (RandR::has_1_2)
 
303
        {
 
304
                foreach(RandRScreen *s, m_screens)
 
305
                        s->save(config);
 
306
        }
 
307
        else
 
308
#endif
 
309
        {
 
310
                foreach(LegacyRandRScreen *s, m_legacyScreens)
 
311
                        s->save(config);
 
312
        }
 
313
}
 
314
 
 
315
// to be used during desktop startup, make all screens provide the shell commands
 
316
// (using xrandr cli tool), save them here and a script will perform these commands
 
317
// early during desktop startup
 
318
void RandRDisplay::saveStartup(KConfig& config)
 
319
{
 
320
        KConfigGroup group = config.group("Display");
 
321
        group.writeEntry("ApplyOnStartup", true);
 
322
        QStringList commands;
 
323
#ifdef HAS_RANDR_1_2
 
324
        if (RandR::has_1_2)
 
325
        {
 
326
                foreach(RandRScreen *s, m_screens)
 
327
                        commands += s->startupCommands();
 
328
        }
 
329
        else
 
330
#endif
 
331
        {
 
332
                foreach(LegacyRandRScreen *s, m_legacyScreens)
 
333
                        commands += s->startupCommands();
 
334
        }
 
335
        group.writeEntry( "StartupCommands", commands.join( "\n" ));
 
336
}
 
337
 
 
338
void RandRDisplay::disableStartup(KConfig& config)
 
339
{
 
340
        KConfigGroup group = config.group("Display");
 
341
        group.writeEntry("ApplyOnStartup", false);
 
342
        group.deleteEntry( "StartupCommands" );
 
343
}
 
344
 
 
345
void RandRDisplay::applyProposed(bool confirm)
 
346
{
 
347
 
 
348
#ifdef HAS_RANDR_1_2
 
349
        if (RandR::has_1_2)
 
350
                foreach(RandRScreen *s, m_screens)
 
351
                        s->applyProposed(confirm);
 
352
        else
 
353
#endif
 
354
        {
 
355
                foreach(LegacyRandRScreen *s, m_legacyScreens)
 
356
                {
 
357
                        if (s->proposedChanged()) {
 
358
                                if (confirm)
 
359
                                                s->applyProposedAndConfirm();
 
360
                                else
 
361
                                                s->applyProposed();
 
362
                        }
 
363
                }
 
364
        }
 
365
}
 
366
 
 
367
// vim:noet:sts=8:sw=8: