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 "xrandroutputs.h"
24
#include "xrandr12/randrscreen.h"
25
#include "xrandr12/randroutput.h"
27
#include <X11/Xatom.h>
36
XRandROutputs::XRandROutputs(QObject * parent, RandRDisplay * display)
37
: BackendOutputs(parent)
43
QList<Output *> XRandROutputs::outputs() {
44
QList<Output *> result;
45
foreach (XRandROutput * output, m_outputs) {
46
result.append(output);
51
void XRandROutputs::init() {
53
RandRScreen * screen = m_display->screen(0);
54
foreach (RandROutput * output, screen->outputs()) {
55
XRandROutput * o = new XRandROutput(this, output->id());
57
connect(o, SIGNAL(outputConnected(Kephal::Output *)),
58
this, SIGNAL(outputConnected(Kephal::Output *)));
60
connect(o, SIGNAL(outputDisconnected(Kephal::Output *)),
61
this, SIGNAL(outputDisconnected(Kephal::Output *)));
63
connect(o, SIGNAL(outputActivated(Kephal::Output *)),
64
this, SIGNAL(outputActivated(Kephal::Output *)));
66
connect(o, SIGNAL(outputDeactivated(Kephal::Output *)),
67
this, SIGNAL(outputDeactivated(Kephal::Output *)));
69
connect(o, SIGNAL(outputResized(Kephal::Output *, QSize, QSize)),
70
this, SIGNAL(outputResized(Kephal::Output *, QSize, QSize)));
72
connect(o, SIGNAL(outputMoved(Kephal::Output *, QPoint, QPoint)),
73
this, SIGNAL(outputMoved(Kephal::Output *, QPoint, QPoint)));
75
connect(o, SIGNAL(outputRateChanged(Kephal::Output *, float, float)),
76
this, SIGNAL(outputRateChanged(Kephal::Output *, float, float)));
78
connect(o, SIGNAL(outputRotated(Kephal::Output *, Kephal::Rotation, Kephal::Rotation)),
79
this, SIGNAL(outputRotated(Kephal::Output *, Kephal::Rotation, Kephal::Rotation)));
80
connect(o, SIGNAL(outputReflected(Kephal::Output *, bool, bool, bool, bool)),
81
this, SIGNAL(outputReflected(Kephal::Output *, bool, bool, bool, bool)));
83
kDebug() << " added output " << output->id();
84
m_outputs.insert(o->id(), o);
88
RandROutput * XRandROutputs::output(RROutput rrId) {
89
return m_display->screen(0)->outputs()[rrId];
92
RandRDisplay * XRandROutputs::display() {
96
XRandROutput::XRandROutput(XRandROutputs * parent, RROutput rrId)
97
: BackendOutput(parent), m_productId(-1), m_serialNumber(0)
106
connect(output(), SIGNAL(outputChanged(RROutput, int)),
107
this, SLOT(outputChanged(RROutput, int)));
108
//connect(this, SLOT(_activate()), output(), SLOT(slotEnable()));
109
//connect(this, SLOT(_deactivate()), output(), SLOT(slotDisable()));
112
void XRandROutput::parseEdid() {
114
Atom atom = XInternAtom (QX11Info::display(), "EDID_DATA", false);
116
unsigned char * data;
121
XRRGetOutputProperty(QX11Info::display(), m_rrId, atom, 0, 100,
122
False, False, AnyPropertyType,
123
&type, &format, &size, &after, &data);
125
if (type == XA_INTEGER && format == 8 && EDID_TEST_HEADER(data)) {
126
//kDebug() << "got a valid edid block...";
129
* parse the 3 letter vendor code
131
char * vendor = new char[4];
133
vendor[0] = EDID_VENDOR_1(data);
134
vendor[1] = EDID_VENDOR_2(data);
135
vendor[2] = EDID_VENDOR_3(data);
139
kDebug() << "vendor code:" << m_vendor;
144
* parse the 16bit product id
146
m_productId = EDID_PRODUCT_ID(data);
148
kDebug() << "product id:" << m_productId;
151
* parse the 32bit serial number
153
m_serialNumber = EDID_SERIAL_NUMBER(data);
155
kDebug() << "serial number:" << m_serialNumber;
157
m_vendor = QString();
165
void XRandROutput::outputChanged(RROutput id, int changes) {
166
Q_ASSERT(id == m_rrId);
167
kDebug() << isConnected() << isActivated() << geom();
168
if (isConnected() != m_previousConnected) {
172
emit outputConnected(this);
174
emit outputActivated(this);
177
if (m_previousActivated) {
179
emit outputDeactivated(this);
182
emit outputDisconnected(this);
186
if (! isConnected()) {
189
if (isActivated() != m_previousActivated) {
192
emit outputActivated(this);
194
emit outputDeactivated(this);
199
QRect previousGeom = m_previousGeom;
200
Rotation previousRotation = m_previousRotation;
201
float previousRate = m_previousRate;
202
bool previousReflectX = m_previousReflectX;
203
bool previousReflectY = m_previousReflectY;
205
if (size() != previousGeom.size()) {
206
emit outputResized(this, previousGeom.size(), size());
208
if (position() != previousGeom.topLeft()) {
209
emit outputMoved(this, previousGeom.topLeft(), position());
211
if (rotation() != previousRotation) {
212
emit outputRotated(this, previousRotation, rotation());
214
if (rate() != previousRate) {
215
emit outputRateChanged(this, previousRate, rate());
217
if ((reflectX() != previousReflectX) || (reflectY() != previousReflectY)) {
218
emit outputReflected(this, previousReflectX, previousReflectY, reflectX(), reflectY());
222
void XRandROutput::saveAsPrevious() {
223
m_previousConnected = isConnected();
224
m_previousActivated = isActivated();
225
m_previousGeom = geom();
226
m_previousRotation = rotation();
227
m_previousRate = rate();
228
m_previousReflectX = reflectX();
229
m_previousReflectY = reflectY();
232
bool XRandROutput::applyGeom(const QRect & geom, float rate) {
233
if ((geom == this->geom()) && ((rate < 1) || (qFuzzyCompare(rate, this->rate())))) {
237
output()->proposeRect(geom);
239
rate = output()->refreshRate();
242
QList<float> rates = output()->refreshRates(geom.size());
243
foreach (float r, rates) {
244
if (qFuzzyCompare(rate, r)) {
250
if ((! found) && (! rates.empty())) {
254
output()->proposeRefreshRate(rate);
257
return output()->applyProposed();
260
bool XRandROutput::applyOrientation(Rotation rotation, bool reflectX, bool reflectY) {
261
if ((rotation == this->rotation()) && (reflectX == this->reflectX()) && (reflectY == this->reflectY())) {
269
orientation |= RandR::Rotate90;
272
orientation |= RandR::Rotate270;
275
orientation |= RandR::Rotate180;
278
orientation |= RandR::Rotate0;
282
orientation |= RandR::ReflectX;
285
orientation |= RandR::ReflectY;
288
output()->proposeRotation(orientation);
289
return output()->applyProposed();
292
void XRandROutput::deactivate()
294
output()->slotDisable();
297
RandROutput * XRandROutput::output() const
299
return m_outputs->output(m_rrId);
302
QString XRandROutput::id() const
304
return output()->name();
307
QSize XRandROutput::size() const
309
return output()->rect().size();
312
QSize XRandROutput::preferredSize() const
314
if (output()->preferredMode().size().isEmpty()) {
317
return output()->preferredMode().size();
321
QList<QSize> XRandROutput::availableSizes() const {
322
QList<QSize> sizes = output()->sizes();
326
QPoint XRandROutput::position() const {
327
return output()->rect().topLeft();
330
bool XRandROutput::isConnected() const {
331
return output()->isConnected();
334
bool XRandROutput::isActivated() const
336
return output()->isActive();
339
QString XRandROutput::vendor() const
344
int XRandROutput::productId() const
349
unsigned int XRandROutput::serialNumber() const
351
return m_serialNumber;
354
RROutput XRandROutput::_id() const {
358
Rotation XRandROutput::rotation() const
360
switch (output()->rotation() & RandR::RotateMask) {
361
case RandR::Rotate90:
363
case RandR::Rotate180:
364
return RotateInverted;
365
case RandR::Rotate270:
372
bool XRandROutput::reflectX() const
374
return (output()->rotation() & RandR::ReflectX);
377
bool XRandROutput::reflectY() const
379
return (output()->rotation() & RandR::ReflectY);
382
float XRandROutput::rate() const
384
return output()->refreshRate();
387
QList<float> XRandROutput::availableRates() const
389
return output()->refreshRates(size());
392
void XRandROutput::resize(const QSize & size)
398
void XRandROutput::rotate(Rotation rotation)
404
void XRandROutput::setReflectX(bool reflect)
410
void XRandROutput::setReflectY(bool reflect)
416
void XRandROutput::changeRate(double rate)