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