#include "x.h"
#include <QDebug>
namespace X
{
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Screen * Screen::_instance = NULL;
Screen::Screen()
{
// Get initial data (to be freed)
_display = XOpenDisplay(NULL);
_screenResources = XRRGetScreenResourcesCurrent(_display, DefaultRootWindow(_display));
/* Get informations about Xserver */
updateScreenResources();
}
//___________________________________________________________________________
void Screen::updateScreenResources()
{
// Create the modemap
_modeMap.clear();
for (int i = 0; i < _screenResources->nmode; ++i)
{
_modeMap.insert(
_screenResources->modes[i].id,
Mode(&_screenResources->modes[i])
);
}
// Create crtcMap
_crtcMap.clear();
for (int i = 0; i < _screenResources->ncrtc; ++i)
{
_crtcMap.insert(
_screenResources->crtcs[i],
Crtc(_screenResources->crtcs[i],this)
);
}
// Create outputMap
_outputMap.clear();
for (int i = 0; i < _screenResources->noutput; ++i)
{
_outputMap.insert(
_screenResources->outputs[i],
new Output(_screenResources->outputs[i], this)
);
}
// Create connectedOutputMap
_connectedOutputList.clear();
for (OutputMap::iterator it = _outputMap.begin();
it != _outputMap.end(); ++it)
if ( (*it)->isConnected() )
_connectedOutputList.push_back((*it)->_id);
}
//___________________________________________________________________________
void Screen::createMode(
unsigned int resX,
unsigned int resY,
unsigned long dotClock,
unsigned int hSyncStart,
unsigned int hSyncEnd,
unsigned int hTotal,
unsigned int vSyncStart,
unsigned int vSyncEnd,
unsigned int vTotal,
QString name)
{
XRRModeInfo m;
m.width = resX;
m.height = resY;
m.dotClock = dotClock;
m.hSyncStart= hSyncStart;
m.hSyncEnd = hSyncEnd;
m.hTotal = hTotal;
m.hSkew = 0;
m.vSyncStart= vSyncStart;
m.vSyncEnd = vSyncEnd;
m.vTotal = vTotal;
QByteArray ba = name.toLocal8Bit();
m.name = ba.data();
XRRCreateMode(const_cast<Display*>(X::Screen::inst()->display()), DefaultRootWindow(X::Screen::inst()->display()), &m);
//XRRAddOutputMode();
}
//___________________________________________________________________________
Screen::~Screen()
{
XCloseDisplay(_display);
XRRFreeScreenResources(_screenResources);
for (int i = 0; i < _outputMap.size(); ++i)
delete _outputMap[i];
}
// //_________________________________________________________________________
//// int Screen::applyChanges()
//// {
//// // First make backup to restore in case of an error or user interaction
//// // Calculate screensize
//// QRect screenSize;
//// for (CrtcMap::iterator i = _crtcMap.begin(); i != _crtcMap.end(); ++i)
//// screenSize = screenSize.united(i->getRect());
//// /* values from xrandr */
//// float dpi = (25.4 * DisplayHeight(_display, 0)) /
//// DisplayHeightMM(_display, 0);
//// int widthMM = (int) ((25.4 * screenSize.width()) / dpi);
//// int heightMM = (int) ((25.4 * screenSize.height()) / dpi);
//// // Set screensize
//// XRRSetScreenSize(_display, DefaultRootWindow(_display),
//// screenSize.width(),
//// screenSize.height(),
//// widthMM, heightMM);
//// // Apply changes of each crtc
//// // Stupid applying here, sanitychecks have to be done before
//// for (CrtcMap::iterator i = _crtcMap.begin(); i != _crtcMap.end(); ++i)
//// {
//// if ( i->applyChanges() )
//// {
//// revertChanges();
//// return EXIT_FAILURE;
//// }
//// }
//// return EXIT_SUCCESS;
//// }
//// //_________________________________________________________________________
//// void Screen::revertChanges()
//// {
//// // TODO
//// }
//// OutputList Screen::getConnectedOutputs() const
//// {
//// OutputList result;
//// for (OutputMap::const_iterator it = _outputMap.begin();
//// it != _outputMap.end(); ++it)
//// if (it->isConnected())
//// result.push_back(it->_id);
//// return result;
//// }
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
XElement::XElement(XID xid)
: _id(xid), _validity(false) {}
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
Mode::Mode(XRRModeInfo *info)
{
if ( info == NULL )
return;
_id = info->id;
_dotClock = info->dotClock;
_hSyncStart = info->hSyncStart;
_hSyncEnd = info->hSyncEnd;
_hTotal = info->hTotal;
_hSkew = info->hSkew;
_vSyncStart = info->vSyncStart;
_vSyncEnd = info->vSyncEnd;
_vTotal = info->vTotal;
_name = QString(info->name);
_modeFlags = info->modeFlags;
_resolution.setWidth(info->width);
_resolution.setHeight(info->height);
_validity = true;
// rate = ((float) info->dotClock / ((float) info->hTotal * (float) info->vTotal));
qDebug() << "Mode: " << _id << _resolution.width() << _resolution.height();
}
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
Crtc::Crtc(XID id = None, Screen * parent = NULL)
: XElement(id), _parent(parent)
{
// Get the information from XRROutputInfo
XRRCrtcInfo * info = XRRGetCrtcInfo(
const_cast<Display*>(_parent->display()),
const_cast<XRRScreenResources*>(_parent->screenResources()),
id);
// Leave invalid if XID not existent
if ( !info ){
return;
}
_timestamp = info->timestamp;
_crtcRect = QRect(
info->x,
info->y,
info->width,
info->height);
_mode = info->mode;
for (int i = 0; i < info->noutput; ++i)
_outputs.append(info->outputs[i]);
for (int i = 0; i < info->npossible; ++i)
_possible.append(info->possible[i]);
_rotation = info->rotation;
_rotations = info->rotations;
_validity = true;
XRRFreeCrtcInfo(info);
qDebug() << "Crtc: " << _id << _mode << _outputs
<< _crtcRect;
}
//// int Crtc::applyChanges()
//// {
//// return XRRSetCrtcConfig(_parent->display,
//// _parent->screenResources,
//// _id,
//// _timestamp,
//// _crtcRect.x(),
//// _crtcRect.y(),
//// _mode,
//// _rotation,
//// _outputs.toVector().data(),
//// _outputs.size()
//// );
//// }
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
Output::Output(XID id, Screen * parent)
: XElement(id), _parent(parent), _hasReliableEDID(false)
{
// Get the information from XRROutputInfo
XRROutputInfo* info = XRRGetOutputInfo(
const_cast<Display*>(_parent->display()),
const_cast<XRRScreenResources*>(_parent->screenResources()),
id);
// Leave invalid if XID not existent
if ( !info ){
return;
}
_timestamp = info->timestamp;
_crtc = info->crtc;
_name = QString(info->name);
_metricDimension.setWidth(info->mm_width);
_metricDimension.setHeight(info->mm_height);
_connection = (State)info->connection;
//subpixel_order = info->subpixel_order;
for (int i = 0; i < info->ncrtc; ++i)
_crtcs.append(info->crtcs[i]);
for (int i = 0; i < info->nclone; ++i)
_clones.append(info->clones[i]);
// List the supported modes and extract preferred
// This is the point where creating the modemap before the outputmap
// gets a contition.
for (int i = 0; i < info->nmode; ++i){
_modes.insert(info->modes[i]);
if (i < info->npreferred)
_preferred = i;
}
XRRFreeOutputInfo(info);
// Check if this is a beamer
_isProjector = _metricDimension.isEmpty();
// Maybe obsolete, since no preferred mode means no EDID.
// // EDID = ?;
int nprop;
Atom *props = XRRListOutputProperties(
const_cast<Display*>(_parent->display()),
_id,
&nprop);
for (int i = 0; i < nprop; ++i)
{
char *atom_name = XGetAtomName (
const_cast<Display*>(_parent->display()),
props[i]);
if ( strcmp (atom_name, "EDID") == 0)
{
// // Print Stuff
// unsigned long nitems, bytes_after;
// unsigned char *prop;
// int actual_format;
// Atom actual_type;
// int bytes_per_item;
// XRRGetOutputProperty (dpy, ID, props[i],
// 0, 100, False, False,
// AnyPropertyType,
// &actual_type, &actual_format,
// &nitems, &bytes_after, &prop);
// XRRPropertyInfo *propinfo = XRRQueryOutputProperty(dpy, ID, props[i]);
// bytes_per_item = actual_format / 8;
// fprintf (stderr, "\t%s: ", atom_name);
// for (unsigned int k = 0; k < nitems; k++)
// {
// if (k != 0)
// {
// if ((k % 16) == 0)
// {
// fprintf (stderr, "\n\t\t");
// }
// }
// const uint8_t *val = prop + (k * bytes_per_item);
// fprintf (stderr, "%d02", *val);
// }
// free(propinfo);
_hasReliableEDID = true;
}
}
free(props);
qDebug() << "Output: " << _id << _name << _crtc
<< _metricDimension << _clones << _modes;
}
// //_________________________________________________________________________
//// int Screen::Output::changeMode(XID mode)
//// {
//// // Check if this mode is supported
//// if ( ! _modes.contains(mode) )
//// return 1;
//// // Check if this output is connected
//// if ( _connection != Output::Connected )
//// return 2;
//// // If this output is NOT conected to a crtc
//// if ( ! isActive() )
//// {
//// // Try to find a unconnected crtc which
//// // this output can be connected to
//// for (CrtcList::iterator i = _crtcs.begin(); ; ++i)
//// {
//// // If this search reches end no appropriate
//// // crtc has been found
//// if ( i == _crtcs.end() )
//// return 3;
//// // If a free crtc was found connect and apply mode
//// if ( _parent->_crtcMap[*i].getConnectedOutputs().empty() )
//// {
//// _parent->_crtcMap[*i].connect(this, mode);
//// break;
//// }
//// }
//// }
//// //If it is already connected apply mode to the crtc
//// // TODO(Manuel):continue
//// return 0;
//// }
//// //_________________________________________________________________________
//// int Output::changePos()
//// {
//// return 1;
//// }
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
}
//// qDebug() << XRRSetCrtcConfig(display,
//// screenResources,
//// screenResources->crtcs[1],
//// CurrentTime,
//// 0, 0,
//// 597,
//// RR_Rotate_0,
//// &(screenResources->outputs[3]),
//// 1);
//// qDebug() << XRRSetCrtcConfig(display,
//// screenResources,
//// screenResources->crtcs[0],
//// CurrentTime,
//// 1920, 0,
//// 586,
//// RR_Rotate_0,
//// &(screenResources->outputs[1]),
//// 1);
//// HOLY!!
//// XRRSetCrtcConfig(display,
//// screenResources,
//// screenResources->crtcs[1],
//// CurrentTime,
//// 0, 0,
//// 587,
//// RR_Rotate_0,
//// &screenResources->outputs[1],
//// 1);
/////////////////////////////// DBEUG //// DEBUG //////////////////////////////////
//// //SCREEN
//// qDebug() << "ScreenResources: ";
//// qDebug() << "Count of crtcs: " << screenResources->ncrtc;
//// qDebug() << "Count of outputs: " << screenResources->noutput;
//// qDebug() << "Count of modes: " << screenResources->nmode;
//// //MODES
//// for (int i = 0; i < screenResources->nmode; ++i)
//// {
//// qDebug() << screenResources->modes[i].id
//// << screenResources->modes[i].width
//// << screenResources->modes[i].height
////// << screenResources->modes[i].dotClock
////// << screenResources->modes[i].hSyncStart
////// << screenResources->modes[i].hSyncEnd
////// << screenResources->modes[i].hTotal
////// << screenResources->modes[i].hSkew
////// << screenResources->modes[i].vSyncStart
////// << screenResources->modes[i].vSyncEnd
////// << screenResources->modes[i].vTotal
////// << screenResources->modes[i].nameLength
//// << screenResources->modes[i].name;
//// }
//// //CRTCS
//// for (int j = 0; j < screenResources->ncrtc; ++j)
//// {
//// XRRCrtcInfo *CrtcInfo = XRRGetCrtcInfo(display, screenResources, screenResources->crtcs[j]);
//// qDebug() << "\n-------- CrtcInfo";
//// qDebug() << "timestamp: " << CrtcInfo->timestamp;
//// qDebug() << "x: " << CrtcInfo->x;
//// qDebug() << "y: " << CrtcInfo->y;
//// qDebug() << "width: " << CrtcInfo->width;
//// qDebug() << "height: " << CrtcInfo->height;
//// qDebug() << "rotation: " << CrtcInfo->rotation;
//// qDebug() << "noutput: " << CrtcInfo->noutput;
//// qDebug() << "rotations: " << CrtcInfo->rotations;
//// qDebug() << "npossible: " << CrtcInfo->npossible;
//// XRRFreeCrtcInfo(CrtcInfo);
//// }
//// // OUTPUTS
//// for (int nOut = 0; nOut < screenResources->noutput; ++nOut)
//// {
//// XRROutputInfo *OutputInfo = XRRGetOutputInfo (display, screenResources, screenResources->outputs[nOut]);
////// if (OutputInfo->connection == RR_Connected) {
//// qDebug() << "\n--- Output " << nOut;
//// qDebug() << "name " << OutputInfo->name;
//// qDebug() << "mm_width " << OutputInfo->mm_width;
//// qDebug() << "mm_height " << OutputInfo->mm_height;
//// qDebug() << "ncrtc " << OutputInfo->ncrtc;
//// qDebug() << "nclone " << OutputInfo->nclone;
//// qDebug() << "nmode " << OutputInfo->nmode;
//// qDebug() << "npreferred " << OutputInfo->npreferred;
//// for (int j = 0; j < OutputInfo->nmode; j++)
//// {
//// qDebug() << "mode" << j << ": " << OutputInfo->modes[j];
//// }
////// }
//// XRRFreeOutputInfo (OutputInfo);
//// }
///////////////////////////////////////////////////////////////////////////////////