#include "x.h" #include 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(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, Screen * parent) : XElement(id), _parent(parent) { // Get the information from XRROutputInfo XRRCrtcInfo * info = XRRGetCrtcInfo( const_cast(_parent->display()), const_cast(_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(_parent->display()), const_cast(_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(_parent->display()), _id, &nprop); for (int i = 0; i < nprop; ++i) { char *atom_name = XGetAtomName ( const_cast(_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); //// } ///////////////////////////////////////////////////////////////////////////////////