From 491fda343c43fa761acd01dca1dab044284aaf5c Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 27 Nov 2013 20:53:54 +0100 Subject: [Experimental] Finally list is sorted --- src/beamer.conf | 30 ++++++ src/beamer.conf2 | 26 ----- src/config.cpp | 30 ++++-- src/config.h | 12 +-- src/main.cpp | 82 ++++---------- src/widget.cpp | 321 +++++++++++++++++++++++++++++++++++++++++++------------ src/widget.h | 32 ++++-- src/x.cpp | 42 +++++++- src/x.h | 14 ++- 9 files changed, 403 insertions(+), 186 deletions(-) create mode 100644 src/beamer.conf delete mode 100644 src/beamer.conf2 diff --git a/src/beamer.conf b/src/beamer.conf new file mode 100644 index 0000000..2a6d0c3 --- /dev/null +++ b/src/beamer.conf @@ -0,0 +1,30 @@ +[Modelines] +# 16:10 +1/Modeline=1280x800 83.50 1280 1352 1480 1680 800 803 809 831 -hsync +vsync +2/Modeline=1440x1050 106.50 1440 1528 1672 1904 900 903 909 934 -hsync +vsync +3/Modeline=1680x1200 146.25 1680 1784 1960 2240 1050 1053 1059 1089 -hsync +vsync +4/Modeline=1920x1200 193.25 1920 2056 2256 2592 1200 1203 1209 1245 -hsync +vsync +5/Modeline=2560x1600 348.50 2560 2760 3032 3504 1600 1603 1609 1658 -hsync +vsync +# 16:9 +6/Modeline=1280x720 74.50 1280 1344 1472 1664 720 723 728 748 -hsync +vsync +7/Modeline=1368x768 85.25 1368 1440 1576 1784 768 771 781 798 -hsync +vsync +8/Modeline=1600x900 118.25 1600 1696 1856 2112 900 903 908 934 -hsync +vsync +9/Modeline=1920x1080 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync +10/Modeline=2560x1440 312.25 2560 2752 3024 3488 1440 1443 1448 1493 -hsync +vsync +# 4:3 +11/Modeline=800x600 38.25 800 832 912 1024 600 603 607 624 -hsync +vsync +12/Modeline=1024x768 63.50 1024 1072 1176 1328 768 771 775 798 -hsync +vsync +13/Modeline=1152x864 81.75 1152 1216 1336 1520 864 867 871 897 -hsync +vsync +14/Modeline=1280x960 101.25 1280 1360 1488 1696 960 963 967 996 -hsync +vsync +15/Modeline=1400x1050 121.75 1400 1488 1632 1864 1050 1053 1057 1089 -hsync +vsync +size=15 + +[General] +# Display to use +display :0 +interface eth0 + +[SpecificSettings] +# IP specific configs +1/IP=132.230.4.100 1280x900 +size=1 diff --git a/src/beamer.conf2 b/src/beamer.conf2 deleted file mode 100644 index 0cf780f..0000000 --- a/src/beamer.conf2 +++ /dev/null @@ -1,26 +0,0 @@ -# 16:10 -Modeline 83.50 1280 1352 1480 1680 800 803 809 831 -hsync +vsync -Modeline 106.50 1440 1528 1672 1904 900 903 909 934 -hsync +vsync -Modeline 146.25 1680 1784 1960 2240 1050 1053 1059 1089 -hsync +vsync -Modeline 193.25 1920 2056 2256 2592 1200 1203 1209 1245 -hsync +vsync -Modeline 348.50 2560 2760 3032 3504 1600 1603 1609 1658 -hsync +vsync - -# 16:9 -Modeline 74.50 1280 1344 1472 1664 720 723 728 748 -hsync +vsync -Modeline 85.25 1368 1440 1576 1784 768 771 781 798 -hsync +vsync -Modeline 118.25 1600 1696 1856 2112 900 903 908 934 -hsync +vsync -Modeline 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync -Modeline 312.25 2560 2752 3024 3488 1440 1443 1448 1493 -hsync +vsync - -# 4:3 -Modeline 38.25 800 832 912 1024 600 603 607 624 -hsync +vsync -Modeline 63.50 1024 1072 1176 1328 768 771 775 798 -hsync +vsync -Modeline 81.75 1152 1216 1336 1520 864 867 871 897 -hsync +vsync -Modeline 101.25 1280 1360 1488 1696 960 963 967 996 -hsync +vsync -Modeline 121.75 1400 1488 1632 1864 1050 1053 1057 1089 -hsync +vsync - -# Display to use -Display :0 - -# IP specific configs -IP 132.230.4.100 1280x900 diff --git a/src/config.cpp b/src/config.cpp index 1e3f827..c8327f7 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -45,7 +45,6 @@ void Config::loadSettings(QString _file) /* Check for ip specific settings */ - // Get local ip QString IPV4 = getIPV4ofInterface(interface); @@ -58,18 +57,27 @@ void Config::loadSettings(QString _file) /* Get the "must-have-modelines" */ - settings.beginGroup(GROUP_MODELINES); + int size = settings.beginReadArray(GROUP_MODELINES); + for (int i = 0; i < size; ++i) { + settings.setArrayIndex(i); + qDebug()<< settings.value("Modeline").toString(); + modeLines.append(settings.value("Modeline").toString()); + } + settings.endArray(); - // Get all keys in this group (Keys are modenames) - QStringList modeKeys = settings.allKeys(); - // Get the modeline for each key - for (QStringList::const_iterator i = modeKeys.constBegin(); i != modeKeys.constEnd(); ++i) - { - // Prepend the name and save in list - modeLines.insert(*i, settings.value(*i).toStringList()); - } - settings.endGroup(); + +// // Get all keys in this group (Keys are modenames) +// QStringList modeKeys = settings.allKeys(); + +// // Get the modeline for each key +// for (QStringList::const_iterator i = modeKeys.constBegin(); i != modeKeys.constEnd(); ++i) +// { +// qDebug()<< "found" << *i; +// // Prepend the name and save in list +// modeLines.insert(*i, settings.value(*i).toStringList()); +// } +// settings.endGroup(); } diff --git a/src/config.h b/src/config.h index 20f67d3..7248d57 100644 --- a/src/config.h +++ b/src/config.h @@ -20,7 +20,7 @@ class Config QString display; QString interface; QStringList ipSpecificXConf; - QMap modeLines; + QList modeLines; QString getIPV4ofInterface(QString) const; @@ -29,11 +29,11 @@ public: void loadSettings(QString); // Getters - inline const QString& getSettingsPath() { return settingsPath; } - inline const QString& getDisplay() { return display; } - inline const QString& getInterface() { return interface; } - inline const QStringList& getIpSpecificXConf(){ return ipSpecificXConf; } - inline const QMap& getModeLines() { return modeLines; } + inline const QString& getSettingsPath() { return settingsPath; } + inline const QString& getDisplay() { return display; } + inline const QString& getInterface() { return interface; } + inline const QStringList& getIpSpecificXConf(){ return ipSpecificXConf; } + inline const QList& getModeLines() { return modeLines; } // Singleton // inline static Config * inst() { diff --git a/src/main.cpp b/src/main.cpp index 9c95f7c..584c121 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,73 +20,29 @@ void usage() int main(int argc, char *argv[]) { -// /////////////////// -// // Debug -// argv[1] = "/home/manuel/beamer.conf"; -// ///////////////////7 - -// if ( argc < 1 ) -// { -// std::cerr << "Too many arguments. The only parameter shall be a path to a config file." << std::endl; -// exit(1); +// if (argc != 1) +// std::cout << "Usage: " << argv[0] << " " << std::endl; +// else { +// // Check if file exists +// std::ifstream f(argv[1]); +// if (!f) { +// std::cerr << "The config file does not exist." << std::endl; +// exit(1); // } -// if ( argc == 1 ) -// { -// // Check if file exists -// std::ifstream f(argv[1]); -// if (!f) -// { -// std::cerr << "The config file does not exist" << std::endl; -// exit(1); -// } -// else -// f.close(); -// } - -// //Load settings -// Config::inst()->loadSettings(argv[1]); -// qDebug() << X::Screen::inst(); - - -// qDebug() << Config::inst()->getDisplay(); -// qDebug() << Config::inst()->getInterface(); -// qDebug() << Config::inst()->getIpSpecificXConf(); -// qDebug() << Config::inst()->getModeLines(); -// qDebug() << Config::inst()->getSettingsPath(); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// else +// f.close(); +// } +// //Load settings +// Config::inst()->loadSettings(argv[1]); +// qDebug() << X::Screen::inst(); +// qDebug() << Config::inst()->getDisplay(); +// qDebug() << Config::inst()->getInterface(); +// qDebug() << Config::inst()->getIpSpecificXConf(); +// qDebug() << Config::inst()->getModeLines(); +// qDebug() << Config::inst()->getSettingsPath(); // // Get initial data (to be freed) diff --git a/src/widget.cpp b/src/widget.cpp index 994f3d1..d2a6765 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -1,98 +1,277 @@ #include "widget.h" #include "ui_widget.h" +#include "config.h" #include #include #include +#include +//___________________________________________________________________________ +int compareModeString (const QString & a, const QString & b) { + if (a.size() == b.size()) + return a.compare(b); + else + if (a.size() > b.size()) + return -1; + else + return 1; +} +//___________________________________________________________________________ Widget::Widget(QWidget *parent) : QWidget(parent), - ui(new Ui::Widget) + _ui(new Ui::Widget) { - ui->setupUi(this); - - X::OutputList outputs = X::Screen::inst()->getConnectedOutputList(); - - switch ( X::Screen::inst()->getConnectedOutputList().size() ){ - /*************************************************************************/ - case 1:// In case of one connected output - xrandr --auto - qDebug() << "Normal output"; - exit(0); - break; - /*************************************************************************/ - case 2: // In case of two connected outputs - - // If one of the two connected outputs is a beamer - if (true) - //X::Screen::inst()->getOutputMap()[outputs[0]]->isProjector() - // || X::Screen::inst()->getOutputMap()[outputs[1]]->isProjector() ) - { - qDebug() << "Cloned output"; - /*****************************************************************/ - // If the beamer transmits no reliable EDID data add modes - if ( ! ( X::Screen::inst()->getOutputMap()[outputs[0]]->hasReliableEDID() - && X::Screen::inst()->getOutputMap()[outputs[1]]->hasReliableEDID() ) ) - { - // TODO ADD MODES - qDebug() << "Normal output"; - } + _ui->setupUi(this); - // Get a set of unique modes as string. Ugly but same resolutions may - // have different ids. This means modes are compared by name which is - X::ModeSet ModeSet1 = X::Screen::inst()->getOutputMap()[outputs[0]]->getModeSet(); - X::ModeSet ModeSet2 = X::Screen::inst()->getOutputMap()[outputs[1]]->getModeSet(); - QSet ModeNames1, ModeNames2; - for (X::ModeSet::iterator i = ModeSet1.begin(); - i != ModeSet1.end(); ++i) - ModeNames1.insert(X::Screen::inst()->getModeMap()[*i]._name); - for (X::ModeSet::iterator i = ModeSet2.begin(); - i != ModeSet2.end(); ++i) - ModeNames2.insert(X::Screen::inst()->getModeMap()[*i]._name); - ModeNames1.intersect(ModeNames2); - - // Fill widget with data - for ( QSet::iterator i = ModeNames1.begin(); i != ModeNames1.end(); ++i ) - ui->comboBox->addItem(*i); - } - /*********************************************************************/ - // If NEITHER of the outputs is a beamer (likely dualscreen setup) - else - { - // TODO(manuel): Furture feature. Setup dualscreen - qDebug() << "Dual output"; + // Get initial data (to be freed) + _display = XOpenDisplay(NULL); + _screenResources = XRRGetScreenResourcesCurrent(_display, DefaultRootWindow(_display)); + + // Get the information about the X elements + updateScreenResources(); + + switch ( _connectedOutputList.size() ){ + /*************************************************************************/ + case 1:// In case of one connected output - xrandr --auto + qDebug() << "Normal output"; exit(0); - } - break; - /*************************************************************************/ - default: - // If there are more than 3 outputs - // its up to the user. Quit. - qDebug() << ">2 outputs. Quit."; - exit(0); - break; - } - /*************************************************************************/ + break; + /*************************************************************************/ + case 2: // In case of two connected outputs + // Check if one of the connected outputs is a beamer. This program only + // adresses cases in which eiter of the outouts is a beamer. Meaning + // either output one has dimension zero or output tow has no dimension. + // The case of two beamers is not covered. + if (/*true*/((_outputMap[_connectedOutputList[0]]->mm_width == 0 + && _outputMap[_connectedOutputList[0]]->mm_height == 0 ) + && ! (_outputMap[_connectedOutputList[1]]->mm_width == 0 + && _outputMap[_connectedOutputList[1]]->mm_height == 0 )) + || ( ! (_outputMap[_connectedOutputList[0]]->mm_width == 0 + && _outputMap[_connectedOutputList[0]]->mm_height == 0 ) + && (_outputMap[_connectedOutputList[1]]->mm_width == 0 + && _outputMap[_connectedOutputList[1]]->mm_height == 0 ))) { + std::cout << "BEAMER CONNECTED!" << std::endl; + // Get a human readable reference + if (_outputMap[_connectedOutputList[0]]->mm_width == 0 + && _outputMap[_connectedOutputList[0]]->mm_height == 0 ) { + _beamer = _connectedOutputList[0]; + _monitor = _connectedOutputList[1]; + } else { + _beamer = _connectedOutputList[1]; + _monitor = _connectedOutputList[0]; + } + // Check if the beamer transmitted reliable data. + bool gotEDID = false; + int nprop; + Atom *props = XRRListOutputProperties(_display, _beamer, &nprop); + for (int i = 0; i < nprop; ++i) { + char *atom_name = XGetAtomName (_display, props[i]); + if ( strcmp (atom_name, "EDID") == 0) { + gotEDID = true; + break; + } + } + free(props); + // // TO BE DONE VIA BASH +// // Iterate over the modes in the config file +// for (QList::const_iterator it = +// Config::inst()->getModeLines().begin(); +// it != Config::inst()->getModeLines().end(); ++it) { +// // Add mode to xrandr +// QProcess p; +// QStringList arguments; +// arguments << "--current" << "--newmode" +// << it->split(" ", QString::SkipEmptyParts); +// p.start("xrandr", arguments); +// p.waitForFinished(); +// } + // Get the names of the modes and intersect + QSet beamerModes, monitorModes; + for (int i = 0; i < _outputMap[_beamer]->nmode; ++i) + beamerModes.insert(_modeMap[_outputMap[_beamer]->modes[i]]); + for (int i = 0; i < _outputMap[_beamer]->nmode; ++i) + monitorModes.insert(_modeMap[_outputMap[_monitor]->modes[i]]); - // Remove borders and stuff COMMENT FOR DEBUIGGIN - //setWindowFlags(windowFlags() | Qt::FramelessWindowHint); + // Intersect them by the resolution sorted + // dont care about O(n³) + QList commonModes; + for (QSet::iterator i = beamerModes.begin(); + i != beamerModes.end(); ++i) { + for (QSet::iterator j = monitorModes.begin(); + j != monitorModes.end(); ++j) { + QList::iterator k = commonModes.begin(); + for (;;) { + if (k == commonModes.end()){ + commonModes.insert(k, *i); + break; + } + if ( (*i)->width == (*k)->width ) { + if ( (*i)->height == (*k)->height ) + break; + if ( (*i)->height > (*k)->height ) { + commonModes.insert(k, *i); + break; + } + } + if ( (*i)->width > (*k)->width ) { + commonModes.insert(k, *i); + break; + } + ++k; + } + } + } - // Resize widget to its content - resize(sizeHint()); + // If the beamer transmits no reliable EDID data add modes + if (gotEDID) { + std::cout << "GOT EDID!" << std::endl; + // Extract the preferred mode of the beamer + RRMode preferredBeamerModeId; + for (int i = 0; i < _outputMap[_beamer]->nmode; ++i) { + if (i < _outputMap[_beamer]->npreferred) { + preferredBeamerModeId = _outputMap[_beamer]->modes[i]; + break; + } + } - // Center dialog on screenbottom - const QRect desktopRect = QApplication::desktop()->screenGeometry(); - this->move( desktopRect.width()/2-this->width()/2, - desktopRect.height()-this->height()); + // Compute the aspect ratio of the beamer + float aspectRatio = (float)_modeMap[preferredBeamerModeId]->width + / _modeMap[preferredBeamerModeId]->height; + + // Fill widget with data + for ( QList::iterator i = commonModes.begin(); + i != commonModes.end(); ++i ) { + float modeAspectRatio = ((float)(*i)->width / (*i)->height); + if ( modeAspectRatio == aspectRatio ) // TODO APPROX + _ui->comboBox->addItem((*i)->name); + } + +// // TO BE DONE VIA BASH +// // Iterate over all modes and add them to the outputs, +// // if the AR matches. +// for(ModeMap::iterator it = _modeMap.begin(); +// it != _modeMap.end(); ++it) { +// float MODEAR = ((float)(*it)->width / (*it)->height); +// if ( MODEAR == AR ) { +// XRRAddOutputMode(_display, _beamer, (*it)->id); +// XRRAddOutputMode(_display, _monitor, (*it)->id); +// } +// } + } else { + std::cout << "NO EDID!" << std::endl; + // Fill widget with data without AR match + // Fill widget with data + for ( QList::iterator i = commonModes.begin(); + i != commonModes.end(); ++i ) { + _ui->comboBox->addItem((*i)->name); + } + // TO BE DONE VIA BASH +// // Iterate over all modes and add them to the outputs +// for(ModeMap::iterator it = _modeMap.begin(); +// it != _modeMap.end(); ++it) { +// XRRAddOutputMode(_display, _beamer, (*it)->id); +// XRRAddOutputMode(_display, _monitor, (*it)->id); +// } + } + + // Remove borders and stuff COMMENT FOR DEBUIGGIN + setWindowFlags(windowFlags() | Qt::FramelessWindowHint); + + // Resize widget to its content + resize(sizeHint()); + + // Center dialog on screenbottom + const QRect desktopRect = QApplication::desktop()->screenGeometry(); + this->move( desktopRect.width()/2-this->width()/2, + desktopRect.height()-this->height()); + + + } // End of the beamer section + /*********************************************************************/ + // If NEITHER of the outputs is a beamer (likely dualscreen setup) + else { + // TODO(manuel): Furture feature. Setup dualscreen + qDebug() << "Dual output"; + exit(0); + } + break; + /*************************************************************************/ + default: + // If there are more than 3 outputs + // its up to the user. Quit. + qDebug() << ">2 outputs. Quit."; + exit(0); + break; + } + /*************************************************************************/ +} + +//___________________________________________________________________________ +void Widget::updateScreenResources() +{ + // Clear the modemap (nothing to be freed, stored in screenResources) + _modeMap.clear(); + + // Create the modemap + for (int i = 0; i < _screenResources->nmode; ++i) { + _modeMap.insert( + _screenResources->modes[i].id, + &_screenResources->modes[i]); + } + + // Clear the crtmap + for (CrtcMap::iterator it = _crtcMap.begin(); + it != _crtcMap.end();) { + XRRFreeCrtcInfo(*it); + it = _crtcMap.erase(it); + } + + // Create crtcMap + for (int i = 0; i < _screenResources->ncrtc; ++i) { + XRRCrtcInfo * info = XRRGetCrtcInfo( + _display, + _screenResources, + _screenResources->crtcs[i]); + _crtcMap.insert( + _screenResources->crtcs[i], + info); + } + + // Clear the outputmap + for (OutputMap::iterator it = _outputMap.begin(); + it != _outputMap.end();) { + XRRFreeOutputInfo(*it); + it = _outputMap.erase(it); + } + + // Create outputmap and connectedOutputMap + for (int i = 0; i < _screenResources->noutput; ++i) { + XRROutputInfo* info = XRRGetOutputInfo( + _display, + _screenResources, + _screenResources->outputs[i]); + _outputMap.insert( + _screenResources->outputs[i], + info); + + // Store the connected ones separate + if ( info->connection == RR_Connected ) + _connectedOutputList.push_back(_screenResources->outputs[i]); + } } +//___________________________________________________________________________ Widget::~Widget() { - delete ui; + delete _ui; + XCloseDisplay(_display); + XRRFreeScreenResources(_screenResources); } diff --git a/src/widget.h b/src/widget.h index fff5510..efcf9e9 100644 --- a/src/widget.h +++ b/src/widget.h @@ -15,20 +15,38 @@ class Widget : public QWidget Q_OBJECT - -public: - explicit Widget(QWidget *parent = 0); - ~Widget(); + typedef QSet ModeSet; + typedef QSet CrtcSet; + typedef QSet OutputSet; + + typedef QList ModeList; + typedef QList CrtcList; + typedef QList OutputList; + + typedef QMap ModeMap; + typedef QMap CrtcMap; + typedef QMap OutputMap; + + public: + explicit Widget(QWidget *parent = 0); + ~Widget(); private: - - Ui::Widget * ui; - + void updateScreenResources(); + + Ui::Widget * _ui; + Display* _display; + XRRScreenResources* _screenResources; + ModeMap _modeMap; + CrtcMap _crtcMap; + OutputMap _outputMap; + OutputList _connectedOutputList; + RROutput _beamer, _monitor; }; diff --git a/src/x.cpp b/src/x.cpp index 6c9e0e2..82c07fc 100644 --- a/src/x.cpp +++ b/src/x.cpp @@ -16,8 +16,15 @@ namespace X _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( @@ -27,6 +34,7 @@ namespace X } // Create crtcMap + _crtcMap.clear(); for (int i = 0; i < _screenResources->ncrtc; ++i) { _crtcMap.insert( @@ -36,6 +44,7 @@ namespace X } // Create outputMap + _outputMap.clear(); for (int i = 0; i < _screenResources->noutput; ++i) { _outputMap.insert( @@ -45,11 +54,42 @@ namespace X } // 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(); } //___________________________________________________________________________ @@ -299,7 +339,7 @@ namespace X qDebug() << "Output: " << _id << _name << _crtc - << _metricDimension << _clones << _modes; + << _metricDimension << _clones << _modes; } // //_________________________________________________________________________ diff --git a/src/x.h b/src/x.h index 4e2265e..855a05c 100644 --- a/src/x.h +++ b/src/x.h @@ -43,7 +43,19 @@ namespace X typedef QMap OutputMap; int applyChanges(); + void 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); void revertChanges(); + void updateScreenResources(); // Getters inline const Display* display() const {return _display;} @@ -90,7 +102,7 @@ namespace X struct Mode : public XElement { - Mode(XRRModeInfo* = NULL); + Mode(XRRModeInfo* = NULL); // Xlib internal stuff QSize _resolution; -- cgit v1.2.3-55-g7522