26 #include <tqstringlist.h>
30 #include <kmessagebox.h>
31 #include <kapplication.h>
36 #include "libkrandr.h"
38 #include <X11/extensions/dpms.h>
42 #define USE_XRANDR_PROGRAM
46 unsigned int reverse_bits(
unsigned int x)
48 x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
49 x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
50 x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
51 x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
52 return((x >> 16) | (x << 16));
56 TQString exec(
const char * cmd) {
57 TQString bashcommand = cmd;
58 bashcommand = bashcommand.replace(
"\"",
"\\\"");
59 bashcommand = TQString(
"/bin/bash -c \"%1\" 2>&1").arg(bashcommand);
60 FILE* pipe = popen(bashcommand.ascii(),
"r");
61 if (!pipe)
return "ERROR";
65 if(fgets(buffer, 128, pipe) != NULL) {
70 result.remove(result.length(), 1);
74 TQString capitalizeString(TQString in) {
75 return in.left(1).upper() + in.right(in.length()-1);
78 TQString KRandrSimpleAPI::getIccFileName(TQString profileName, TQString screenName, TQString kde_confdir) {
81 int t_numberOfProfiles;
82 TQStringList t_cfgProfiles;
85 if ((profileName != NULL) && (profileName !=
"")) {
86 t_config =
new KSimpleConfig( TQString::fromLatin1(
"kiccconfigrc" ));
98 t_systemconfig =
new KSimpleConfig( kde_confdir + TQString(
"/kicc/kiccconfigrc") );
100 if (t_systemconfig->
readBoolEntry(
"EnableICC",
false) ==
true) {
101 retval = t_systemconfig->
readEntry(
"ICCFile");
106 delete t_systemconfig;
112 TQString KRandrSimpleAPI::applyIccFile(TQString screenName, TQString fileName) {
115 Display *randr_display;
116 ScreenInfo *randr_screen_info;
117 XRROutputInfo *output_info;
119 int screenNumber = 0;
121 if (fileName !=
"") {
130 if (isValid() ==
true) {
132 randr_display = qt_xdisplay();
133 randr_screen_info = read_screen_info(randr_display);
134 if (randr_screen_info == NULL) {
138 for (i = 0; i < randr_screen_info->n_output; i++) {
139 output_info = randr_screen_info->outputs[i]->info;
141 if (!randr_screen_info->outputs[i]->cur_crtc) {
145 if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
148 if (output_info->name == screenName) {
153 freeScreenInfoStructure(randr_screen_info);
156 if (screenNumber >= 0) {
158 TQString icc_command;
160 char xcalib_result[2048];
164 icc_command = TQString(
"xcalib \"%1\"").arg(fileName);
165 if ((pipe_xcalib = popen(icc_command.ascii(),
"r")) == NULL)
167 printf(
"Xcalib pipe error\n [xcalib apply]");
170 fgets(xcalib_result, 2048, pipe_xcalib);
172 for (i=1;i<2048;i++) {
173 if (xcalib_result[i] == 0) {
174 xcalib_result[i-1]=0;
178 if (strlen(xcalib_result) > 2) {
179 return xcalib_result;
195 if (isValid() ==
true) {
197 randr_display = qt_xdisplay();
198 randr_screen_info = read_screen_info(randr_display);
199 if (randr_screen_info == NULL) {
203 for (i = 0; i < randr_screen_info->n_output; i++) {
204 output_info = randr_screen_info->outputs[i]->info;
206 if (!randr_screen_info->outputs[i]->cur_crtc) {
210 if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
213 if (output_info->name == screenName) {
218 freeScreenInfoStructure(randr_screen_info);
221 if (screenNumber >= 0) {
223 TQString icc_command;
225 char xcalib_result[2048];
229 icc_command = TQString(
"xcalib -c");
230 if ((pipe_xcalib = popen(icc_command.ascii(),
"r")) == NULL)
232 printf(
"Xcalib pipe error\n [xcalib clear]");
235 fgets(xcalib_result, 2048, pipe_xcalib);
237 for (i=1;i<2048;i++) {
238 if (xcalib_result[i] == 0) {
239 xcalib_result[i-1]=0;
243 if (strlen(xcalib_result) > 2) {
244 return xcalib_result;
252 TQString KRandrSimpleAPI::applyIccConfiguration(TQString profileName, TQString kde_confdir) {
254 Display *randr_display;
255 ScreenInfo *randr_screen_info;
256 XRROutputInfo *output_info;
259 int screenNumber = 0;
260 TQString errorstr =
"";
262 t_config =
new KSimpleConfig( TQString::fromLatin1(
"kiccconfigrc" ));
265 if (isValid() ==
true) {
266 randr_display = qt_xdisplay();
267 randr_screen_info = read_screen_info(randr_display);
268 if (randr_screen_info == NULL) {
271 for (i = 0; i < randr_screen_info->n_output; i++) {
272 output_info = randr_screen_info->outputs[i]->info;
273 errorstr = applyIccFile(output_info->name, getIccFileName(profileName, output_info->name, kde_confdir));
274 if (errorstr !=
"") {
278 freeScreenInfoStructure(randr_screen_info);
281 return applyIccFile(getIccFileName(profileName,
"Default", kde_confdir),
"Default");
284 t_config->
writeEntry(
"CurrentProfile", profileName);
291 TQString KRandrSimpleAPI::getEDIDMonitorName(
int card, TQString displayname) {
293 TQByteArray binaryedid = getEDID(card, displayname);
294 if (binaryedid.isNull())
298 unsigned char letter_1 = ((binaryedid[8]>>2) & 0x1F) + 0x40;
299 unsigned char letter_2 = (((binaryedid[8] & 0x03) << 3) | ((binaryedid[9]>>5) & 0x07)) + 0x40;
300 unsigned char letter_3 = (binaryedid[9] & 0x1F) + 0x40;
301 TQChar qletter_1 = TQChar(letter_1);
302 TQChar qletter_2 = TQChar(letter_2);
303 TQChar qletter_3 = TQChar(letter_3);
304 TQString manufacturer_id = TQString(
"%1%2%3").arg(qletter_1).arg(qletter_2).arg(qletter_3);
307 unsigned int raw_model_id = (((binaryedid[10] << 8) | binaryedid[11]) << 16) & 0xFFFF0000;
309 unsigned int model_id = reverse_bits(raw_model_id);
312 bool has_friendly_name =
false;
313 unsigned char descriptor_block[18];
315 for (i=72;i<90;i++) {
316 descriptor_block[i-72] = binaryedid[i] & 0xFF;
318 if ((descriptor_block[0] != 0) || (descriptor_block[1] != 0) || (descriptor_block[3] != 0xFC)) {
319 for (i=90;i<108;i++) {
320 descriptor_block[i-90] = binaryedid[i] & 0xFF;
322 if ((descriptor_block[0] != 0) || (descriptor_block[1] != 0) || (descriptor_block[3] != 0xFC)) {
323 for (i=108;i<126;i++) {
324 descriptor_block[i-108] = binaryedid[i] & 0xFF;
329 TQString monitor_name;
330 if ((descriptor_block[0] == 0) && (descriptor_block[1] == 0) && (descriptor_block[3] == 0xFC)) {
331 char* pos = strchr((
char *)(descriptor_block+5),
'\n');
334 has_friendly_name =
true;
335 monitor_name = TQString((
char *)(descriptor_block+5));
338 has_friendly_name =
false;
345 if (has_friendly_name)
346 edid = TQString(
"%1 %2").arg(manufacturer_id).arg(monitor_name);
348 edid = TQString(
"%1 0x%2").arg(manufacturer_id).arg(model_id, 0, 16);
353 TQByteArray KRandrSimpleAPI::getEDID(
int card, TQString displayname) {
354 TQFile file(TQString(
"/sys/class/drm/card%1-%2/edid").arg(card).arg(displayname));
355 if (!file.open (IO_ReadOnly))
356 return TQByteArray();
357 TQByteArray binaryedid = file.readAll();
362 TQString KRandrSimpleAPI::getCurrentProfile () {
363 TQString profileName;
366 t_config =
new KSimpleConfig( TQString::fromLatin1(
"kiccconfigrc" ));
367 profileName = t_config->
readEntry(
"CurrentProfile");
372 TQString KRandrSimpleAPI::applySystemWideIccConfiguration(TQString kde_confdir) {
374 TQString icc_command;
376 char xcalib_result[2048];
380 icc_command = TQString(
"xcalib \"%1\"").arg(getIccFileName(NULL,
"Default", kde_confdir));
381 if ((pipe_xcalib = popen(icc_command.ascii(),
"r")) == NULL)
383 printf(
"Xcalib pipe error [xcalib apply]\n");
386 fgets(xcalib_result, 2048, pipe_xcalib);
388 for (i=1;i<2048;i++) {
389 if (xcalib_result[i] == 0) {
390 xcalib_result[i-1]=0;
394 if (strlen(xcalib_result) > 2) {
395 return xcalib_result;
401 void KRandrSimpleAPI::saveSystemwideDisplayConfiguration(
bool enable, TQString profilename, TQString kde_confdir, TQPtrList<SingleScreenData> screenInfoArray) {
406 filename =
"displayglobals";
407 filename.prepend(kde_confdir.append(
"/"));
409 display_config->
setGroup(
"General");
410 display_config->
writeEntry(
"ApplySettingsOnStart", enable);
411 display_config->
sync();
412 delete display_config;
414 filename = profilename;
416 filename =
"default";
417 filename.prepend(kde_confdir.append(
"/displayconfig/"));
422 SingleScreenData *screendata;
423 for ( screendata=screenInfoArray.first(); screendata; screendata=screenInfoArray.next() ) {
424 display_config->
setGroup(TQString(
"SCREEN %1").arg(i));
425 display_config->
writeEntry(
"ScreenFriendlyName", screendata->screenFriendlyName);
426 display_config->
writeEntry(
"GenericScreenDetected", screendata->generic_screen_detected);
427 display_config->
writeEntry(
"ScreenConnected", screendata->screen_connected);
428 display_config->
writeEntry(
"Resolutions", screendata->resolutions);
429 display_config->
writeEntry(
"RefreshRates", screendata->refresh_rates);
430 display_config->
writeEntry(
"ColorDepths", screendata->color_depths);
431 display_config->
writeEntry(
"AvailableRotations", screendata->rotations);
432 display_config->
writeEntry(
"CurrentResolution", screendata->current_resolution_index);
433 display_config->
writeEntry(
"CurrentRefreshRate", screendata->current_refresh_rate_index);
434 display_config->
writeEntry(
"CurrentColorDepth", screendata->current_color_depth_index);
435 display_config->
writeEntry(
"CurrentRotation", screendata->current_rotation_index);
436 display_config->
writeEntry(
"CurrentOrientiation", screendata->current_orientation_mask);
437 display_config->
writeEntry(
"GammaRed", screendata->gamma_red);
438 display_config->
writeEntry(
"GammaGreen", screendata->gamma_green);
439 display_config->
writeEntry(
"GammaBlue", screendata->gamma_blue);
440 display_config->
writeEntry(
"CurrentXFlip", screendata->has_x_flip);
441 display_config->
writeEntry(
"CurrentYFlip", screendata->has_y_flip);
442 display_config->
writeEntry(
"SupportsTransformation", screendata->supports_transformations);
443 display_config->
writeEntry(
"IsPrimary", screendata->is_primary);
444 display_config->
writeEntry(
"IsExtended", screendata->is_extended);
445 display_config->
writeEntry(
"AbsXPos", screendata->absolute_x_position);
446 display_config->
writeEntry(
"AbsYPos", screendata->absolute_y_position);
447 display_config->
writeEntry(
"CurrentXPixelCount", screendata->current_x_pixel_count);
448 display_config->
writeEntry(
"CurrentYPixelCount", screendata->current_y_pixel_count);
449 display_config->
writeEntry(
"HasDPMS", screendata->has_dpms);
450 display_config->
writeEntry(
"EnableDPMS", screendata->enable_dpms);
451 display_config->
writeEntry(
"DPMSStandbyDelay", screendata->dpms_standby_delay);
452 display_config->
writeEntry(
"DPMSSuspendDelay", screendata->dpms_suspend_delay);
453 display_config->
writeEntry(
"DPMSPowerDownDelay", screendata->dpms_off_delay);
457 display_config->
sync();
458 delete display_config;
461 TQPoint KRandrSimpleAPI::applySystemwideDisplayConfiguration(TQString profilename, TQString kde_confdir) {
464 TQString filename =
"displayglobals";
465 filename.prepend(kde_confdir.append(
"/"));
467 display_config->
setGroup(
"General");
468 bool enabled = display_config->
readBoolEntry(
"ApplySettingsOnStart",
false);
469 delete display_config;
472 TQPtrList<SingleScreenData> screenInfoArray;
473 screenInfoArray = loadSystemwideDisplayConfiguration(profilename, kde_confdir);
474 if (screenInfoArray.count() > 0) {
475 applySystemwideDisplayConfiguration(screenInfoArray, FALSE, kde_confdir);
477 destroyScreenInformationObject(screenInfoArray);
478 screenInfoArray = readCurrentDisplayConfiguration();
479 ensureMonitorDataConsistency(screenInfoArray);
480 ret = primaryScreenOffsetFromTLC(screenInfoArray);
481 destroyScreenInformationObject(screenInfoArray);
487 TQPtrList<SingleScreenData> KRandrSimpleAPI::loadSystemwideDisplayConfiguration(TQString profilename, TQString kde_confdir) {
491 filename = profilename;
493 filename =
"default";
494 filename.prepend(kde_confdir.append(
"/displayconfig/"));
498 TQStringList grouplist = display_config->
groupList();
499 SingleScreenData *screendata;
500 TQPtrList<SingleScreenData> screenInfoArray;
501 for ( TQStringList::Iterator it = grouplist.begin(); it != grouplist.end(); ++it ) {
502 if ((*it).startsWith(
"SCREEN ")) {
504 i = ((*it).remove(
"SCREEN ")).toInt();
505 screendata =
new SingleScreenData;
506 screenInfoArray.append(screendata);
507 screendata->screenFriendlyName = display_config->
readEntry(
"ScreenFriendlyName");
508 screendata->generic_screen_detected = display_config->
readBoolEntry(
"GenericScreenDetected");
509 screendata->screen_connected = display_config->
readBoolEntry(
"ScreenConnected");
510 screendata->resolutions = display_config->
readListEntry(
"Resolutions");
511 screendata->refresh_rates = display_config->
readListEntry(
"RefreshRates");
512 screendata->color_depths = display_config->
readListEntry(
"ColorDepths");
513 screendata->rotations = display_config->
readListEntry(
"AvailableRotations");
514 screendata->current_resolution_index = display_config->
readNumEntry(
"CurrentResolution");
515 screendata->current_refresh_rate_index = display_config->
readNumEntry(
"CurrentRefreshRate");
516 screendata->current_color_depth_index = display_config->
readNumEntry(
"CurrentColorDepth");
517 screendata->current_rotation_index = display_config->
readNumEntry(
"CurrentRotation");
518 screendata->current_orientation_mask = display_config->
readNumEntry(
"CurrentOrientiation");
522 screendata->has_x_flip = display_config->
readBoolEntry(
"CurrentXFlip");
523 screendata->has_y_flip = display_config->
readBoolEntry(
"CurrentYFlip");
524 screendata->supports_transformations = display_config->
readBoolEntry(
"SupportsTransformation");
525 screendata->is_primary = display_config->
readBoolEntry(
"IsPrimary");
526 screendata->is_extended = display_config->
readBoolEntry(
"IsExtended");
527 screendata->absolute_x_position = display_config->
readNumEntry(
"AbsXPos");
528 screendata->absolute_y_position = display_config->
readNumEntry(
"AbsYPos");
529 screendata->current_x_pixel_count = display_config->
readNumEntry(
"CurrentXPixelCount");
530 screendata->current_y_pixel_count = display_config->
readNumEntry(
"CurrentYPixelCount");
531 screendata->has_dpms = display_config->
readBoolEntry(
"HasDPMS");
532 screendata->enable_dpms = display_config->
readBoolEntry(
"EnableDPMS");
533 screendata->dpms_standby_delay = display_config->
readNumEntry(
"DPMSStandbyDelay");
534 screendata->dpms_suspend_delay = display_config->
readNumEntry(
"DPMSSuspendDelay");
535 screendata->dpms_off_delay = display_config->
readNumEntry(
"DPMSPowerDownDelay");
539 delete display_config;
541 return screenInfoArray;
544 int KRandrSimpleAPI::getHardwareRotationFlags(SingleScreenData* screendata) {
545 int rotationFlags = 0;
546 TQString rotationDesired = *screendata->rotations.at(screendata->current_rotation_index);
547 if (rotationDesired ==
"Normal") {
548 rotationFlags = rotationFlags | RandRScreen::Rotate0;
550 else if (rotationDesired ==
"Rotate 90 degrees") {
551 rotationFlags = rotationFlags | RandRScreen::Rotate90;
553 else if (rotationDesired ==
"Rotate 180 degrees") {
554 rotationFlags = rotationFlags | RandRScreen::Rotate180;
556 else if (rotationDesired ==
"Rotate 270 degrees") {
557 rotationFlags = rotationFlags | RandRScreen::Rotate270;
559 if (screendata->has_x_flip) {
560 rotationFlags = rotationFlags | RandRScreen::ReflectX;
562 if (screendata->has_y_flip) {
563 rotationFlags = rotationFlags | RandRScreen::ReflectY;
565 return rotationFlags;
568 #define USE_XRANDR_PROGRAM
570 bool KRandrSimpleAPI::applySystemwideDisplayConfiguration(TQPtrList<SingleScreenData> screenInfoArray,
bool test, TQString kde_confdir) {
573 bool accepted =
true;
574 Display *randr_display;
575 XRROutputInfo *output_info;
576 ScreenInfo *randr_screen_info;
578 SingleScreenData *screendata;
580 TQPtrList<SingleScreenData> oldconfig;
582 oldconfig = readCurrentDisplayConfiguration();
585 if (isValid() ==
true) {
586 #ifdef USE_XRANDR_PROGRAM
591 randr_display = qt_xdisplay();
592 randr_screen_info = read_screen_info(randr_display);
593 for (i = 0; i < screenInfoArray.count(); i++) {
594 screendata = screenInfoArray.at(i);
596 output_info = randr_screen_info->outputs[i]->info;
597 command.append(
" --output ").append(output_info->name);
598 if (screendata->is_primary || screendata->is_extended) {
599 command.append(TQString(
" --mode %1x%2").arg(screendata->current_x_pixel_count).arg(screendata->current_y_pixel_count));
600 command.append(TQString(
" --pos %1x%2").arg(screendata->absolute_x_position).arg(screendata->absolute_y_position));
601 command.append(TQString(
" --refresh %1").arg(atoi((*screendata->refresh_rates.at(screendata->current_refresh_rate_index)).ascii())));
602 command.append(TQString(
" --gamma %1:%2:%3").arg(screendata->gamma_red).arg(screendata->gamma_green).arg(screendata->gamma_blue));
603 if (screendata->current_rotation_index == 0) command.append(
" --rotate ").append(
"normal");
604 if (screendata->current_rotation_index == 1) command.append(
" --rotate ").append(
"left");
605 if (screendata->current_rotation_index == 2) command.append(
" --rotate ").append(
"inverted");
606 if (screendata->current_rotation_index == 3) command.append(
" --rotate ").append(
"right");
607 if ((screendata->has_x_flip == 0) && (screendata->has_y_flip == 0)) command.append(
" --reflect ").append(
"normal");
608 if ((screendata->has_x_flip == 1) && (screendata->has_y_flip == 0)) command.append(
" --reflect ").append(
"x");
609 if ((screendata->has_x_flip == 0) && (screendata->has_y_flip == 1)) command.append(
" --reflect ").append(
"y");
610 if ((screendata->has_x_flip == 1) && (screendata->has_y_flip == 1)) command.append(
" --reflect ").append(
"xy");
611 if (screendata->is_primary) {
612 command.append(
" --primary");
616 command.append(
" --off");
620 printf(
"[WARNING] Unable to find configuration for monitor %d; settings may not be correctly applied...\n", i); fflush(stdout);
623 freeScreenInfoStructure(randr_screen_info);
625 TQString xrandr_command_output = exec(command.ascii());
626 xrandr_command_output = xrandr_command_output.stripWhiteSpace();
629 if (xrandr_command_output ==
"xrandr: Gamma size is 0.") {
630 command = command.replace(TQRegExp(
"--gamma [0-9\\.]*:[0-9\\.]*:[0-9\\.]*"),
"");
631 xrandr_command_output = exec(command.ascii());
632 xrandr_command_output = xrandr_command_output.stripWhiteSpace();
635 if(xrandr_command_output.startsWith(
"xrandr: Failed to get size of gamma for output")) {
636 KMessageBox::sorry(0, xrandr_command_output, i18n(
"Setting gamma failed."));
637 }
else if (xrandr_command_output !=
"") {
638 applySystemwideDisplayConfiguration(oldconfig, FALSE, kde_confdir);
640 destroyScreenInformationObject(oldconfig);
641 KMessageBox::sorry(0, xrandr_command_output, i18n(
"XRandR encountered a problem"));
652 if (kapp->desktop()->numScreens() > 1) {
653 for (i = 0; i < screenInfoArray.count(); i++) {
654 screendata = screenInfoArray.at(i);
655 if (screendata->is_primary ==
true) {
656 kapp->desktop()->emitResizedSignal(i);
661 randr_display = qt_xdisplay();
662 randr_screen_info = read_screen_info(randr_display);
664 for (i = 0; i < screenInfoArray.count(); i++) {
665 screendata = screenInfoArray.at(i);
666 output_info = randr_screen_info->outputs[i]->info;
668 randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
669 randr_screen_info->cur_output = randr_screen_info->outputs[i];
670 randr_screen_info->cur_output->auto_set = 0;
671 randr_screen_info->cur_output->off_set = 1;
672 output_off (randr_screen_info, randr_screen_info->cur_output);
673 j=main_low_apply(randr_screen_info);
675 freeScreenInfoStructure(randr_screen_info);
676 randr_screen_info = read_screen_info(randr_display);
678 for (i = 0; i < screenInfoArray.count(); i++) {
679 screendata = screenInfoArray.at(i);
680 output_info = randr_screen_info->outputs[i]->info;
682 if (screendata->is_primary ==
true) {
683 randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
684 randr_screen_info->cur_output = randr_screen_info->outputs[i];
685 randr_screen_info->cur_output->auto_set = 1;
686 randr_screen_info->cur_output->off_set = 0;
687 output_auto (randr_screen_info, randr_screen_info->cur_output);
688 j=main_low_apply(randr_screen_info);
691 freeScreenInfoStructure(randr_screen_info);
693 randr_screen_info = read_screen_info(randr_display);
694 for (i = 0; i < screenInfoArray.count(); i++) {
695 screendata = screenInfoArray.at(i);
696 output_info = randr_screen_info->outputs[i]->info;
699 randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
700 randr_screen_info->cur_output = randr_screen_info->outputs[i];
701 if (screendata->is_primary ==
false) {
702 if (screendata->is_primary || screendata->is_extended) {
703 randr_screen_info->cur_output->auto_set = 1;
704 randr_screen_info->cur_output->off_set = 0;
705 output_auto (randr_screen_info, randr_screen_info->cur_output);
706 j=main_low_apply(randr_screen_info);
709 randr_screen_info->cur_output->auto_set = 0;
710 randr_screen_info->cur_output->off_set = 1;
711 output_off (randr_screen_info, randr_screen_info->cur_output);
712 j=main_low_apply(randr_screen_info);
716 freeScreenInfoStructure(randr_screen_info);
717 randr_screen_info = read_screen_info(randr_display);
718 for (i = 0; i < screenInfoArray.count(); i++) {
719 screendata = screenInfoArray.at(i);
720 output_info = randr_screen_info->outputs[i]->info;
722 if (screendata->is_primary || screendata->is_extended) {
724 RandRScreen *cur_screen =
new RandRScreen(i);
725 cur_screen->proposeSize(screendata->current_resolution_index);
726 cur_screen->proposeRefreshRate(screendata->current_refresh_rate_index);
727 cur_screen->proposeRotation(getHardwareRotationFlags(screendata));
728 cur_screen->applyProposed();
732 randr_screen_info = read_screen_info(randr_display);
733 output_info = randr_screen_info->outputs[i]->info;
736 randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
737 if (randr_screen_info->cur_crtc) {
738 randr_screen_info->cur_crtc->cur_x = screendata->absolute_x_position;
739 randr_screen_info->cur_crtc->cur_y = screendata->absolute_y_position;
740 j=main_low_apply(randr_screen_info);
744 freeScreenInfoStructure(randr_screen_info);
748 applySystemwideDisplayGamma(screenInfoArray);
749 applySystemwideDisplayDPMS(screenInfoArray);
750 TQString current_icc_profile = getCurrentProfile();
751 applySystemWideIccConfiguration(kde_confdir);
752 applyIccConfiguration(current_icc_profile, kde_confdir);
755 int ret = showTestConfigurationDialog();
757 applySystemwideDisplayConfiguration(oldconfig, FALSE, kde_confdir);
760 destroyScreenInformationObject(oldconfig);
766 void KRandrSimpleAPI::destroyScreenInformationObject(TQPtrList<SingleScreenData> screenInfoArray) {
767 SingleScreenData *screendata;
768 for ( screendata = screenInfoArray.first(); screendata; screendata = screenInfoArray.next() ) {
769 screenInfoArray.remove(screendata);
774 void KRandrSimpleAPI::ensureMonitorDataConsistency(TQPtrList<SingleScreenData> screenInfoArray) {
776 SingleScreenData *screendata;
778 int numberOfScreens = screenInfoArray.count();
780 for (i=0;i<numberOfScreens;i++) {
781 screendata = screenInfoArray.at(i);
782 if (!screendata->screen_connected) {
783 screendata->is_primary =
false;
784 screendata->is_extended =
false;
788 bool has_primary_monitor =
false;
789 for (i=0;i<numberOfScreens;i++) {
790 screendata = screenInfoArray.at(i);
791 if (screendata->is_primary)
792 has_primary_monitor =
true;
794 if (!has_primary_monitor) {
795 for (i=0;i<numberOfScreens;i++) {
796 screendata = screenInfoArray.at(i);
797 if (!has_primary_monitor) {
798 if (screendata->screen_connected && screendata->is_extended) {
799 screendata->is_primary =
true;
800 screendata->is_extended =
true;
801 has_primary_monitor =
true;
806 if (!has_primary_monitor) {
807 for (i=0;i<numberOfScreens;i++) {
808 screendata = screenInfoArray.at(i);
809 if (!has_primary_monitor) {
810 if (screendata->screen_connected) {
811 screendata->is_primary =
true;
812 screendata->is_extended =
true;
813 has_primary_monitor =
true;
819 bool found_first_primary_monitor =
false;
820 for (i=0;i<numberOfScreens;i++) {
821 screendata = screenInfoArray.at(i);
822 if (screendata->is_primary) {
823 if (!found_first_primary_monitor) {
824 found_first_primary_monitor =
true;
827 screendata->is_primary =
false;
832 for (i=0;i<numberOfScreens;i++) {
833 screendata = screenInfoArray.at(i);
834 if (screendata->is_primary) {
835 screendata->is_extended =
true;
839 for (i=0;i<numberOfScreens;i++) {
840 screendata = screenInfoArray.at(i);
841 TQString resolutionstring = screendata->resolutions[screendata->current_resolution_index];
842 int separator_pos = resolutionstring.find(
" x ");
843 TQString x_res_string = resolutionstring.left(separator_pos);
844 TQString y_res_string = resolutionstring.right(resolutionstring.length()-separator_pos-3);
845 screendata->current_x_pixel_count = x_res_string.toInt();
846 screendata->current_y_pixel_count = y_res_string.toInt();
847 screendata->current_orientation_mask = getHardwareRotationFlags(screendata);
852 int primary_offset_x = 0;
853 int primary_offset_y = 0;
854 for (i=0;i<numberOfScreens;i++) {
855 screendata = screenInfoArray.at(i);
856 if (screendata->is_primary) {
857 primary_offset_x = screendata->absolute_x_position;
858 primary_offset_y = screendata->absolute_y_position;
859 primary_offset_x = primary_offset_x * (-1);
860 primary_offset_y = primary_offset_y * (-1);
863 for (i=0;i<numberOfScreens;i++) {
864 screendata = screenInfoArray.at(i);
865 screendata->absolute_x_position = screendata->absolute_x_position + primary_offset_x;
866 screendata->absolute_y_position = screendata->absolute_y_position + primary_offset_y;
870 TQPoint KRandrSimpleAPI::primaryScreenOffsetFromTLC(TQPtrList<SingleScreenData> screenInfoArray) {
872 SingleScreenData *screendata;
873 int numberOfScreens = screenInfoArray.count();
875 int primary_offset_x = 0;
876 int primary_offset_y = 0;
877 for (i=0;i<numberOfScreens;i++) {
878 screendata = screenInfoArray.at(i);
879 if (screendata->absolute_x_position < primary_offset_x) {
880 primary_offset_x = screendata->absolute_x_position;
882 if (screendata->absolute_y_position < primary_offset_y) {
883 primary_offset_y = screendata->absolute_y_position;
886 primary_offset_x = primary_offset_x * (-1);
887 primary_offset_y = primary_offset_y * (-1);
889 return TQPoint(primary_offset_x, primary_offset_y);
892 void KRandrSimpleAPI::applySystemwideDisplayGamma(TQPtrList<SingleScreenData> screenInfoArray) {
894 Display *randr_display;
895 XRROutputInfo *output_info;
896 ScreenInfo *randr_screen_info;
899 SingleScreenData *screendata;
901 if (isValid() ==
true) {
902 randr_display = qt_xdisplay();
903 randr_screen_info = read_screen_info(randr_display);
904 for (i = 0; i < screenInfoArray.count(); i++) {
905 screendata = screenInfoArray.at(i);
906 output_info = randr_screen_info->outputs[i]->info;
907 CrtcInfo *current_crtc = randr_screen_info->outputs[i]->cur_crtc;
912 int size = XRRGetCrtcGammaSize(randr_display, current_crtc->id);
916 gamma = XRRAllocGamma(size);
920 for (i = 0; i < size; i++) {
921 if (screendata->gamma_red == 1.0)
922 gamma->red[i] = i << 8;
924 gamma->red[i] = (pow((
double)i/(
double)(size-1), (
double)screendata->gamma_red) * (double)(size-1)*256);
926 if (screendata->gamma_green == 1.0)
927 gamma->green[i] = i << 8;
929 gamma->green[i] = (pow((
double)i/(
double)(size-1), (
double)screendata->gamma_green) * (double)(size-1)*256);
931 if (screendata->gamma_blue == 1.0)
932 gamma->blue[i] = i << 8;
934 gamma->blue[i] = (pow((
double)i/(
double)(size-1), (
double)screendata->gamma_blue) * (double)(size-1)*256);
936 XRRSetCrtcGamma(randr_display, current_crtc->id, gamma);
940 freeScreenInfoStructure(randr_screen_info);
944 void KRandrSimpleAPI::applySystemwideDisplayDPMS(TQPtrList<SingleScreenData> screenInfoArray) {
946 Display *randr_display;
947 XRROutputInfo *output_info;
948 ScreenInfo *randr_screen_info;
951 SingleScreenData *screendata;
953 if (isValid() ==
true) {
954 randr_display = qt_xdisplay();
955 randr_screen_info = read_screen_info(randr_display);
956 for (i = 0; i < screenInfoArray.count(); i++) {
957 screendata = screenInfoArray.at(i);
958 output_info = randr_screen_info->outputs[i]->info;
959 CrtcInfo *current_crtc = randr_screen_info->outputs[i]->cur_crtc;
963 if (!screendata->has_dpms) {
966 if (screendata->enable_dpms) {
967 DPMSSetTimeouts(randr_display, screendata->dpms_standby_delay, screendata->dpms_suspend_delay, screendata->dpms_off_delay);
968 DPMSEnable(randr_display);
971 DPMSDisable(randr_display);
974 freeScreenInfoStructure(randr_screen_info);
978 void KRandrSimpleAPI::freeScreenInfoStructure(ScreenInfo* screen_info) {
981 for (i=0; i<screen_info->n_crtc; i++) {
982 free(screen_info->crtcs[i]);
984 for (i=0; i<screen_info->n_output; i++) {
985 free(screen_info->outputs[i]);
987 free(screen_info->outputs);
988 free(screen_info->crtcs);
992 TQPtrList<SingleScreenData> KRandrSimpleAPI::readCurrentDisplayConfiguration() {
997 XRROutputInfo *output_info;
998 SingleScreenData *screendata;
999 TQPtrList<SingleScreenData> screenInfoArray;
1001 Display *randr_display;
1002 ScreenInfo *randr_screen_info;
1005 destroyScreenInformationObject(screenInfoArray);
1007 int numberOfScreens = 0;
1008 if (isValid() ==
true) {
1009 randr_display = qt_xdisplay();
1010 randr_screen_info = read_screen_info(randr_display);
1011 for (i = 0; i < randr_screen_info->n_output; i++) {
1012 output_info = randr_screen_info->outputs[i]->info;
1013 CrtcInfo *current_crtc = randr_screen_info->outputs[i]->cur_crtc;
1016 screendata =
new SingleScreenData;
1017 screenInfoArray.append(screendata);
1018 screendata->screenFriendlyName = TQString(i18n(
"%1. %2 output on %3")).arg(i+1).arg(capitalizeString(output_info->name)).arg(
":0");
1019 screendata->generic_screen_detected =
false;
1022 TQString edid = getEDIDMonitorName(0, output_info->name);
1023 if (!edid.isNull()) {
1024 screendata->screenFriendlyName = TQString(i18n(
"%1. %2 on %3 on card %4")).arg(i+1).arg(edid).arg(capitalizeString(output_info->name)).arg(
"0");
1029 RandRScreen *cur_screen = 0;
1030 if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
1032 screen_active =
false;
1035 if (randr_screen_info->outputs[i]->cur_crtc) {
1037 screen_active =
true;
1038 cur_screen =
new RandRScreen(i);
1042 screen_active =
false;
1043 cur_screen =
new RandRScreen(i);
1048 screendata->has_dpms = 1;
1049 if (screendata->has_dpms) {
1050 CARD16 dpms_standby_delay;
1051 CARD16 dpms_suspend_delay;
1052 CARD16 dpms_off_delay;
1053 screendata->has_dpms = DPMSGetTimeouts(randr_display, &dpms_standby_delay, &dpms_suspend_delay, &dpms_off_delay);
1054 screendata->dpms_standby_delay = dpms_standby_delay;
1055 screendata->dpms_suspend_delay = dpms_suspend_delay;
1056 screendata->dpms_off_delay = dpms_off_delay;
1057 if (screendata->has_dpms) {
1060 screendata->has_dpms = DPMSInfo(randr_display, &power_level, &enable_dpms);
1061 screendata->enable_dpms = enable_dpms;
1064 if (!screendata->has_dpms) {
1065 screendata->enable_dpms =
false;
1066 screendata->dpms_standby_delay = 0;
1067 screendata->dpms_suspend_delay = 0;
1068 screendata->dpms_off_delay = 0;
1072 screendata->screen_connected =
true;
1073 for (
int j = 0; j < cur_screen->numSizes(); j++) {
1074 screendata->resolutions.append(i18n(
"%1 x %2").arg(cur_screen->pixelSize(j).width()).arg(cur_screen->pixelSize(j).height()));
1076 screendata->current_resolution_index = 0;
1078 screendata->current_resolution_index = screendata->resolutions.findIndex(i18n(
"%1 x %2").arg(current_crtc->info->width).arg(current_crtc->info->height));
1080 if (screendata->current_resolution_index < 0) {
1081 screendata->current_resolution_index = cur_screen->proposedSize();
1085 TQStringList rr = cur_screen->refreshRates(screendata->current_resolution_index);
1086 for (TQStringList::Iterator it = rr.begin(); it != rr.end(); ++it) {
1087 screendata->refresh_rates.append(*it);
1089 screendata->current_refresh_rate_index = cur_screen->proposedRefreshRate();
1093 screendata->color_depths.append(i18n(
"Default"));
1094 screendata->current_color_depth_index = 0;
1104 screendata->rotations.append(i18n(
"Normal"));
1105 screendata->rotations.append(i18n(
"Rotate 90 degrees"));
1106 screendata->rotations.append(i18n(
"Rotate 180 degrees"));
1107 screendata->rotations.append(i18n(
"Rotate 270 degrees"));
1108 screendata->current_orientation_mask = cur_screen->proposedRotation();
1109 switch (screendata->current_orientation_mask & RandRScreen::RotateMask) {
1110 case RandRScreen::Rotate0:
1111 screendata->current_rotation_index = 0;
1113 case RandRScreen::Rotate90:
1114 screendata->current_rotation_index = 1;
1116 case RandRScreen::Rotate180:
1117 screendata->current_rotation_index = 2;
1119 case RandRScreen::Rotate270:
1120 screendata->current_rotation_index = 3;
1124 Q_ASSERT(screendata->current_orientation_mask & RandRScreen::RotateMask);
1127 screendata->has_x_flip = (screendata->current_orientation_mask & RandRScreen::ReflectX);
1128 screendata->has_y_flip = (screendata->current_orientation_mask & RandRScreen::ReflectY);
1129 screendata->supports_transformations = (cur_screen->rotations() != RandRScreen::Rotate0);
1132 RROutput primaryoutput = XRRGetOutputPrimary(qt_xdisplay(), DefaultRootWindow(qt_xdisplay()));
1133 if (primaryoutput == randr_screen_info->outputs[i]->id)
1134 screendata->is_primary =
false;
1136 screendata->is_primary =
true;
1137 screendata->is_extended = screen_active;
1138 if (!screendata->is_extended)
1139 screendata->is_primary =
false;
1142 screendata->absolute_x_position = 0;
1143 screendata->absolute_y_position = 0;
1145 screendata->absolute_x_position = current_crtc->info->x;
1146 screendata->absolute_y_position = current_crtc->info->y;
1150 screendata->current_x_pixel_count = cur_screen->pixelSize(screendata->current_resolution_index).width();
1151 screendata->current_y_pixel_count = cur_screen->pixelSize(screendata->current_resolution_index).height();
1159 screendata->gamma_red = 2.2;
1160 screendata->gamma_green = 2.2;
1161 screendata->gamma_blue = 2.2;
1165 int size = XRRGetCrtcGammaSize(randr_display, current_crtc->id);
1167 XRRCrtcGamma *gammastruct = XRRGetCrtcGamma (randr_display, current_crtc->id);
1168 screendata->gamma_red = log(gammastruct->red[slot]/((size-1.0)*256.0))/log(slot/(size-1.0));
1169 screendata->gamma_green = log(gammastruct->green[slot]/((size-1.0)*256.0))/log(slot/(size-1.0));
1170 screendata->gamma_blue = log(gammastruct->blue[slot]/((size-1.0)*256.0))/log(slot/(size-1.0));
1174 screendata->gamma_red = floorf(screendata->gamma_red * 10 + 0.5) / 10;
1175 screendata->gamma_green = floorf(screendata->gamma_green * 10 + 0.5) / 10;
1176 screendata->gamma_blue = floorf(screendata->gamma_blue * 10 + 0.5) / 10;
1182 screendata->screenFriendlyName = screendata->screenFriendlyName + TQString(
" (") + i18n(
"disconnected") + TQString(
")");
1183 screendata->screen_connected =
false;
1185 screendata->resolutions = i18n(
"Default");
1186 screendata->refresh_rates = i18n(
"Default");
1187 screendata->color_depths = i18n(
"Default");
1188 screendata->rotations = i18n(
"N/A");
1190 screendata->current_resolution_index = 0;
1191 screendata->current_refresh_rate_index = 0;
1192 screendata->current_color_depth_index = 0;
1194 screendata->gamma_red = 2.2;
1195 screendata->gamma_green = 2.2;
1196 screendata->gamma_blue = 2.2;
1198 screendata->current_rotation_index = 0;
1199 screendata->current_orientation_mask = 0;
1200 screendata->has_x_flip =
false;
1201 screendata->has_y_flip =
false;
1202 screendata->supports_transformations =
false;
1204 screendata->is_primary =
false;
1205 screendata->is_extended =
false;
1206 screendata->absolute_x_position = 0;
1207 screendata->absolute_y_position = 0;
1208 screendata->current_x_pixel_count = 640;
1209 screendata->current_y_pixel_count = 480;
1216 freeScreenInfoStructure(randr_screen_info);
1219 screendata =
new SingleScreenData;
1220 screenInfoArray.append(screendata);
1223 screendata->screenFriendlyName = i18n(
"Default output on generic video card");
1224 screendata->generic_screen_detected =
true;
1225 screendata->screen_connected =
true;
1227 screendata->resolutions = i18n(
"Default");
1228 screendata->refresh_rates = i18n(
"Default");
1229 screendata->color_depths = i18n(
"Default");
1230 screendata->rotations = i18n(
"N/A");
1232 screendata->current_resolution_index = 0;
1233 screendata->current_refresh_rate_index = 0;
1234 screendata->current_color_depth_index = 0;
1236 screendata->gamma_red = 2.2;
1237 screendata->gamma_green = 2.2;
1238 screendata->gamma_blue = 2.2;
1240 screendata->current_rotation_index = 0;
1241 screendata->current_orientation_mask = 0;
1242 screendata->has_x_flip =
false;
1243 screendata->has_y_flip =
false;
1244 screendata->supports_transformations =
false;
1246 screendata->is_primary =
true;
1247 screendata->is_extended =
true;
1248 screendata->absolute_x_position = 0;
1249 screendata->absolute_y_position = 0;
1250 screendata->current_x_pixel_count = 640;
1251 screendata->current_y_pixel_count = 480;
1258 screendata = screenInfoArray.at(0);
1259 screendata->is_primary =
true;
1261 return screenInfoArray;
1264 TQString KRandrSimpleAPI::clearIccConfiguration() {
1266 TQString icc_command;
1268 char xcalib_result[2048];
1272 icc_command = TQString(
"xcalib -c");
1273 if ((pipe_xcalib = popen(icc_command.ascii(),
"r")) == NULL)
1275 printf(
"Xcalib pipe error [xcalib clear]\n");
1278 fgets(xcalib_result, 2048, pipe_xcalib);
1279 pclose(pipe_xcalib);
1280 for (i=1;i<2048;i++) {
1281 if (xcalib_result[i] == 0) {
1282 xcalib_result[i-1]=0;
1286 if (strlen(xcalib_result) > 2) {
1287 return xcalib_result;
1293 ScreenInfo* KRandrSimpleAPI::read_screen_info (Display *display)
1295 return internal_read_screen_info(display);
1298 int KRandrSimpleAPI::set_screen_size (ScreenInfo *screen_info)
1300 return internal_set_screen_size(screen_info);
1303 void KRandrSimpleAPI::output_auto (ScreenInfo *screen_info, OutputInfo *output_info)
1305 internal_output_auto (screen_info, output_info);
1308 void KRandrSimpleAPI::output_off(ScreenInfo *screen_info, OutputInfo *output)
1310 internal_output_off(screen_info, output);
1313 CrtcInfo* KRandrSimpleAPI::auto_find_crtc (ScreenInfo *screen_info, OutputInfo *output_info)
1315 return internal_auto_find_crtc (screen_info, output_info);
1318 XRRModeInfo *KRandrSimpleAPI::find_mode_by_xid (ScreenInfo *screen_info, RRMode mode_id)
1320 return internal_find_mode_by_xid (screen_info, mode_id);
1323 int KRandrSimpleAPI::mode_height (XRRModeInfo *mode_info, Rotation rotation)
1325 return internal_mode_height (mode_info, rotation);
1328 int KRandrSimpleAPI::mode_width (XRRModeInfo *mode_info, Rotation rotation)
1330 return internal_mode_width (mode_info, rotation);
1333 int KRandrSimpleAPI::get_width_by_output_id (ScreenInfo *screen_info, RROutput output_id)
1335 return internal_get_width_by_output_id (screen_info, output_id);
1338 int KRandrSimpleAPI::get_height_by_output_id (ScreenInfo *screen_info, RROutput output_id)
1340 return internal_get_height_by_output_id (screen_info, output_id);
1343 char *KRandrSimpleAPI::get_output_name (ScreenInfo *screen_info, RROutput
id)
1345 return internal_get_output_name (screen_info,
id);
1348 Status KRandrSimpleAPI::crtc_apply (CrtcInfo *crtc_info)
1350 return internal_crtc_apply (crtc_info);
1353 Status KRandrSimpleAPI::crtc_disable (CrtcInfo *crtc)
1355 return internal_crtc_disable (crtc);
1358 int KRandrSimpleAPI::main_low_apply (ScreenInfo *screen_info)
1360 return internal_main_low_apply (screen_info);
1363 bool KRandrSimpleAPI::kRandrHasRandr(
void)
1368 const char *KRandrSimpleAPI::kRandrVersion(
void)
1373 const char *KRandrSimpleAPI::kRandrCopyright(
void)
1375 return "LibKRandr 0.9.5 (C)2010 Timothy Pearson <kb9vqf@pearsoncomputing.net>. U.S.A.";
1383 const char *kRandrVersion(
void)
1385 return KRandrSimpleAPI::kRandrVersion();
1388 const char *kRandrCopyright(
void)
1390 return KRandrSimpleAPI::kRandrCopyright();
int readListEntry(const TQString &pKey, TQStrList &list, char sep=',') const
TQString readEntry(const TQString &pKey, const TQString &aDefault=TQString::null) const
double readDoubleNumEntry(const TQString &pKey, double nDefault=0.0) const
void writeEntry(const TQString &pKey, const TQString &pValue, bool bPersistent=true, bool bGlobal=false, bool bNLS=false)
void setGroup(const TQString &group)
int readNumEntry(const TQString &pKey, int nDefault=0) const
bool readBoolEntry(const TQString &pKey, bool bDefault=false) const
virtual TQStringList groupList() const