not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kcontrol / randr / randrdisplay.cpp
blob3df3f7096260ae4d7ebd14a3a010c7e97939724e
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>
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.
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.
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.
21 #include <KLocale>
22 #include <KConfigGroup>
23 #include <KDebug>
24 #include <QApplication>
25 #include <QDesktopWidget>
26 #include <QX11Info>
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>
35 RandRDisplay::RandRDisplay()
36 : m_valid(true)
38 m_dpy = QX11Info::display();
40 // Check extension
41 if(XRRQueryExtension(m_dpy, &m_eventBase, &m_errorBase) == False) {
42 m_valid = false;
43 return;
46 int major_version, minor_version;
47 XRRQueryVersion(m_dpy, &major_version, &minor_version);
49 m_version = i18n("X Resize and Rotate extension version %1.%2",
50 major_version,minor_version);
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));
55 if(RandR::has_1_2)
56 kDebug() << "Using XRANDR extension 1.2 or greater.";
57 else kDebug() << "Using legacy XRANDR extension (1.1 or earlier).";
59 kDebug() << "XRANDR error base: " << m_errorBase;
60 m_numScreens = ScreenCount(m_dpy);
61 m_currentScreenIndex = 0;
63 // set the timestamp to 0
64 RandR::timestamp = 0;
66 // This assumption is WRONG with Xinerama
67 // Q_ASSERT(QApplication::desktop()->numScreens() == ScreenCount(QX11Info::display()));
69 for (int i = 0; i < m_numScreens; i++) {
70 #ifdef HAS_RANDR_1_2
71 if (RandR::has_1_2)
72 m_screens.append(new RandRScreen(i));
73 else
74 #endif
75 m_legacyScreens.append(new LegacyRandRScreen(i));
78 #if 0
79 //#ifdef HAS_RANDR_1_2
80 // check if we have more than one output, if no, revert to the legacy behavior
81 if (RandR::has_1_2)
83 int count = 0;
84 foreach(RandRScreen *screen, m_screens)
85 count += screen->outputs().count();
87 if (count < 2)
89 RandR::has_1_2 = false;
90 for (int i = 0; i < m_numScreens; ++i)
92 delete m_screens[i];
93 m_legacyScreens.append(new LegacyRandRScreen(i));
95 m_screens.clear();
98 #endif
99 setCurrentScreen(DefaultScreen(QX11Info::display()));
102 RandRDisplay::~RandRDisplay()
104 qDeleteAll(m_legacyScreens);
105 #ifdef HAS_RANDR_1_2
106 qDeleteAll(m_screens);
107 #endif
110 bool RandRDisplay::isValid() const
112 return m_valid;
115 const QString& RandRDisplay::errorCode() const
117 return m_errorCode;
120 int RandRDisplay::eventBase() const
122 return m_eventBase;
125 int RandRDisplay::errorBase() const
127 return m_errorBase;
130 const QString& RandRDisplay::version() const
132 return m_version;
135 void RandRDisplay::setCurrentScreen(int index)
137 Q_ASSERT(index < ScreenCount(m_dpy));
138 m_currentScreenIndex = index;
141 int RandRDisplay::screenIndexOfWidget(QWidget* widget)
143 //int ret = QApplication::desktop()->screenNumber(widget);
144 //return ret != -1 ? ret : QApplication::desktop()->primaryScreen();
146 // get info from Qt's X11 info directly; QDesktopWidget seems to use
147 // Xinerama by default, which doesn't work properly with randr.
148 // It will return more screens than exist for the display, causing
149 // a crash in the screen/currentScreen methods.
150 if(widget)
151 return widget->x11Info().screen();
153 return -1;
156 int RandRDisplay::currentScreenIndex() const
158 return m_currentScreenIndex;
161 bool RandRDisplay::needsRefresh() const
163 Time time, config_timestamp;
164 time = XRRTimes(m_dpy, m_currentScreenIndex, &config_timestamp);
166 kDebug() << "Cache:" << RandR::timestamp << "Server:" << time << "Config:" << config_timestamp;
167 return (RandR::timestamp < time);
170 void RandRDisplay::refresh()
172 #ifdef HAS_RANDR_1_2
173 if (RandR::has_1_2) {
174 for (int i = 0; i < m_screens.count(); ++i) {
175 RandRScreen* s = m_screens.at(i);
176 s->loadSettings();
179 else
180 #endif
182 for (int i = 0; i < m_legacyScreens.size(); ++i) {
183 LegacyRandRScreen* s = m_legacyScreens.at(i);
184 s->loadSettings();
189 bool RandRDisplay::canHandle(const XEvent *e) const
191 if (e->type == m_eventBase + RRScreenChangeNotify)
192 return true;
193 #ifdef HAS_RANDR_1_2
194 else if (e->type == m_eventBase + RRNotify)
195 return true;
196 #endif
197 return false;
201 void RandRDisplay::handleEvent(XEvent *e)
203 if (e->type == m_eventBase + RRScreenChangeNotify) {
204 #ifdef HAS_RANDR_1_2
205 if (RandR::has_1_2) {
206 XRRScreenChangeNotifyEvent *event = (XRRScreenChangeNotifyEvent*)(e);
207 for (int i=0; i < m_screens.count(); ++i) {
208 RandRScreen *screen = m_screens.at(i);
209 if (screen->rootWindow() == event->root)
210 screen->handleEvent(event);
214 else
215 #endif
217 // handle the event
220 #ifdef HAS_RANDR_1_2
221 else if (e->type == m_eventBase + RRNotify) {
222 //forward the event to the right screen
223 XRRNotifyEvent *event = (XRRNotifyEvent*)e;
224 for (int i=0; i < m_screens.count(); ++i) {
225 RandRScreen *screen = m_screens.at(i);
226 if ( screen->rootWindow() == event->window ) {
227 screen->handleRandREvent(event);
231 #endif
234 int RandRDisplay::numScreens() const
236 Q_ASSERT(ScreenCount(QX11Info::display()) == m_numScreens);
237 return m_numScreens;
240 LegacyRandRScreen* RandRDisplay::legacyScreen(int index)
242 return m_legacyScreens.at(index);
245 LegacyRandRScreen* RandRDisplay::currentLegacyScreen()
247 return m_legacyScreens.at(m_currentScreenIndex);
250 #ifdef HAS_RANDR_1_2
251 RandRScreen* RandRDisplay::screen(int index)
253 return m_screens.at(index);
256 RandRScreen* RandRDisplay::currentScreen()
258 return m_screens.at(m_currentScreenIndex);
260 #endif
262 bool RandRDisplay::loadDisplay(KConfig& config, bool loadScreens)
264 if (loadScreens)
266 #ifdef HAS_RANDR_1_2
267 if (RandR::has_1_2)
269 foreach(RandRScreen *s, m_screens)
270 s->load(config);
273 else
274 #endif
276 foreach(LegacyRandRScreen* s, m_legacyScreens)
277 s->load(config);
280 return applyOnStartup(config);
283 bool RandRDisplay::applyOnStartup(KConfig& config)
285 return config.group("Display").readEntry("ApplyOnStartup", false);
288 bool RandRDisplay::syncTrayApp(KConfig& config)
290 return config.group("Display").readEntry("SyncTrayApp", false);
293 void RandRDisplay::saveDisplay(KConfig& config, bool applyOnStartup, bool syncTrayApp)
295 KConfigGroup group = config.group("Display");
296 group.writeEntry("ApplyOnStartup", applyOnStartup);
297 group.writeEntry("SyncTrayApp", syncTrayApp);
299 #ifdef HAS_RANDR_1_2
300 if (RandR::has_1_2)
302 foreach(RandRScreen *s, m_screens)
303 s->save(config);
305 else
306 #endif
308 foreach(LegacyRandRScreen *s, m_legacyScreens)
309 s->save(config);
313 void RandRDisplay::applyProposed(bool confirm)
316 #ifdef HAS_RANDR_1_2
317 if (RandR::has_1_2)
318 foreach(RandRScreen *s, m_screens)
319 s->applyProposed(confirm);
320 else
321 #endif
323 foreach(LegacyRandRScreen *s, m_legacyScreens)
325 if (s->proposedChanged()) {
326 if (confirm)
327 s->applyProposedAndConfirm();
328 else
329 s->applyProposed();