2 * Copyright (c) 2007 Gustavo Pichorim Boiko <gustavo.boiko@kdemail.net>
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 published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (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 General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #include "randrscreen.h"
20 #include "randrcrtc.h"
21 #include "randroutput.h"
22 #include "randrmode.h"
25 RandRScreen::RandRScreen(int screenIndex
)
28 m_index
= screenIndex
;
29 m_rect
= QRect(0, 0, XDisplayWidth(QX11Info::display(), m_index
),
30 XDisplayHeight(QX11Info::display(), m_index
));
35 // select for randr input events
36 int mask
= RRScreenChangeNotifyMask
|
37 RRCrtcChangeNotifyMask
|
38 RROutputChangeNotifyMask
|
39 RROutputPropertyNotifyMask
;
41 XRRSelectInput(QX11Info::display(), rootWindow(), 0);
42 XRRSelectInput(QX11Info::display(), rootWindow(), mask
);
44 qDebug() << "RRInput mask is set!!";
49 RandRScreen::~RandRScreen()
52 XRRFreeScreenResources(m_resources
);
55 int RandRScreen::index() const
60 XRRScreenResources
* RandRScreen::resources() const
65 Window
RandRScreen::rootWindow() const
67 return RootWindow(QX11Info::display(), m_index
);
70 void RandRScreen::pollState()
72 XRRFreeScreenResources(XRRGetScreenResources(QX11Info::display(), rootWindow()));
75 void RandRScreen::reloadResources()
78 XRRFreeScreenResources(m_resources
);
80 m_resources
= XRRGetScreenResources(QX11Info::display(), rootWindow());
81 Q_ASSERT(m_resources
);
84 void RandRScreen::loadSettings(bool notify
)
87 int minW
, minH
, maxW
, maxH
;
89 Status status
= XRRGetScreenSizeRange(QX11Info::display(), rootWindow(),
90 &minW
, &minH
, &maxW
, &maxH
);
91 //FIXME: we should check the status here
93 QSize minSize
= QSize(minW
, minH
);
94 QSize maxSize
= QSize(maxW
, maxH
);
96 if (minSize
!= m_minSize
|| maxSize
!= m_maxSize
)
105 RandR::timestamp
= m_resources
->timestamp
;
108 changed
|= loadModes();
111 RandRCrtc
*c_none
= new RandRCrtc(this, None
);
112 m_crtcs
[None
] = c_none
;
114 for (int i
= 0; i
< m_resources
->ncrtc
; ++i
)
116 RRCrtc crtc
= m_resources
->crtcs
[i
];
117 if (m_crtcs
.contains(crtc
))
118 m_crtcs
[crtc
]->loadSettings(notify
);
121 qDebug() << "RandRScreen::loadSettings - adding crtc: " << crtc
;
122 RandRCrtc
*c
= new RandRCrtc(this, crtc
);
123 c
->loadSettings(notify
);
124 connect(c
, SIGNAL(crtcChanged(RRCrtc
, int)), this, SIGNAL(configChanged()));
131 for (int i
= 0; i
< m_resources
->noutput
; ++i
)
133 RROutput output
= m_resources
->outputs
[i
];
134 if (m_outputs
.contains(output
))
135 ;//m_outputs[m_resources->outputs[i]]->loadSettings(notify);
138 qDebug() << "RandRScreen::loadSettings - adding output: " << output
;
139 RandROutput
*o
= new RandROutput(this, output
);
140 connect(o
, SIGNAL(outputChanged(RROutput
, int)), this,
141 SLOT(slotOutputChanged(RROutput
, int)));
142 m_outputs
[output
] = o
;
143 if (o
->isConnected())
152 if (notify
&& changed
)
153 emit
configChanged();
157 bool RandRScreen::loadModes()
159 bool changed
= false;
160 for (int i
= 0; i
< m_resources
->nmode
; ++i
)
162 XRRModeInfo mode
= m_resources
->modes
[i
];
163 if (!m_modes
.contains(mode
.id
))
165 qDebug() << "RandRScreen::loadSettings - adding mode: " << mode
.id
<< mode
.width
<< "x" << mode
.height
;
166 m_modes
[mode
.id
] = RandRMode(&mode
);
174 void RandRScreen::handleEvent(XRRScreenChangeNotifyEvent
* event
)
176 qDebug() << "RandRScreen::handleEvent";
178 m_rect
.setWidth(event
->width
);
179 m_rect
.setHeight(event
->height
);
183 qDebug() << "Reloaded modes";
185 // foreach(RandROutput *output, m_outputs) {
186 // output->loadSettings(false);
190 emit
configChanged();
193 void RandRScreen::handleRandREvent(XRRNotifyEvent
* event
)
197 XRRCrtcChangeNotifyEvent
*crtcEvent
;
198 XRROutputChangeNotifyEvent
*outputEvent
;
199 XRROutputPropertyNotifyEvent
*propertyEvent
;
201 // forward events to crtcs and outputs
202 switch (event
->subtype
) {
203 case RRNotify_CrtcChange
:
204 qDebug() << "RandRScreen::handleRandREvent - CrtcChange";
205 crtcEvent
= (XRRCrtcChangeNotifyEvent
*)event
;
206 c
= crtc(crtcEvent
->crtc
);
208 c
->handleEvent(crtcEvent
);
211 case RRNotify_OutputChange
:
212 qDebug() << "RandRScreen::handleRandREvent - OutputChange";
213 outputEvent
= (XRROutputChangeNotifyEvent
*)event
;
214 o
= output(outputEvent
->output
);
216 o
->handleEvent(outputEvent
);
219 case RRNotify_OutputProperty
:
220 qDebug() << "RandRScreen::handleRandREvent - OutputProperty";
221 propertyEvent
= (XRROutputPropertyNotifyEvent
*)event
;
222 o
= output(propertyEvent
->output
);
224 o
->handlePropertyEvent(propertyEvent
);
228 qDebug() << "RandRScreen::handleRandREvent - Other";
232 QSize
RandRScreen::minSize() const
237 QSize
RandRScreen::maxSize() const
242 CrtcMap
RandRScreen::crtcs() const
247 RandRCrtc
* RandRScreen::crtc(RRCrtc id
) const
249 if (m_crtcs
.contains(id
))
255 OutputMap
RandRScreen::outputs() const
260 RandROutput
* RandRScreen::output(RROutput id
) const
262 if (m_outputs
.contains(id
))
263 return m_outputs
[id
];
268 ModeMap
RandRScreen::modes() const
273 RandRMode
RandRScreen::mode(RRMode id
) const
275 if (m_modes
.contains(id
))
281 bool RandRScreen::adjustSize(const QRect
&minimumSize
)
283 //try to find a size in which all outputs fit
285 //start with a given minimum rect
286 QRect rect
= QRect(0, 0, 0, 0).united(minimumSize
);
288 foreach(RandROutput
*output
, m_outputs
)
290 // outputs that are not active should not be taken into account
291 // when calculating the screen size
292 if (!output
->isActive())
294 rect
= rect
.united(output
->rect());
299 if (rect
.width() < m_minSize
.width())
300 rect
.setWidth(m_minSize
.width());
301 if (rect
.height() < m_minSize
.height())
302 rect
.setHeight(m_minSize
.height());
304 if (rect
.width() > m_maxSize
.width())
306 if (rect
.height() > m_maxSize
.height())
309 return setSize(rect
.size());
312 bool RandRScreen::setSize(const QSize
&s
)
314 if (s
== m_rect
.size())
317 if (s
.width() < m_minSize
.width() ||
318 s
.height() < m_minSize
.height() ||
319 s
.width() > m_maxSize
.width() ||
320 s
.height() > m_maxSize
.height())
323 int widthMM
, heightMM
;
326 /* values taken from xrandr */
327 dpi
= (25.4 * DisplayHeight(QX11Info::display(), m_index
)) / DisplayHeightMM(QX11Info::display(), m_index
);
328 widthMM
= (int) ((25.4 * s
.width()) / dpi
);
329 heightMM
= (int) ((25.4 * s
.height()) / dpi
);
331 XRRSetScreenSize(QX11Info::display(), rootWindow(), s
.width(), s
.height(), widthMM
, heightMM
);
337 int RandRScreen::connectedCount() const
339 return m_connectedCount
;
342 int RandRScreen::activeCount() const
344 return m_activeCount
;
347 QRect
RandRScreen::rect() const
352 void RandRScreen::slotOutputChanged(RROutput id
, int changes
)
357 int connected
= 0, active
= 0;
358 foreach(RandROutput
*output
, m_outputs
)
360 if (output
->isConnected())
362 if (output
->isActive())
366 m_connectedCount
= connected
;
367 m_activeCount
= active
;