• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • krandr
 

krandr

libkrandr.cc
00001 /*  libkrandr.cc     - class KRandr that makes it easy to use XRandr in KDE
00002     This file is part of KRandr 0.9.5
00003     Copyright (C) 2010  Timothy Pearson
00004     LibKRandr's homepage : http://www.trinitydesktop.org
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public License
00017     along with this library; see the file COPYING.LIB.  If not, write to
00018     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019     Boston, MA 02110-1301, USA.
00020 
00021     Send comments and bug fixes to Timothy Pearson <kb9vqf@pearsoncomputing.net>
00022 
00023 ***************************************************************************/
00024 
00025 #include <tqtimer.h>
00026 #include <tqstringlist.h>
00027 #include <tqregexp.h>
00028 
00029 #include <klocale.h>
00030 #include <kmessagebox.h>
00031 #include <kapplication.h>
00032 
00033 #include <stdlib.h>
00034 #include <cmath>
00035 
00036 #include "libkrandr.h"
00037 
00038 #include <X11/extensions/dpms.h>
00039 
00040 // FIXME
00041 // For now, just use the standalone xrandr program to apply the display settings
00042 #define USE_XRANDR_PROGRAM
00043 
00044 // This routine is courtsey of an answer on "Stack Overflow"
00045 // It takes an LSB-first int and makes it an MSB-first int (or vice versa)
00046 unsigned int reverse_bits(unsigned int x)
00047 {
00048     x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
00049     x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
00050     x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
00051     x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
00052     return((x >> 16) | (x << 16));
00053 }
00054 
00055 // This routine returns the output of an arbitrary Bash command
00056 TQString exec(const char * cmd) {
00057     TQString bashcommand = cmd;
00058     bashcommand = bashcommand.replace("\"", "\\\"");
00059     bashcommand = TQString("/bin/bash -c \"%1\" 2>&1").arg(bashcommand);
00060     FILE* pipe = popen(bashcommand.ascii(), "r");
00061     if (!pipe) return "ERROR";
00062     char buffer[128];
00063     TQString result = "";
00064     while(!feof(pipe)) {
00065         if(fgets(buffer, 128, pipe) != NULL) {
00066             result += buffer;
00067         }
00068     }
00069     pclose(pipe);
00070     result.remove(result.length(), 1);
00071     return result;
00072 }
00073 
00074 TQString capitalizeString(TQString in) {
00075     return in.left(1).upper() + in.right(in.length()-1);
00076 }
00077 
00078 TQString KRandrSimpleAPI::getIccFileName(TQString profileName, TQString screenName, TQString kde_confdir) {
00079     KSimpleConfig *t_config = NULL;
00080     KSimpleConfig *t_systemconfig = NULL;
00081     int t_numberOfProfiles;
00082     TQStringList t_cfgProfiles;
00083     TQString retval;
00084 
00085     if ((profileName != NULL) && (profileName != "")) {
00086         t_config = new KSimpleConfig( TQString::fromLatin1( "kiccconfigrc" ));
00087         t_config->setGroup(NULL);
00088         if (t_config->readBoolEntry("EnableICC", false) == true) {
00089             t_config->setGroup(profileName);
00090             retval = t_config->readEntry(screenName);
00091         }
00092         else {
00093             retval = "";
00094         }
00095         delete t_config;
00096     }
00097     else {
00098         t_systemconfig = new KSimpleConfig( kde_confdir + TQString("/kicc/kiccconfigrc") );
00099         t_systemconfig->setGroup(NULL);
00100         if (t_systemconfig->readBoolEntry("EnableICC", false) == true) {
00101             retval = t_systemconfig->readEntry("ICCFile");
00102         }
00103         else {
00104             retval = "";
00105         }
00106         delete t_systemconfig;
00107     }
00108 
00109     return retval;
00110 }
00111 
00112 TQString KRandrSimpleAPI::applyIccFile(TQString screenName, TQString fileName) {
00113     int i;
00114     int j;
00115     Display *randr_display;
00116     ScreenInfo *randr_screen_info;
00117     XRROutputInfo *output_info;
00118 
00119     int screenNumber = 0;
00120 
00121     if (fileName != "") {
00122         // FIXME
00123         // This should use the RRSetCrtcGamma function when available
00124         // That is the only way to get proper setting when two output are active at the same time
00125         // (otherwise in clone mode only one screen is available)
00126 
00127         // HACK
00128         // For now, simply exit with no changes if screenName is not an active output
00129 
00130         if (isValid() == true) {
00131             screenNumber = -1;
00132             randr_display = qt_xdisplay();
00133             randr_screen_info = read_screen_info(randr_display);
00134             if (randr_screen_info == NULL) {
00135                 return "";
00136             }
00137             j=0;
00138             for (i = 0; i < randr_screen_info->n_output; i++) {
00139                 output_info = randr_screen_info->outputs[i]->info;
00140                 // Look for ON outputs...
00141                 if (!randr_screen_info->outputs[i]->cur_crtc) {
00142                     continue;
00143                 }
00144                 // ...that are connected
00145                 if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
00146                     continue;
00147                 }
00148                 if (output_info->name == screenName) {
00149                     screenNumber = j;
00150                 }
00151                 j++;
00152             }
00153             freeScreenInfoStructure(randr_screen_info);
00154         }
00155 
00156         if (screenNumber >= 0) {
00157             // Apply ICC settings with XCalib
00158             TQString icc_command;
00159             FILE *pipe_xcalib;
00160             char xcalib_result[2048];
00161             int i;
00162             xcalib_result[0]=0;
00163 
00164             icc_command = TQString("xcalib \"%1\"").arg(fileName);
00165             if ((pipe_xcalib = popen(icc_command.ascii(), "r")) == NULL)
00166             {
00167                 printf("Xcalib pipe error\n [xcalib apply]");
00168             }
00169             else {
00170                 fgets(xcalib_result, 2048, pipe_xcalib);
00171                 pclose(pipe_xcalib);
00172                 for (i=1;i<2048;i++) {
00173                     if (xcalib_result[i] == 0) {
00174                         xcalib_result[i-1]=0;
00175                         i=2048;
00176                     }
00177                 }
00178                 if (strlen(xcalib_result) > 2) {
00179                     return xcalib_result;
00180                 }
00181             }
00182         }
00183     }
00184     else {
00185         // Reset ICC profile on this screen
00186 
00187         // FIXME
00188         // This should use the RRSetCrtcGamma function when available
00189         // That is the only way to get proper setting when two output are active at the same time
00190         // (otherwise in clone mode only one screen is available)
00191 
00192         // HACK
00193         // For now, simply exit with no changes if screenName is not an active output
00194 
00195         if (isValid() == true) {
00196             screenNumber = -1;
00197             randr_display = qt_xdisplay();
00198             randr_screen_info = read_screen_info(randr_display);
00199             if (randr_screen_info == NULL) {
00200                 return "";
00201             }
00202             j=0;
00203             for (i = 0; i < randr_screen_info->n_output; i++) {
00204                 output_info = randr_screen_info->outputs[i]->info;
00205                 // Look for ON outputs...
00206                 if (!randr_screen_info->outputs[i]->cur_crtc) {
00207                     continue;
00208                 }
00209                 // ...that are connected
00210                 if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
00211                     continue;
00212                 }
00213                 if (output_info->name == screenName) {
00214                     screenNumber = j;
00215                 }
00216                 j++;
00217             }
00218             freeScreenInfoStructure(randr_screen_info);
00219         }
00220 
00221         if (screenNumber >= 0) {
00222             // Apply ICC settings with XCalib
00223             TQString icc_command;
00224             FILE *pipe_xcalib;
00225             char xcalib_result[2048];
00226             int i;
00227             xcalib_result[0]=0;
00228 
00229             icc_command = TQString("xcalib -c");
00230             if ((pipe_xcalib = popen(icc_command.ascii(), "r")) == NULL)
00231             {
00232                 printf("Xcalib pipe error\n [xcalib clear]");
00233             }
00234             else {
00235                 fgets(xcalib_result, 2048, pipe_xcalib);
00236                 pclose(pipe_xcalib);
00237                 for (i=1;i<2048;i++) {
00238                     if (xcalib_result[i] == 0) {
00239                         xcalib_result[i-1]=0;
00240                         i=2048;
00241                     }
00242                 }
00243                 if (strlen(xcalib_result) > 2) {
00244                     return xcalib_result;
00245                 }
00246             }
00247         }
00248     }
00249     return "";
00250 }
00251 
00252 TQString KRandrSimpleAPI::applyIccConfiguration(TQString profileName, TQString kde_confdir) {
00253     int i;
00254     Display *randr_display;
00255     ScreenInfo *randr_screen_info;
00256     XRROutputInfo *output_info;
00257     KSimpleConfig *t_config;
00258 
00259     int screenNumber = 0;
00260     TQString errorstr = "";
00261 
00262     t_config = new KSimpleConfig( TQString::fromLatin1( "kiccconfigrc" ));
00263 
00264     // Find all screens
00265     if (isValid() == true) {
00266         randr_display = qt_xdisplay();
00267         randr_screen_info = read_screen_info(randr_display);
00268         if (randr_screen_info == NULL) {
00269             return "";
00270         }
00271         for (i = 0; i < randr_screen_info->n_output; i++) {
00272             output_info = randr_screen_info->outputs[i]->info;
00273             errorstr = applyIccFile(output_info->name, getIccFileName(profileName, output_info->name, kde_confdir));
00274             if (errorstr != "") {
00275                 return errorstr;
00276             }
00277         }
00278         freeScreenInfoStructure(randr_screen_info);
00279     }
00280     else {
00281         return applyIccFile(getIccFileName(profileName, "Default", kde_confdir), "Default");
00282     }
00283 
00284     t_config->writeEntry("CurrentProfile", profileName);
00285     t_config->sync();
00286     delete t_config;
00287 
00288     return "";
00289 }
00290 
00291 TQString KRandrSimpleAPI::getEDIDMonitorName(int card, TQString displayname) {
00292     TQString edid;
00293     TQByteArray binaryedid = getEDID(card, displayname);
00294     if (binaryedid.isNull())
00295         return TQString();
00296 
00297     // Get the manufacturer ID
00298     unsigned char letter_1 = ((binaryedid[8]>>2) & 0x1F) + 0x40;
00299     unsigned char letter_2 = (((binaryedid[8] & 0x03) << 3) | ((binaryedid[9]>>5) & 0x07)) + 0x40;
00300     unsigned char letter_3 = (binaryedid[9] & 0x1F) + 0x40;
00301     TQChar qletter_1 = TQChar(letter_1);
00302     TQChar qletter_2 = TQChar(letter_2);
00303     TQChar qletter_3 = TQChar(letter_3);
00304     TQString manufacturer_id = TQString("%1%2%3").arg(qletter_1).arg(qletter_2).arg(qletter_3);
00305 
00306     // Get the model ID
00307     unsigned int raw_model_id = (((binaryedid[10] << 8) | binaryedid[11]) << 16) & 0xFFFF0000;
00308     // Reverse the bit order
00309     unsigned int model_id = reverse_bits(raw_model_id);
00310 
00311     // Try to get the model name
00312     bool has_friendly_name = false;
00313     unsigned char descriptor_block[18];
00314     int i;
00315     for (i=72;i<90;i++) {
00316         descriptor_block[i-72] = binaryedid[i] & 0xFF;
00317     }
00318     if ((descriptor_block[0] != 0) || (descriptor_block[1] != 0) || (descriptor_block[3] != 0xFC)) {
00319         for (i=90;i<108;i++) {
00320             descriptor_block[i-90] = binaryedid[i] & 0xFF;
00321         }
00322         if ((descriptor_block[0] != 0) || (descriptor_block[1] != 0) || (descriptor_block[3] != 0xFC)) {
00323             for (i=108;i<126;i++) {
00324                 descriptor_block[i-108] = binaryedid[i] & 0xFF;
00325             }
00326         }
00327     }
00328 
00329     TQString monitor_name;
00330     if ((descriptor_block[0] == 0) && (descriptor_block[1] == 0) && (descriptor_block[3] == 0xFC)) {
00331         char* pos = strchr((char *)(descriptor_block+5), '\n');
00332         if (pos) {
00333             *pos = 0;
00334             has_friendly_name = true;
00335             monitor_name = TQString((char *)(descriptor_block+5));
00336         }
00337         else {
00338             has_friendly_name = false;
00339         }
00340     }
00341 
00342     // [FIXME]
00343     // Look up manudacturer names if possible!
00344 
00345     if (has_friendly_name)
00346         edid = TQString("%1 %2").arg(manufacturer_id).arg(monitor_name);
00347     else
00348         edid = TQString("%1 0x%2").arg(manufacturer_id).arg(model_id, 0, 16);
00349 
00350     return edid;
00351 }
00352 
00353 TQByteArray KRandrSimpleAPI::getEDID(int card, TQString displayname) {
00354     TQFile file(TQString("/sys/class/drm/card%1-%2/edid").arg(card).arg(displayname));
00355     if (!file.open (IO_ReadOnly))
00356         return TQByteArray();
00357     TQByteArray binaryedid = file.readAll();
00358     file.close();
00359     return binaryedid;
00360 }
00361 
00362 TQString KRandrSimpleAPI::getCurrentProfile () {
00363     TQString profileName;
00364     KSimpleConfig *t_config;
00365 
00366     t_config = new KSimpleConfig( TQString::fromLatin1( "kiccconfigrc" ));
00367     profileName = t_config->readEntry("CurrentProfile");
00368     delete t_config;
00369     return profileName;
00370 }
00371 
00372 TQString KRandrSimpleAPI::applySystemWideIccConfiguration(TQString kde_confdir) {
00373     // Apply ICC settings with XCalib
00374     TQString icc_command;
00375     FILE *pipe_xcalib;
00376     char xcalib_result[2048];
00377     int i;
00378     xcalib_result[0]=0;
00379 
00380     icc_command = TQString("xcalib \"%1\"").arg(getIccFileName(NULL, "Default", kde_confdir));
00381     if ((pipe_xcalib = popen(icc_command.ascii(), "r")) == NULL)
00382     {
00383         printf("Xcalib pipe error [xcalib apply]\n");
00384     }
00385     else {
00386         fgets(xcalib_result, 2048, pipe_xcalib);
00387         pclose(pipe_xcalib);
00388         for (i=1;i<2048;i++) {
00389             if (xcalib_result[i] == 0) {
00390                 xcalib_result[i-1]=0;
00391                 i=2048;
00392             }
00393         }
00394         if (strlen(xcalib_result) > 2) {
00395             return xcalib_result;
00396         }
00397     }
00398     return "";
00399 }
00400 
00401 void KRandrSimpleAPI::saveSystemwideDisplayConfiguration(bool enable, TQString profilename, TQString kde_confdir, TQPtrList<SingleScreenData> screenInfoArray) {
00402     int i;
00403 
00404     TQString filename;
00405 
00406     filename = "displayglobals";
00407     filename.prepend(kde_confdir.append("/"));
00408     KSimpleConfig* display_config = new KSimpleConfig( filename );
00409     display_config->setGroup("General");
00410     display_config->writeEntry("ApplySettingsOnStart", enable);
00411     display_config->sync();
00412     delete display_config;
00413 
00414     filename = profilename;
00415     if (filename == "")
00416         filename = "default";
00417     filename.prepend(kde_confdir.append("/displayconfig/"));
00418 
00419     display_config = new KSimpleConfig( filename );
00420 
00421     i=0;
00422     SingleScreenData *screendata;
00423     for ( screendata=screenInfoArray.first(); screendata; screendata=screenInfoArray.next() ) {
00424         display_config->setGroup(TQString("SCREEN %1").arg(i));
00425         display_config->writeEntry("ScreenFriendlyName", screendata->screenFriendlyName);
00426         display_config->writeEntry("GenericScreenDetected", screendata->generic_screen_detected);
00427         display_config->writeEntry("ScreenConnected", screendata->screen_connected);
00428         display_config->writeEntry("Resolutions", screendata->resolutions);
00429         display_config->writeEntry("RefreshRates", screendata->refresh_rates);
00430         display_config->writeEntry("ColorDepths", screendata->color_depths);
00431         display_config->writeEntry("AvailableRotations", screendata->rotations);
00432         display_config->writeEntry("CurrentResolution", screendata->current_resolution_index);
00433         display_config->writeEntry("CurrentRefreshRate", screendata->current_refresh_rate_index);
00434         display_config->writeEntry("CurrentColorDepth", screendata->current_color_depth_index);
00435         display_config->writeEntry("CurrentRotation", screendata->current_rotation_index);
00436         display_config->writeEntry("CurrentOrientiation", screendata->current_orientation_mask);
00437         display_config->writeEntry("GammaRed", screendata->gamma_red);
00438         display_config->writeEntry("GammaGreen", screendata->gamma_green);
00439         display_config->writeEntry("GammaBlue", screendata->gamma_blue);
00440         display_config->writeEntry("CurrentXFlip", screendata->has_x_flip);
00441         display_config->writeEntry("CurrentYFlip", screendata->has_y_flip);
00442         display_config->writeEntry("SupportsTransformation", screendata->supports_transformations);
00443         display_config->writeEntry("IsPrimary", screendata->is_primary);
00444         display_config->writeEntry("IsExtended", screendata->is_extended);
00445         display_config->writeEntry("AbsXPos", screendata->absolute_x_position);
00446         display_config->writeEntry("AbsYPos", screendata->absolute_y_position);
00447         display_config->writeEntry("CurrentXPixelCount", screendata->current_x_pixel_count);
00448         display_config->writeEntry("CurrentYPixelCount", screendata->current_y_pixel_count);
00449         display_config->writeEntry("HasDPMS", screendata->has_dpms);
00450         display_config->writeEntry("EnableDPMS", screendata->enable_dpms);
00451         display_config->writeEntry("DPMSStandbyDelay", screendata->dpms_standby_delay);
00452         display_config->writeEntry("DPMSSuspendDelay", screendata->dpms_suspend_delay);
00453         display_config->writeEntry("DPMSPowerDownDelay", screendata->dpms_off_delay);
00454         i++;
00455     }
00456 
00457     display_config->sync();
00458     delete display_config;
00459 }
00460 
00461 TQPoint KRandrSimpleAPI::applySystemwideDisplayConfiguration(TQString profilename, TQString kde_confdir) {
00462     TQPoint ret;
00463 
00464     TQString filename = "displayglobals";
00465     filename.prepend(kde_confdir.append("/"));
00466     KSimpleConfig* display_config = new KSimpleConfig( filename );
00467     display_config->setGroup("General");
00468     bool enabled = display_config->readBoolEntry("ApplySettingsOnStart", false);
00469     delete display_config;
00470 
00471     if (enabled) {
00472         TQPtrList<SingleScreenData> screenInfoArray;
00473         screenInfoArray = loadSystemwideDisplayConfiguration(profilename, kde_confdir);
00474         if (screenInfoArray.count() > 0) {
00475             applySystemwideDisplayConfiguration(screenInfoArray, FALSE, kde_confdir);
00476         }
00477         destroyScreenInformationObject(screenInfoArray);
00478         screenInfoArray = readCurrentDisplayConfiguration();
00479         ensureMonitorDataConsistency(screenInfoArray);
00480         ret = primaryScreenOffsetFromTLC(screenInfoArray);
00481         destroyScreenInformationObject(screenInfoArray);
00482     }
00483 
00484     return ret;
00485 }
00486 
00487 TQPtrList<SingleScreenData> KRandrSimpleAPI::loadSystemwideDisplayConfiguration(TQString profilename, TQString kde_confdir) {
00488     int i;
00489 
00490     TQString filename;
00491     filename = profilename;
00492     if (filename == "")
00493         filename = "default";
00494     filename.prepend(kde_confdir.append("/displayconfig/"));
00495 
00496     KSimpleConfig* display_config = new KSimpleConfig( filename );
00497 
00498     TQStringList grouplist = display_config->groupList();
00499     SingleScreenData *screendata;
00500     TQPtrList<SingleScreenData> screenInfoArray;
00501     for ( TQStringList::Iterator it = grouplist.begin(); it != grouplist.end(); ++it ) {
00502         if ((*it).startsWith("SCREEN ")) {
00503             display_config->setGroup(*it);
00504             i = ((*it).remove("SCREEN ")).toInt();
00505             screendata = new SingleScreenData;
00506             screenInfoArray.append(screendata);
00507             screendata->screenFriendlyName = display_config->readEntry("ScreenFriendlyName");
00508             screendata->generic_screen_detected = display_config->readBoolEntry("GenericScreenDetected");
00509             screendata->screen_connected = display_config->readBoolEntry("ScreenConnected");
00510             screendata->resolutions = display_config->readListEntry("Resolutions");
00511             screendata->refresh_rates = display_config->readListEntry("RefreshRates");
00512             screendata->color_depths = display_config->readListEntry("ColorDepths");
00513             screendata->rotations = display_config->readListEntry("AvailableRotations");
00514             screendata->current_resolution_index = display_config->readNumEntry("CurrentResolution");
00515             screendata->current_refresh_rate_index = display_config->readNumEntry("CurrentRefreshRate");
00516             screendata->current_color_depth_index = display_config->readNumEntry("CurrentColorDepth");
00517             screendata->current_rotation_index = display_config->readNumEntry("CurrentRotation");
00518             screendata->current_orientation_mask = display_config->readNumEntry("CurrentOrientiation");
00519             screendata->gamma_red = display_config->readDoubleNumEntry("GammaRed");
00520             screendata->gamma_green = display_config->readDoubleNumEntry("GammaGreen");
00521             screendata->gamma_blue = display_config->readDoubleNumEntry("GammaBlue");
00522             screendata->has_x_flip = display_config->readBoolEntry("CurrentXFlip");
00523             screendata->has_y_flip = display_config->readBoolEntry("CurrentYFlip");
00524             screendata->supports_transformations = display_config->readBoolEntry("SupportsTransformation");
00525             screendata->is_primary = display_config->readBoolEntry("IsPrimary");
00526             screendata->is_extended = display_config->readBoolEntry("IsExtended");
00527             screendata->absolute_x_position = display_config->readNumEntry("AbsXPos");
00528             screendata->absolute_y_position = display_config->readNumEntry("AbsYPos");
00529             screendata->current_x_pixel_count = display_config->readNumEntry("CurrentXPixelCount");
00530             screendata->current_y_pixel_count = display_config->readNumEntry("CurrentYPixelCount");
00531             screendata->has_dpms = display_config->readBoolEntry("HasDPMS");
00532             screendata->enable_dpms = display_config->readBoolEntry("EnableDPMS");
00533             screendata->dpms_standby_delay = display_config->readNumEntry("DPMSStandbyDelay");
00534             screendata->dpms_suspend_delay = display_config->readNumEntry("DPMSSuspendDelay");
00535             screendata->dpms_off_delay = display_config->readNumEntry("DPMSPowerDownDelay");
00536         }
00537     }
00538 
00539     delete display_config;
00540 
00541     return screenInfoArray;
00542 }
00543 
00544 int KRandrSimpleAPI::getHardwareRotationFlags(SingleScreenData* screendata) {
00545     int rotationFlags = 0;
00546     TQString rotationDesired = *screendata->rotations.at(screendata->current_rotation_index);
00547     if (rotationDesired == "Normal") {
00548         rotationFlags = rotationFlags | RandRScreen::Rotate0;
00549     }
00550     else if (rotationDesired == "Rotate 90 degrees") {
00551         rotationFlags = rotationFlags | RandRScreen::Rotate90;
00552     }
00553     else if (rotationDesired == "Rotate 180 degrees") {
00554         rotationFlags = rotationFlags | RandRScreen::Rotate180;
00555     }
00556     else if (rotationDesired == "Rotate 270 degrees") {
00557         rotationFlags = rotationFlags | RandRScreen::Rotate270;
00558     }
00559     if (screendata->has_x_flip) {
00560         rotationFlags = rotationFlags | RandRScreen::ReflectX;
00561     }
00562     if (screendata->has_y_flip) {
00563         rotationFlags = rotationFlags | RandRScreen::ReflectY;
00564     }
00565     return rotationFlags;
00566 }
00567 
00568 #define USE_XRANDR_PROGRAM
00569 
00570 bool KRandrSimpleAPI::applySystemwideDisplayConfiguration(TQPtrList<SingleScreenData> screenInfoArray, bool test, TQString kde_confdir) {
00571     int i;
00572     int j;
00573     bool accepted = true;
00574     Display *randr_display;
00575     XRROutputInfo *output_info;
00576     ScreenInfo *randr_screen_info;
00577 
00578     SingleScreenData *screendata;
00579 
00580     TQPtrList<SingleScreenData> oldconfig;
00581     if (test == TRUE) {
00582         oldconfig = readCurrentDisplayConfiguration();
00583     }
00584 
00585     if (isValid() == true) {
00586 #ifdef USE_XRANDR_PROGRAM
00587         // Assemble the command string for xrandr
00588         TQString command;
00589         command = "xrandr";
00590 
00591         randr_display = qt_xdisplay();
00592         randr_screen_info = read_screen_info(randr_display);
00593         for (i = 0; i < screenInfoArray.count(); i++) {
00594             screendata = screenInfoArray.at(i);
00595             if (screendata) {
00596                 output_info = randr_screen_info->outputs[i]->info;
00597                 command.append(" --output ").append(output_info->name);
00598                 if (screendata->is_primary || screendata->is_extended) {
00599                     command.append(TQString(" --mode %1x%2").arg(screendata->current_x_pixel_count).arg(screendata->current_y_pixel_count));
00600                     command.append(TQString(" --pos %1x%2").arg(screendata->absolute_x_position).arg(screendata->absolute_y_position));
00601                     command.append(TQString(" --refresh %1").arg(atoi((*screendata->refresh_rates.at(screendata->current_refresh_rate_index)).ascii())));
00602                     command.append(TQString(" --gamma %1:%2:%3").arg(screendata->gamma_red).arg(screendata->gamma_green).arg(screendata->gamma_blue));
00603                     if (screendata->current_rotation_index == 0) command.append(" --rotate ").append("normal");
00604                     if (screendata->current_rotation_index == 1) command.append(" --rotate ").append("left");
00605                     if (screendata->current_rotation_index == 2) command.append(" --rotate ").append("inverted");
00606                     if (screendata->current_rotation_index == 3) command.append(" --rotate ").append("right");
00607                     if ((screendata->has_x_flip == 0) && (screendata->has_y_flip == 0)) command.append(" --reflect ").append("normal");
00608                     if ((screendata->has_x_flip == 1) && (screendata->has_y_flip == 0)) command.append(" --reflect ").append("x");
00609                     if ((screendata->has_x_flip == 0) && (screendata->has_y_flip == 1)) command.append(" --reflect ").append("y");
00610                     if ((screendata->has_x_flip == 1) && (screendata->has_y_flip == 1)) command.append(" --reflect ").append("xy");
00611                     if (screendata->is_primary) {
00612                         command.append(" --primary");
00613                     }
00614                 }
00615                 else {
00616                     command.append(" --off");
00617                 }
00618             }
00619             else {
00620                 printf("[WARNING] Unable to find configuration for monitor %d; settings may not be correctly applied...\n", i); fflush(stdout);
00621             }
00622         }
00623         freeScreenInfoStructure(randr_screen_info);
00624 
00625         TQString xrandr_command_output = exec(command.ascii());
00626         xrandr_command_output = xrandr_command_output.stripWhiteSpace();
00627         if (test) {
00628             // In case gamma settings is not supported, try again without '--gamma' parameter
00629             if (xrandr_command_output == "xrandr: Gamma size is 0.") {
00630                 command = command.replace(TQRegExp("--gamma [0-9\\.]*:[0-9\\.]*:[0-9\\.]*"), "");
00631                 xrandr_command_output = exec(command.ascii());
00632                 xrandr_command_output = xrandr_command_output.stripWhiteSpace();
00633             }
00634             
00635             if(xrandr_command_output.startsWith("xrandr: Failed to get size of gamma for output")) {
00636                 KMessageBox::sorry(0, xrandr_command_output, i18n("Setting gamma failed."));
00637             } else if (xrandr_command_output != "") {
00638                 applySystemwideDisplayConfiguration(oldconfig, FALSE, kde_confdir);
00639                 accepted = false;
00640                 destroyScreenInformationObject(oldconfig);
00641                 KMessageBox::sorry(0, xrandr_command_output, i18n("XRandR encountered a problem"));
00642                 return accepted;
00643             }
00644         }
00645 
00646         // HACK
00647         // This is needed because Qt does not properly generate screen
00648         // resize events when switching screens, so KDE gets stuck in the old resolution
00649         // This only seems to happen with more than one screen, so check for that condition...
00650         // FIXME: This also only occurs when the primary display has been changed
00651         // FIXME: Check for that condition as well!
00652         if (kapp->desktop()->numScreens() > 1) {
00653             for (i = 0; i < screenInfoArray.count(); i++) {
00654                 screendata = screenInfoArray.at(i);
00655                 if (screendata->is_primary == true) {
00656                     kapp->desktop()->emitResizedSignal(i);
00657                 }
00658             }
00659         }
00660 #else
00661         randr_display = qt_xdisplay();
00662         randr_screen_info = read_screen_info(randr_display);
00663         // Turn off all displays
00664         for (i = 0; i < screenInfoArray.count(); i++) {
00665             screendata = screenInfoArray.at(i);
00666             output_info = randr_screen_info->outputs[i]->info;
00667 
00668             randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
00669             randr_screen_info->cur_output = randr_screen_info->outputs[i];
00670             randr_screen_info->cur_output->auto_set = 0;
00671             randr_screen_info->cur_output->off_set = 1;
00672             output_off (randr_screen_info, randr_screen_info->cur_output);
00673             j=main_low_apply(randr_screen_info);
00674         }
00675         freeScreenInfoStructure(randr_screen_info);
00676         randr_screen_info = read_screen_info(randr_display);
00677         // Turn on the primary display
00678         for (i = 0; i < screenInfoArray.count(); i++) {
00679             screendata = screenInfoArray.at(i);
00680             output_info = randr_screen_info->outputs[i]->info;
00681 
00682             if (screendata->is_primary == true) {
00683                 randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
00684                 randr_screen_info->cur_output = randr_screen_info->outputs[i];
00685                 randr_screen_info->cur_output->auto_set = 1;
00686                 randr_screen_info->cur_output->off_set = 0;
00687                 output_auto (randr_screen_info, randr_screen_info->cur_output);
00688                 j=main_low_apply(randr_screen_info);
00689             }
00690         }
00691         freeScreenInfoStructure(randr_screen_info);
00692         // Handle the remaining displays
00693         randr_screen_info = read_screen_info(randr_display);
00694         for (i = 0; i < screenInfoArray.count(); i++) {
00695             screendata = screenInfoArray.at(i);
00696             output_info = randr_screen_info->outputs[i]->info;
00697 
00698             // Activate or deactivate the screens as necessary
00699             randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
00700             randr_screen_info->cur_output = randr_screen_info->outputs[i];
00701             if (screendata->is_primary == false) {
00702                 if (screendata->is_primary || screendata->is_extended) {
00703                     randr_screen_info->cur_output->auto_set = 1;
00704                     randr_screen_info->cur_output->off_set = 0;
00705                     output_auto (randr_screen_info, randr_screen_info->cur_output);
00706                     j=main_low_apply(randr_screen_info);
00707                 }
00708                 else {
00709                     randr_screen_info->cur_output->auto_set = 0;
00710                     randr_screen_info->cur_output->off_set = 1;
00711                     output_off (randr_screen_info, randr_screen_info->cur_output);
00712                     j=main_low_apply(randr_screen_info);
00713                 }
00714             }
00715         }
00716         freeScreenInfoStructure(randr_screen_info);
00717         randr_screen_info = read_screen_info(randr_display);
00718         for (i = 0; i < screenInfoArray.count(); i++) {
00719             screendata = screenInfoArray.at(i);
00720             output_info = randr_screen_info->outputs[i]->info;
00721 
00722             if (screendata->is_primary || screendata->is_extended) {
00723                 // Set rotation, refresh rate, and size
00724                 RandRScreen *cur_screen = new RandRScreen(i);
00725                 cur_screen->proposeSize(screendata->current_resolution_index);
00726                 cur_screen->proposeRefreshRate(screendata->current_refresh_rate_index);
00727                 cur_screen->proposeRotation(getHardwareRotationFlags(screendata));
00728                 cur_screen->applyProposed();
00729                 delete cur_screen;
00730 
00731                 // Force data reload
00732                 randr_screen_info = read_screen_info(randr_display);
00733                 output_info = randr_screen_info->outputs[i]->info;
00734 
00735                 // Finally, set the screen's position
00736                 randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
00737                 if (randr_screen_info->cur_crtc) {
00738                     randr_screen_info->cur_crtc->cur_x = screendata->absolute_x_position;
00739                     randr_screen_info->cur_crtc->cur_y = screendata->absolute_y_position;
00740                     j=main_low_apply(randr_screen_info);
00741                 }
00742             }
00743         }
00744         freeScreenInfoStructure(randr_screen_info);
00745 #endif
00746     }
00747 
00748     applySystemwideDisplayGamma(screenInfoArray);
00749     applySystemwideDisplayDPMS(screenInfoArray);
00750     TQString current_icc_profile = getCurrentProfile();
00751     applySystemWideIccConfiguration(kde_confdir);
00752     applyIccConfiguration(current_icc_profile, kde_confdir);
00753 
00754     if (test == TRUE) {
00755         int ret = showTestConfigurationDialog();
00756         if (!ret) {
00757             applySystemwideDisplayConfiguration(oldconfig, FALSE, kde_confdir);
00758             accepted = false;
00759         }
00760         destroyScreenInformationObject(oldconfig);
00761     }
00762 
00763     return accepted;
00764 }
00765 
00766 void KRandrSimpleAPI::destroyScreenInformationObject(TQPtrList<SingleScreenData> screenInfoArray) {
00767     SingleScreenData *screendata;
00768     for ( screendata = screenInfoArray.first(); screendata; screendata = screenInfoArray.next() ) {
00769         screenInfoArray.remove(screendata);
00770         delete screendata;
00771     }
00772 }
00773 
00774 void KRandrSimpleAPI::ensureMonitorDataConsistency(TQPtrList<SingleScreenData> screenInfoArray) {
00775     int i;
00776     SingleScreenData *screendata;
00777 
00778     int numberOfScreens = screenInfoArray.count();
00779 
00780     for (i=0;i<numberOfScreens;i++) {
00781         screendata = screenInfoArray.at(i);
00782         if (!screendata->screen_connected) {
00783             screendata->is_primary = false;
00784             screendata->is_extended = false;
00785         }
00786     }
00787 
00788     bool has_primary_monitor = false;
00789     for (i=0;i<numberOfScreens;i++) {
00790         screendata = screenInfoArray.at(i);
00791         if (screendata->is_primary)
00792             has_primary_monitor = true;
00793     }
00794     if (!has_primary_monitor) {
00795         for (i=0;i<numberOfScreens;i++) {
00796             screendata = screenInfoArray.at(i);
00797             if (!has_primary_monitor) {
00798                 if (screendata->screen_connected && screendata->is_extended) {
00799                     screendata->is_primary = true;
00800                     screendata->is_extended = true;
00801                     has_primary_monitor = true;
00802                 }
00803             }
00804         }
00805     }
00806     if (!has_primary_monitor) {
00807         for (i=0;i<numberOfScreens;i++) {
00808             screendata = screenInfoArray.at(i);
00809             if (!has_primary_monitor) {
00810                 if (screendata->screen_connected) {
00811                     screendata->is_primary = true;
00812                     screendata->is_extended = true;
00813                     has_primary_monitor = true;
00814                 }
00815             }
00816         }
00817     }
00818 
00819     bool found_first_primary_monitor = false;
00820     for (i=0;i<numberOfScreens;i++) {
00821         screendata = screenInfoArray.at(i);
00822         if (screendata->is_primary) {
00823             if (!found_first_primary_monitor) {
00824                 found_first_primary_monitor = true;
00825             }
00826             else {
00827                 screendata->is_primary = false;
00828             }
00829         }
00830     }
00831 
00832     for (i=0;i<numberOfScreens;i++) {
00833         screendata = screenInfoArray.at(i);
00834         if (screendata->is_primary) {
00835             screendata->is_extended = true;
00836         }
00837     }
00838 
00839     for (i=0;i<numberOfScreens;i++) {
00840         screendata = screenInfoArray.at(i);
00841         TQString resolutionstring = screendata->resolutions[screendata->current_resolution_index];
00842         int separator_pos = resolutionstring.find(" x ");
00843         TQString x_res_string = resolutionstring.left(separator_pos);
00844         TQString y_res_string = resolutionstring.right(resolutionstring.length()-separator_pos-3);
00845         screendata->current_x_pixel_count = x_res_string.toInt();
00846         screendata->current_y_pixel_count = y_res_string.toInt();
00847         screendata->current_orientation_mask = getHardwareRotationFlags(screendata);
00848     }
00849 
00850     // Each screen's absolute position is given relative to the primary monitor
00851     // Fix up the absolute positions
00852     int primary_offset_x = 0;
00853     int primary_offset_y = 0;
00854     for (i=0;i<numberOfScreens;i++) {
00855         screendata = screenInfoArray.at(i);
00856         if (screendata->is_primary) {
00857             primary_offset_x = screendata->absolute_x_position;
00858             primary_offset_y = screendata->absolute_y_position;
00859             primary_offset_x = primary_offset_x * (-1);
00860             primary_offset_y = primary_offset_y * (-1);
00861         }
00862     }
00863     for (i=0;i<numberOfScreens;i++) {
00864         screendata = screenInfoArray.at(i);
00865         screendata->absolute_x_position = screendata->absolute_x_position + primary_offset_x;
00866         screendata->absolute_y_position = screendata->absolute_y_position + primary_offset_y;
00867     }
00868 }
00869 
00870 TQPoint KRandrSimpleAPI::primaryScreenOffsetFromTLC(TQPtrList<SingleScreenData> screenInfoArray) {
00871     int i;
00872     SingleScreenData *screendata;
00873     int numberOfScreens = screenInfoArray.count();
00874 
00875     int primary_offset_x = 0;
00876     int primary_offset_y = 0;
00877     for (i=0;i<numberOfScreens;i++) {
00878         screendata = screenInfoArray.at(i);
00879         if (screendata->absolute_x_position < primary_offset_x) {
00880             primary_offset_x = screendata->absolute_x_position;
00881         }
00882         if (screendata->absolute_y_position < primary_offset_y) {
00883             primary_offset_y = screendata->absolute_y_position;
00884         }
00885     }
00886     primary_offset_x = primary_offset_x * (-1);
00887     primary_offset_y = primary_offset_y * (-1);
00888 
00889     return TQPoint(primary_offset_x, primary_offset_y);
00890 }
00891 
00892 void KRandrSimpleAPI::applySystemwideDisplayGamma(TQPtrList<SingleScreenData> screenInfoArray) {
00893     int i;
00894     Display *randr_display;
00895     XRROutputInfo *output_info;
00896     ScreenInfo *randr_screen_info;
00897     XRRCrtcGamma *gamma;
00898 
00899     SingleScreenData *screendata;
00900 
00901     if (isValid() == true) {
00902         randr_display = qt_xdisplay();
00903         randr_screen_info = read_screen_info(randr_display);
00904         for (i = 0; i < screenInfoArray.count(); i++) {
00905             screendata = screenInfoArray.at(i);
00906             output_info = randr_screen_info->outputs[i]->info;
00907             CrtcInfo *current_crtc = randr_screen_info->outputs[i]->cur_crtc;
00908             if (!current_crtc) {
00909                 continue;
00910             }
00911             // vvvvvvvvv This chunk of code is borrowed from xrandr vvvvvvvvvv
00912             int size = XRRGetCrtcGammaSize(randr_display, current_crtc->id);
00913             if (!size) {
00914                 continue;
00915             }
00916             gamma = XRRAllocGamma(size);
00917             if (!gamma) {
00918                 continue;
00919             }
00920             for (i = 0; i < size; i++) {
00921                 if (screendata->gamma_red == 1.0)
00922                     gamma->red[i] = i << 8;
00923                 else
00924                     gamma->red[i] = (pow((double)i/(double)(size-1), (double)screendata->gamma_red) * (double)(size-1)*256);
00925 
00926                 if (screendata->gamma_green == 1.0)
00927                     gamma->green[i] = i << 8;
00928                 else
00929                     gamma->green[i] = (pow((double)i/(double)(size-1), (double)screendata->gamma_green) * (double)(size-1)*256);
00930 
00931                 if (screendata->gamma_blue == 1.0)
00932                     gamma->blue[i] = i << 8;
00933                 else
00934                     gamma->blue[i] = (pow((double)i/(double)(size-1), (double)screendata->gamma_blue) * (double)(size-1)*256);
00935             }
00936             XRRSetCrtcGamma(randr_display, current_crtc->id, gamma);
00937             free(gamma);
00938             // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
00939         }
00940         freeScreenInfoStructure(randr_screen_info);
00941     }
00942 }
00943 
00944 void KRandrSimpleAPI::applySystemwideDisplayDPMS(TQPtrList<SingleScreenData> screenInfoArray) {
00945     int i;
00946     Display *randr_display;
00947     XRROutputInfo *output_info;
00948     ScreenInfo *randr_screen_info;
00949     XRRCrtcGamma *gamma;
00950 
00951     SingleScreenData *screendata;
00952 
00953     if (isValid() == true) {
00954         randr_display = qt_xdisplay();
00955         randr_screen_info = read_screen_info(randr_display);
00956         for (i = 0; i < screenInfoArray.count(); i++) {
00957             screendata = screenInfoArray.at(i);
00958             output_info = randr_screen_info->outputs[i]->info;
00959             CrtcInfo *current_crtc = randr_screen_info->outputs[i]->cur_crtc;
00960             if (!current_crtc) {
00961                 continue;
00962             }
00963             if (!screendata->has_dpms) {
00964                 continue;
00965             }
00966             if (screendata->enable_dpms) {
00967                 DPMSSetTimeouts(randr_display, screendata->dpms_standby_delay, screendata->dpms_suspend_delay, screendata->dpms_off_delay);
00968                 DPMSEnable(randr_display);
00969             }
00970             else {
00971                 DPMSDisable(randr_display);
00972             }
00973         }
00974         freeScreenInfoStructure(randr_screen_info);
00975     }
00976 }
00977 
00978 void KRandrSimpleAPI::freeScreenInfoStructure(ScreenInfo* screen_info) {
00979     int i;
00980 
00981     for (i=0; i<screen_info->n_crtc; i++) {
00982         free(screen_info->crtcs[i]);
00983     }
00984     for (i=0; i<screen_info->n_output; i++) {
00985         free(screen_info->outputs[i]);
00986     }
00987     free(screen_info->outputs);
00988     free(screen_info->crtcs);
00989     free(screen_info);
00990 }
00991 
00992 TQPtrList<SingleScreenData> KRandrSimpleAPI::readCurrentDisplayConfiguration() {
00993     // Discover display information
00994     int i;
00995     int j;
00996 
00997     XRROutputInfo *output_info;
00998     SingleScreenData *screendata;
00999     TQPtrList<SingleScreenData> screenInfoArray;
01000 
01001     Display *randr_display;
01002     ScreenInfo *randr_screen_info;
01003 
01004     // Clear existing info
01005     destroyScreenInformationObject(screenInfoArray);
01006 
01007     int numberOfScreens = 0;
01008     if (isValid() == true) {
01009         randr_display = qt_xdisplay();
01010         randr_screen_info = read_screen_info(randr_display);
01011         for (i = 0; i < randr_screen_info->n_output; i++) {
01012             output_info = randr_screen_info->outputs[i]->info;
01013             CrtcInfo *current_crtc = randr_screen_info->outputs[i]->cur_crtc;
01014 
01015             // Create new data object
01016             screendata = new SingleScreenData;
01017             screenInfoArray.append(screendata);
01018             screendata->screenFriendlyName = TQString(i18n("%1. %2 output on %3")).arg(i+1).arg(capitalizeString(output_info->name)).arg(":0"); // [FIXME] How can I get the name of the Xorg graphics driver currently in use?
01019             screendata->generic_screen_detected = false;
01020 
01021             // Attempt to use KMS to find screen EDID and name
01022             TQString edid = getEDIDMonitorName(0, output_info->name);   // [FIXME] Don't hardwire to card 0!
01023             if (!edid.isNull()) {
01024                 screendata->screenFriendlyName = TQString(i18n("%1. %2 on %3 on card %4")).arg(i+1).arg(edid).arg(capitalizeString(output_info->name)).arg("0");    // [FIXME] How can I get the name of the Xorg graphics driver currently in use?
01025             }
01026 
01027             // Get resolutions
01028             bool screen_active;
01029             RandRScreen *cur_screen = 0;
01030             if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
01031                 // Output DISCONNECTED
01032                 screen_active = false;
01033             }
01034             else {
01035                 if (randr_screen_info->outputs[i]->cur_crtc) {
01036                     // Output CONNECTED and ON
01037                     screen_active = true;
01038                     cur_screen = new RandRScreen(i);
01039                 }
01040                 else {
01041                     // Output CONNECTED and OFF
01042                     screen_active = false;
01043                     cur_screen = new RandRScreen(i);
01044                 }
01045             }
01046 
01047             // Get DPMS information
01048             screendata->has_dpms = 1;   // [FIXME] Master Xorg check for global DPMS support should go here if possible
01049             if (screendata->has_dpms) {
01050                 CARD16 dpms_standby_delay;
01051                 CARD16 dpms_suspend_delay;
01052                 CARD16 dpms_off_delay;
01053                 screendata->has_dpms = DPMSGetTimeouts(randr_display, &dpms_standby_delay, &dpms_suspend_delay, &dpms_off_delay);
01054                 screendata->dpms_standby_delay = dpms_standby_delay;
01055                 screendata->dpms_suspend_delay = dpms_suspend_delay;
01056                 screendata->dpms_off_delay = dpms_off_delay;
01057                 if (screendata->has_dpms) {
01058                     CARD16 power_level;
01059                     BOOL enable_dpms;
01060                     screendata->has_dpms = DPMSInfo(randr_display, &power_level, &enable_dpms);
01061                     screendata->enable_dpms = enable_dpms;
01062                 }
01063             }
01064             if (!screendata->has_dpms) {
01065                 screendata->enable_dpms = false;
01066                 screendata->dpms_standby_delay = 0;
01067                 screendata->dpms_suspend_delay = 0;
01068                 screendata->dpms_off_delay = 0;
01069             }
01070 
01071             if (cur_screen) {
01072                 screendata->screen_connected = true;
01073                 for (int j = 0; j < cur_screen->numSizes(); j++) {
01074                     screendata->resolutions.append(i18n("%1 x %2").arg(cur_screen->pixelSize(j).width()).arg(cur_screen->pixelSize(j).height()));
01075                 }
01076                 screendata->current_resolution_index = 0;
01077                 if (current_crtc) {
01078                     screendata->current_resolution_index = screendata->resolutions.findIndex(i18n("%1 x %2").arg(current_crtc->info->width).arg(current_crtc->info->height));
01079                 }
01080                 if (screendata->current_resolution_index < 0) {
01081                     screendata->current_resolution_index = cur_screen->proposedSize();
01082                 }
01083 
01084                 // Get refresh rates
01085                 TQStringList rr = cur_screen->refreshRates(screendata->current_resolution_index);
01086                 for (TQStringList::Iterator it = rr.begin(); it != rr.end(); ++it) {
01087                     screendata->refresh_rates.append(*it);
01088                 }
01089                 screendata->current_refresh_rate_index = cur_screen->proposedRefreshRate();
01090 
01091                 // Get color depths
01092                 // [FIXME]
01093                 screendata->color_depths.append(i18n("Default"));
01094                 screendata->current_color_depth_index = 0;
01095 
01096                 // Get orientation flags
01097                 // RandRScreen::Rotate0
01098                 // RandRScreen::Rotate90
01099                 // RandRScreen::Rotate180
01100                 // RandRScreen::Rotate270
01101                 // RandRScreen::ReflectX
01102                 // RandRScreen::ReflectY
01103 
01104                 screendata->rotations.append(i18n("Normal"));
01105                 screendata->rotations.append(i18n("Rotate 90 degrees"));
01106                 screendata->rotations.append(i18n("Rotate 180 degrees"));
01107                 screendata->rotations.append(i18n("Rotate 270 degrees"));
01108                 screendata->current_orientation_mask = cur_screen->proposedRotation();
01109                 switch (screendata->current_orientation_mask & RandRScreen::RotateMask) {
01110                     case RandRScreen::Rotate0:
01111                         screendata->current_rotation_index = 0;
01112                         break;
01113                     case RandRScreen::Rotate90:
01114                         screendata->current_rotation_index = 1;
01115                         break;
01116                     case RandRScreen::Rotate180:
01117                         screendata->current_rotation_index = 2;
01118                         break;
01119                     case RandRScreen::Rotate270:
01120                         screendata->current_rotation_index = 3;
01121                         break;
01122                     default:
01123                         // Shouldn't hit this one
01124                         Q_ASSERT(screendata->current_orientation_mask & RandRScreen::RotateMask);
01125                         break;
01126                 }
01127                 screendata->has_x_flip = (screendata->current_orientation_mask & RandRScreen::ReflectX);
01128                 screendata->has_y_flip = (screendata->current_orientation_mask & RandRScreen::ReflectY);
01129                 screendata->supports_transformations = (cur_screen->rotations() != RandRScreen::Rotate0);
01130 
01131                 // Determine if this display is primary and/or extended
01132                 RROutput primaryoutput = XRRGetOutputPrimary(qt_xdisplay(), DefaultRootWindow(qt_xdisplay()));
01133                 if (primaryoutput == randr_screen_info->outputs[i]->id)
01134                     screendata->is_primary = false;
01135                 else
01136                     screendata->is_primary = true;
01137                 screendata->is_extended = screen_active;
01138                 if (!screendata->is_extended)
01139                     screendata->is_primary = false;
01140 
01141                 // Get this screen's absolute position
01142                 screendata->absolute_x_position = 0;
01143                 screendata->absolute_y_position = 0;
01144                 if (current_crtc) {
01145                     screendata->absolute_x_position = current_crtc->info->x;
01146                     screendata->absolute_y_position = current_crtc->info->y;
01147                 }
01148 
01149                 // Get this screen's current resolution
01150                 screendata->current_x_pixel_count = cur_screen->pixelSize(screendata->current_resolution_index).width();
01151                 screendata->current_y_pixel_count = cur_screen->pixelSize(screendata->current_resolution_index).height();
01152 
01153                 // Get this screen's current gamma values
01154                 // [FIXME]
01155                 // This attempts to guess a gamma value based on the LUT settings at 50%
01156                 // It may not always be 100% correct, or even anywhere close...
01157                 // Essentially it "undoes" the LUT gamma calculation from xrandr
01158                 // lut_gamma->green[i] = (pow(i/(size - 1), desired_gamma.green) * (size - 1) * 256);
01159                 screendata->gamma_red = 2.2;
01160                 screendata->gamma_green = 2.2;
01161                 screendata->gamma_blue = 2.2;
01162                 if (current_crtc) {
01163                     //int slot = 127;
01164                     int slot = 7;
01165                     int size = XRRGetCrtcGammaSize(randr_display, current_crtc->id);
01166                     if(size>0) {
01167                         XRRCrtcGamma *gammastruct = XRRGetCrtcGamma (randr_display, current_crtc->id);
01168                         screendata->gamma_red = log(gammastruct->red[slot]/((size-1.0)*256.0))/log(slot/(size-1.0));
01169                         screendata->gamma_green = log(gammastruct->green[slot]/((size-1.0)*256.0))/log(slot/(size-1.0));
01170                         screendata->gamma_blue = log(gammastruct->blue[slot]/((size-1.0)*256.0))/log(slot/(size-1.0));
01171                     }
01172                 }
01173                 // Round off the gamma to one decimal place
01174                 screendata->gamma_red = floorf(screendata->gamma_red * 10 + 0.5) / 10;
01175                 screendata->gamma_green = floorf(screendata->gamma_green * 10 + 0.5) / 10;
01176                 screendata->gamma_blue = floorf(screendata->gamma_blue * 10 + 0.5) / 10;
01177 
01178                 delete cur_screen;
01179             }
01180             else {
01181                 // Fill in generic data for this disconnected output
01182                 screendata->screenFriendlyName = screendata->screenFriendlyName + TQString(" (") + i18n("disconnected") + TQString(")");
01183                 screendata->screen_connected = false;
01184 
01185                 screendata->resolutions = i18n("Default");
01186                 screendata->refresh_rates = i18n("Default");
01187                 screendata->color_depths = i18n("Default");
01188                 screendata->rotations = i18n("N/A");
01189 
01190                 screendata->current_resolution_index = 0;
01191                 screendata->current_refresh_rate_index = 0;
01192                 screendata->current_color_depth_index = 0;
01193 
01194                 screendata->gamma_red = 2.2;
01195                 screendata->gamma_green = 2.2;
01196                 screendata->gamma_blue = 2.2;
01197 
01198                 screendata->current_rotation_index = 0;
01199                 screendata->current_orientation_mask = 0;
01200                 screendata->has_x_flip = false;
01201                 screendata->has_y_flip = false;
01202                 screendata->supports_transformations = false;
01203 
01204                 screendata->is_primary = false;
01205                 screendata->is_extended = false;
01206                 screendata->absolute_x_position = 0;
01207                 screendata->absolute_y_position = 0;
01208                 screendata->current_x_pixel_count = 640;
01209                 screendata->current_y_pixel_count = 480;
01210             }
01211 
01212             // Check for more screens...
01213             numberOfScreens++;
01214         }
01215 
01216         freeScreenInfoStructure(randr_screen_info);
01217     }
01218     else {
01219         screendata = new SingleScreenData;
01220         screenInfoArray.append(screendata);
01221 
01222         // Fill in a bunch of generic data
01223         screendata->screenFriendlyName = i18n("Default output on generic video card");
01224         screendata->generic_screen_detected = true;
01225         screendata->screen_connected = true;
01226 
01227         screendata->resolutions = i18n("Default");
01228         screendata->refresh_rates = i18n("Default");
01229         screendata->color_depths = i18n("Default");
01230         screendata->rotations = i18n("N/A");
01231 
01232         screendata->current_resolution_index = 0;
01233         screendata->current_refresh_rate_index = 0;
01234         screendata->current_color_depth_index = 0;
01235 
01236         screendata->gamma_red = 2.2;
01237         screendata->gamma_green = 2.2;
01238         screendata->gamma_blue = 2.2;
01239 
01240         screendata->current_rotation_index = 0;
01241         screendata->current_orientation_mask = 0;
01242         screendata->has_x_flip = false;
01243         screendata->has_y_flip = false;
01244         screendata->supports_transformations = false;
01245 
01246         screendata->is_primary = true;
01247         screendata->is_extended = true;
01248         screendata->absolute_x_position = 0;
01249         screendata->absolute_y_position = 0;
01250         screendata->current_x_pixel_count = 640;
01251         screendata->current_y_pixel_count = 480;
01252 
01253         numberOfScreens++;
01254     }
01255 
01256     // [FIXME]
01257     // Set this on the real primary monitor only!
01258     screendata = screenInfoArray.at(0);
01259     screendata->is_primary = true;
01260 
01261     return screenInfoArray;
01262 }
01263 
01264 TQString KRandrSimpleAPI::clearIccConfiguration() {
01265     // Clear ICC settings with XCalib
01266     TQString icc_command;
01267     FILE *pipe_xcalib;
01268     char xcalib_result[2048];
01269     int i;
01270     xcalib_result[0]=0;
01271 
01272     icc_command = TQString("xcalib -c");
01273     if ((pipe_xcalib = popen(icc_command.ascii(), "r")) == NULL)
01274     {
01275         printf("Xcalib pipe error [xcalib clear]\n");
01276     }
01277     else {
01278         fgets(xcalib_result, 2048, pipe_xcalib);
01279         pclose(pipe_xcalib);
01280         for (i=1;i<2048;i++) {
01281             if (xcalib_result[i] == 0) {
01282                 xcalib_result[i-1]=0;
01283                 i=2048;
01284             }
01285         }
01286         if (strlen(xcalib_result) > 2) {
01287             return xcalib_result;
01288         }
01289     }
01290     return "";
01291 }
01292 
01293 ScreenInfo* KRandrSimpleAPI::read_screen_info (Display *display)
01294 {
01295     return internal_read_screen_info(display);
01296 }
01297 
01298 int KRandrSimpleAPI::set_screen_size (ScreenInfo *screen_info)
01299 {
01300     return internal_set_screen_size(screen_info);
01301 }
01302 
01303 void KRandrSimpleAPI::output_auto (ScreenInfo *screen_info, OutputInfo *output_info)
01304 {
01305     internal_output_auto (screen_info, output_info);
01306 }
01307 
01308 void KRandrSimpleAPI::output_off(ScreenInfo *screen_info, OutputInfo *output)
01309 {
01310     internal_output_off(screen_info, output);
01311 }
01312 
01313 CrtcInfo* KRandrSimpleAPI::auto_find_crtc (ScreenInfo *screen_info, OutputInfo *output_info)
01314 {
01315     return internal_auto_find_crtc (screen_info, output_info);
01316 }
01317 
01318 XRRModeInfo *KRandrSimpleAPI::find_mode_by_xid (ScreenInfo *screen_info, RRMode mode_id)
01319 {
01320     return internal_find_mode_by_xid (screen_info, mode_id);
01321 }
01322 
01323 int KRandrSimpleAPI::mode_height (XRRModeInfo *mode_info, Rotation rotation)
01324 {
01325     return internal_mode_height (mode_info, rotation);
01326 }
01327 
01328 int KRandrSimpleAPI::mode_width (XRRModeInfo *mode_info, Rotation rotation)
01329 {
01330     return internal_mode_width (mode_info, rotation);
01331 }
01332 
01333 int KRandrSimpleAPI::get_width_by_output_id (ScreenInfo *screen_info, RROutput output_id)
01334 {
01335     return internal_get_width_by_output_id (screen_info, output_id);
01336 }
01337 
01338 int KRandrSimpleAPI::get_height_by_output_id (ScreenInfo *screen_info, RROutput output_id)
01339 {
01340     return internal_get_height_by_output_id (screen_info, output_id);
01341 }
01342 
01343 char *KRandrSimpleAPI::get_output_name (ScreenInfo *screen_info, RROutput id)
01344 {
01345     return internal_get_output_name (screen_info, id);
01346 }
01347 
01348 Status KRandrSimpleAPI::crtc_apply (CrtcInfo *crtc_info)
01349 {
01350     return internal_crtc_apply (crtc_info);
01351 }
01352 
01353 Status KRandrSimpleAPI::crtc_disable (CrtcInfo *crtc)
01354 {
01355     return internal_crtc_disable (crtc);
01356 }
01357 
01358 int KRandrSimpleAPI::main_low_apply (ScreenInfo *screen_info)
01359 {
01360     return internal_main_low_apply (screen_info);
01361 }
01362 
01363 bool KRandrSimpleAPI::kRandrHasRandr(void)
01364 {
01365     return isValid();
01366 }
01367 
01368 const char *KRandrSimpleAPI::kRandrVersion(void)
01369 {
01370     return "0.9.5";
01371 }
01372 
01373 const char *KRandrSimpleAPI::kRandrCopyright(void)
01374 {
01375    return "LibKRandr 0.9.5 (C)2010 Timothy Pearson <kb9vqf@pearsoncomputing.net>. U.S.A.";
01376 }
01377 
01378 /* * * * * *
01379 
01380  Under this line (------) there's only a C wrapper for the KRandrSimpleAPI class
01381 
01382 * * * * * */
01383 const char *kRandrVersion(void)
01384 {
01385   return KRandrSimpleAPI::kRandrVersion();
01386 }
01387 
01388 const char *kRandrCopyright(void)
01389 {
01390   return KRandrSimpleAPI::kRandrCopyright();
01391 }
01392 

krandr

Skip menu "krandr"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

krandr

Skip menu "krandr"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for krandr by doxygen 1.7.6.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |