summaryrefslogblamecommitdiffstats
path: root/src/x.cpp
blob: e0aa12fa5135d39e0d2675f8075c672ff2efa849 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

















                                                                                           
                            
 




                                                                               
                         
                     








                                                     
                     








                                                     
                       








                                                          
                                 



                                                     
   
 




























                                                                                                                           





































































































                                                                                         
                                     

















































































































































                                                                                      
                                                        










































































































































































                                                                                                                        
#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, Screen * parent)
      : 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);
////        }
///////////////////////////////////////////////////////////////////////////////////