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

tderandr

  • tderandr
libtderandr.cpp
1/* libtderandr.cpp - class KRandr that makes it easy to use XRandr in KDE
2 This file is part of KRandr 0.9.5
3 Copyright (C) 2010 Timothy Pearson
4 LibKRandr's homepage : http://www.trinitydesktop.org
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20
21 Send comments and bug fixes to Timothy Pearson <kb9vqf@pearsoncomputing.net>
22
23***************************************************************************/
24
25#include <tqdir.h>
26#include <tqtimer.h>
27#include <tqstringlist.h>
28#include <tqregexp.h>
29
30#include <tdelocale.h>
31#include <tdemessagebox.h>
32#include <tdeapplication.h>
33
34#include <stdlib.h>
35#include <unistd.h>
36#include <cmath>
37
38#include "libtderandr.h"
39
40#include <X11/extensions/dpms.h>
41
42// FIXME
43// For now, just use the standalone xrandr program to apply the display settings
44#define USE_XRANDR_PROGRAM
45
46// This routine is courtsey of an answer on "Stack Overflow"
47// It takes an LSB-first int and makes it an MSB-first int (or vice versa)
48unsigned int reverse_bits(unsigned int x)
49{
50 x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
51 x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
52 x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
53 x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
54 return((x >> 16) | (x << 16));
55}
56
57// This routine returns the output of an arbitrary Bash command
58TQString exec(const char * cmd) {
59 TQString bashcommand = cmd;
60 bashcommand = bashcommand.replace("\"", "\\\"");
61 bashcommand = TQString("/bin/bash -c \"%1\" 2>&1").arg(bashcommand);
62 FILE* pipe = popen(bashcommand.ascii(), "r");
63 if (!pipe) return "ERROR";
64 char buffer[128];
65 TQString result = "";
66 while(!feof(pipe)) {
67 if(fgets(buffer, 128, pipe) != NULL) {
68 result += buffer;
69 }
70 }
71 pclose(pipe);
72 result.remove(result.length(), 1);
73 return result;
74}
75
76TQString capitalizeString(TQString in) {
77 return in.left(1).upper() + in.right(in.length()-1);
78}
79
80TQString KRandrSimpleAPI::getIccFileName(TQString profileName, TQString screenName, TQString kde_confdir) {
81 KSimpleConfig *t_config = NULL;
82 KSimpleConfig *t_systemconfig = NULL;
83 int t_numberOfProfiles;
84 TQStringList t_cfgProfiles;
85 TQString retval;
86
87 if ((profileName != NULL) && (profileName != "")) {
88 t_config = new KSimpleConfig( TQString::fromLatin1( "kiccconfigrc" ));
89 t_config->setGroup(NULL);
90 if (t_config->readBoolEntry("EnableICC", false) == true) {
91 t_config->setGroup(profileName);
92 retval = t_config->readEntry(screenName);
93 }
94 else {
95 retval = "";
96 }
97 delete t_config;
98 }
99 else {
100 t_systemconfig = new KSimpleConfig( kde_confdir + TQString("/kicc/kiccconfigrc") );
101 t_systemconfig->setGroup(NULL);
102 if (t_systemconfig->readBoolEntry("EnableICC", false) == true) {
103 retval = t_systemconfig->readEntry("ICCFile");
104 }
105 else {
106 retval = "";
107 }
108 delete t_systemconfig;
109 }
110
111 return retval;
112}
113
114TQString KRandrSimpleAPI::applyIccFile(TQString screenName, TQString fileName) {
115 int i;
116 int j;
117 Display *randr_display;
118 ScreenInfo *randr_screen_info;
119 XRROutputInfo *output_info;
120
121 int screenNumber = 0;
122
123 if (fileName != "") {
124 // FIXME
125 // This should use the RRSetCrtcGamma function when available
126 // That is the only way to get proper setting when two output are active at the same time
127 // (otherwise in clone mode only one screen is available)
128
129 // HACK
130 // For now, simply exit with no changes if screenName is not an active output
131
132 if (isValid() == true) {
133 screenNumber = -1;
134 randr_display = tqt_xdisplay();
135 randr_screen_info = read_screen_info(randr_display);
136 if (randr_screen_info == NULL) {
137 return "";
138 }
139 j=0;
140 for (i = 0; i < randr_screen_info->n_output; i++) {
141 output_info = randr_screen_info->outputs[i]->info;
142 // Look for ON outputs...
143 if (!randr_screen_info->outputs[i]->cur_crtc) {
144 continue;
145 }
146 // ...that are connected
147 if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
148 continue;
149 }
150 if (output_info->name == screenName) {
151 screenNumber = j;
152 }
153 j++;
154 }
155 freeScreenInfoStructure(randr_screen_info);
156 }
157
158 if (screenNumber >= 0) {
159 // Apply ICC settings with XCalib
160 TQString icc_command;
161 FILE *pipe_xcalib;
162 char xcalib_result[2048];
163 int i;
164 xcalib_result[0]=0;
165
166 icc_command = TQString("xcalib \"%1\"").arg(fileName);
167 if ((pipe_xcalib = popen(icc_command.ascii(), "r")) == NULL)
168 {
169 printf("Xcalib pipe error\n [xcalib apply]");
170 }
171 else {
172 if (fgets(xcalib_result, 2048, pipe_xcalib)) {
173 pclose(pipe_xcalib);
174 for (i=1;i<2048;i++) {
175 if (xcalib_result[i] == 0) {
176 xcalib_result[i-1]=0;
177 i=2048;
178 }
179 }
180 if (strlen(xcalib_result) > 2) {
181 return xcalib_result;
182 }
183 }
184 else {
185 return "";
186 }
187 }
188 }
189 }
190 else {
191 // Reset ICC profile on this screen
192
193 // FIXME
194 // This should use the RRSetCrtcGamma function when available
195 // That is the only way to get proper setting when two output are active at the same time
196 // (otherwise in clone mode only one screen is available)
197
198 // HACK
199 // For now, simply exit with no changes if screenName is not an active output
200
201 if (isValid() == true) {
202 screenNumber = -1;
203 randr_display = tqt_xdisplay();
204 randr_screen_info = read_screen_info(randr_display);
205 if (randr_screen_info == NULL) {
206 return "";
207 }
208 j=0;
209 for (i = 0; i < randr_screen_info->n_output; i++) {
210 output_info = randr_screen_info->outputs[i]->info;
211 // Look for ON outputs...
212 if (!randr_screen_info->outputs[i]->cur_crtc) {
213 continue;
214 }
215 // ...that are connected
216 if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
217 continue;
218 }
219 if (output_info->name == screenName) {
220 screenNumber = j;
221 }
222 j++;
223 }
224 freeScreenInfoStructure(randr_screen_info);
225 }
226
227 if (screenNumber >= 0) {
228 // Apply ICC settings with XCalib
229 TQString icc_command;
230 FILE *pipe_xcalib;
231 char xcalib_result[2048];
232 int i;
233 xcalib_result[0]=0;
234
235 icc_command = TQString("xcalib -c");
236 if ((pipe_xcalib = popen(icc_command.ascii(), "r")) == NULL)
237 {
238 printf("Xcalib pipe error\n [xcalib clear]");
239 }
240 else {
241 if (fgets(xcalib_result, 2048, pipe_xcalib)) {
242 pclose(pipe_xcalib);
243 for (i=1;i<2048;i++) {
244 if (xcalib_result[i] == 0) {
245 xcalib_result[i-1]=0;
246 i=2048;
247 }
248 }
249 if (strlen(xcalib_result) > 2) {
250 return xcalib_result;
251 }
252 }
253 else {
254 return "";
255 }
256 }
257 }
258 }
259 return "";
260}
261
262TQString KRandrSimpleAPI::applyIccConfiguration(TQString profileName, TQString kde_confdir) {
263 int i;
264 Display *randr_display;
265 ScreenInfo *randr_screen_info;
266 XRROutputInfo *output_info;
267 KSimpleConfig *t_config;
268
269 int screenNumber = 0;
270 TQString errorstr = "";
271
272 t_config = new KSimpleConfig( TQString::fromLatin1( "kiccconfigrc" ));
273
274 // Find all screens
275 if (isValid() == true) {
276 randr_display = tqt_xdisplay();
277 randr_screen_info = read_screen_info(randr_display);
278 if (randr_screen_info == NULL) {
279 return "";
280 }
281 for (i = 0; i < randr_screen_info->n_output; i++) {
282 output_info = randr_screen_info->outputs[i]->info;
283 errorstr = applyIccFile(output_info->name, getIccFileName(profileName, output_info->name, kde_confdir));
284 if (errorstr != "") {
285 return errorstr;
286 }
287 }
288 freeScreenInfoStructure(randr_screen_info);
289 }
290 else {
291 return applyIccFile(getIccFileName(profileName, "Default", kde_confdir), "Default");
292 }
293
294 t_config->writeEntry("CurrentProfile", profileName);
295 t_config->sync();
296 delete t_config;
297
298 return "";
299}
300
301TQString KRandrSimpleAPI::getEDIDMonitorName(int card, TQString displayname) {
302 TQString edid;
303 TQByteArray binaryedid = getEDID(card, displayname);
304 if (binaryedid.isNull())
305 return TQString();
306
307 // Get the manufacturer ID
308 unsigned char letter_1 = ((binaryedid[8]>>2) & 0x1F) + 0x40;
309 unsigned char letter_2 = (((binaryedid[8] & 0x03) << 3) | ((binaryedid[9]>>5) & 0x07)) + 0x40;
310 unsigned char letter_3 = (binaryedid[9] & 0x1F) + 0x40;
311 TQChar qletter_1 = TQChar(letter_1);
312 TQChar qletter_2 = TQChar(letter_2);
313 TQChar qletter_3 = TQChar(letter_3);
314 TQString manufacturer_id = TQString("%1%2%3").arg(qletter_1).arg(qletter_2).arg(qletter_3);
315
316 // Get the model ID
317 unsigned int raw_model_id = (((binaryedid[10] << 8) | binaryedid[11]) << 16) & 0xFFFF0000;
318 // Reverse the bit order
319 unsigned int model_id = reverse_bits(raw_model_id);
320
321 // Try to get the model name
322 bool has_friendly_name = false;
323 unsigned char descriptor_block[18];
324 int i;
325 for (i=72;i<90;i++) {
326 descriptor_block[i-72] = binaryedid[i] & 0xFF;
327 }
328 if ((descriptor_block[0] != 0) || (descriptor_block[1] != 0) || (descriptor_block[3] != 0xFC)) {
329 for (i=90;i<108;i++) {
330 descriptor_block[i-90] = binaryedid[i] & 0xFF;
331 }
332 if ((descriptor_block[0] != 0) || (descriptor_block[1] != 0) || (descriptor_block[3] != 0xFC)) {
333 for (i=108;i<126;i++) {
334 descriptor_block[i-108] = binaryedid[i] & 0xFF;
335 }
336 }
337 }
338
339 TQString monitor_name;
340 if ((descriptor_block[0] == 0) && (descriptor_block[1] == 0) && (descriptor_block[3] == 0xFC)) {
341 char* pos = strchr((char *)(descriptor_block+5), '\n');
342 if (pos) {
343 *pos = 0;
344 has_friendly_name = true;
345 monitor_name = TQString((char *)(descriptor_block+5));
346 }
347 else {
348 has_friendly_name = false;
349 }
350 }
351
352 // [FIXME]
353 // Look up manudacturer names if possible!
354
355 if (has_friendly_name)
356 edid = TQString("%1 %2").arg(manufacturer_id).arg(monitor_name);
357 else
358 edid = TQString("%1 0x%2").arg(manufacturer_id).arg(model_id, 0, 16);
359
360 return edid;
361}
362
363TQByteArray KRandrSimpleAPI::getEDID(int card, TQString displayname) {
364 TQFile file(TQString("/sys/class/drm/card%1-%2/edid").arg(card).arg(displayname));
365 if (!file.open (IO_ReadOnly))
366 return TQByteArray();
367 TQByteArray binaryedid = file.readAll();
368 file.close();
369 return binaryedid;
370}
371
372TQString KRandrSimpleAPI::getCurrentProfile () {
373 TQString profileName;
374 KSimpleConfig *t_config;
375
376 t_config = new KSimpleConfig( TQString::fromLatin1( "kiccconfigrc" ));
377 profileName = t_config->readEntry("CurrentProfile");
378 delete t_config;
379 return profileName;
380}
381
382TQString KRandrSimpleAPI::applySystemWideIccConfiguration(TQString kde_confdir) {
383 // Apply ICC settings with XCalib
384 TQString icc_command;
385 FILE *pipe_xcalib;
386 char xcalib_result[2048];
387 int i;
388 xcalib_result[0]=0;
389
390 icc_command = TQString("xcalib \"%1\"").arg(getIccFileName(NULL, "Default", kde_confdir));
391 if ((pipe_xcalib = popen(icc_command.ascii(), "r")) == NULL)
392 {
393 printf("Xcalib pipe error [xcalib apply]\n");
394 }
395 else {
396 if (fgets(xcalib_result, 2048, pipe_xcalib)) {
397 pclose(pipe_xcalib);
398 for (i=1;i<2048;i++) {
399 if (xcalib_result[i] == 0) {
400 xcalib_result[i-1]=0;
401 i=2048;
402 }
403 }
404 if (strlen(xcalib_result) > 2) {
405 return xcalib_result;
406 }
407 }
408 else {
409 return "";
410 }
411 }
412 return "";
413}
414
415TQStringList KRandrSimpleAPI::getDisplayConfigurationProfiles(TQString kde_confdir) {
416 TQStringList ret;
417
418 TQDir d(kde_confdir + "/displayconfig/");
419 d.setFilter(TQDir::Files);
420 d.setSorting(TQDir::Name);
421
422 const TQFileInfoList *list = d.entryInfoList();
423 if (list) {
424 TQFileInfoListIterator it(*list);
425 TQFileInfo *fi;
426
427 while ((fi = it.current()) != 0) {
428 if (fi->fileName() != "default") {
429 ret.append(fi->fileName());
430 }
431 ++it;
432 }
433 }
434
435 return ret;
436}
437
438bool KRandrSimpleAPI::deleteDisplayConfiguration(TQString profilename, TQString kde_confdir) {
439 TQString fileName = kde_confdir + "/displayconfig/";
440 fileName.append(profilename);
441 return (!unlink(fileName.ascii()));
442}
443
444bool KRandrSimpleAPI::renameDisplayConfiguration(TQString profilename, TQString newprofilename, TQString kde_confdir) {
445 TQString fileName = kde_confdir + "/displayconfig/";
446 TQString newFileName = fileName;
447 fileName.append(profilename);
448 newFileName.append(newprofilename);
449 TQDir d(kde_confdir + "/displayconfig/");
450 return (d.rename(fileName, newFileName));
451}
452
453void KRandrSimpleAPI::saveDisplayConfiguration(bool enable, bool applyonstart, TQString profilename, TQString defaultprofilename, TQString kde_confdir, TQPtrList<SingleScreenData> screenInfoArray) {
454 int i;
455
456 TQString filename;
457
458 filename = "displayglobals";
459 filename.prepend(kde_confdir.append("/"));
460 KSimpleConfig* display_config = new KSimpleConfig( filename );
461 display_config->setGroup("General");
462 display_config->writeEntry("EnableDisplayControl", enable);
463 display_config->writeEntry("ApplySettingsOnStart", applyonstart);
464 display_config->writeEntry("StartupProfileName", defaultprofilename);
465 display_config->sync();
466 delete display_config;
467
468 filename = profilename;
469 if (filename == "") {
470 filename = "default";
471 }
472 filename.prepend(kde_confdir.append("/displayconfig/"));
473
474 display_config = new KSimpleConfig( filename );
475
476 i=0;
477 SingleScreenData *screendata;
478 for ( screendata=screenInfoArray.first(); screendata; screendata=screenInfoArray.next() ) {
479 display_config->setGroup(TQString("SCREEN %1").arg(i));
480 display_config->writeEntry("ScreenUniqueName", screendata->screenUniqueName);
481 display_config->writeEntry("ScreenFriendlyName", screendata->screenFriendlyName);
482 display_config->writeEntry("GenericScreenDetected", screendata->generic_screen_detected);
483 display_config->writeEntry("ScreenConnected", screendata->screen_connected);
484 display_config->writeEntry("Resolutions", screendata->resolutions);
485 display_config->writeEntry("RefreshRates", screendata->refresh_rates);
486 display_config->writeEntry("ColorDepths", screendata->color_depths);
487 display_config->writeEntry("AvailableRotations", screendata->rotations);
488 display_config->writeEntry("CurrentResolution", screendata->current_resolution_index);
489 display_config->writeEntry("CurrentRefreshRate", screendata->current_refresh_rate_index);
490 display_config->writeEntry("CurrentColorDepth", screendata->current_color_depth_index);
491 display_config->writeEntry("CurrentRotation", screendata->current_rotation_index);
492 display_config->writeEntry("CurrentOrientiation", screendata->current_orientation_mask);
493 display_config->writeEntry("GammaRed", screendata->gamma_red);
494 display_config->writeEntry("GammaGreen", screendata->gamma_green);
495 display_config->writeEntry("GammaBlue", screendata->gamma_blue);
496 display_config->writeEntry("CurrentXFlip", screendata->has_x_flip);
497 display_config->writeEntry("CurrentYFlip", screendata->has_y_flip);
498 display_config->writeEntry("SupportsTransformation", screendata->supports_transformations);
499 display_config->writeEntry("IsPrimary", screendata->is_primary);
500 display_config->writeEntry("IsExtended", screendata->is_extended);
501 display_config->writeEntry("AbsXPos", screendata->absolute_x_position);
502 display_config->writeEntry("AbsYPos", screendata->absolute_y_position);
503 display_config->writeEntry("CurrentXPixelCount", screendata->current_x_pixel_count);
504 display_config->writeEntry("CurrentYPixelCount", screendata->current_y_pixel_count);
505 display_config->writeEntry("HasDPMS", screendata->has_dpms);
506 display_config->writeEntry("EnableDPMS", screendata->enable_dpms);
507 display_config->writeEntry("DPMSStandbyDelay", screendata->dpms_standby_delay);
508 display_config->writeEntry("DPMSSuspendDelay", screendata->dpms_suspend_delay);
509 display_config->writeEntry("DPMSPowerDownDelay", screendata->dpms_off_delay);
510 i++;
511 }
512
513 display_config->sync();
514 delete display_config;
515}
516
517TQPoint KRandrSimpleAPI::applyStartupDisplayConfiguration(TQString kde_confdir) {
518 bool applyonstart = getDisplayConfigurationStartupAutoApplyEnabled(kde_confdir);
519 if (applyonstart) {
520 TQString profilename = getDisplayConfigurationStartupAutoApplyName(kde_confdir);
521 return applyDisplayConfiguration(profilename, kde_confdir);
522 }
523 else {
524 return TQPoint();
525 }
526}
527
528TQPoint KRandrSimpleAPI::applyDisplayConfiguration(TQString profilename, TQString kde_confdir) {
529 TQPoint ret;
530
531 bool enabled = getDisplayConfigurationEnabled(kde_confdir);
532 if (profilename == "") {
533 profilename = "default";
534 }
535
536 if (enabled) {
537 TQPtrList<SingleScreenData> screenInfoArray;
538 screenInfoArray = loadDisplayConfiguration(profilename, kde_confdir);
539 if (screenInfoArray.count() > 0) {
540 applyDisplayConfiguration(screenInfoArray, FALSE, kde_confdir);
541 }
542 destroyScreenInformationObject(screenInfoArray);
543 screenInfoArray = readCurrentDisplayConfiguration();
544 ensureMonitorDataConsistency(screenInfoArray);
545 ret = primaryScreenOffsetFromTLC(screenInfoArray);
546 destroyScreenInformationObject(screenInfoArray);
547 }
548
549 return ret;
550}
551
552TQPtrList<SingleScreenData> KRandrSimpleAPI::loadDisplayConfiguration(TQString profilename, TQString kde_confdir) {
553 int i;
554
555 TQString filename;
556 filename = profilename;
557 if (filename == "") {
558 filename = "default";
559 }
560 filename.prepend(kde_confdir.append("/displayconfig/"));
561
562 KSimpleConfig* display_config = new KSimpleConfig( filename );
563
564 TQStringList grouplist = display_config->groupList();
565 SingleScreenData *screendata;
566 TQPtrList<SingleScreenData> screenInfoArray;
567 for ( TQStringList::Iterator it = grouplist.begin(); it != grouplist.end(); ++it ) {
568 if ((*it).startsWith("SCREEN ")) {
569 display_config->setGroup(*it);
570 i = ((*it).remove("SCREEN ")).toInt();
571 screendata = new SingleScreenData;
572 screenInfoArray.append(screendata);
573 screendata->screenUniqueName = display_config->readEntry("ScreenUniqueName");
574 screendata->screenFriendlyName = display_config->readEntry("ScreenFriendlyName");
575 screendata->generic_screen_detected = display_config->readBoolEntry("GenericScreenDetected");
576 screendata->screen_connected = display_config->readBoolEntry("ScreenConnected");
577 screendata->resolutions = display_config->readListEntry("Resolutions");
578 screendata->refresh_rates = display_config->readListEntry("RefreshRates");
579 screendata->color_depths = display_config->readListEntry("ColorDepths");
580 screendata->rotations = display_config->readListEntry("AvailableRotations");
581 screendata->current_resolution_index = display_config->readNumEntry("CurrentResolution");
582 screendata->current_refresh_rate_index = display_config->readNumEntry("CurrentRefreshRate");
583 screendata->current_color_depth_index = display_config->readNumEntry("CurrentColorDepth");
584 screendata->current_rotation_index = display_config->readNumEntry("CurrentRotation");
585 screendata->current_orientation_mask = display_config->readNumEntry("CurrentOrientiation");
586 screendata->gamma_red = display_config->readDoubleNumEntry("GammaRed");
587 screendata->gamma_green = display_config->readDoubleNumEntry("GammaGreen");
588 screendata->gamma_blue = display_config->readDoubleNumEntry("GammaBlue");
589 screendata->has_x_flip = display_config->readBoolEntry("CurrentXFlip");
590 screendata->has_y_flip = display_config->readBoolEntry("CurrentYFlip");
591 screendata->supports_transformations = display_config->readBoolEntry("SupportsTransformation");
592 screendata->is_primary = display_config->readBoolEntry("IsPrimary");
593 screendata->is_extended = display_config->readBoolEntry("IsExtended");
594 screendata->absolute_x_position = display_config->readNumEntry("AbsXPos");
595 screendata->absolute_y_position = display_config->readNumEntry("AbsYPos");
596 screendata->current_x_pixel_count = display_config->readNumEntry("CurrentXPixelCount");
597 screendata->current_y_pixel_count = display_config->readNumEntry("CurrentYPixelCount");
598 screendata->has_dpms = display_config->readBoolEntry("HasDPMS");
599 screendata->enable_dpms = display_config->readBoolEntry("EnableDPMS");
600 screendata->dpms_standby_delay = display_config->readNumEntry("DPMSStandbyDelay");
601 screendata->dpms_suspend_delay = display_config->readNumEntry("DPMSSuspendDelay");
602 screendata->dpms_off_delay = display_config->readNumEntry("DPMSPowerDownDelay");
603 }
604 }
605
606 delete display_config;
607
608 return screenInfoArray;
609}
610
611int KRandrSimpleAPI::getHardwareRotationFlags(SingleScreenData* screendata) {
612 int rotationFlags = 0;
613 if (screendata->current_rotation_index == ROTATION_0_DEGREES_INDEX) {
614 rotationFlags = rotationFlags | RandRScreen::Rotate0;
615 }
616 else if (screendata->current_rotation_index == ROTATION_90_DEGREES_INDEX) {
617 rotationFlags = rotationFlags | RandRScreen::Rotate90;
618 }
619 else if (screendata->current_rotation_index == ROTATION_180_DEGREES_INDEX) {
620 rotationFlags = rotationFlags | RandRScreen::Rotate180;
621 }
622 else if (screendata->current_rotation_index == ROTATION_270_DEGREES_INDEX) {
623 rotationFlags = rotationFlags | RandRScreen::Rotate270;
624 }
625 if (screendata->has_x_flip) {
626 rotationFlags = rotationFlags | RandRScreen::ReflectX;
627 }
628 if (screendata->has_y_flip) {
629 rotationFlags = rotationFlags | RandRScreen::ReflectY;
630 }
631 return rotationFlags;
632}
633
634#define USE_XRANDR_PROGRAM
635
636bool KRandrSimpleAPI::applyDisplayConfiguration(TQPtrList<SingleScreenData> screenInfoArray, bool test, TQString kde_confdir) {
637 int i;
638 int j;
639 bool accepted = true;
640 Display *randr_display;
641 XRROutputInfo *output_info;
642 ScreenInfo *randr_screen_info;
643
644 SingleScreenData *screendata;
645
646 TQPtrList<SingleScreenData> oldconfig;
647 if (test == TRUE) {
648 oldconfig = readCurrentDisplayConfiguration();
649 }
650
651 if (isValid() == true) {
652#ifdef USE_XRANDR_PROGRAM
653 // Assemble the command string for xrandr
654 TQString command;
655 command = "xrandr";
656
657 randr_display = tqt_xdisplay();
658 randr_screen_info = read_screen_info(randr_display);
659 for (i = 0; i < screenInfoArray.count(); i++) {
660 screendata = screenInfoArray.at(i);
661 if (screendata) {
662 output_info = randr_screen_info->outputs[i]->info;
663 command.append(" --output ").append(output_info->name);
664 if (screendata->is_primary || screendata->is_extended) {
665 command.append(TQString(" --mode %1x%2").arg(screendata->current_x_pixel_count).arg(screendata->current_y_pixel_count));
666 command.append(TQString(" --pos %1x%2").arg(screendata->absolute_x_position).arg(screendata->absolute_y_position));
667 command.append(TQString(" --refresh %1").arg(atoi((*screendata->refresh_rates.at(screendata->current_refresh_rate_index)).ascii())));
668 command.append(TQString(" --gamma %1:%2:%3").arg(screendata->gamma_red).arg(screendata->gamma_green).arg(screendata->gamma_blue));
669 if (screendata->current_rotation_index == ROTATION_0_DEGREES_INDEX) command.append(" --rotate ").append("normal");
670 if (screendata->current_rotation_index == ROTATION_90_DEGREES_INDEX) command.append(" --rotate ").append("left");
671 if (screendata->current_rotation_index == ROTATION_180_DEGREES_INDEX) command.append(" --rotate ").append("inverted");
672 if (screendata->current_rotation_index == ROTATION_270_DEGREES_INDEX) command.append(" --rotate ").append("right");
673 if ((screendata->has_x_flip == 0) && (screendata->has_y_flip == 0)) command.append(" --reflect ").append("normal");
674 if ((screendata->has_x_flip == 1) && (screendata->has_y_flip == 0)) command.append(" --reflect ").append("x");
675 if ((screendata->has_x_flip == 0) && (screendata->has_y_flip == 1)) command.append(" --reflect ").append("y");
676 if ((screendata->has_x_flip == 1) && (screendata->has_y_flip == 1)) command.append(" --reflect ").append("xy");
677 if (screendata->is_primary) {
678 command.append(" --primary");
679 }
680 }
681 else {
682 command.append(" --off");
683 }
684 }
685 else {
686 printf("[WARNING] Unable to find configuration for monitor %d; settings may not be correctly applied...\n", i); fflush(stdout);
687 }
688 }
689 freeScreenInfoStructure(randr_screen_info);
690
691 TQString xrandr_command_output = exec(command.ascii());
692 xrandr_command_output = xrandr_command_output.stripWhiteSpace();
693 if (test) {
694 // In case gamma settings is not supported, try again without '--gamma' parameter
695 if (xrandr_command_output == "xrandr: Gamma size is 0.") {
696 command = command.replace(TQRegExp("--gamma [0-9\\.]*:[0-9\\.]*:[0-9\\.]*"), "");
697 xrandr_command_output = exec(command.ascii());
698 xrandr_command_output = xrandr_command_output.stripWhiteSpace();
699 }
700
701 if(xrandr_command_output.startsWith("xrandr: Failed to get size of gamma for output")) {
702 KMessageBox::sorry(0, xrandr_command_output, i18n("Setting gamma failed."));
703 } else if (xrandr_command_output != "") {
704 applyDisplayConfiguration(oldconfig, FALSE, kde_confdir);
705 accepted = false;
706 destroyScreenInformationObject(oldconfig);
707 KMessageBox::sorry(0, xrandr_command_output, i18n("XRandR encountered a problem"));
708 return accepted;
709 }
710 }
711#else
712 randr_display = tqt_xdisplay();
713 randr_screen_info = read_screen_info(randr_display);
714 // Turn off all displays
715 for (i = 0; i < screenInfoArray.count(); i++) {
716 screendata = screenInfoArray.at(i);
717 output_info = randr_screen_info->outputs[i]->info;
718
719 randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
720 randr_screen_info->cur_output = randr_screen_info->outputs[i];
721 randr_screen_info->cur_output->auto_set = 0;
722 randr_screen_info->cur_output->off_set = 1;
723 output_off (randr_screen_info, randr_screen_info->cur_output);
724 j=main_low_apply(randr_screen_info);
725 }
726 freeScreenInfoStructure(randr_screen_info);
727 randr_screen_info = read_screen_info(randr_display);
728 // Turn on the primary display
729 for (i = 0; i < screenInfoArray.count(); i++) {
730 screendata = screenInfoArray.at(i);
731 output_info = randr_screen_info->outputs[i]->info;
732
733 if (screendata->is_primary == true) {
734 randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
735 randr_screen_info->cur_output = randr_screen_info->outputs[i];
736 randr_screen_info->cur_output->auto_set = 1;
737 randr_screen_info->cur_output->off_set = 0;
738 output_auto (randr_screen_info, randr_screen_info->cur_output);
739 j=main_low_apply(randr_screen_info);
740 }
741 }
742 freeScreenInfoStructure(randr_screen_info);
743 // Handle the remaining displays
744 randr_screen_info = read_screen_info(randr_display);
745 for (i = 0; i < screenInfoArray.count(); i++) {
746 screendata = screenInfoArray.at(i);
747 output_info = randr_screen_info->outputs[i]->info;
748
749 // Activate or deactivate the screens as necessary
750 randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
751 randr_screen_info->cur_output = randr_screen_info->outputs[i];
752 if (screendata->is_primary == false) {
753 if (screendata->is_primary || screendata->is_extended) {
754 randr_screen_info->cur_output->auto_set = 1;
755 randr_screen_info->cur_output->off_set = 0;
756 output_auto (randr_screen_info, randr_screen_info->cur_output);
757 j=main_low_apply(randr_screen_info);
758 }
759 else {
760 randr_screen_info->cur_output->auto_set = 0;
761 randr_screen_info->cur_output->off_set = 1;
762 output_off (randr_screen_info, randr_screen_info->cur_output);
763 j=main_low_apply(randr_screen_info);
764 }
765 }
766 }
767 freeScreenInfoStructure(randr_screen_info);
768 randr_screen_info = read_screen_info(randr_display);
769 for (i = 0; i < screenInfoArray.count(); i++) {
770 screendata = screenInfoArray.at(i);
771 output_info = randr_screen_info->outputs[i]->info;
772
773 if (screendata->is_primary || screendata->is_extended) {
774 // Set rotation, refresh rate, and size
775 RandRScreen *cur_screen = new RandRScreen(i);
776 cur_screen->proposeSize(screendata->current_resolution_index);
777 cur_screen->proposeRefreshRate(screendata->current_refresh_rate_index);
778 cur_screen->proposeRotation(getHardwareRotationFlags(screendata));
779 cur_screen->applyProposed();
780 delete cur_screen;
781
782 // Force data reload
783 randr_screen_info = read_screen_info(randr_display);
784 output_info = randr_screen_info->outputs[i]->info;
785
786 // Finally, set the screen's position
787 randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
788 if (randr_screen_info->cur_crtc) {
789 randr_screen_info->cur_crtc->cur_x = screendata->absolute_x_position;
790 randr_screen_info->cur_crtc->cur_y = screendata->absolute_y_position;
791 j=main_low_apply(randr_screen_info);
792 }
793 }
794 }
795 freeScreenInfoStructure(randr_screen_info);
796#endif
797 }
798
799 applyDisplayGamma(screenInfoArray);
800 applyDisplayDPMS(screenInfoArray);
801 TQString current_icc_profile = getCurrentProfile();
802 applySystemWideIccConfiguration(kde_confdir);
803 applyIccConfiguration(current_icc_profile, kde_confdir);
804
805 if (test == TRUE) {
806 int ret = showTestConfigurationDialog();
807 if (!ret) {
808 applyDisplayConfiguration(oldconfig, FALSE, kde_confdir);
809 accepted = false;
810 }
811 destroyScreenInformationObject(oldconfig);
812 }
813
814 return accepted;
815}
816
817TQPtrList<SingleScreenData> KRandrSimpleAPI::copyScreenInformationObject(TQPtrList<SingleScreenData> screenInfoArray) {
818 SingleScreenData *origscreendata;
819 SingleScreenData *copyscreendata;
820 TQPtrList<SingleScreenData> retArray;
821 for ( origscreendata = screenInfoArray.first(); origscreendata; origscreendata = screenInfoArray.next() ) {
822 copyscreendata = new SingleScreenData;
823 *copyscreendata = *origscreendata;
824 retArray.append(copyscreendata);
825 }
826 return retArray;
827}
828
829void KRandrSimpleAPI::destroyScreenInformationObject(TQPtrList<SingleScreenData> screenInfoArray) {
830 SingleScreenData *screendata;
831 for ( screendata = screenInfoArray.first(); screendata; screendata = screenInfoArray.next() ) {
832 screenInfoArray.remove(screendata);
833 delete screendata;
834 }
835}
836
837void KRandrSimpleAPI::ensureMonitorDataConsistency(TQPtrList<SingleScreenData> screenInfoArray) {
838 int i;
839 SingleScreenData *screendata;
840
841 int numberOfScreens = screenInfoArray.count();
842
843 for (i=0;i<numberOfScreens;i++) {
844 screendata = screenInfoArray.at(i);
845 if (!screendata->screen_connected) {
846 screendata->is_primary = false;
847 screendata->is_extended = false;
848 }
849 }
850
851 bool has_primary_monitor = false;
852 for (i=0;i<numberOfScreens;i++) {
853 screendata = screenInfoArray.at(i);
854 if (screendata->is_primary) {
855 has_primary_monitor = true;
856 }
857 }
858 if (!has_primary_monitor) {
859 for (i=0;i<numberOfScreens;i++) {
860 screendata = screenInfoArray.at(i);
861 if (!has_primary_monitor) {
862 if (screendata->screen_connected && screendata->is_extended) {
863 screendata->is_primary = true;
864 screendata->is_extended = true;
865 has_primary_monitor = true;
866 }
867 }
868 }
869 }
870 if (!has_primary_monitor) {
871 for (i=0;i<numberOfScreens;i++) {
872 screendata = screenInfoArray.at(i);
873 if (!has_primary_monitor) {
874 if (screendata->screen_connected) {
875 screendata->is_primary = true;
876 screendata->is_extended = true;
877 has_primary_monitor = true;
878 }
879 }
880 }
881 }
882
883 bool found_first_primary_monitor = false;
884 for (i=0;i<numberOfScreens;i++) {
885 screendata = screenInfoArray.at(i);
886 if (screendata->is_primary) {
887 if (!found_first_primary_monitor) {
888 found_first_primary_monitor = true;
889 }
890 else {
891 screendata->is_primary = false;
892 }
893 }
894 }
895
896 for (i=0;i<numberOfScreens;i++) {
897 screendata = screenInfoArray.at(i);
898 if (screendata->is_primary) {
899 screendata->is_extended = true;
900 }
901 }
902
903 for (i=0;i<numberOfScreens;i++) {
904 screendata = screenInfoArray.at(i);
905 TQString resolutionstring = screendata->resolutions[screendata->current_resolution_index];
906 int separator_pos = resolutionstring.find(" x ");
907 TQString x_res_string = resolutionstring.left(separator_pos);
908 TQString y_res_string = resolutionstring.right(resolutionstring.length()-separator_pos-3);
909 screendata->current_x_pixel_count = x_res_string.toInt();
910 screendata->current_y_pixel_count = y_res_string.toInt();
911 screendata->current_orientation_mask = getHardwareRotationFlags(screendata);
912 }
913
914 // Each screen's absolute position is given relative to the primary monitor
915 // Fix up the absolute positions
916 int primary_offset_x = 0;
917 int primary_offset_y = 0;
918 for (i=0;i<numberOfScreens;i++) {
919 screendata = screenInfoArray.at(i);
920 if (screendata->is_primary) {
921 primary_offset_x = screendata->absolute_x_position;
922 primary_offset_y = screendata->absolute_y_position;
923 primary_offset_x = primary_offset_x * (-1);
924 primary_offset_y = primary_offset_y * (-1);
925 }
926 }
927 for (i=0;i<numberOfScreens;i++) {
928 screendata = screenInfoArray.at(i);
929 screendata->absolute_x_position = screendata->absolute_x_position + primary_offset_x;
930 screendata->absolute_y_position = screendata->absolute_y_position + primary_offset_y;
931 }
932}
933
934TQPoint KRandrSimpleAPI::primaryScreenOffsetFromTLC(TQPtrList<SingleScreenData> screenInfoArray) {
935 int i;
936 SingleScreenData *screendata;
937 int numberOfScreens = screenInfoArray.count();
938
939 int primary_offset_x = 0;
940 int primary_offset_y = 0;
941 for (i=0;i<numberOfScreens;i++) {
942 screendata = screenInfoArray.at(i);
943 if (screendata->absolute_x_position < primary_offset_x) {
944 primary_offset_x = screendata->absolute_x_position;
945 }
946 if (screendata->absolute_y_position < primary_offset_y) {
947 primary_offset_y = screendata->absolute_y_position;
948 }
949 }
950 primary_offset_x = primary_offset_x * (-1);
951 primary_offset_y = primary_offset_y * (-1);
952
953 return TQPoint(primary_offset_x, primary_offset_y);
954}
955
956HotPlugRulesList KRandrSimpleAPI::getHotplugRules(TQString kde_confdir) {
957 int i;
958 TQString filename;
959 HotPlugRulesList ret;
960
961 filename = "displayglobals";
962 filename.prepend(kde_confdir.append("/"));
963 KSimpleConfig* display_config = new KSimpleConfig( filename );
964
965 TQStringList grouplist = display_config->groupList();
966 for ( TQStringList::Iterator it = grouplist.begin(); it != grouplist.end(); ++it ) {
967 if (!(*it).startsWith("Hotplug-Rule")) {
968 continue;
969 }
970 HotPlugRule rule;
971 display_config->setGroup(*it);
972 rule.outputs = display_config->readListEntry("Outputs");
973 rule.states = display_config->readIntListEntry("States");
974 rule.profileName = display_config->readEntry("Profile");
975 ret.append(rule);
976 }
977 delete display_config;
978
979 return ret;
980}
981
982void KRandrSimpleAPI::saveHotplugRules(HotPlugRulesList rules, TQString kde_confdir) {
983 int i;
984 TQString filename;
985
986 filename = "displayglobals";
987 filename.prepend(kde_confdir.append("/"));
988 KSimpleConfig* display_config = new KSimpleConfig( filename );
989 TQStringList grouplist = display_config->groupList();
990 for ( TQStringList::Iterator it = grouplist.begin(); it != grouplist.end(); ++it ) {
991 if (!(*it).startsWith("Hotplug-Rule")) {
992 continue;
993 }
994 display_config->deleteGroup(*it, true, false);
995 }
996 HotPlugRulesList::Iterator it;
997 i=0;
998 for (it=rules.begin(); it != rules.end(); ++it) {
999 display_config->setGroup(TQString("Hotplug-Rule%1").arg(i));
1000 display_config->writeEntry("Outputs", (*it).outputs);
1001 display_config->writeEntry("States", (*it).states);
1002 display_config->writeEntry("Profile", (*it).profileName);
1003 i++;
1004 }
1005 display_config->sync();
1006 delete display_config;
1007}
1008
1009bool KRandrSimpleAPI::getDisplayConfigurationEnabled(TQString kde_confdir) {
1010 TQString filename = "displayglobals";
1011 filename.prepend(kde_confdir.append("/"));
1012 KSimpleConfig* display_config = new KSimpleConfig( filename );
1013 display_config->setGroup("General");
1014 bool enabled = display_config->readBoolEntry("EnableDisplayControl", false);
1015 delete display_config;
1016
1017 return enabled;
1018}
1019
1020bool KRandrSimpleAPI::getDisplayConfigurationStartupAutoApplyEnabled(TQString kde_confdir) {
1021 TQString filename = "displayglobals";
1022 filename.prepend(kde_confdir.append("/"));
1023 KSimpleConfig* display_config = new KSimpleConfig( filename );
1024 display_config->setGroup("General");
1025 bool applyonstart = display_config->readBoolEntry("ApplySettingsOnStart", false);
1026 delete display_config;
1027
1028 return applyonstart;
1029}
1030
1031TQString KRandrSimpleAPI::getDisplayConfigurationStartupAutoApplyName(TQString kde_confdir) {
1032 TQString filename = "displayglobals";
1033 filename.prepend(kde_confdir.append("/"));
1034 KSimpleConfig* display_config = new KSimpleConfig( filename );
1035 display_config->setGroup("General");
1036 TQString profilename = display_config->readEntry("StartupProfileName", "");
1037 delete display_config;
1038
1039 return profilename;
1040}
1041
1042void KRandrSimpleAPI::applyHotplugRules(TQString kde_confdir) {
1043 bool enabled = getDisplayConfigurationEnabled(kde_confdir);
1044 if (!enabled) {
1045 return;
1046 }
1047
1048 HotPlugRulesList rules = getHotplugRules(kde_confdir);
1049 TQPtrList<SingleScreenData> screenInfoArray = readCurrentDisplayConfiguration();
1050
1051 int i;
1052 int j;
1053 TQString bestRule;
1054 int bestRuleMatchCount = 0;
1055 SingleScreenData *screendata = NULL;
1056 HotPlugRulesList::Iterator it;
1057 for (it=rules.begin(); it != rules.end(); ++it) {
1058 // Compare each rule against the current display configuration
1059 // It an output matches the state given in the rule, increment matchCount
1060 HotPlugRule rule = *it;
1061 int matchCount = 0;
1062 int numberOfScreens = screenInfoArray.count();
1063 for (i=0;i<numberOfScreens;i++) {
1064 screendata = screenInfoArray.at(i);
1065 for (j=0; j<(*it).outputs.count(); j++) {
1066 if ((*it).outputs[j] != screendata->screenUniqueName) {
1067 continue;
1068 }
1069 if ((*it).states[j] == HotPlugRule::Connected) {
1070 if (screendata->screen_connected) {
1071 matchCount++;
1072 }
1073 }
1074 else if ((*it).states[j] == HotPlugRule::Disconnected) {
1075 if (!screendata->screen_connected) {
1076 matchCount++;
1077 }
1078 }
1079 }
1080 }
1081
1082 if (matchCount > bestRuleMatchCount) {
1083 bestRuleMatchCount = matchCount;
1084 bestRule = rule.profileName;
1085 }
1086 }
1087
1088 destroyScreenInformationObject(screenInfoArray);
1089
1090 if (bestRuleMatchCount > 0) {
1091 // At least one rule matched...
1092 // Apply the profile name in bestRule to the display hardware
1093 applyDisplayConfiguration(bestRule, kde_confdir);
1094 }
1095}
1096
1097void KRandrSimpleAPI::applyDisplayGamma(TQPtrList<SingleScreenData> screenInfoArray) {
1098 int i;
1099 Display *randr_display;
1100 XRROutputInfo *output_info;
1101 ScreenInfo *randr_screen_info;
1102 XRRCrtcGamma *gamma;
1103
1104 SingleScreenData *screendata;
1105
1106 if (isValid() == true) {
1107 randr_display = tqt_xdisplay();
1108 randr_screen_info = read_screen_info(randr_display);
1109 for (i = 0; i < screenInfoArray.count(); i++) {
1110 screendata = screenInfoArray.at(i);
1111 output_info = randr_screen_info->outputs[i]->info;
1112 CrtcInfo *current_crtc = randr_screen_info->outputs[i]->cur_crtc;
1113 if (!current_crtc) {
1114 continue;
1115 }
1116 // vvvvvvvvv This chunk of code is borrowed from xrandr vvvvvvvvvv
1117 int size = XRRGetCrtcGammaSize(randr_display, current_crtc->id);
1118 if (!size) {
1119 continue;
1120 }
1121 gamma = XRRAllocGamma(size);
1122 if (!gamma) {
1123 continue;
1124 }
1125 for (i = 0; i < size; i++) {
1126 if (screendata->gamma_red == 1.0)
1127 gamma->red[i] = i << 8;
1128 else
1129 gamma->red[i] = (pow((double)i/(double)(size-1), (double)screendata->gamma_red) * (double)(size-1)*256);
1130
1131 if (screendata->gamma_green == 1.0)
1132 gamma->green[i] = i << 8;
1133 else
1134 gamma->green[i] = (pow((double)i/(double)(size-1), (double)screendata->gamma_green) * (double)(size-1)*256);
1135
1136 if (screendata->gamma_blue == 1.0)
1137 gamma->blue[i] = i << 8;
1138 else
1139 gamma->blue[i] = (pow((double)i/(double)(size-1), (double)screendata->gamma_blue) * (double)(size-1)*256);
1140 }
1141 XRRSetCrtcGamma(randr_display, current_crtc->id, gamma);
1142 free(gamma);
1143 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1144 }
1145 freeScreenInfoStructure(randr_screen_info);
1146 }
1147}
1148
1149void KRandrSimpleAPI::applyDisplayDPMS(TQPtrList<SingleScreenData> screenInfoArray) {
1150 int i;
1151 Display *randr_display;
1152 XRROutputInfo *output_info;
1153 ScreenInfo *randr_screen_info;
1154 XRRCrtcGamma *gamma;
1155
1156 SingleScreenData *screendata;
1157
1158 if (isValid() == true) {
1159 randr_display = tqt_xdisplay();
1160 randr_screen_info = read_screen_info(randr_display);
1161 for (i = 0; i < screenInfoArray.count(); i++) {
1162 screendata = screenInfoArray.at(i);
1163 output_info = randr_screen_info->outputs[i]->info;
1164 CrtcInfo *current_crtc = randr_screen_info->outputs[i]->cur_crtc;
1165 if (!current_crtc) {
1166 continue;
1167 }
1168 if (!screendata->has_dpms) {
1169 continue;
1170 }
1171 if (screendata->enable_dpms) {
1172 DPMSSetTimeouts(randr_display, screendata->dpms_standby_delay, screendata->dpms_suspend_delay, screendata->dpms_off_delay);
1173 DPMSEnable(randr_display);
1174 }
1175 else {
1176 DPMSDisable(randr_display);
1177 }
1178 }
1179 freeScreenInfoStructure(randr_screen_info);
1180 }
1181}
1182
1183void KRandrSimpleAPI::freeScreenInfoStructure(ScreenInfo* screen_info) {
1184 int i;
1185
1186 for (i=0; i<screen_info->n_crtc; i++) {
1187 free(screen_info->crtcs[i]);
1188 }
1189 for (i=0; i<screen_info->n_output; i++) {
1190 free(screen_info->outputs[i]);
1191 }
1192 free(screen_info->outputs);
1193 free(screen_info->crtcs);
1194 free(screen_info);
1195}
1196
1197TQPtrList<SingleScreenData> KRandrSimpleAPI::readCurrentDisplayConfiguration() {
1198 // Discover display information
1199 int i;
1200 int j;
1201
1202 XRROutputInfo *output_info;
1203 SingleScreenData *screendata;
1204 TQPtrList<SingleScreenData> screenInfoArray;
1205
1206 Display *randr_display;
1207 ScreenInfo *randr_screen_info;
1208
1209 // Clear existing info
1210 destroyScreenInformationObject(screenInfoArray);
1211
1212 int numberOfScreens = 0;
1213 if (isValid() == true) {
1214 randr_display = tqt_xdisplay();
1215 randr_screen_info = read_screen_info(randr_display);
1216 for (i = 0; i < randr_screen_info->n_output; i++) {
1217 output_info = randr_screen_info->outputs[i]->info;
1218 CrtcInfo *current_crtc = randr_screen_info->outputs[i]->cur_crtc;
1219
1220 // Create new data object
1221 screendata = new SingleScreenData;
1222 screenInfoArray.append(screendata);
1223 screendata->screenUniqueName = TQString(i18n("%1:%2")).arg(":0").arg(capitalizeString(output_info->name)); // [FIXME] How can I get the name of the Xorg graphics driver currently in use?
1224 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?
1225 screendata->generic_screen_detected = false;
1226
1227 // Attempt to use KMS to find screen EDID and name
1228 TQString edid = getEDIDMonitorName(0, output_info->name); // [FIXME] Don't hardwire to card 0!
1229 if (!edid.isNull()) {
1230 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?
1231 }
1232
1233 // Get resolutions
1234 bool screen_active;
1235 RandRScreen *cur_screen = 0;
1236 if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
1237 // Output DISCONNECTED
1238 screen_active = false;
1239 }
1240 else {
1241 if (randr_screen_info->outputs[i]->cur_crtc) {
1242 // Output CONNECTED and ON
1243 screen_active = true;
1244 cur_screen = new RandRScreen(i);
1245 }
1246 else {
1247 // Output CONNECTED and OFF
1248 screen_active = false;
1249 cur_screen = new RandRScreen(i);
1250 }
1251 }
1252
1253 // Get DPMS information
1254 screendata->has_dpms = 1; // [FIXME] Master Xorg check for global DPMS support should go here if possible
1255 if (screendata->has_dpms) {
1256 CARD16 dpms_standby_delay;
1257 CARD16 dpms_suspend_delay;
1258 CARD16 dpms_off_delay;
1259 screendata->has_dpms = DPMSGetTimeouts(randr_display, &dpms_standby_delay, &dpms_suspend_delay, &dpms_off_delay);
1260 screendata->dpms_standby_delay = dpms_standby_delay;
1261 screendata->dpms_suspend_delay = dpms_suspend_delay;
1262 screendata->dpms_off_delay = dpms_off_delay;
1263 if (screendata->has_dpms) {
1264 CARD16 power_level;
1265 BOOL enable_dpms;
1266 screendata->has_dpms = DPMSInfo(randr_display, &power_level, &enable_dpms);
1267 screendata->enable_dpms = enable_dpms;
1268 }
1269 }
1270 if (!screendata->has_dpms) {
1271 screendata->enable_dpms = false;
1272 screendata->dpms_standby_delay = 0;
1273 screendata->dpms_suspend_delay = 0;
1274 screendata->dpms_off_delay = 0;
1275 }
1276
1277 if (cur_screen) {
1278 screendata->screen_connected = true;
1279 for (int j = 0; j < cur_screen->numSizes(); j++) {
1280 screendata->resolutions.append(i18n("%1 x %2").arg(cur_screen->pixelSize(j).width()).arg(cur_screen->pixelSize(j).height()));
1281 }
1282 screendata->current_resolution_index = 0;
1283 if (current_crtc) {
1284 screendata->current_resolution_index = screendata->resolutions.findIndex(i18n("%1 x %2").arg(current_crtc->info->width).arg(current_crtc->info->height));
1285 }
1286 if (screendata->current_resolution_index < 0) {
1287 screendata->current_resolution_index = cur_screen->proposedSize();
1288 }
1289
1290 // Get refresh rates
1291 TQStringList rr = cur_screen->refreshRates(screendata->current_resolution_index);
1292 for (TQStringList::Iterator it = rr.begin(); it != rr.end(); ++it) {
1293 screendata->refresh_rates.append(*it);
1294 }
1295 screendata->current_refresh_rate_index = cur_screen->proposedRefreshRate();
1296
1297 // Get color depths
1298 // [FIXME]
1299 screendata->color_depths.append(i18n("Default"));
1300 screendata->current_color_depth_index = 0;
1301
1302 // Get orientation flags
1303 // RandRScreen::Rotate0
1304 // RandRScreen::Rotate90
1305 // RandRScreen::Rotate180
1306 // RandRScreen::Rotate270
1307 // RandRScreen::ReflectX
1308 // RandRScreen::ReflectY
1309
1310 screendata->rotations.append(i18n("0 degrees"));
1311 screendata->rotations.append(i18n("90 degrees"));
1312 screendata->rotations.append(i18n("180 degrees"));
1313 screendata->rotations.append(i18n("270 degrees"));
1314 screendata->supports_transformations = (cur_screen->rotations() != RandRScreen::Rotate0);
1315 if (screendata->supports_transformations) {
1316 screendata->current_orientation_mask = cur_screen->proposedRotation();
1317 switch (screendata->current_orientation_mask & RandRScreen::RotateMask) {
1318 case RandRScreen::Rotate0:
1319 screendata->current_rotation_index = ROTATION_0_DEGREES_INDEX;
1320 break;
1321 case RandRScreen::Rotate90:
1322 screendata->current_rotation_index = ROTATION_90_DEGREES_INDEX;
1323 break;
1324 case RandRScreen::Rotate180:
1325 screendata->current_rotation_index = ROTATION_180_DEGREES_INDEX;
1326 break;
1327 case RandRScreen::Rotate270:
1328 screendata->current_rotation_index = ROTATION_270_DEGREES_INDEX;
1329 break;
1330 default:
1331 // Shouldn't hit this one
1332 Q_ASSERT(screendata->current_orientation_mask & RandRScreen::RotateMask);
1333 screendata->current_rotation_index = ROTATION_0_DEGREES_INDEX;
1334 break;
1335 }
1336 screendata->has_x_flip = (screendata->current_orientation_mask & RandRScreen::ReflectX);
1337 screendata->has_y_flip = (screendata->current_orientation_mask & RandRScreen::ReflectY);
1338 }
1339 else {
1340 screendata->has_x_flip = false;
1341 screendata->has_y_flip = false;
1342 screendata->current_rotation_index = ROTATION_0_DEGREES_INDEX;
1343 }
1344
1345 // Determine if this display is primary and/or extended
1346 RROutput primaryoutput = XRRGetOutputPrimary(tqt_xdisplay(), DefaultRootWindow(tqt_xdisplay()));
1347 if (primaryoutput == randr_screen_info->outputs[i]->id) {
1348 screendata->is_primary = false;
1349 }
1350 else {
1351 screendata->is_primary = true;
1352 }
1353 screendata->is_extended = screen_active;
1354 if (!screendata->is_extended) {
1355 screendata->is_primary = false;
1356 }
1357
1358 // Get this screen's absolute position
1359 screendata->absolute_x_position = 0;
1360 screendata->absolute_y_position = 0;
1361 if (current_crtc) {
1362 screendata->absolute_x_position = current_crtc->info->x;
1363 screendata->absolute_y_position = current_crtc->info->y;
1364 }
1365
1366 // Get this screen's current resolution
1367 screendata->current_x_pixel_count = cur_screen->pixelSize(screendata->current_resolution_index).width();
1368 screendata->current_y_pixel_count = cur_screen->pixelSize(screendata->current_resolution_index).height();
1369
1370 // Get this screen's current gamma values
1371 // [FIXME]
1372 // This attempts to guess a gamma value based on the LUT settings at 50%
1373 // It may not always be 100% correct, or even anywhere close...
1374 // Essentially it "undoes" the LUT gamma calculation from xrandr
1375 // lut_gamma->green[i] = (pow(i/(size - 1), desired_gamma.green) * (size - 1) * 256);
1376 screendata->gamma_red = 2.2;
1377 screendata->gamma_green = 2.2;
1378 screendata->gamma_blue = 2.2;
1379 if (current_crtc) {
1380 //int slot = 127;
1381 int slot = 7;
1382 int size = XRRGetCrtcGammaSize(randr_display, current_crtc->id);
1383 if(size>0) {
1384 XRRCrtcGamma *gammastruct = XRRGetCrtcGamma (randr_display, current_crtc->id);
1385 screendata->gamma_red = log(gammastruct->red[slot]/((size-1.0)*256.0))/log(slot/(size-1.0));
1386 screendata->gamma_green = log(gammastruct->green[slot]/((size-1.0)*256.0))/log(slot/(size-1.0));
1387 screendata->gamma_blue = log(gammastruct->blue[slot]/((size-1.0)*256.0))/log(slot/(size-1.0));
1388 }
1389 }
1390 // Round off the gamma to one decimal place
1391 screendata->gamma_red = floorf(screendata->gamma_red * 10 + 0.5) / 10;
1392 screendata->gamma_green = floorf(screendata->gamma_green * 10 + 0.5) / 10;
1393 screendata->gamma_blue = floorf(screendata->gamma_blue * 10 + 0.5) / 10;
1394
1395 delete cur_screen;
1396 }
1397 else {
1398 // Fill in generic data for this disconnected output
1399 screendata->screenFriendlyName = screendata->screenFriendlyName + TQString(" (") + i18n("disconnected") + TQString(")");
1400 screendata->screen_connected = false;
1401
1402 screendata->resolutions = i18n("Default");
1403 screendata->refresh_rates = i18n("Default");
1404 screendata->color_depths = i18n("Default");
1405 screendata->rotations = i18n("N/A");
1406
1407 screendata->current_resolution_index = 0;
1408 screendata->current_refresh_rate_index = 0;
1409 screendata->current_color_depth_index = 0;
1410
1411 screendata->gamma_red = 2.2;
1412 screendata->gamma_green = 2.2;
1413 screendata->gamma_blue = 2.2;
1414
1415 screendata->current_rotation_index = ROTATION_0_DEGREES_INDEX;
1416 screendata->current_orientation_mask = 0;
1417 screendata->has_x_flip = false;
1418 screendata->has_y_flip = false;
1419 screendata->supports_transformations = false;
1420
1421 screendata->is_primary = false;
1422 screendata->is_extended = false;
1423 screendata->absolute_x_position = 0;
1424 screendata->absolute_y_position = 0;
1425 screendata->current_x_pixel_count = 640;
1426 screendata->current_y_pixel_count = 480;
1427 }
1428
1429 // Check for more screens...
1430 numberOfScreens++;
1431 }
1432
1433 freeScreenInfoStructure(randr_screen_info);
1434 }
1435 else {
1436 screendata = new SingleScreenData;
1437 screenInfoArray.append(screendata);
1438
1439 // Fill in a bunch of generic data
1440 screendata->screenFriendlyName = i18n("Default output on generic video card");
1441 screendata->generic_screen_detected = true;
1442 screendata->screen_connected = true;
1443
1444 screendata->resolutions = i18n("Default");
1445 screendata->refresh_rates = i18n("Default");
1446 screendata->color_depths = i18n("Default");
1447 screendata->rotations = i18n("N/A");
1448
1449 screendata->current_resolution_index = 0;
1450 screendata->current_refresh_rate_index = 0;
1451 screendata->current_color_depth_index = 0;
1452
1453 screendata->gamma_red = 2.2;
1454 screendata->gamma_green = 2.2;
1455 screendata->gamma_blue = 2.2;
1456
1457 screendata->current_rotation_index = ROTATION_0_DEGREES_INDEX;
1458 screendata->current_orientation_mask = 0;
1459 screendata->has_x_flip = false;
1460 screendata->has_y_flip = false;
1461 screendata->supports_transformations = false;
1462
1463 screendata->is_primary = true;
1464 screendata->is_extended = true;
1465 screendata->absolute_x_position = 0;
1466 screendata->absolute_y_position = 0;
1467 screendata->current_x_pixel_count = 640;
1468 screendata->current_y_pixel_count = 480;
1469
1470 numberOfScreens++;
1471 }
1472
1473 bool primary_set = false;
1474 for ( screendata=screenInfoArray.first(); screendata; screendata=screenInfoArray.next() ) {
1475 if (screendata->is_primary) {
1476 primary_set = true;
1477 break;
1478 }
1479 }
1480 // If there is no primary monitor set, xrandr is probably not functioning correctly!
1481 Q_ASSERT(primary_set);
1482 if (!primary_set) {
1483 // [FIXME]
1484 // Set this on the real primary monitor only!
1485 screendata = screenInfoArray.at(0);
1486 screendata->is_primary = true;
1487 }
1488
1489 return screenInfoArray;
1490}
1491
1492TQString KRandrSimpleAPI::clearIccConfiguration() {
1493 // Clear ICC settings with XCalib
1494 TQString icc_command;
1495 FILE *pipe_xcalib;
1496 char xcalib_result[2048];
1497 int i;
1498 xcalib_result[0]=0;
1499
1500 icc_command = TQString("xcalib -c");
1501 if ((pipe_xcalib = popen(icc_command.ascii(), "r")) == NULL)
1502 {
1503 printf("Xcalib pipe error [xcalib clear]\n");
1504 }
1505 else {
1506 if (fgets(xcalib_result, 2048, pipe_xcalib)) {
1507 pclose(pipe_xcalib);
1508 for (i=1;i<2048;i++) {
1509 if (xcalib_result[i] == 0) {
1510 xcalib_result[i-1]=0;
1511 i=2048;
1512 }
1513 }
1514 if (strlen(xcalib_result) > 2) {
1515 return xcalib_result;
1516 }
1517 }
1518 else {
1519 return "";
1520 }
1521 }
1522 return "";
1523}
1524
1525ScreenInfo* KRandrSimpleAPI::read_screen_info (Display *display)
1526{
1527 return internal_read_screen_info(display);
1528}
1529
1530int KRandrSimpleAPI::set_screen_size (ScreenInfo *screen_info)
1531{
1532 return internal_set_screen_size(screen_info);
1533}
1534
1535void KRandrSimpleAPI::output_auto (ScreenInfo *screen_info, OutputInfo *output_info)
1536{
1537 internal_output_auto (screen_info, output_info);
1538}
1539
1540void KRandrSimpleAPI::output_off(ScreenInfo *screen_info, OutputInfo *output)
1541{
1542 internal_output_off(screen_info, output);
1543}
1544
1545CrtcInfo* KRandrSimpleAPI::auto_find_crtc (ScreenInfo *screen_info, OutputInfo *output_info)
1546{
1547 return internal_auto_find_crtc (screen_info, output_info);
1548}
1549
1550XRRModeInfo *KRandrSimpleAPI::find_mode_by_xid (ScreenInfo *screen_info, RRMode mode_id)
1551{
1552 return internal_find_mode_by_xid (screen_info, mode_id);
1553}
1554
1555int KRandrSimpleAPI::mode_height (XRRModeInfo *mode_info, Rotation rotation)
1556{
1557 return internal_mode_height (mode_info, rotation);
1558}
1559
1560int KRandrSimpleAPI::mode_width (XRRModeInfo *mode_info, Rotation rotation)
1561{
1562 return internal_mode_width (mode_info, rotation);
1563}
1564
1565int KRandrSimpleAPI::get_width_by_output_id (ScreenInfo *screen_info, RROutput output_id)
1566{
1567 return internal_get_width_by_output_id (screen_info, output_id);
1568}
1569
1570int KRandrSimpleAPI::get_height_by_output_id (ScreenInfo *screen_info, RROutput output_id)
1571{
1572 return internal_get_height_by_output_id (screen_info, output_id);
1573}
1574
1575char *KRandrSimpleAPI::get_output_name (ScreenInfo *screen_info, RROutput id)
1576{
1577 return internal_get_output_name (screen_info, id);
1578}
1579
1580Status KRandrSimpleAPI::crtc_apply (CrtcInfo *crtc_info)
1581{
1582 return internal_crtc_apply (crtc_info);
1583}
1584
1585Status KRandrSimpleAPI::crtc_disable (CrtcInfo *crtc)
1586{
1587 return internal_crtc_disable (crtc);
1588}
1589
1590int KRandrSimpleAPI::main_low_apply (ScreenInfo *screen_info)
1591{
1592 return internal_main_low_apply (screen_info);
1593}
1594
1595void KRandrSimpleAPI::set_primary_output (ScreenInfo *screen_info, RROutput output_id)
1596{
1597 internal_output_set_primary(screen_info, output_id);
1598}
1599
1600bool KRandrSimpleAPI::kRandrHasRandr(void)
1601{
1602 return isValid();
1603}
1604
1605const char *KRandrSimpleAPI::kRandrVersion(void)
1606{
1607 return "0.9.5";
1608}
1609
1610const char *KRandrSimpleAPI::kRandrCopyright(void)
1611{
1612 return "LibKRandr 0.9.5 (C)2010 Timothy Pearson <kb9vqf@pearsoncomputing.net>. U.S.A.";
1613}
1614
1615/* * * * * *
1616
1617 Under this line (------) there's only a C wrapper for the KRandrSimpleAPI class
1618
1619* * * * * */
1620const char *kRandrVersion(void)
1621{
1622 return KRandrSimpleAPI::kRandrVersion();
1623}
1624
1625const char *kRandrCopyright(void)
1626{
1627 return KRandrSimpleAPI::kRandrCopyright();
1628}
1629
KSimpleConfig
KSimpleConfig::sync
virtual void sync()
TDEConfigBase::readEntry
TQString readEntry(const TQString &pKey, const TQString &aDefault=TQString::null) const
TDEConfigBase::deleteGroup
bool deleteGroup(const TQString &group, bool bDeep=true, bool bGlobal=false)
TDEConfigBase::readNumEntry
int readNumEntry(const TQString &pKey, int nDefault=0) const
TDEConfigBase::readBoolEntry
bool readBoolEntry(const TQString &pKey, bool bDefault=false) const
TDEConfigBase::readDoubleNumEntry
double readDoubleNumEntry(const TQString &pKey, double nDefault=0.0) const
TDEConfigBase::readIntListEntry
TQValueList< int > readIntListEntry(const TQString &pKey) const
TDEConfigBase::readListEntry
int readListEntry(const TQString &pKey, TQStrList &list, char sep=',') const
TDEConfigBase::writeEntry
void writeEntry(const TQString &pKey, const TQString &pValue, bool bPersistent=true, bool bGlobal=false, bool bNLS=false)
TDEConfigBase::setGroup
void setGroup(const TQString &group)
TDEConfig::groupList
virtual TQStringList groupList() const
tdelocale.h

tderandr

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

tderandr

Skip menu "tderandr"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tderandr by doxygen 1.9.8
This website is maintained by Timothy Pearson.