From 0cacb756cf15b7bd2f6441b57bbcd599e6391ec2 Mon Sep 17 00:00:00 2001 From: "P.L. Lucas" Date: Sat, 7 Dec 2013 15:43:24 +0100 Subject: [PATCH 1/6] Get information from Xrandr. Virtual resolutions added (sacle and panning). Brightness control added. --- randr.cpp | 347 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ randr.h | 55 +++++++++ 2 files changed, 402 insertions(+) create mode 100644 randr.cpp create mode 100644 randr.h diff --git a/randr.cpp b/randr.cpp new file mode 100644 index 0000000..969bfb6 --- /dev/null +++ b/randr.cpp @@ -0,0 +1,347 @@ +/* + + Copyright (C) 2013 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "randr.h" + +#include +#include +#include +#include +#include +#include +#include + + + +static double mode_refresh (XRRModeInfo *mode_info) +{ + double rate; + unsigned int vTotal = mode_info->vTotal; + + if (mode_info->modeFlags & RR_DoubleScan) { + /* doublescan doubles the number of lines */ + vTotal *= 2; + } + + if (mode_info->modeFlags & RR_Interlace) { + /* interlace splits the frame into two fields */ + /* the field rate is what is typically reported by monitors */ + vTotal /= 2; + } + + if (mode_info->hTotal && vTotal) + rate = ((double) mode_info->dotClock / + ((double) mode_info->hTotal * (double) vTotal)); + else + rate = 0; + return rate; +} + +/* Returns the index of the last value in an array < 0xffff */ +static int find_last_non_clamped(unsigned short array[], int size) { + int i; + for (i = size - 1; i > 0; i--) { + if (array[i] < 0xffff) + return i; + } + return 0; +} + + +static void get_gamma_info(Display *dpy, XRRScreenResources *res, RRCrtc crtc, float *brightness, float *red, float *blue, float *green) +{ + XRRCrtcGamma *crtc_gamma; + double i1, v1, i2, v2; + int size, middle, last_best, last_red, last_green, last_blue; + unsigned short *best_array; + + size = XRRGetCrtcGammaSize(dpy, crtc); + if (!size) { + printf("Failed to get size of gamma for output\n"); + return; + } + + crtc_gamma = XRRGetCrtcGamma(dpy, crtc); + if (!crtc_gamma) { + printf("Failed to get gamma for output\n"); + return; + } + + /* + * Here is a bit tricky because gamma is a whole curve for each + * color. So, typically, we need to represent 3 * 256 values as 3 + 1 + * values. Therefore, we approximate the gamma curve (v) by supposing + * it always follows the way we set it: a power function (i^g) + * multiplied by a brightness (b). + * v = i^g * b + * so g = (ln(v) - ln(b))/ln(i) + * and b can be found using two points (v1,i1) and (v2, i2): + * b = e^((ln(v2)*ln(i1) - ln(v1)*ln(i2))/ln(i1/i2)) + * For the best resolution, we select i2 at the highest place not + * clamped and i1 at i2/2. Note that if i2 = 1 (as in most normal + * cases), then b = v2. + */ + last_red = find_last_non_clamped(crtc_gamma->red, size); + last_green = find_last_non_clamped(crtc_gamma->green, size); + last_blue = find_last_non_clamped(crtc_gamma->blue, size); + best_array = crtc_gamma->red; + last_best = last_red; + if (last_green > last_best) { + last_best = last_green; + best_array = crtc_gamma->green; + } + if (last_blue > last_best) { + last_best = last_blue; + best_array = crtc_gamma->blue; + } + if (last_best == 0) + last_best = 1; + + middle = last_best / 2; + i1 = (double)(middle + 1) / size; + v1 = (double)(best_array[middle]) / 65535; + i2 = (double)(last_best + 1) / size; + v2 = (double)(best_array[last_best]) / 65535; + if (v2 < 0.0001) { /* The screen is black */ + *brightness = 0; + *red = 1; + *green = 1; + *blue = 1; + } else { + if ((last_best + 1) == size) + *brightness = v2; + else + *brightness = exp((log(v2)*log(i1) - log(v1)*log(i2))/log(i1/i2)); + *red = log((double)(crtc_gamma->red[last_red / 2]) / *brightness + / 65535) / log((double)((last_red / 2) + 1) / size); + *green = log((double)(crtc_gamma->green[last_green / 2]) / *brightness + / 65535) / log((double)((last_green / 2) + 1) / size); + *blue = log((double)(crtc_gamma->blue[last_blue / 2]) / *brightness + / 65535) / log((double)((last_blue / 2) + 1) / size); + } + + XRRFreeGamma(crtc_gamma); +} + +/** Sort modeLines using pixels size. + */ +static void sort_modes(QList &modes) +{ + int max=0; + int pixels=0; + QRegExp re("([0-9]*)x([0-9]*)"); + for(int i=0; i max) + { + modes.swap(i,j); + max = pixels; + } + } + } + } +} + +/** Add virtual mode lines. Returns number of virtual modelines added. + */ +static int add_virtual_modes(QList &modes) +{ + if(modes.size()==0) + return 0; + QRegExp re("([0-9]*)x([0-9]*)"); + if( re.indexIn(modes[0]) != -1 ) + { + int x = re.cap(1).toInt(); + int y = re.cap(2).toInt(); + for(int i=1;i<=4; i++) + { + float scale=1.0+0.25*(float)i; + QString mode = QString("%1x%2 *").arg(round(scale*(float)x)).arg(round(scale*(float)y)); + modes.prepend(mode); + } + return 4; + } + return 0; +} + +static QList get_outputs (Display *dpy, XRRScreenResources *res) +{ + QList monitors; + int o; + int jj = 0; + QString currentMode; + QString currentRate; + QString preferredMode; + QString preferredRate; + for (o = 0; o < res->noutput; o++) + { + // Get output name + XRROutputInfo *output_info = XRRGetOutputInfo (dpy, res, res->outputs[o]); + Monitor *monitor = new Monitor(); + monitor->name = output_info->name; + //printf("Nombre Output: %s\n", output_info->name); + switch (output_info->connection) { + case RR_Disconnected: + //printf(" Desconectado\n"); + continue; + break; + case RR_Connected: + //printf(" Conectado\n"); + if (!output_info->crtc) { + //output->changes |= changes_automatic; + //output->automatic = True; + } + } + { + // Get output modes + QHash > modes_hash; + for (int j = jj; j < output_info->nmode; j++) + { + // Get mode rates + XID mode_xid = output_info->modes[j]; + for(int k=0; k < res->nmode; k++) + { + XRRModeInfo *mode = &res->modes[k]; + if(mode->id==mode_xid) + { + //printf(" Modo %d: %s\n", j, mode->name); + //printf (" %s (0x%x) %6.1fMHz\n", mode->name, (int)mode->id, (double)mode->dotClock / 1000000.0); + //printf(" %6.1fMHz\n", mode_refresh (mode)); + char buffer[10]; + sprintf(buffer, "%6.1f", mode_refresh (mode)); + QString rate(buffer); + if(!modes_hash.contains(QString(mode->name))) + { + QList rates; + modes_hash[QString(mode->name)] = rates; + } + modes_hash[QString(mode->name)].append(rate); + if (j < output_info->npreferred) + { + // printf (" +preferred\n"); + preferredMode = mode->name; + preferredRate = rate; + } + // Is this mode current mode? + for (int c = 0; c < res->ncrtc; c++) + { + XRRCrtcInfo *crtc_info = XRRGetCrtcInfo (dpy, res, res->crtcs[c]); + if(crtc_info->mode==mode_xid) + { + float brightness, red, blue, green; + get_gamma_info(dpy, res, res->crtcs[c], &brightness, &red, &blue, &green); + //printf (" +current\n"); + //printf (" Brightness: %6.1f\n", brightness); + //printf (" Gamma:\n"); + //printf (" Red: %6.1f\n", red); + //printf (" Blue: %6.1f\n", blue); + //printf (" Green: %6.1f\n", green); + currentMode = mode->name; + currentRate = rate; + monitor->brightness = brightness; + monitor->red = red; + monitor->blue = blue; + monitor->green = green; + } + XRRFreeCrtcInfo (crtc_info); + } + //printf("\n"); + } + } + //jj++; + } + QList modeLines; + QList keys = modes_hash.uniqueKeys(); + sort_modes(keys); + int n_virtual_modelines = add_virtual_modes(keys); + for(int i=0; icurrentMode = modeLines.size(); + if(modeline.modeline==preferredMode) + monitor->preferredMode = modeLines.size(); + for(int rates_index=0; rates_indexcurrentRate=rates_index; + if(modeline.rates[rates_index]==preferredRate) + monitor->preferredRate=rates_index; + } + if(imodeLines = modeLines; + monitor->modes_hash = modes_hash; + } + monitors.append(monitor); + } + printf("[get_outputs]: Finalizado\n"); + return monitors; +} + + +QList get_monitors_info(){ + int event_base, error_base; + int major, minor; + Display *dpy; + Window root; + + QList monitors; + + // CONNECT TO X-SERVER, GET ROOT WINDOW ID + dpy = XOpenDisplay(NULL); + root = RootWindow(dpy, 0); + XRRScreenResources *res; + int screenNo = ScreenCount(dpy); + + if (!XRRQueryExtension (dpy, &event_base, &error_base) || + !XRRQueryVersion (dpy, &major, &minor)) + { + fprintf (stderr, "RandR extension missing\n"); + return monitors; + } + + res = XRRGetScreenResources (dpy, root); + if (!res) + { + fprintf (stderr, "Could not get screen resources\n"); + return monitors; + } + + monitors = get_outputs(dpy, res); + XCloseDisplay(dpy); + return monitors; +} +// +// gcc -o Xrandr Xrandr.cc -lX11 -lXrandr -lstdc++ +// diff --git a/randr.h b/randr.h new file mode 100644 index 0000000..c22e593 --- /dev/null +++ b/randr.h @@ -0,0 +1,55 @@ +/* + + Copyright (C) 2013 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + + +#ifndef randr_H +#define randr_H + +#include +#include +#include +#include +#include + +struct ModeLine { + QString modeline; + QString scale; + QList rates; +}; + +struct Monitor { + QString name; + QList modeLines; + QHash > modes_hash; + short currentMode; + short currentRate; + short preferredMode; + short preferredRate; + float brightness, red, blue, green; + + QCheckBox* enable; + QComboBox* resolutionCombo; + QComboBox* rateCombo; + QCheckBox* panning; + QSlider* brightness_slider; +}; + +QList get_monitors_info(); + +#endif // randr_H \ No newline at end of file From ee120cb16e78d41743f82c76f3eb4f6bc2aab63a Mon Sep 17 00:00:00 2001 From: "P.L. Lucas" Date: Sat, 7 Dec 2013 15:47:59 +0100 Subject: [PATCH 2/6] Get information from Xrandr. Virtual resolutions added (scale and panning). Brightness control added. --- CMakeLists.txt | 14 ++++ monitor.ui | 30 ++++++- monitorsettingsdialog.cpp | 167 +++++++++++++++++++++++--------------- monitorsettingsdialog.h | 2 +- 4 files changed, 144 insertions(+), 69 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index acc03ac..1603747 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,12 +5,21 @@ cmake_minimum_required(VERSION 2.8.6) # Qt find_package(Qt4 REQUIRED QtCore QtGui) + # glib using pkg-config find_package(PkgConfig) pkg_check_modules(GLIB REQUIRED glib-2.0 ) +pkg_check_modules(X11 REQUIRED + x11 +) + +pkg_check_modules(XRANDR REQUIRED + xrandr +) + # set visibility to hidden to hide symbols, unlesss they're exporeted manually in the code set(CMAKE_CXX_FLAGS "-DQT_NO_KEYWORDS -fno-exceptions") @@ -18,6 +27,8 @@ include_directories( ${QT_INCLUDES} ${GLIB_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} + ${XRANDR_INCLUDE_DIRS} + ${X11_INCLUDE_DIRS} ) set(CMAKE_AUTOMOC TRUE) @@ -25,6 +36,7 @@ set(CMAKE_AUTOMOC TRUE) set(lxrandr-qt_SRCS lxrandr-qt.cpp monitorsettingsdialog.cpp + randr.cpp ) set(lxrandr-qt_UIS @@ -45,6 +57,8 @@ target_link_libraries(lxrandr-qt ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${GLIB_LIBRARIES} + ${XRANDR_LIBRARIES} + ${X11_LIBRARIES} ) install(TARGETS lxrandr-qt RUNTIME DESTINATION bin) diff --git a/monitor.ui b/monitor.ui index 4bb18d0..9569209 100644 --- a/monitor.ui +++ b/monitor.ui @@ -6,8 +6,8 @@ 0 0 - 197 - 92 + 312 + 175 @@ -34,7 +34,7 @@ - + Qt::Horizontal @@ -48,6 +48,30 @@ + + + + Panning + + + + + + + 100 + + + Qt::Horizontal + + + + + + + Brightness: + + + diff --git a/monitorsettingsdialog.cpp b/monitorsettingsdialog.cpp index 3ee03a6..323701b 100644 --- a/monitorsettingsdialog.cpp +++ b/monitorsettingsdialog.cpp @@ -27,68 +27,51 @@ #include #include + +#include +#include + #include "ui_monitor.h" #include #include +#include -struct Monitor { - char* name; - GSList* modeLines; - short currentMode; - short currentRate; - short preferredMode; - short preferredRate; - - QCheckBox* enable; - QComboBox* resolutionCombo; - QComboBox* rateCombo; -}; +#include "randr.h" MonitorSettingsDialog::MonitorSettingsDialog(): QDialog(NULL, 0), - monitors(NULL), + monitors(), LVDS(NULL) { setupUi(); } -void monitor_free(Monitor* monitor) { - g_free(monitor->name); - g_slist_free(monitor->modeLines); - g_free(monitor); -} MonitorSettingsDialog::~MonitorSettingsDialog() { - g_slist_foreach(monitors, (GFunc)monitor_free, NULL); - g_slist_free(monitors); + while (!monitors.isEmpty()) + delete monitors.takeFirst(); } QString MonitorSettingsDialog::humanReadableName(Monitor* monitor) { if(monitor == LVDS) return tr("Laptop LCD Monitor"); - else if(g_str_has_prefix(monitor->name, "VGA") || g_str_has_prefix(monitor->name, "Analog")) + else if( monitor->name.startsWith("VGA") || monitor->name.startsWith("Analog") ) return tr(LVDS ? "External VGA Monitor" : "VGA Monitor"); - else if(g_str_has_prefix(monitor->name, "DVI") || g_str_has_prefix(monitor->name, "TMDS") || g_str_has_prefix(monitor->name, "Digital") || g_str_has_prefix(monitor->name, "LVDS")) + else if( monitor->name.startsWith("DVI") || monitor->name.startsWith("TMDS") || monitor->name.startsWith("Digital") || monitor->name.startsWith("LVDS") ) return tr(LVDS ? "External DVI Monitor" : "DVI Monitor"); - else if(g_str_has_prefix(monitor->name, "TV") || g_str_has_prefix(monitor->name, "S-Video")) + else if( monitor->name.startsWith("TV") || monitor->name.startsWith("S-Video") ) return tr("TV"); - else if(strcmp(monitor->name, "default") == 0) + else if( monitor->name=="default" ) return tr("Default Monitor"); - return QString(monitor->name); + return monitor->name; } bool MonitorSettingsDialog::getXRandRInfo() { - // execute xrandr command and read its output - QProcess process; - // set locale to "C" guarantee English output of xrandr - process.processEnvironment().insert("LC_ALL", "c"); - process.start("xrandr"); - process.waitForFinished(-1); - if(process.exitCode() != 0) - return false; - - QByteArray output = process.readAllStandardOutput(); + monitors = get_monitors_info(); + + + /* GRegex* regex = g_regex_new("([a-zA-Z]+[-0-9]*) +connected .*((\n +[0-9]+x[0-9]+[^\n]+)+)", GRegexCompileFlags(0), GRegexMatchFlags(0), NULL); @@ -166,6 +149,7 @@ bool MonitorSettingsDialog::getXRandRInfo() { g_match_info_free(match); } g_regex_unref(regex); + */ return true; } @@ -173,44 +157,79 @@ void MonitorSettingsDialog::onResolutionChanged(int index) { QComboBox* combo = static_cast(sender()); Monitor* monitor = reinterpret_cast(qVariantValue(combo->property("monitor"))); char** rate; - int sel = combo->currentIndex(); - char** mode_line = reinterpret_cast(g_slist_nth_data(monitor->modeLines, sel - 1)); + QStandardItemModel *model = (QStandardItemModel *) combo->model(); + int sel = model->item(combo->currentIndex())->data().toInt(); + //int sel = combo->currentIndex() - 1; + printf("MonitorSettingsDialog::onResolutionChanged sel = %d\n", sel); monitor->rateCombo->clear(); monitor->rateCombo->addItem(tr("Auto")); - if(sel >= 0 && mode_line && *mode_line) { - for(rate = mode_line + 1; *rate; ++rate) - monitor->rateCombo->addItem(*rate); + if( sel >= 0 ) { + ModeLine mode_line = monitor->modeLines[sel]; + printf("scale = %s\n", mode_line.scale.toAscii().data()); + for (int i = 0; i < mode_line.rates.size(); ++i) + monitor->rateCombo->addItem(mode_line.rates[i]); } monitor->rateCombo->setCurrentIndex(0); + QString mode = combo->currentText(); + if(mode.endsWith("*")) + monitor->panning->setEnabled(true); + else + monitor->panning->setEnabled(false); } void MonitorSettingsDialog::setXRandRInfo() { - GSList* l; + Monitor* l; QByteArray cmd = "xrandr"; - for(l = monitors; l; l = l->next) { - Monitor* monitor = (Monitor*)l->data; + for(int i=0; iname); cmd.append(' '); // if the monitor is turned on if(monitor->enable->isChecked()) { - int sel_res = monitor->resolutionCombo->currentIndex(); + int sel_res = monitor->resolutionCombo->currentIndex(); // the fist item in the combo box is "Auto", indecis of resolutions are 1, 2, 3... int sel_rate = monitor->rateCombo->currentIndex(); if(sel_res < 1) // auto resolution cmd.append("--auto"); else { - cmd.append("--mode "); - ++sel_res; // the fist item in the combo box is "Auto", indecis of resolutions are 1, 2, 3... - cmd.append(monitor->resolutionCombo->currentText()); + QStandardItemModel *model = (QStandardItemModel *) monitor->resolutionCombo->model(); + ModeLine modeLine = monitor->modeLines[ model->item(sel_res)->data().toInt() ]; + QString mode = monitor->resolutionCombo->currentText(); + bool mode_virtual_ok = mode.endsWith("*"); + if(mode_virtual_ok) + mode = mode.replace(QString("*"), QString()); + else + { + cmd.append("--mode "); + cmd.append(mode); + } + + cmd.append(" --panning "); + cmd.append(mode); + + if(mode_virtual_ok) + { + cmd.append(" --fb "); + cmd.append(mode); + } + + cmd.append(" --scale "); + if( mode_virtual_ok && monitor->panning->checkState()==Qt::Checked ) + cmd.append("1.0x1.0"); + else + cmd.append(modeLine.scale); if(sel_rate >= 1) { // not auto refresh rate cmd.append(" --rate "); cmd.append(monitor->resolutionCombo->currentText()); } } + + cmd.append(" --brightness "); + cmd.append(QString().setNum((float)monitor->brightness_slider->value()/100.0)); } else // turn off cmd.append("--off"); @@ -219,6 +238,7 @@ void MonitorSettingsDialog::setXRandRInfo() { QProcess process; process.start(cmd); process.waitForFinished(); + printf("%s\n", cmd.constData() ); } void MonitorSettingsDialog::chooseMaxResolution(Monitor* monitor) { @@ -228,8 +248,8 @@ void MonitorSettingsDialog::chooseMaxResolution(Monitor* monitor) { // turn on both laptop LCD and the external monitor void MonitorSettingsDialog::onUseBoth() { - for(GSList* l = monitors; l; l = l->next) { - Monitor* monitor = (Monitor*)l->data; + for(int i=0; ienable->setChecked(true); } @@ -238,8 +258,8 @@ void MonitorSettingsDialog::onUseBoth() { // external monitor only void MonitorSettingsDialog::onExternalOnly() { - for(GSList* l = monitors; l; l = l->next) { - Monitor* monitor = (Monitor*)l->data; + for(int i=0; ienable->setChecked(monitor != LVDS); } @@ -248,8 +268,8 @@ void MonitorSettingsDialog::onExternalOnly() { // laptop panel - LVDS only void MonitorSettingsDialog::onLaptopOnly() { - for(GSList* l = monitors; l; l = l->next) { - Monitor* monitor = (Monitor*)l->data; + for(int i=0; ienable->setChecked(monitor == LVDS); } @@ -270,24 +290,21 @@ void MonitorSettingsDialog::setupUi() { getXRandRInfo(); // If this is a laptop and there is an external monitor, offer quick options - if(LVDS && g_slist_length(monitors) == 2) + if(LVDS && monitors.size() == 2) ui.tabWidget->setCurrentIndex(0); else { ui.tabWidget->removeTab(0); } - int i = 0; - GSList* l; - for(l = monitors; l; l = l->next) { - Monitor* monitor = (Monitor*)l->data; - GSList* mode_line; + for(int i=0; iname)) + .arg(monitor->name) .arg(humanReadableName(monitor)); - + printf("%s\n", title.toAscii().data()); box->setTitle(title); Ui::MonitorWidget mui = Ui::MonitorWidget(); mui.setupUi(box); @@ -298,21 +315,41 @@ void MonitorSettingsDialog::setupUi() { monitor->resolutionCombo = mui.resolution; monitor->resolutionCombo->setProperty("monitor", qVariantFromValue(monitor)); monitor->rateCombo = mui.rate; + monitor->panning = mui.panning; + monitor->brightness_slider = mui.brightness; // turn off screen is not allowed since there should be at least one monitor available. - if(g_slist_length(monitors) == 1) + if(monitors.size() == 1) monitor->enable->setEnabled(false); if(monitor->currentMode >= 0) monitor->enable->setChecked(true); connect(monitor->resolutionCombo, SIGNAL(currentIndexChanged(int)), SLOT(onResolutionChanged(int))); + + QStandardItemModel *model=new QStandardItemModel(monitor->modeLines.size()+1,1); + QStandardItem *item = new QStandardItem(QString(tr("Auto"))); + item->setData(QVariant(-1)); + model->setItem(0, 0, item); + for(int j=0; jmodeLines.size(); j++) + { + item = new QStandardItem(monitor->modeLines[j].modeline); + item->setData(QVariant(j)); //Stores index of modeLine + model->setItem(j+1, 0, item); + } + monitor->resolutionCombo->setModel(model); + + monitor->brightness_slider->setValue((int)(monitor->brightness*100.0)); + + /* monitor->resolutionCombo->addItem(tr("Auto")); - for(mode_line = monitor->modeLines; mode_line; mode_line = mode_line->next) { - char** strv = (char**)mode_line->data; - monitor->resolutionCombo->addItem(strv[0]); + for(int j=0; jmodeLines.size(); j++) { + QString strv = monitor->modeLines[j].modeline; + monitor->resolutionCombo->addItem(strv); } + */ + monitor->resolutionCombo->setCurrentIndex(monitor->currentMode + 1); monitor->rateCombo->setCurrentIndex(monitor->currentRate + 1); ++i; diff --git a/monitorsettingsdialog.h b/monitorsettingsdialog.h index b203fdf..71b3fa1 100644 --- a/monitorsettingsdialog.h +++ b/monitorsettingsdialog.h @@ -56,7 +56,7 @@ private Q_SLOTS: private: Ui::MonitorSettingsDialog ui; QPushButton* aboutButton; - GSList* monitors; + QList monitors; Monitor* LVDS; }; From fe1adb58b33dd6496b5d2eedca85638647664d80 Mon Sep 17 00:00:00 2001 From: "P.L. Lucas" Date: Sun, 8 Dec 2013 15:51:35 +0100 Subject: [PATCH 3/6] Added LVDS output settings --- monitorsettingsdialog.cpp | 92 ++-------- monitorsettingsdialog.cpp~ | 303 ++++++++++++++++++++++++++++++++ randr.cpp | 8 +- randr.cpp~ | 347 +++++++++++++++++++++++++++++++++++++ 4 files changed, 665 insertions(+), 85 deletions(-) create mode 100644 monitorsettingsdialog.cpp~ create mode 100644 randr.cpp~ diff --git a/monitorsettingsdialog.cpp b/monitorsettingsdialog.cpp index 323701b..c1380b4 100644 --- a/monitorsettingsdialog.cpp +++ b/monitorsettingsdialog.cpp @@ -70,86 +70,17 @@ QString MonitorSettingsDialog::humanReadableName(Monitor* monitor) { bool MonitorSettingsDialog::getXRandRInfo() { monitors = get_monitors_info(); - - /* - - GRegex* regex = g_regex_new("([a-zA-Z]+[-0-9]*) +connected .*((\n +[0-9]+x[0-9]+[^\n]+)+)", - GRegexCompileFlags(0), GRegexMatchFlags(0), NULL); - GMatchInfo* match; - if(g_regex_match(regex, output.constData(), GRegexMatchFlags(0), &match)) { - do { - Monitor* monitor = g_new0(Monitor, 1); - char* modes = g_match_info_fetch(match, 2); - char** lines, **line; - int imode = 0; - - monitor->currentMode = monitor->currentRate = -1; - monitor->preferredMode = monitor->preferredRate = -1; - monitor->name = g_match_info_fetch(match, 1); - - // check if this is the built-in LCD of laptop - if(! LVDS && (strcmp(monitor->name, "LVDS") == 0 || strcmp(monitor->name, "PANEL") == 0)) - LVDS = monitor; - - lines = g_strsplit(modes, "\n", -1); - - for(line = lines; *line; ++line) { - char* str = strtok(*line, " "); - int irate = 0; - GPtrArray* strv; - - if(! str) - continue; - - strv = g_ptr_array_sized_new(8); - g_ptr_array_add(strv, g_strdup(str)); - - while(str = strtok(NULL, " ")) { - if(*str) { - char* star, *plus; - str = g_strdup(str); - - // sometimes, + goes after a space - if(0 == strcmp(str, "+")) - --irate; - else - g_ptr_array_add(strv, str); - - if(star = strchr(str, '*')) { - monitor->currentMode = imode; - monitor->currentRate = irate; - } - - if(plus = strchr(str, '+')) { - monitor->preferredMode = imode; - monitor->preferredRate = irate; - } - - if(star) - *star = '\0'; - - if(plus) - *plus = '\0'; - - ++irate; - } - } - - g_ptr_array_add(strv, NULL); - monitor->modeLines = g_slist_append(monitor->modeLines, g_ptr_array_free(strv, FALSE)); - ++imode; - } - - g_strfreev(lines); - g_free(modes); - monitors = g_slist_prepend(monitors, monitor); + // check if this is the built-in LCD of laptop + for(int i=0; iname.startsWith("LVSD") || monitor->name.startsWith("PANEL") ) ) + { + LVDS = monitor; + break; } - while(g_match_info_next(match, NULL)); - - g_match_info_free(match); } - g_regex_unref(regex); - */ + return true; } @@ -159,13 +90,12 @@ void MonitorSettingsDialog::onResolutionChanged(int index) { char** rate; QStandardItemModel *model = (QStandardItemModel *) combo->model(); int sel = model->item(combo->currentIndex())->data().toInt(); - //int sel = combo->currentIndex() - 1; - printf("MonitorSettingsDialog::onResolutionChanged sel = %d\n", sel); + //printf("MonitorSettingsDialog::onResolutionChanged sel = %d\n", sel); monitor->rateCombo->clear(); monitor->rateCombo->addItem(tr("Auto")); if( sel >= 0 ) { ModeLine mode_line = monitor->modeLines[sel]; - printf("scale = %s\n", mode_line.scale.toAscii().data()); + //printf("scale = %s\n", mode_line.scale.toAscii().data()); for (int i = 0; i < mode_line.rates.size(); ++i) monitor->rateCombo->addItem(mode_line.rates[i]); } diff --git a/monitorsettingsdialog.cpp~ b/monitorsettingsdialog.cpp~ new file mode 100644 index 0000000..20434cd --- /dev/null +++ b/monitorsettingsdialog.cpp~ @@ -0,0 +1,303 @@ +/* + + Copyright (C) 2013 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + + +#include "monitorsettingsdialog.h" +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "ui_monitor.h" + +#include +#include +#include + +#include "randr.h" + +MonitorSettingsDialog::MonitorSettingsDialog(): + QDialog(NULL, 0), + monitors(), + LVDS(NULL) { + setupUi(); +} + + +MonitorSettingsDialog::~MonitorSettingsDialog() { + while (!monitors.isEmpty()) + delete monitors.takeFirst(); +} + +QString MonitorSettingsDialog::humanReadableName(Monitor* monitor) { + if(monitor == LVDS) + return tr("Laptop LCD Monitor"); + else if( monitor->name.startsWith("VGA") || monitor->name.startsWith("Analog") ) + return tr(LVDS ? "External VGA Monitor" : "VGA Monitor"); + else if( monitor->name.startsWith("DVI") || monitor->name.startsWith("TMDS") || monitor->name.startsWith("Digital") || monitor->name.startsWith("LVDS") ) + return tr(LVDS ? "External DVI Monitor" : "DVI Monitor"); + else if( monitor->name.startsWith("TV") || monitor->name.startsWith("S-Video") ) + return tr("TV"); + else if( monitor->name=="default" ) + return tr("Default Monitor"); + + return monitor->name; +} + +bool MonitorSettingsDialog::getXRandRInfo() { + monitors = get_monitors_info(); + + // check if this is the built-in LCD of laptop + for(int i=0; iname.startsWith("LVSD") || monitor->name.startsWith("PANEL") ) ) + { + LVDS = monitor; + break; + } + } + + return true; +} + +void MonitorSettingsDialog::onResolutionChanged(int index) { + QComboBox* combo = static_cast(sender()); + Monitor* monitor = reinterpret_cast(qVariantValue(combo->property("monitor"))); + char** rate; + QStandardItemModel *model = (QStandardItemModel *) combo->model(); + int sel = model->item(combo->currentIndex())->data().toInt(); + //int sel = combo->currentIndex() - 1; + printf("MonitorSettingsDialog::onResolutionChanged sel = %d\n", sel); + monitor->rateCombo->clear(); + monitor->rateCombo->addItem(tr("Auto")); + if( sel >= 0 ) { + ModeLine mode_line = monitor->modeLines[sel]; + printf("scale = %s\n", mode_line.scale.toAscii().data()); + for (int i = 0; i < mode_line.rates.size(); ++i) + monitor->rateCombo->addItem(mode_line.rates[i]); + } + monitor->rateCombo->setCurrentIndex(0); + QString mode = combo->currentText(); + if(mode.endsWith("*")) + monitor->panning->setEnabled(true); + else + monitor->panning->setEnabled(false); +} + +void MonitorSettingsDialog::setXRandRInfo() { + Monitor* l; + QByteArray cmd = "xrandr"; + + for(int i=0; iname); + cmd.append(' '); + + // if the monitor is turned on + if(monitor->enable->isChecked()) { + int sel_res = monitor->resolutionCombo->currentIndex(); // the fist item in the combo box is "Auto", indecis of resolutions are 1, 2, 3... + int sel_rate = monitor->rateCombo->currentIndex(); + + if(sel_res < 1) // auto resolution + cmd.append("--auto"); + else { + QStandardItemModel *model = (QStandardItemModel *) monitor->resolutionCombo->model(); + ModeLine modeLine = monitor->modeLines[ model->item(sel_res)->data().toInt() ]; + QString mode = monitor->resolutionCombo->currentText(); + bool mode_virtual_ok = mode.endsWith("*"); + if(mode_virtual_ok) + mode = mode.replace(QString("*"), QString()); + else + { + cmd.append("--mode "); + cmd.append(mode); + } + + cmd.append(" --panning "); + cmd.append(mode); + + if(mode_virtual_ok) + { + cmd.append(" --fb "); + cmd.append(mode); + } + + cmd.append(" --scale "); + if( mode_virtual_ok && monitor->panning->checkState()==Qt::Checked ) + cmd.append("1.0x1.0"); + else + cmd.append(modeLine.scale); + + if(sel_rate >= 1) { // not auto refresh rate + cmd.append(" --rate "); + cmd.append(monitor->resolutionCombo->currentText()); + } + } + + cmd.append(" --brightness "); + cmd.append(QString().setNum((float)monitor->brightness_slider->value()/100.0)); + } + else // turn off + cmd.append("--off"); + } + + QProcess process; + process.start(cmd); + process.waitForFinished(); + printf("%s\n", cmd.constData() ); +} + +void MonitorSettingsDialog::chooseMaxResolution(Monitor* monitor) { + if(monitor->resolutionCombo->count() > 1) + monitor->resolutionCombo->setCurrentIndex(1); +} + +// turn on both laptop LCD and the external monitor +void MonitorSettingsDialog::onUseBoth() { + for(int i=0; ienable->setChecked(true); + } + accept(); +} + +// external monitor only +void MonitorSettingsDialog::onExternalOnly() { + for(int i=0; ienable->setChecked(monitor != LVDS); + } + accept(); +} + +// laptop panel - LVDS only +void MonitorSettingsDialog::onLaptopOnly() { + for(int i=0; ienable->setChecked(monitor == LVDS); + } + accept(); +} + +void MonitorSettingsDialog::setupUi() { + ui.setupUi(this); + connect(ui.useBoth, SIGNAL(clicked(bool)), SLOT(onUseBoth())); + connect(ui.externalOnly, SIGNAL(clicked(bool)), SLOT(onExternalOnly())); + connect(ui.laptopOnly, SIGNAL(clicked(bool)), SLOT(onLaptopOnly())); + + connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton*)), SLOT(onDialogButtonClicked(QAbstractButton*))); + aboutButton = new QPushButton(ui.buttonBox); + aboutButton->setText(tr("About")); + ui.buttonBox->addButton(aboutButton, QDialogButtonBox::HelpRole); + + getXRandRInfo(); + + // If this is a laptop and there is an external monitor, offer quick options + if(LVDS && monitors.size() == 2) + ui.tabWidget->setCurrentIndex(0); + else { + ui.tabWidget->removeTab(0); + } + + for(int i=0; iname) + .arg(humanReadableName(monitor)); + printf("%s\n", title.toAscii().data()); + box->setTitle(title); + Ui::MonitorWidget mui = Ui::MonitorWidget(); + mui.setupUi(box); + ui.monitorLayout->insertWidget(ui.monitorLayout->count() - 1, box); + ui.monitorLayout->setStretchFactor(box, 0); + + monitor->enable = mui.enabled; + monitor->resolutionCombo = mui.resolution; + monitor->resolutionCombo->setProperty("monitor", qVariantFromValue(monitor)); + monitor->rateCombo = mui.rate; + monitor->panning = mui.panning; + monitor->brightness_slider = mui.brightness; + + // turn off screen is not allowed since there should be at least one monitor available. + if(monitors.size() == 1) + monitor->enable->setEnabled(false); + + if(monitor->currentMode >= 0) + monitor->enable->setChecked(true); + + connect(monitor->resolutionCombo, SIGNAL(currentIndexChanged(int)), SLOT(onResolutionChanged(int))); + + QStandardItemModel *model=new QStandardItemModel(monitor->modeLines.size()+1,1); + QStandardItem *item = new QStandardItem(QString(tr("Auto"))); + item->setData(QVariant(-1)); + model->setItem(0, 0, item); + for(int j=0; jmodeLines.size(); j++) + { + item = new QStandardItem(monitor->modeLines[j].modeline); + item->setData(QVariant(j)); //Stores index of modeLine + model->setItem(j+1, 0, item); + } + monitor->resolutionCombo->setModel(model); + + monitor->brightness_slider->setValue((int)(monitor->brightness*100.0)); + + /* + monitor->resolutionCombo->addItem(tr("Auto")); + + for(int j=0; jmodeLines.size(); j++) { + QString strv = monitor->modeLines[j].modeline; + monitor->resolutionCombo->addItem(strv); + } + */ + + monitor->resolutionCombo->setCurrentIndex(monitor->currentMode + 1); + monitor->rateCombo->setCurrentIndex(monitor->currentRate + 1); + ++i; + } +} + +void MonitorSettingsDialog::accept() { + setXRandRInfo(); + QDialog::accept(); +} + +void MonitorSettingsDialog::onDialogButtonClicked(QAbstractButton* button) { + if(ui.buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole) + setXRandRInfo(); + else if(button == aboutButton) { + // about dialog + QMessageBox::about(this, tr("About"), tr("LXRandR-Qt\n\nMonitor configuration tool for LXDE.")); + } +} + diff --git a/randr.cpp b/randr.cpp index 969bfb6..ba8014f 100644 --- a/randr.cpp +++ b/randr.cpp @@ -202,14 +202,14 @@ static QList get_outputs (Display *dpy, XRRScreenResources *res) XRROutputInfo *output_info = XRRGetOutputInfo (dpy, res, res->outputs[o]); Monitor *monitor = new Monitor(); monitor->name = output_info->name; - //printf("Nombre Output: %s\n", output_info->name); + //printf("Output: %s\n", output_info->name); switch (output_info->connection) { case RR_Disconnected: - //printf(" Desconectado\n"); + //printf(" Disconnected\n"); continue; break; case RR_Connected: - //printf(" Conectado\n"); + //printf(" Connected\n"); if (!output_info->crtc) { //output->changes |= changes_automatic; //output->automatic = True; @@ -305,7 +305,7 @@ static QList get_outputs (Display *dpy, XRRScreenResources *res) } monitors.append(monitor); } - printf("[get_outputs]: Finalizado\n"); + //printf("[get_outputs]: End\n"); return monitors; } diff --git a/randr.cpp~ b/randr.cpp~ new file mode 100644 index 0000000..66ff738 --- /dev/null +++ b/randr.cpp~ @@ -0,0 +1,347 @@ +/* + + Copyright (C) 2013 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "randr.h" + +#include +#include +#include +#include +#include +#include +#include + + + +static double mode_refresh (XRRModeInfo *mode_info) +{ + double rate; + unsigned int vTotal = mode_info->vTotal; + + if (mode_info->modeFlags & RR_DoubleScan) { + /* doublescan doubles the number of lines */ + vTotal *= 2; + } + + if (mode_info->modeFlags & RR_Interlace) { + /* interlace splits the frame into two fields */ + /* the field rate is what is typically reported by monitors */ + vTotal /= 2; + } + + if (mode_info->hTotal && vTotal) + rate = ((double) mode_info->dotClock / + ((double) mode_info->hTotal * (double) vTotal)); + else + rate = 0; + return rate; +} + +/* Returns the index of the last value in an array < 0xffff */ +static int find_last_non_clamped(unsigned short array[], int size) { + int i; + for (i = size - 1; i > 0; i--) { + if (array[i] < 0xffff) + return i; + } + return 0; +} + + +static void get_gamma_info(Display *dpy, XRRScreenResources *res, RRCrtc crtc, float *brightness, float *red, float *blue, float *green) +{ + XRRCrtcGamma *crtc_gamma; + double i1, v1, i2, v2; + int size, middle, last_best, last_red, last_green, last_blue; + unsigned short *best_array; + + size = XRRGetCrtcGammaSize(dpy, crtc); + if (!size) { + printf("Failed to get size of gamma for output\n"); + return; + } + + crtc_gamma = XRRGetCrtcGamma(dpy, crtc); + if (!crtc_gamma) { + printf("Failed to get gamma for output\n"); + return; + } + + /* + * Here is a bit tricky because gamma is a whole curve for each + * color. So, typically, we need to represent 3 * 256 values as 3 + 1 + * values. Therefore, we approximate the gamma curve (v) by supposing + * it always follows the way we set it: a power function (i^g) + * multiplied by a brightness (b). + * v = i^g * b + * so g = (ln(v) - ln(b))/ln(i) + * and b can be found using two points (v1,i1) and (v2, i2): + * b = e^((ln(v2)*ln(i1) - ln(v1)*ln(i2))/ln(i1/i2)) + * For the best resolution, we select i2 at the highest place not + * clamped and i1 at i2/2. Note that if i2 = 1 (as in most normal + * cases), then b = v2. + */ + last_red = find_last_non_clamped(crtc_gamma->red, size); + last_green = find_last_non_clamped(crtc_gamma->green, size); + last_blue = find_last_non_clamped(crtc_gamma->blue, size); + best_array = crtc_gamma->red; + last_best = last_red; + if (last_green > last_best) { + last_best = last_green; + best_array = crtc_gamma->green; + } + if (last_blue > last_best) { + last_best = last_blue; + best_array = crtc_gamma->blue; + } + if (last_best == 0) + last_best = 1; + + middle = last_best / 2; + i1 = (double)(middle + 1) / size; + v1 = (double)(best_array[middle]) / 65535; + i2 = (double)(last_best + 1) / size; + v2 = (double)(best_array[last_best]) / 65535; + if (v2 < 0.0001) { /* The screen is black */ + *brightness = 0; + *red = 1; + *green = 1; + *blue = 1; + } else { + if ((last_best + 1) == size) + *brightness = v2; + else + *brightness = exp((log(v2)*log(i1) - log(v1)*log(i2))/log(i1/i2)); + *red = log((double)(crtc_gamma->red[last_red / 2]) / *brightness + / 65535) / log((double)((last_red / 2) + 1) / size); + *green = log((double)(crtc_gamma->green[last_green / 2]) / *brightness + / 65535) / log((double)((last_green / 2) + 1) / size); + *blue = log((double)(crtc_gamma->blue[last_blue / 2]) / *brightness + / 65535) / log((double)((last_blue / 2) + 1) / size); + } + + XRRFreeGamma(crtc_gamma); +} + +/** Sort modeLines using pixels size. + */ +static void sort_modes(QList &modes) +{ + int max=0; + int pixels=0; + QRegExp re("([0-9]*)x([0-9]*)"); + for(int i=0; i max) + { + modes.swap(i,j); + max = pixels; + } + } + } + } +} + +/** Add virtual mode lines. Returns number of virtual modelines added. + */ +static int add_virtual_modes(QList &modes) +{ + if(modes.size()==0) + return 0; + QRegExp re("([0-9]*)x([0-9]*)"); + if( re.indexIn(modes[0]) != -1 ) + { + int x = re.cap(1).toInt(); + int y = re.cap(2).toInt(); + for(int i=1;i<=4; i++) + { + float scale=1.0+0.25*(float)i; + QString mode = QString("%1x%2 *").arg(round(scale*(float)x)).arg(round(scale*(float)y)); + modes.prepend(mode); + } + return 4; + } + return 0; +} + +static QList get_outputs (Display *dpy, XRRScreenResources *res) +{ + QList monitors; + int o; + int jj = 0; + QString currentMode; + QString currentRate; + QString preferredMode; + QString preferredRate; + for (o = 0; o < res->noutput; o++) + { + // Get output name + XRROutputInfo *output_info = XRRGetOutputInfo (dpy, res, res->outputs[o]); + Monitor *monitor = new Monitor(); + monitor->name = output_info->name; + //printf("Output: %s\n", output_info->name); + switch (output_info->connection) { + case RR_Disconnected: + //printf(" Disconnected\n"); + continue; + break; + case RR_Connected: + //printf(" Connected\n"); + if (!output_info->crtc) { + //output->changes |= changes_automatic; + //output->automatic = True; + } + } + { + // Get output modes + QHash > modes_hash; + for (int j = jj; j < output_info->nmode; j++) + { + // Get mode rates + XID mode_xid = output_info->modes[j]; + for(int k=0; k < res->nmode; k++) + { + XRRModeInfo *mode = &res->modes[k]; + if(mode->id==mode_xid) + { + //printf(" Modo %d: %s\n", j, mode->name); + //printf (" %s (0x%x) %6.1fMHz\n", mode->name, (int)mode->id, (double)mode->dotClock / 1000000.0); + //printf(" %6.1fMHz\n", mode_refresh (mode)); + char buffer[10]; + sprintf(buffer, "%6.1f", mode_refresh (mode)); + QString rate(buffer); + if(!modes_hash.contains(QString(mode->name))) + { + QList rates; + modes_hash[QString(mode->name)] = rates; + } + modes_hash[QString(mode->name)].append(rate); + if (j < output_info->npreferred) + { + // printf (" +preferred\n"); + preferredMode = mode->name; + preferredRate = rate; + } + // Is this mode current mode? + for (int c = 0; c < res->ncrtc; c++) + { + XRRCrtcInfo *crtc_info = XRRGetCrtcInfo (dpy, res, res->crtcs[c]); + if(crtc_info->mode==mode_xid) + { + float brightness, red, blue, green; + get_gamma_info(dpy, res, res->crtcs[c], &brightness, &red, &blue, &green); + //printf (" +current\n"); + //printf (" Brightness: %6.1f\n", brightness); + //printf (" Gamma:\n"); + //printf (" Red: %6.1f\n", red); + //printf (" Blue: %6.1f\n", blue); + //printf (" Green: %6.1f\n", green); + currentMode = mode->name; + currentRate = rate; + monitor->brightness = brightness; + monitor->red = red; + monitor->blue = blue; + monitor->green = green; + } + XRRFreeCrtcInfo (crtc_info); + } + //printf("\n"); + } + } + //jj++; + } + QList modeLines; + QList keys = modes_hash.uniqueKeys(); + sort_modes(keys); + int n_virtual_modelines = add_virtual_modes(keys); + for(int i=0; icurrentMode = modeLines.size(); + if(modeline.modeline==preferredMode) + monitor->preferredMode = modeLines.size(); + for(int rates_index=0; rates_indexcurrentRate=rates_index; + if(modeline.rates[rates_index]==preferredRate) + monitor->preferredRate=rates_index; + } + if(imodeLines = modeLines; + monitor->modes_hash = modes_hash; + } + monitors.append(monitor); + } + printf("[get_outputs]: Finalizado\n"); + return monitors; +} + + +QList get_monitors_info(){ + int event_base, error_base; + int major, minor; + Display *dpy; + Window root; + + QList monitors; + + // CONNECT TO X-SERVER, GET ROOT WINDOW ID + dpy = XOpenDisplay(NULL); + root = RootWindow(dpy, 0); + XRRScreenResources *res; + int screenNo = ScreenCount(dpy); + + if (!XRRQueryExtension (dpy, &event_base, &error_base) || + !XRRQueryVersion (dpy, &major, &minor)) + { + fprintf (stderr, "RandR extension missing\n"); + return monitors; + } + + res = XRRGetScreenResources (dpy, root); + if (!res) + { + fprintf (stderr, "Could not get screen resources\n"); + return monitors; + } + + monitors = get_outputs(dpy, res); + XCloseDisplay(dpy); + return monitors; +} +// +// gcc -o Xrandr Xrandr.cc -lX11 -lXrandr -lstdc++ +// From 3e33921650a1ed590ff09ce7cada0505baf0c111 Mon Sep 17 00:00:00 2001 From: "P.L. Lucas" Date: Sun, 8 Dec 2013 15:52:56 +0100 Subject: [PATCH 4/6] Added LVDS output settings --- monitorsettingsdialog.cpp~ | 303 -------------------------------- randr.cpp~ | 347 ------------------------------------- 2 files changed, 650 deletions(-) delete mode 100644 monitorsettingsdialog.cpp~ delete mode 100644 randr.cpp~ diff --git a/monitorsettingsdialog.cpp~ b/monitorsettingsdialog.cpp~ deleted file mode 100644 index 20434cd..0000000 --- a/monitorsettingsdialog.cpp~ +++ /dev/null @@ -1,303 +0,0 @@ -/* - - Copyright (C) 2013 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - - -#include "monitorsettingsdialog.h" -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "ui_monitor.h" - -#include -#include -#include - -#include "randr.h" - -MonitorSettingsDialog::MonitorSettingsDialog(): - QDialog(NULL, 0), - monitors(), - LVDS(NULL) { - setupUi(); -} - - -MonitorSettingsDialog::~MonitorSettingsDialog() { - while (!monitors.isEmpty()) - delete monitors.takeFirst(); -} - -QString MonitorSettingsDialog::humanReadableName(Monitor* monitor) { - if(monitor == LVDS) - return tr("Laptop LCD Monitor"); - else if( monitor->name.startsWith("VGA") || monitor->name.startsWith("Analog") ) - return tr(LVDS ? "External VGA Monitor" : "VGA Monitor"); - else if( monitor->name.startsWith("DVI") || monitor->name.startsWith("TMDS") || monitor->name.startsWith("Digital") || monitor->name.startsWith("LVDS") ) - return tr(LVDS ? "External DVI Monitor" : "DVI Monitor"); - else if( monitor->name.startsWith("TV") || monitor->name.startsWith("S-Video") ) - return tr("TV"); - else if( monitor->name=="default" ) - return tr("Default Monitor"); - - return monitor->name; -} - -bool MonitorSettingsDialog::getXRandRInfo() { - monitors = get_monitors_info(); - - // check if this is the built-in LCD of laptop - for(int i=0; iname.startsWith("LVSD") || monitor->name.startsWith("PANEL") ) ) - { - LVDS = monitor; - break; - } - } - - return true; -} - -void MonitorSettingsDialog::onResolutionChanged(int index) { - QComboBox* combo = static_cast(sender()); - Monitor* monitor = reinterpret_cast(qVariantValue(combo->property("monitor"))); - char** rate; - QStandardItemModel *model = (QStandardItemModel *) combo->model(); - int sel = model->item(combo->currentIndex())->data().toInt(); - //int sel = combo->currentIndex() - 1; - printf("MonitorSettingsDialog::onResolutionChanged sel = %d\n", sel); - monitor->rateCombo->clear(); - monitor->rateCombo->addItem(tr("Auto")); - if( sel >= 0 ) { - ModeLine mode_line = monitor->modeLines[sel]; - printf("scale = %s\n", mode_line.scale.toAscii().data()); - for (int i = 0; i < mode_line.rates.size(); ++i) - monitor->rateCombo->addItem(mode_line.rates[i]); - } - monitor->rateCombo->setCurrentIndex(0); - QString mode = combo->currentText(); - if(mode.endsWith("*")) - monitor->panning->setEnabled(true); - else - monitor->panning->setEnabled(false); -} - -void MonitorSettingsDialog::setXRandRInfo() { - Monitor* l; - QByteArray cmd = "xrandr"; - - for(int i=0; iname); - cmd.append(' '); - - // if the monitor is turned on - if(monitor->enable->isChecked()) { - int sel_res = monitor->resolutionCombo->currentIndex(); // the fist item in the combo box is "Auto", indecis of resolutions are 1, 2, 3... - int sel_rate = monitor->rateCombo->currentIndex(); - - if(sel_res < 1) // auto resolution - cmd.append("--auto"); - else { - QStandardItemModel *model = (QStandardItemModel *) monitor->resolutionCombo->model(); - ModeLine modeLine = monitor->modeLines[ model->item(sel_res)->data().toInt() ]; - QString mode = monitor->resolutionCombo->currentText(); - bool mode_virtual_ok = mode.endsWith("*"); - if(mode_virtual_ok) - mode = mode.replace(QString("*"), QString()); - else - { - cmd.append("--mode "); - cmd.append(mode); - } - - cmd.append(" --panning "); - cmd.append(mode); - - if(mode_virtual_ok) - { - cmd.append(" --fb "); - cmd.append(mode); - } - - cmd.append(" --scale "); - if( mode_virtual_ok && monitor->panning->checkState()==Qt::Checked ) - cmd.append("1.0x1.0"); - else - cmd.append(modeLine.scale); - - if(sel_rate >= 1) { // not auto refresh rate - cmd.append(" --rate "); - cmd.append(monitor->resolutionCombo->currentText()); - } - } - - cmd.append(" --brightness "); - cmd.append(QString().setNum((float)monitor->brightness_slider->value()/100.0)); - } - else // turn off - cmd.append("--off"); - } - - QProcess process; - process.start(cmd); - process.waitForFinished(); - printf("%s\n", cmd.constData() ); -} - -void MonitorSettingsDialog::chooseMaxResolution(Monitor* monitor) { - if(monitor->resolutionCombo->count() > 1) - monitor->resolutionCombo->setCurrentIndex(1); -} - -// turn on both laptop LCD and the external monitor -void MonitorSettingsDialog::onUseBoth() { - for(int i=0; ienable->setChecked(true); - } - accept(); -} - -// external monitor only -void MonitorSettingsDialog::onExternalOnly() { - for(int i=0; ienable->setChecked(monitor != LVDS); - } - accept(); -} - -// laptop panel - LVDS only -void MonitorSettingsDialog::onLaptopOnly() { - for(int i=0; ienable->setChecked(monitor == LVDS); - } - accept(); -} - -void MonitorSettingsDialog::setupUi() { - ui.setupUi(this); - connect(ui.useBoth, SIGNAL(clicked(bool)), SLOT(onUseBoth())); - connect(ui.externalOnly, SIGNAL(clicked(bool)), SLOT(onExternalOnly())); - connect(ui.laptopOnly, SIGNAL(clicked(bool)), SLOT(onLaptopOnly())); - - connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton*)), SLOT(onDialogButtonClicked(QAbstractButton*))); - aboutButton = new QPushButton(ui.buttonBox); - aboutButton->setText(tr("About")); - ui.buttonBox->addButton(aboutButton, QDialogButtonBox::HelpRole); - - getXRandRInfo(); - - // If this is a laptop and there is an external monitor, offer quick options - if(LVDS && monitors.size() == 2) - ui.tabWidget->setCurrentIndex(0); - else { - ui.tabWidget->removeTab(0); - } - - for(int i=0; iname) - .arg(humanReadableName(monitor)); - printf("%s\n", title.toAscii().data()); - box->setTitle(title); - Ui::MonitorWidget mui = Ui::MonitorWidget(); - mui.setupUi(box); - ui.monitorLayout->insertWidget(ui.monitorLayout->count() - 1, box); - ui.monitorLayout->setStretchFactor(box, 0); - - monitor->enable = mui.enabled; - monitor->resolutionCombo = mui.resolution; - monitor->resolutionCombo->setProperty("monitor", qVariantFromValue(monitor)); - monitor->rateCombo = mui.rate; - monitor->panning = mui.panning; - monitor->brightness_slider = mui.brightness; - - // turn off screen is not allowed since there should be at least one monitor available. - if(monitors.size() == 1) - monitor->enable->setEnabled(false); - - if(monitor->currentMode >= 0) - monitor->enable->setChecked(true); - - connect(monitor->resolutionCombo, SIGNAL(currentIndexChanged(int)), SLOT(onResolutionChanged(int))); - - QStandardItemModel *model=new QStandardItemModel(monitor->modeLines.size()+1,1); - QStandardItem *item = new QStandardItem(QString(tr("Auto"))); - item->setData(QVariant(-1)); - model->setItem(0, 0, item); - for(int j=0; jmodeLines.size(); j++) - { - item = new QStandardItem(monitor->modeLines[j].modeline); - item->setData(QVariant(j)); //Stores index of modeLine - model->setItem(j+1, 0, item); - } - monitor->resolutionCombo->setModel(model); - - monitor->brightness_slider->setValue((int)(monitor->brightness*100.0)); - - /* - monitor->resolutionCombo->addItem(tr("Auto")); - - for(int j=0; jmodeLines.size(); j++) { - QString strv = monitor->modeLines[j].modeline; - monitor->resolutionCombo->addItem(strv); - } - */ - - monitor->resolutionCombo->setCurrentIndex(monitor->currentMode + 1); - monitor->rateCombo->setCurrentIndex(monitor->currentRate + 1); - ++i; - } -} - -void MonitorSettingsDialog::accept() { - setXRandRInfo(); - QDialog::accept(); -} - -void MonitorSettingsDialog::onDialogButtonClicked(QAbstractButton* button) { - if(ui.buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole) - setXRandRInfo(); - else if(button == aboutButton) { - // about dialog - QMessageBox::about(this, tr("About"), tr("LXRandR-Qt\n\nMonitor configuration tool for LXDE.")); - } -} - diff --git a/randr.cpp~ b/randr.cpp~ deleted file mode 100644 index 66ff738..0000000 --- a/randr.cpp~ +++ /dev/null @@ -1,347 +0,0 @@ -/* - - Copyright (C) 2013 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "randr.h" - -#include -#include -#include -#include -#include -#include -#include - - - -static double mode_refresh (XRRModeInfo *mode_info) -{ - double rate; - unsigned int vTotal = mode_info->vTotal; - - if (mode_info->modeFlags & RR_DoubleScan) { - /* doublescan doubles the number of lines */ - vTotal *= 2; - } - - if (mode_info->modeFlags & RR_Interlace) { - /* interlace splits the frame into two fields */ - /* the field rate is what is typically reported by monitors */ - vTotal /= 2; - } - - if (mode_info->hTotal && vTotal) - rate = ((double) mode_info->dotClock / - ((double) mode_info->hTotal * (double) vTotal)); - else - rate = 0; - return rate; -} - -/* Returns the index of the last value in an array < 0xffff */ -static int find_last_non_clamped(unsigned short array[], int size) { - int i; - for (i = size - 1; i > 0; i--) { - if (array[i] < 0xffff) - return i; - } - return 0; -} - - -static void get_gamma_info(Display *dpy, XRRScreenResources *res, RRCrtc crtc, float *brightness, float *red, float *blue, float *green) -{ - XRRCrtcGamma *crtc_gamma; - double i1, v1, i2, v2; - int size, middle, last_best, last_red, last_green, last_blue; - unsigned short *best_array; - - size = XRRGetCrtcGammaSize(dpy, crtc); - if (!size) { - printf("Failed to get size of gamma for output\n"); - return; - } - - crtc_gamma = XRRGetCrtcGamma(dpy, crtc); - if (!crtc_gamma) { - printf("Failed to get gamma for output\n"); - return; - } - - /* - * Here is a bit tricky because gamma is a whole curve for each - * color. So, typically, we need to represent 3 * 256 values as 3 + 1 - * values. Therefore, we approximate the gamma curve (v) by supposing - * it always follows the way we set it: a power function (i^g) - * multiplied by a brightness (b). - * v = i^g * b - * so g = (ln(v) - ln(b))/ln(i) - * and b can be found using two points (v1,i1) and (v2, i2): - * b = e^((ln(v2)*ln(i1) - ln(v1)*ln(i2))/ln(i1/i2)) - * For the best resolution, we select i2 at the highest place not - * clamped and i1 at i2/2. Note that if i2 = 1 (as in most normal - * cases), then b = v2. - */ - last_red = find_last_non_clamped(crtc_gamma->red, size); - last_green = find_last_non_clamped(crtc_gamma->green, size); - last_blue = find_last_non_clamped(crtc_gamma->blue, size); - best_array = crtc_gamma->red; - last_best = last_red; - if (last_green > last_best) { - last_best = last_green; - best_array = crtc_gamma->green; - } - if (last_blue > last_best) { - last_best = last_blue; - best_array = crtc_gamma->blue; - } - if (last_best == 0) - last_best = 1; - - middle = last_best / 2; - i1 = (double)(middle + 1) / size; - v1 = (double)(best_array[middle]) / 65535; - i2 = (double)(last_best + 1) / size; - v2 = (double)(best_array[last_best]) / 65535; - if (v2 < 0.0001) { /* The screen is black */ - *brightness = 0; - *red = 1; - *green = 1; - *blue = 1; - } else { - if ((last_best + 1) == size) - *brightness = v2; - else - *brightness = exp((log(v2)*log(i1) - log(v1)*log(i2))/log(i1/i2)); - *red = log((double)(crtc_gamma->red[last_red / 2]) / *brightness - / 65535) / log((double)((last_red / 2) + 1) / size); - *green = log((double)(crtc_gamma->green[last_green / 2]) / *brightness - / 65535) / log((double)((last_green / 2) + 1) / size); - *blue = log((double)(crtc_gamma->blue[last_blue / 2]) / *brightness - / 65535) / log((double)((last_blue / 2) + 1) / size); - } - - XRRFreeGamma(crtc_gamma); -} - -/** Sort modeLines using pixels size. - */ -static void sort_modes(QList &modes) -{ - int max=0; - int pixels=0; - QRegExp re("([0-9]*)x([0-9]*)"); - for(int i=0; i max) - { - modes.swap(i,j); - max = pixels; - } - } - } - } -} - -/** Add virtual mode lines. Returns number of virtual modelines added. - */ -static int add_virtual_modes(QList &modes) -{ - if(modes.size()==0) - return 0; - QRegExp re("([0-9]*)x([0-9]*)"); - if( re.indexIn(modes[0]) != -1 ) - { - int x = re.cap(1).toInt(); - int y = re.cap(2).toInt(); - for(int i=1;i<=4; i++) - { - float scale=1.0+0.25*(float)i; - QString mode = QString("%1x%2 *").arg(round(scale*(float)x)).arg(round(scale*(float)y)); - modes.prepend(mode); - } - return 4; - } - return 0; -} - -static QList get_outputs (Display *dpy, XRRScreenResources *res) -{ - QList monitors; - int o; - int jj = 0; - QString currentMode; - QString currentRate; - QString preferredMode; - QString preferredRate; - for (o = 0; o < res->noutput; o++) - { - // Get output name - XRROutputInfo *output_info = XRRGetOutputInfo (dpy, res, res->outputs[o]); - Monitor *monitor = new Monitor(); - monitor->name = output_info->name; - //printf("Output: %s\n", output_info->name); - switch (output_info->connection) { - case RR_Disconnected: - //printf(" Disconnected\n"); - continue; - break; - case RR_Connected: - //printf(" Connected\n"); - if (!output_info->crtc) { - //output->changes |= changes_automatic; - //output->automatic = True; - } - } - { - // Get output modes - QHash > modes_hash; - for (int j = jj; j < output_info->nmode; j++) - { - // Get mode rates - XID mode_xid = output_info->modes[j]; - for(int k=0; k < res->nmode; k++) - { - XRRModeInfo *mode = &res->modes[k]; - if(mode->id==mode_xid) - { - //printf(" Modo %d: %s\n", j, mode->name); - //printf (" %s (0x%x) %6.1fMHz\n", mode->name, (int)mode->id, (double)mode->dotClock / 1000000.0); - //printf(" %6.1fMHz\n", mode_refresh (mode)); - char buffer[10]; - sprintf(buffer, "%6.1f", mode_refresh (mode)); - QString rate(buffer); - if(!modes_hash.contains(QString(mode->name))) - { - QList rates; - modes_hash[QString(mode->name)] = rates; - } - modes_hash[QString(mode->name)].append(rate); - if (j < output_info->npreferred) - { - // printf (" +preferred\n"); - preferredMode = mode->name; - preferredRate = rate; - } - // Is this mode current mode? - for (int c = 0; c < res->ncrtc; c++) - { - XRRCrtcInfo *crtc_info = XRRGetCrtcInfo (dpy, res, res->crtcs[c]); - if(crtc_info->mode==mode_xid) - { - float brightness, red, blue, green; - get_gamma_info(dpy, res, res->crtcs[c], &brightness, &red, &blue, &green); - //printf (" +current\n"); - //printf (" Brightness: %6.1f\n", brightness); - //printf (" Gamma:\n"); - //printf (" Red: %6.1f\n", red); - //printf (" Blue: %6.1f\n", blue); - //printf (" Green: %6.1f\n", green); - currentMode = mode->name; - currentRate = rate; - monitor->brightness = brightness; - monitor->red = red; - monitor->blue = blue; - monitor->green = green; - } - XRRFreeCrtcInfo (crtc_info); - } - //printf("\n"); - } - } - //jj++; - } - QList modeLines; - QList keys = modes_hash.uniqueKeys(); - sort_modes(keys); - int n_virtual_modelines = add_virtual_modes(keys); - for(int i=0; icurrentMode = modeLines.size(); - if(modeline.modeline==preferredMode) - monitor->preferredMode = modeLines.size(); - for(int rates_index=0; rates_indexcurrentRate=rates_index; - if(modeline.rates[rates_index]==preferredRate) - monitor->preferredRate=rates_index; - } - if(imodeLines = modeLines; - monitor->modes_hash = modes_hash; - } - monitors.append(monitor); - } - printf("[get_outputs]: Finalizado\n"); - return monitors; -} - - -QList get_monitors_info(){ - int event_base, error_base; - int major, minor; - Display *dpy; - Window root; - - QList monitors; - - // CONNECT TO X-SERVER, GET ROOT WINDOW ID - dpy = XOpenDisplay(NULL); - root = RootWindow(dpy, 0); - XRRScreenResources *res; - int screenNo = ScreenCount(dpy); - - if (!XRRQueryExtension (dpy, &event_base, &error_base) || - !XRRQueryVersion (dpy, &major, &minor)) - { - fprintf (stderr, "RandR extension missing\n"); - return monitors; - } - - res = XRRGetScreenResources (dpy, root); - if (!res) - { - fprintf (stderr, "Could not get screen resources\n"); - return monitors; - } - - monitors = get_outputs(dpy, res); - XCloseDisplay(dpy); - return monitors; -} -// -// gcc -o Xrandr Xrandr.cc -lX11 -lXrandr -lstdc++ -// From 45180d7ef3cf5217dd970451755f424996764673 Mon Sep 17 00:00:00 2001 From: "P.L. Lucas" Date: Sun, 8 Dec 2013 16:46:03 +0100 Subject: [PATCH 5/6] Bug fixed: External outputs are all shown --- monitorsettingsdialog.cpp | 17 ++++++++++------- randr.cpp | 8 ++++---- randr.h | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/monitorsettingsdialog.cpp b/monitorsettingsdialog.cpp index c1380b4..bd7566d 100644 --- a/monitorsettingsdialog.cpp +++ b/monitorsettingsdialog.cpp @@ -109,9 +109,10 @@ void MonitorSettingsDialog::onResolutionChanged(int index) { void MonitorSettingsDialog::setXRandRInfo() { Monitor* l; - QByteArray cmd = "xrandr"; + for(int i=0; iname); @@ -154,7 +155,7 @@ void MonitorSettingsDialog::setXRandRInfo() { if(sel_rate >= 1) { // not auto refresh rate cmd.append(" --rate "); - cmd.append(monitor->resolutionCombo->currentText()); + cmd.append(monitor->rateCombo->currentText()); } } @@ -163,12 +164,15 @@ void MonitorSettingsDialog::setXRandRInfo() { } else // turn off cmd.append("--off"); + + //Exec xrandr + QProcess process; + process.start(cmd); + process.waitForFinished(); + printf("%s\n", cmd.constData() ); } - QProcess process; - process.start(cmd); - process.waitForFinished(); - printf("%s\n", cmd.constData() ); + } void MonitorSettingsDialog::chooseMaxResolution(Monitor* monitor) { @@ -282,7 +286,6 @@ void MonitorSettingsDialog::setupUi() { monitor->resolutionCombo->setCurrentIndex(monitor->currentMode + 1); monitor->rateCombo->setCurrentIndex(monitor->currentRate + 1); - ++i; } } diff --git a/randr.cpp b/randr.cpp index ba8014f..e7e7eeb 100644 --- a/randr.cpp +++ b/randr.cpp @@ -202,10 +202,10 @@ static QList get_outputs (Display *dpy, XRRScreenResources *res) XRROutputInfo *output_info = XRRGetOutputInfo (dpy, res, res->outputs[o]); Monitor *monitor = new Monitor(); monitor->name = output_info->name; - //printf("Output: %s\n", output_info->name); + printf("Output: %s\n", output_info->name); switch (output_info->connection) { case RR_Disconnected: - //printf(" Disconnected\n"); + printf(" Disconnected\n"); continue; break; case RR_Connected: @@ -227,9 +227,9 @@ static QList get_outputs (Display *dpy, XRRScreenResources *res) XRRModeInfo *mode = &res->modes[k]; if(mode->id==mode_xid) { - //printf(" Modo %d: %s\n", j, mode->name); + printf(" Modo %d: %s\n", j, mode->name); //printf (" %s (0x%x) %6.1fMHz\n", mode->name, (int)mode->id, (double)mode->dotClock / 1000000.0); - //printf(" %6.1fMHz\n", mode_refresh (mode)); + printf(" %6.1fMHz\n", mode_refresh (mode)); char buffer[10]; sprintf(buffer, "%6.1f", mode_refresh (mode)); QString rate(buffer); diff --git a/randr.h b/randr.h index c22e593..6279a0c 100644 --- a/randr.h +++ b/randr.h @@ -52,4 +52,4 @@ struct Monitor { QList get_monitors_info(); -#endif // randr_H \ No newline at end of file +#endif // randr_H From 9816ae2cef840738b8a4a71c9e61f29b5738df3b Mon Sep 17 00:00:00 2001 From: "P.L. Lucas" Date: Mon, 9 Dec 2013 23:34:52 +0100 Subject: [PATCH 6/6] Mark code from xrandr.c --- randr.cpp | 44 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/randr.cpp b/randr.cpp index e7e7eeb..5c6d318 100644 --- a/randr.cpp +++ b/randr.cpp @@ -27,7 +27,37 @@ #include #include +///////////////////////////////////////////////////////////////////////////// +// Some functions from xrandr.c (Xorg) +// Licenced under The Open Group licence: + +/* + * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc. + * Copyright © 2002 Hewlett Packard Company, Inc. + * Copyright © 2006 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + * + * Thanks to Jim Gettys who wrote most of the client side code, + * and part of the server code for randr. + */ static double mode_refresh (XRRModeInfo *mode_info) { @@ -139,6 +169,10 @@ static void get_gamma_info(Display *dpy, XRRScreenResources *res, RRCrtc crtc, f XRRFreeGamma(crtc_gamma); } + +//////////////////////////////////////////////////////////////////////// +// Next functions are added to connect to Xrandr + /** Sort modeLines using pixels size. */ static void sort_modes(QList &modes) @@ -227,12 +261,10 @@ static QList get_outputs (Display *dpy, XRRScreenResources *res) XRRModeInfo *mode = &res->modes[k]; if(mode->id==mode_xid) { - printf(" Modo %d: %s\n", j, mode->name); + printf(" Mode %d: %s\n", j, mode->name); //printf (" %s (0x%x) %6.1fMHz\n", mode->name, (int)mode->id, (double)mode->dotClock / 1000000.0); printf(" %6.1fMHz\n", mode_refresh (mode)); - char buffer[10]; - sprintf(buffer, "%6.1f", mode_refresh (mode)); - QString rate(buffer); + QString rate=QString("%1").arg(mode_refresh (mode), 6, 'f', 1); if(!modes_hash.contains(QString(mode->name))) { QList rates; @@ -342,6 +374,4 @@ QList get_monitors_info(){ XCloseDisplay(dpy); return monitors; } -// -// gcc -o Xrandr Xrandr.cc -lX11 -lXrandr -lstdc++ -// +