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..bd7566d 100644
--- a/monitorsettingsdialog.cpp
+++ b/monitorsettingsdialog.cpp
@@ -27,145 +27,60 @@
#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();
-
- 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);
+ 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;
}
- while(g_match_info_next(match, NULL));
-
- g_match_info_free(match);
}
- g_regex_unref(regex);
+
return true;
}
@@ -173,52 +88,91 @@ 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();
+ //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;
- QByteArray cmd = "xrandr";
+ Monitor* l;
+
- 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(monitor->rateCombo->currentText());
}
}
+
+ cmd.append(" --brightness ");
+ cmd.append(QString().setNum((float)monitor->brightness_slider->value()/100.0));
}
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();
+
}
void MonitorSettingsDialog::chooseMaxResolution(Monitor* monitor) {
@@ -228,8 +182,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 +192,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 +202,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 +224,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,24 +249,43 @@ 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;
};
diff --git a/randr.cpp b/randr.cpp
new file mode 100644
index 0000000..5c6d318
--- /dev/null
+++ b/randr.cpp
@@ -0,0 +1,377 @@
+/*
+
+ 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
+
+/////////////////////////////////////////////////////////////////////////////
+// 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)
+{
+ 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);
+}
+
+
+////////////////////////////////////////////////////////////////////////
+// Next functions are added to connect to Xrandr
+
+/** 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(" 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));
+ QString rate=QString("%1").arg(mode_refresh (mode), 6, 'f', 1);
+ 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]: End\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;
+}
+
diff --git a/randr.h b/randr.h
new file mode 100644
index 0000000..6279a0c
--- /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