/* libkrandr.cc - class KRandr that makes it easy to use XRandr in KDE
This file is part of KRandr 0.9 .5
Copyright ( C ) 2010 Timothy Pearson
LibKRandr ' s homepage : http : //www.trinitydesktop.org
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation ; either
version 2 of the License , or ( at your option ) any later version .
This library is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Library General Public License for more details .
You should have received a copy of the GNU Library General Public License
along with this library ; see the file COPYING . LIB . If not , write to
the Free Software Foundation , Inc . , 51 Franklin Street , Fifth Floor ,
Boston , MA 02110 - 1301 , USA .
Send comments and bug fixes to Timothy Pearson < kb9vqf @ pearsoncomputing . net >
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <tqdir.h>
# include <tqtimer.h>
# include <tqstringlist.h>
# include <klocale.h>
# include <kmessagebox.h>
# include <kapplication.h>
# include <stdlib.h>
# include <unistd.h>
# include <cmath>
# include "libkrandr.h"
# include <X11/extensions/dpms.h>
// FIXME
// For now, just use the standalone xrandr program to apply the display settings
# define USE_XRANDR_PROGRAM
// This routine is courtsey of an answer on "Stack Overflow"
// It takes an LSB-first int and makes it an MSB-first int (or vice versa)
unsigned int reverse_bits ( register unsigned int x )
{
x = ( ( ( x & 0xaaaaaaaa ) > > 1 ) | ( ( x & 0x55555555 ) < < 1 ) ) ;
x = ( ( ( x & 0xcccccccc ) > > 2 ) | ( ( x & 0x33333333 ) < < 2 ) ) ;
x = ( ( ( x & 0xf0f0f0f0 ) > > 4 ) | ( ( x & 0x0f0f0f0f ) < < 4 ) ) ;
x = ( ( ( x & 0xff00ff00 ) > > 8 ) | ( ( x & 0x00ff00ff ) < < 8 ) ) ;
return ( ( x > > 16 ) | ( x < < 16 ) ) ;
}
// This routine returns the output of an arbitrary Bash command
TQString exec ( const char * cmd ) {
TQString bashcommand = cmd ;
bashcommand = bashcommand . replace ( " \" " , " \\ \" " ) ;
bashcommand = TQString ( " /bin/bash -c \" %1 \" 2>&1 " ) . arg ( bashcommand ) ;
FILE * pipe = popen ( bashcommand . ascii ( ) , " r " ) ;
if ( ! pipe ) return " ERROR " ;
char buffer [ 128 ] ;
TQString result = " " ;
while ( ! feof ( pipe ) ) {
if ( fgets ( buffer , 128 , pipe ) ! = NULL ) {
result + = buffer ;
}
}
pclose ( pipe ) ;
result . remove ( result . length ( ) , 1 ) ;
return result ;
}
TQString capitalizeString ( TQString in ) {
return in . left ( 1 ) . upper ( ) + in . right ( in . length ( ) - 1 ) ;
}
TQString KRandrSimpleAPI : : getIccFileName ( TQString profileName , TQString screenName , TQString kde_confdir ) {
KSimpleConfig * t_config = NULL ;
KSimpleConfig * t_systemconfig = NULL ;
int t_numberOfProfiles ;
TQStringList t_cfgProfiles ;
TQString retval ;
if ( profileName ! = NULL ) {
t_config = new KSimpleConfig ( TQString : : fromLatin1 ( " kiccconfigrc " ) ) ;
}
else {
t_systemconfig = new KSimpleConfig ( kde_confdir + TQString ( " /kicc/kiccconfigrc " ) ) ;
}
if ( profileName ! = NULL ) {
t_config - > setGroup ( NULL ) ;
if ( t_config - > readBoolEntry ( " EnableICC " , false ) = = true ) {
t_config - > setGroup ( profileName ) ;
retval = t_config - > readEntry ( screenName ) ;
}
else {
retval = " " ;
}
}
else {
t_systemconfig - > setGroup ( NULL ) ;
if ( t_systemconfig - > readBoolEntry ( " EnableICC " , false ) = = true ) {
retval = t_systemconfig - > readEntry ( " ICCFile " ) ;
}
else {
retval = " " ;
}
}
if ( profileName ! = " " ) {
if ( t_config ) {
delete t_config ;
}
}
else {
if ( t_systemconfig ) {
delete t_systemconfig ;
}
}
return retval ;
}
TQString KRandrSimpleAPI : : applyIccFile ( TQString screenName , TQString fileName ) {
int i ;
int j ;
Display * randr_display ;
ScreenInfo * randr_screen_info ;
XRROutputInfo * output_info ;
int screenNumber = 0 ;
if ( fileName ! = " " ) {
// FIXME
// This should use the RRSetCrtcGamma function when available
// That is the only way to get proper setting when two output are active at the same time
// (otherwise in clone mode only one screen is available)
// HACK
// For now, simply exit with no changes if screenName is not an active output
if ( isValid ( ) = = true ) {
screenNumber = - 1 ;
randr_display = tqt_xdisplay ( ) ;
randr_screen_info = read_screen_info ( randr_display ) ;
if ( randr_screen_info = = NULL ) {
return " " ;
}
j = 0 ;
for ( i = 0 ; i < randr_screen_info - > n_output ; i + + ) {
output_info = randr_screen_info - > outputs [ i ] - > info ;
// Look for ON outputs...
if ( ! randr_screen_info - > outputs [ i ] - > cur_crtc ) {
continue ;
}
// ...that are connected
if ( RR_Disconnected = = randr_screen_info - > outputs [ i ] - > info - > connection ) {
continue ;
}
if ( output_info - > name = = screenName ) {
screenNumber = j ;
}
j + + ;
}
freeScreenInfoStructure ( randr_screen_info ) ;
}
if ( screenNumber > = 0 ) {
// Apply ICC settings with XCalib
TQString icc_command ;
FILE * pipe_xcalib ;
char xcalib_result [ 2048 ] ;
int i ;
xcalib_result [ 0 ] = 0 ;
icc_command = TQString ( " xcalib \" %1 \" " ) . arg ( fileName ) ;
if ( ( pipe_xcalib = popen ( icc_command . ascii ( ) , " r " ) ) = = NULL )
{
printf ( " Xcalib pipe error \n \r [xcalib apply] " ) ;
}
else {
if ( fgets ( xcalib_result , 2048 , pipe_xcalib ) ) {
pclose ( pipe_xcalib ) ;
for ( i = 1 ; i < 2048 ; i + + ) {
if ( xcalib_result [ i ] = = 0 ) {
xcalib_result [ i - 1 ] = 0 ;
i = 2048 ;
}
}
if ( strlen ( xcalib_result ) > 2 ) {
return xcalib_result ;
}
}
else {
return " " ;
}
}
}
}
else {
// Reset ICC profile on this screen
// FIXME
// This should use the RRSetCrtcGamma function when available
// That is the only way to get proper setting when two output are active at the same time
// (otherwise in clone mode only one screen is available)
// HACK
// For now, simply exit with no changes if screenName is not an active output
if ( isValid ( ) = = true ) {
screenNumber = - 1 ;
randr_display = tqt_xdisplay ( ) ;
randr_screen_info = read_screen_info ( randr_display ) ;
if ( randr_screen_info = = NULL ) {
return " " ;
}
j = 0 ;
for ( i = 0 ; i < randr_screen_info - > n_output ; i + + ) {
output_info = randr_screen_info - > outputs [ i ] - > info ;
// Look for ON outputs...
if ( ! randr_screen_info - > outputs [ i ] - > cur_crtc ) {
continue ;
}
// ...that are connected
if ( RR_Disconnected = = randr_screen_info - > outputs [ i ] - > info - > connection ) {
continue ;
}
if ( output_info - > name = = screenName ) {
screenNumber = j ;
}
j + + ;
}
freeScreenInfoStructure ( randr_screen_info ) ;
}
if ( screenNumber > = 0 ) {
// Apply ICC settings with XCalib
TQString icc_command ;
FILE * pipe_xcalib ;
char xcalib_result [ 2048 ] ;
int i ;
xcalib_result [ 0 ] = 0 ;
icc_command = TQString ( " xcalib -c " ) ;
if ( ( pipe_xcalib = popen ( icc_command . ascii ( ) , " r " ) ) = = NULL )
{
printf ( " Xcalib pipe error \n \r [xcalib clear] " ) ;
}
else {
if ( fgets ( xcalib_result , 2048 , pipe_xcalib ) ) {
pclose ( pipe_xcalib ) ;
for ( i = 1 ; i < 2048 ; i + + ) {
if ( xcalib_result [ i ] = = 0 ) {
xcalib_result [ i - 1 ] = 0 ;
i = 2048 ;
}
}
if ( strlen ( xcalib_result ) > 2 ) {
return xcalib_result ;
}
}
else {
return " " ;
}
}
}
}
return " " ;
}
TQString KRandrSimpleAPI : : applyIccConfiguration ( TQString profileName , TQString kde_confdir ) {
int i ;
Display * randr_display ;
ScreenInfo * randr_screen_info ;
XRROutputInfo * output_info ;
KSimpleConfig * t_config ;
int screenNumber = 0 ;
TQString errorstr = " " ;
t_config = new KSimpleConfig ( TQString : : fromLatin1 ( " kiccconfigrc " ) ) ;
// Find all screens
if ( isValid ( ) = = true ) {
randr_display = tqt_xdisplay ( ) ;
randr_screen_info = read_screen_info ( randr_display ) ;
if ( randr_screen_info = = NULL ) {
return " " ;
}
for ( i = 0 ; i < randr_screen_info - > n_output ; i + + ) {
output_info = randr_screen_info - > outputs [ i ] - > info ;
errorstr = applyIccFile ( output_info - > name , getIccFileName ( profileName , output_info - > name , kde_confdir ) ) ;
if ( errorstr ! = " " ) {
return errorstr ;
}
}
freeScreenInfoStructure ( randr_screen_info ) ;
}
else {
return applyIccFile ( getIccFileName ( profileName , " Default " , kde_confdir ) , " Default " ) ;
}
t_config - > writeEntry ( " CurrentProfile " , profileName ) ;
t_config - > sync ( ) ;
delete t_config ;
return " " ;
}
TQString KRandrSimpleAPI : : getEDIDMonitorName ( int card , TQString displayname ) {
TQString edid ;
TQByteArray binaryedid = getEDID ( card , displayname ) ;
if ( binaryedid . isNull ( ) )
return TQString ( ) ;
// Get the manufacturer ID
unsigned char letter_1 = ( ( binaryedid [ 8 ] > > 2 ) & 0x1F ) + 0x40 ;
unsigned char letter_2 = ( ( ( binaryedid [ 8 ] & 0x03 ) < < 3 ) | ( ( binaryedid [ 9 ] > > 5 ) & 0x07 ) ) + 0x40 ;
unsigned char letter_3 = ( binaryedid [ 9 ] & 0x1F ) + 0x40 ;
TQChar qletter_1 = TQChar ( letter_1 ) ;
TQChar qletter_2 = TQChar ( letter_2 ) ;
TQChar qletter_3 = TQChar ( letter_3 ) ;
TQString manufacturer_id = TQString ( " %1%2%3 " ) . arg ( qletter_1 ) . arg ( qletter_2 ) . arg ( qletter_3 ) ;
// Get the model ID
unsigned int raw_model_id = ( ( ( binaryedid [ 10 ] < < 8 ) | binaryedid [ 11 ] ) < < 16 ) & 0xFFFF0000 ;
// Reverse the bit order
unsigned int model_id = reverse_bits ( raw_model_id ) ;
// Try to get the model name
bool has_friendly_name = false ;
unsigned char descriptor_block [ 18 ] ;
int i ;
for ( i = 72 ; i < 90 ; i + + ) {
descriptor_block [ i - 72 ] = binaryedid [ i ] & 0xFF ;
}
if ( ( descriptor_block [ 0 ] ! = 0 ) | | ( descriptor_block [ 1 ] ! = 0 ) | | ( descriptor_block [ 3 ] ! = 0xFC ) ) {
for ( i = 90 ; i < 108 ; i + + ) {
descriptor_block [ i - 90 ] = binaryedid [ i ] & 0xFF ;
}
if ( ( descriptor_block [ 0 ] ! = 0 ) | | ( descriptor_block [ 1 ] ! = 0 ) | | ( descriptor_block [ 3 ] ! = 0xFC ) ) {
for ( i = 108 ; i < 126 ; i + + ) {
descriptor_block [ i - 108 ] = binaryedid [ i ] & 0xFF ;
}
}
}
TQString monitor_name ;
if ( ( descriptor_block [ 0 ] = = 0 ) & & ( descriptor_block [ 1 ] = = 0 ) & & ( descriptor_block [ 3 ] = = 0xFC ) ) {
char * pos = strchr ( ( char * ) ( descriptor_block + 5 ) , ' \n ' ) ;
if ( pos ) {
* pos = 0 ;
has_friendly_name = true ;
monitor_name = TQString ( ( char * ) ( descriptor_block + 5 ) ) ;
}
else {
has_friendly_name = false ;
}
}
// [FIXME]
// Look up manudacturer names if possible!
if ( has_friendly_name )
edid = TQString ( " %1 %2 " ) . arg ( manufacturer_id ) . arg ( monitor_name ) ;
else
edid = TQString ( " %1 0x%2 " ) . arg ( manufacturer_id ) . arg ( model_id , 0 , 16 ) ;
return edid ;
}
TQByteArray KRandrSimpleAPI : : getEDID ( int card , TQString displayname ) {
TQFile file ( TQString ( " /sys/class/drm/card%1-%2/edid " ) . arg ( card ) . arg ( displayname ) ) ;
if ( ! file . open ( IO_ReadOnly ) )
return TQByteArray ( ) ;
TQByteArray binaryedid = file . readAll ( ) ;
file . close ( ) ;
return binaryedid ;
}
TQString KRandrSimpleAPI : : getCurrentProfile ( ) {
TQString profileName ;
KSimpleConfig * t_config ;
t_config = new KSimpleConfig ( TQString : : fromLatin1 ( " kiccconfigrc " ) ) ;
profileName = t_config - > readEntry ( " CurrentProfile " ) ;
delete t_config ;
return profileName ;
}
TQString KRandrSimpleAPI : : applySystemWideIccConfiguration ( TQString kde_confdir ) {
// Apply ICC settings with XCalib
TQString icc_command ;
FILE * pipe_xcalib ;
char xcalib_result [ 2048 ] ;
int i ;
xcalib_result [ 0 ] = 0 ;
icc_command = TQString ( " xcalib \" %1 \" " ) . arg ( getIccFileName ( NULL , " Default " , kde_confdir ) ) ;
if ( ( pipe_xcalib = popen ( icc_command . ascii ( ) , " r " ) ) = = NULL )
{
printf ( " Xcalib pipe error [xcalib apply] \n \r " ) ;
}
else {
if ( fgets ( xcalib_result , 2048 , pipe_xcalib ) ) {
pclose ( pipe_xcalib ) ;
for ( i = 1 ; i < 2048 ; i + + ) {
if ( xcalib_result [ i ] = = 0 ) {
xcalib_result [ i - 1 ] = 0 ;
i = 2048 ;
}
}
if ( strlen ( xcalib_result ) > 2 ) {
return xcalib_result ;
}
}
else {
return " " ;
}
}
return " " ;
}
TQStringList KRandrSimpleAPI : : getDisplayConfigurationProfiles ( TQString kde_confdir ) {
TQStringList ret ;
TQDir d ( kde_confdir + " /displayconfig/ " ) ;
d . setFilter ( TQDir : : Files ) ;
d . setSorting ( TQDir : : Name ) ;
const TQFileInfoList * list = d . entryInfoList ( ) ;
if ( list ) {
TQFileInfoListIterator it ( * list ) ;
TQFileInfo * fi ;
while ( ( fi = it . current ( ) ) ! = 0 ) {
if ( fi - > fileName ( ) ! = " default " ) {
ret . append ( fi - > fileName ( ) ) ;
}
+ + it ;
}
}
return ret ;
}
bool KRandrSimpleAPI : : deleteDisplayConfiguration ( TQString profilename , TQString kde_confdir ) {
TQString fileName = kde_confdir + " /displayconfig/ " ;
fileName . append ( profilename ) ;
return ( ! unlink ( fileName . ascii ( ) ) ) ;
}
bool KRandrSimpleAPI : : renameDisplayConfiguration ( TQString profilename , TQString newprofilename , TQString kde_confdir ) {
TQString fileName = kde_confdir + " /displayconfig/ " ;
TQString newFileName = fileName ;
fileName . append ( profilename ) ;
newFileName . append ( newprofilename ) ;
TQDir d ( kde_confdir + " /displayconfig/ " ) ;
return ( d . rename ( fileName , newFileName ) ) ;
}
void KRandrSimpleAPI : : saveDisplayConfiguration ( bool enable , bool applyonstart , TQString profilename , TQString defaultprofilename , TQString kde_confdir , TQPtrList < SingleScreenData > screenInfoArray ) {
int i ;
TQString filename ;
filename = " displayglobals " ;
filename . prepend ( kde_confdir . append ( " / " ) ) ;
KSimpleConfig * display_config = new KSimpleConfig ( filename ) ;
display_config - > setGroup ( " General " ) ;
display_config - > writeEntry ( " EnableDisplayControl " , enable ) ;
display_config - > writeEntry ( " ApplySettingsOnStart " , applyonstart ) ;
display_config - > writeEntry ( " StartupProfileName " , defaultprofilename ) ;
display_config - > sync ( ) ;
delete display_config ;
filename = profilename ;
if ( filename = = " " ) {
filename = " default " ;
}
filename . prepend ( kde_confdir . append ( " /displayconfig/ " ) ) ;
display_config = new KSimpleConfig ( filename ) ;
i = 0 ;
SingleScreenData * screendata ;
for ( screendata = screenInfoArray . first ( ) ; screendata ; screendata = screenInfoArray . next ( ) ) {
display_config - > setGroup ( TQString ( " SCREEN %1 " ) . arg ( i ) ) ;
display_config - > writeEntry ( " ScreenUniqueName " , screendata - > screenUniqueName ) ;
display_config - > writeEntry ( " ScreenFriendlyName " , screendata - > screenFriendlyName ) ;
display_config - > writeEntry ( " GenericScreenDetected " , screendata - > generic_screen_detected ) ;
display_config - > writeEntry ( " ScreenConnected " , screendata - > screen_connected ) ;
display_config - > writeEntry ( " Resolutions " , screendata - > resolutions ) ;
display_config - > writeEntry ( " RefreshRates " , screendata - > refresh_rates ) ;
display_config - > writeEntry ( " ColorDepths " , screendata - > color_depths ) ;
display_config - > writeEntry ( " AvailableRotations " , screendata - > rotations ) ;
display_config - > writeEntry ( " CurrentResolution " , screendata - > current_resolution_index ) ;
display_config - > writeEntry ( " CurrentRefreshRate " , screendata - > current_refresh_rate_index ) ;
display_config - > writeEntry ( " CurrentColorDepth " , screendata - > current_color_depth_index ) ;
display_config - > writeEntry ( " CurrentRotation " , screendata - > current_rotation_index ) ;
display_config - > writeEntry ( " CurrentOrientiation " , screendata - > current_orientation_mask ) ;
display_config - > writeEntry ( " GammaRed " , screendata - > gamma_red ) ;
display_config - > writeEntry ( " GammaGreen " , screendata - > gamma_green ) ;
display_config - > writeEntry ( " GammaBlue " , screendata - > gamma_blue ) ;
display_config - > writeEntry ( " CurrentXFlip " , screendata - > has_x_flip ) ;
display_config - > writeEntry ( " CurrentYFlip " , screendata - > has_y_flip ) ;
display_config - > writeEntry ( " SupportsTransformation " , screendata - > supports_transformations ) ;
display_config - > writeEntry ( " IsPrimary " , screendata - > is_primary ) ;
display_config - > writeEntry ( " IsExtended " , screendata - > is_extended ) ;
display_config - > writeEntry ( " AbsXPos " , screendata - > absolute_x_position ) ;
display_config - > writeEntry ( " AbsYPos " , screendata - > absolute_y_position ) ;
display_config - > writeEntry ( " CurrentXPixelCount " , screendata - > current_x_pixel_count ) ;
display_config - > writeEntry ( " CurrentYPixelCount " , screendata - > current_y_pixel_count ) ;
display_config - > writeEntry ( " HasDPMS " , screendata - > has_dpms ) ;
display_config - > writeEntry ( " EnableDPMS " , screendata - > enable_dpms ) ;
display_config - > writeEntry ( " DPMSStandbyDelay " , screendata - > dpms_standby_delay ) ;
display_config - > writeEntry ( " DPMSSuspendDelay " , screendata - > dpms_suspend_delay ) ;
display_config - > writeEntry ( " DPMSPowerDownDelay " , screendata - > dpms_off_delay ) ;
i + + ;
}
display_config - > sync ( ) ;
delete display_config ;
}
TQPoint KRandrSimpleAPI : : applyStartupDisplayConfiguration ( TQString kde_confdir ) {
bool applyonstart = getDisplayConfigurationStartupAutoApplyEnabled ( kde_confdir ) ;
if ( applyonstart ) {
TQString profilename = getDisplayConfigurationStartupAutoApplyName ( kde_confdir ) ;
return applyDisplayConfiguration ( profilename , kde_confdir ) ;
}
else {
return TQPoint ( ) ;
}
}
TQPoint KRandrSimpleAPI : : applyDisplayConfiguration ( TQString profilename , TQString kde_confdir ) {
TQPoint ret ;
bool enabled = getDisplayConfigurationEnabled ( kde_confdir ) ;
if ( profilename = = " " ) {
profilename = " default " ;
}
if ( enabled ) {
TQPtrList < SingleScreenData > screenInfoArray ;
screenInfoArray = loadDisplayConfiguration ( profilename , kde_confdir ) ;
if ( screenInfoArray . count ( ) > 0 ) {
applyDisplayConfiguration ( screenInfoArray , FALSE , kde_confdir ) ;
}
destroyScreenInformationObject ( screenInfoArray ) ;
screenInfoArray = readCurrentDisplayConfiguration ( ) ;
ensureMonitorDataConsistency ( screenInfoArray ) ;
ret = primaryScreenOffsetFromTLC ( screenInfoArray ) ;
destroyScreenInformationObject ( screenInfoArray ) ;
}
return ret ;
}
TQPtrList < SingleScreenData > KRandrSimpleAPI : : loadDisplayConfiguration ( TQString profilename , TQString kde_confdir ) {
int i ;
TQString filename ;
filename = profilename ;
if ( filename = = " " ) {
filename = " default " ;
}
filename . prepend ( kde_confdir . append ( " /displayconfig/ " ) ) ;
KSimpleConfig * display_config = new KSimpleConfig ( filename ) ;
TQStringList grouplist = display_config - > groupList ( ) ;
SingleScreenData * screendata ;
TQPtrList < SingleScreenData > screenInfoArray ;
for ( TQStringList : : Iterator it = grouplist . begin ( ) ; it ! = grouplist . end ( ) ; + + it ) {
if ( ( * it ) . startsWith ( " SCREEN " ) ) {
display_config - > setGroup ( * it ) ;
i = ( ( * it ) . remove ( " SCREEN " ) ) . toInt ( ) ;
screendata = new SingleScreenData ;
screenInfoArray . append ( screendata ) ;
screendata - > screenUniqueName = display_config - > readEntry ( " ScreenUniqueName " ) ;
screendata - > screenFriendlyName = display_config - > readEntry ( " ScreenFriendlyName " ) ;
screendata - > generic_screen_detected = display_config - > readBoolEntry ( " GenericScreenDetected " ) ;
screendata - > screen_connected = display_config - > readBoolEntry ( " ScreenConnected " ) ;
screendata - > resolutions = display_config - > readListEntry ( " Resolutions " ) ;
screendata - > refresh_rates = display_config - > readListEntry ( " RefreshRates " ) ;
screendata - > color_depths = display_config - > readListEntry ( " ColorDepths " ) ;
screendata - > rotations = display_config - > readListEntry ( " AvailableRotations " ) ;
screendata - > current_resolution_index = display_config - > readNumEntry ( " CurrentResolution " ) ;
screendata - > current_refresh_rate_index = display_config - > readNumEntry ( " CurrentRefreshRate " ) ;
screendata - > current_color_depth_index = display_config - > readNumEntry ( " CurrentColorDepth " ) ;
screendata - > current_rotation_index = display_config - > readNumEntry ( " CurrentRotation " ) ;
screendata - > current_orientation_mask = display_config - > readNumEntry ( " CurrentOrientiation " ) ;
screendata - > gamma_red = display_config - > readDoubleNumEntry ( " GammaRed " ) ;
screendata - > gamma_green = display_config - > readDoubleNumEntry ( " GammaGreen " ) ;
screendata - > gamma_blue = display_config - > readDoubleNumEntry ( " GammaBlue " ) ;
screendata - > has_x_flip = display_config - > readBoolEntry ( " CurrentXFlip " ) ;
screendata - > has_y_flip = display_config - > readBoolEntry ( " CurrentYFlip " ) ;
screendata - > supports_transformations = display_config - > readBoolEntry ( " SupportsTransformation " ) ;
screendata - > is_primary = display_config - > readBoolEntry ( " IsPrimary " ) ;
screendata - > is_extended = display_config - > readBoolEntry ( " IsExtended " ) ;
screendata - > absolute_x_position = display_config - > readNumEntry ( " AbsXPos " ) ;
screendata - > absolute_y_position = display_config - > readNumEntry ( " AbsYPos " ) ;
screendata - > current_x_pixel_count = display_config - > readNumEntry ( " CurrentXPixelCount " ) ;
screendata - > current_y_pixel_count = display_config - > readNumEntry ( " CurrentYPixelCount " ) ;
screendata - > has_dpms = display_config - > readBoolEntry ( " HasDPMS " ) ;
screendata - > enable_dpms = display_config - > readBoolEntry ( " EnableDPMS " ) ;
screendata - > dpms_standby_delay = display_config - > readNumEntry ( " DPMSStandbyDelay " ) ;
screendata - > dpms_suspend_delay = display_config - > readNumEntry ( " DPMSSuspendDelay " ) ;
screendata - > dpms_off_delay = display_config - > readNumEntry ( " DPMSPowerDownDelay " ) ;
}
}
delete display_config ;
return screenInfoArray ;
}
int KRandrSimpleAPI : : getHardwareRotationFlags ( SingleScreenData * screendata ) {
int rotationFlags = 0 ;
TQString rotationDesired = * screendata - > rotations . at ( screendata - > current_rotation_index ) ;
if ( rotationDesired = = ROTATION_0_DEGREES_STRING ) {
rotationFlags = rotationFlags | RandRScreen : : Rotate0 ;
}
else if ( rotationDesired = = ROTATION_90_DEGREES_STRING ) {
rotationFlags = rotationFlags | RandRScreen : : Rotate90 ;
}
else if ( rotationDesired = = ROTATION_180_DEGREES_STRING ) {
rotationFlags = rotationFlags | RandRScreen : : Rotate180 ;
}
else if ( rotationDesired = = ROTATION_270_DEGREES_STRING ) {
rotationFlags = rotationFlags | RandRScreen : : Rotate270 ;
}
if ( screendata - > has_x_flip ) {
rotationFlags = rotationFlags | RandRScreen : : ReflectX ;
}
if ( screendata - > has_y_flip ) {
rotationFlags = rotationFlags | RandRScreen : : ReflectY ;
}
return rotationFlags ;
}
# define USE_XRANDR_PROGRAM
bool KRandrSimpleAPI : : applyDisplayConfiguration ( TQPtrList < SingleScreenData > screenInfoArray , bool test , TQString kde_confdir ) {
int i ;
int j ;
bool accepted = true ;
Display * randr_display ;
XRROutputInfo * output_info ;
ScreenInfo * randr_screen_info ;
SingleScreenData * screendata ;
TQPtrList < SingleScreenData > oldconfig ;
if ( test = = TRUE ) {
oldconfig = readCurrentDisplayConfiguration ( ) ;
}
if ( isValid ( ) = = true ) {
# ifdef USE_XRANDR_PROGRAM
// Assemble the command string for xrandr
TQString command ;
command = " xrandr " ;
randr_display = tqt_xdisplay ( ) ;
randr_screen_info = read_screen_info ( randr_display ) ;
for ( i = 0 ; i < screenInfoArray . count ( ) ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
if ( screendata ) {
output_info = randr_screen_info - > outputs [ i ] - > info ;
command . append ( " --output " ) . append ( output_info - > name ) ;
if ( screendata - > is_primary | | screendata - > is_extended ) {
command . append ( TQString ( " --mode %1x%2 " ) . arg ( screendata - > current_x_pixel_count ) . arg ( screendata - > current_y_pixel_count ) ) ;
command . append ( TQString ( " --pos %1x%2 " ) . arg ( screendata - > absolute_x_position ) . arg ( screendata - > absolute_y_position ) ) ;
command . append ( TQString ( " --refresh %1 " ) . arg ( ( * screendata - > refresh_rates . at ( screendata - > current_refresh_rate_index ) ) . replace ( " Hz " , " " ) ) ) ;
command . append ( TQString ( " --gamma %1:%2:%3 " ) . arg ( screendata - > gamma_red ) . arg ( screendata - > gamma_green ) . arg ( screendata - > gamma_blue ) ) ;
if ( screendata - > current_rotation_index = = 0 ) command . append ( " --rotate " ) . append ( " normal " ) ;
if ( screendata - > current_rotation_index = = 1 ) command . append ( " --rotate " ) . append ( " left " ) ;
if ( screendata - > current_rotation_index = = 2 ) command . append ( " --rotate " ) . append ( " inverted " ) ;
if ( screendata - > current_rotation_index = = 3 ) command . append ( " --rotate " ) . append ( " right " ) ;
if ( ( screendata - > has_x_flip = = 0 ) & & ( screendata - > has_y_flip = = 0 ) ) command . append ( " --reflect " ) . append ( " normal " ) ;
if ( ( screendata - > has_x_flip = = 1 ) & & ( screendata - > has_y_flip = = 0 ) ) command . append ( " --reflect " ) . append ( " x " ) ;
if ( ( screendata - > has_x_flip = = 0 ) & & ( screendata - > has_y_flip = = 1 ) ) command . append ( " --reflect " ) . append ( " y " ) ;
if ( ( screendata - > has_x_flip = = 1 ) & & ( screendata - > has_y_flip = = 1 ) ) command . append ( " --reflect " ) . append ( " xy " ) ;
if ( screendata - > is_primary ) {
command . append ( " --primary " ) ;
}
}
else {
command . append ( " --off " ) ;
}
}
else {
printf ( " [WARNING] Unable to find configuration for monitor %d; settings may not be correctly applied... \n \r " , i ) ; fflush ( stdout ) ;
}
}
freeScreenInfoStructure ( randr_screen_info ) ;
TQString xrandr_command_output = exec ( command . ascii ( ) ) ;
xrandr_command_output = xrandr_command_output . stripWhiteSpace ( ) ;
if ( test ) {
if ( xrandr_command_output ! = " " ) {
applyDisplayConfiguration ( oldconfig , FALSE , kde_confdir ) ;
accepted = false ;
destroyScreenInformationObject ( oldconfig ) ;
KMessageBox : : sorry ( 0 , xrandr_command_output , i18n ( " XRandR encountered a problem " ) ) ;
return accepted ;
}
}
# else
randr_display = tqt_xdisplay ( ) ;
randr_screen_info = read_screen_info ( randr_display ) ;
// Turn off all displays
for ( i = 0 ; i < screenInfoArray . count ( ) ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
output_info = randr_screen_info - > outputs [ i ] - > info ;
randr_screen_info - > cur_crtc = randr_screen_info - > outputs [ i ] - > cur_crtc ;
randr_screen_info - > cur_output = randr_screen_info - > outputs [ i ] ;
randr_screen_info - > cur_output - > auto_set = 0 ;
randr_screen_info - > cur_output - > off_set = 1 ;
output_off ( randr_screen_info , randr_screen_info - > cur_output ) ;
j = main_low_apply ( randr_screen_info ) ;
}
freeScreenInfoStructure ( randr_screen_info ) ;
randr_screen_info = read_screen_info ( randr_display ) ;
// Turn on the primary display
for ( i = 0 ; i < screenInfoArray . count ( ) ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
output_info = randr_screen_info - > outputs [ i ] - > info ;
if ( screendata - > is_primary = = true ) {
randr_screen_info - > cur_crtc = randr_screen_info - > outputs [ i ] - > cur_crtc ;
randr_screen_info - > cur_output = randr_screen_info - > outputs [ i ] ;
randr_screen_info - > cur_output - > auto_set = 1 ;
randr_screen_info - > cur_output - > off_set = 0 ;
output_auto ( randr_screen_info , randr_screen_info - > cur_output ) ;
j = main_low_apply ( randr_screen_info ) ;
}
}
freeScreenInfoStructure ( randr_screen_info ) ;
// Handle the remaining displays
randr_screen_info = read_screen_info ( randr_display ) ;
for ( i = 0 ; i < screenInfoArray . count ( ) ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
output_info = randr_screen_info - > outputs [ i ] - > info ;
// Activate or deactivate the screens as necessary
randr_screen_info - > cur_crtc = randr_screen_info - > outputs [ i ] - > cur_crtc ;
randr_screen_info - > cur_output = randr_screen_info - > outputs [ i ] ;
if ( screendata - > is_primary = = false ) {
if ( screendata - > is_primary | | screendata - > is_extended ) {
randr_screen_info - > cur_output - > auto_set = 1 ;
randr_screen_info - > cur_output - > off_set = 0 ;
output_auto ( randr_screen_info , randr_screen_info - > cur_output ) ;
j = main_low_apply ( randr_screen_info ) ;
}
else {
randr_screen_info - > cur_output - > auto_set = 0 ;
randr_screen_info - > cur_output - > off_set = 1 ;
output_off ( randr_screen_info , randr_screen_info - > cur_output ) ;
j = main_low_apply ( randr_screen_info ) ;
}
}
}
freeScreenInfoStructure ( randr_screen_info ) ;
randr_screen_info = read_screen_info ( randr_display ) ;
for ( i = 0 ; i < screenInfoArray . count ( ) ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
output_info = randr_screen_info - > outputs [ i ] - > info ;
if ( screendata - > is_primary | | screendata - > is_extended ) {
// Set rotation, refresh rate, and size
RandRScreen * cur_screen = new RandRScreen ( i ) ;
cur_screen - > proposeSize ( screendata - > current_resolution_index ) ;
cur_screen - > proposeRefreshRate ( screendata - > current_refresh_rate_index ) ;
cur_screen - > proposeRotation ( getHardwareRotationFlags ( screendata ) ) ;
cur_screen - > applyProposed ( ) ;
delete cur_screen ;
// Force data reload
randr_screen_info = read_screen_info ( randr_display ) ;
output_info = randr_screen_info - > outputs [ i ] - > info ;
// Finally, set the screen's position
randr_screen_info - > cur_crtc = randr_screen_info - > outputs [ i ] - > cur_crtc ;
if ( randr_screen_info - > cur_crtc ) {
randr_screen_info - > cur_crtc - > cur_x = screendata - > absolute_x_position ;
randr_screen_info - > cur_crtc - > cur_y = screendata - > absolute_y_position ;
j = main_low_apply ( randr_screen_info ) ;
}
}
}
freeScreenInfoStructure ( randr_screen_info ) ;
# endif
}
applyDisplayGamma ( screenInfoArray ) ;
applyDisplayDPMS ( screenInfoArray ) ;
TQString current_icc_profile = getCurrentProfile ( ) ;
applySystemWideIccConfiguration ( kde_confdir ) ;
applyIccConfiguration ( current_icc_profile , kde_confdir ) ;
if ( test = = TRUE ) {
int ret = showTestConfigurationDialog ( ) ;
if ( ! ret ) {
applyDisplayConfiguration ( oldconfig , FALSE , kde_confdir ) ;
accepted = false ;
}
destroyScreenInformationObject ( oldconfig ) ;
}
return accepted ;
}
TQPtrList < SingleScreenData > KRandrSimpleAPI : : copyScreenInformationObject ( TQPtrList < SingleScreenData > screenInfoArray ) {
SingleScreenData * origscreendata ;
SingleScreenData * copyscreendata ;
TQPtrList < SingleScreenData > retArray ;
for ( origscreendata = screenInfoArray . first ( ) ; origscreendata ; origscreendata = screenInfoArray . next ( ) ) {
copyscreendata = new SingleScreenData ;
* copyscreendata = * origscreendata ;
retArray . append ( copyscreendata ) ;
}
return retArray ;
}
void KRandrSimpleAPI : : destroyScreenInformationObject ( TQPtrList < SingleScreenData > screenInfoArray ) {
SingleScreenData * screendata ;
for ( screendata = screenInfoArray . first ( ) ; screendata ; screendata = screenInfoArray . next ( ) ) {
screenInfoArray . remove ( screendata ) ;
delete screendata ;
}
}
void KRandrSimpleAPI : : ensureMonitorDataConsistency ( TQPtrList < SingleScreenData > screenInfoArray ) {
int i ;
SingleScreenData * screendata ;
int numberOfScreens = screenInfoArray . count ( ) ;
for ( i = 0 ; i < numberOfScreens ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
if ( ! screendata - > screen_connected ) {
screendata - > is_primary = false ;
screendata - > is_extended = false ;
}
}
bool has_primary_monitor = false ;
for ( i = 0 ; i < numberOfScreens ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
if ( screendata - > is_primary ) {
has_primary_monitor = true ;
}
}
if ( ! has_primary_monitor ) {
for ( i = 0 ; i < numberOfScreens ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
if ( ! has_primary_monitor ) {
if ( screendata - > screen_connected & & screendata - > is_extended ) {
screendata - > is_primary = true ;
screendata - > is_extended = true ;
has_primary_monitor = true ;
}
}
}
}
if ( ! has_primary_monitor ) {
for ( i = 0 ; i < numberOfScreens ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
if ( ! has_primary_monitor ) {
if ( screendata - > screen_connected ) {
screendata - > is_primary = true ;
screendata - > is_extended = true ;
has_primary_monitor = true ;
}
}
}
}
bool found_first_primary_monitor = false ;
for ( i = 0 ; i < numberOfScreens ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
if ( screendata - > is_primary ) {
if ( ! found_first_primary_monitor ) {
found_first_primary_monitor = true ;
}
else {
screendata - > is_primary = false ;
}
}
}
for ( i = 0 ; i < numberOfScreens ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
if ( screendata - > is_primary ) {
screendata - > is_extended = true ;
}
}
for ( i = 0 ; i < numberOfScreens ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
TQString resolutionstring = screendata - > resolutions [ screendata - > current_resolution_index ] ;
int separator_pos = resolutionstring . find ( " x " ) ;
TQString x_res_string = resolutionstring . left ( separator_pos ) ;
TQString y_res_string = resolutionstring . right ( resolutionstring . length ( ) - separator_pos - 3 ) ;
screendata - > current_x_pixel_count = x_res_string . toInt ( ) ;
screendata - > current_y_pixel_count = y_res_string . toInt ( ) ;
screendata - > current_orientation_mask = getHardwareRotationFlags ( screendata ) ;
}
// Each screen's absolute position is given relative to the primary monitor
// Fix up the absolute positions
int primary_offset_x = 0 ;
int primary_offset_y = 0 ;
for ( i = 0 ; i < numberOfScreens ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
if ( screendata - > is_primary ) {
primary_offset_x = screendata - > absolute_x_position ;
primary_offset_y = screendata - > absolute_y_position ;
primary_offset_x = primary_offset_x * ( - 1 ) ;
primary_offset_y = primary_offset_y * ( - 1 ) ;
}
}
for ( i = 0 ; i < numberOfScreens ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
screendata - > absolute_x_position = screendata - > absolute_x_position + primary_offset_x ;
screendata - > absolute_y_position = screendata - > absolute_y_position + primary_offset_y ;
}
}
TQPoint KRandrSimpleAPI : : primaryScreenOffsetFromTLC ( TQPtrList < SingleScreenData > screenInfoArray ) {
int i ;
SingleScreenData * screendata ;
int numberOfScreens = screenInfoArray . count ( ) ;
int primary_offset_x = 0 ;
int primary_offset_y = 0 ;
for ( i = 0 ; i < numberOfScreens ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
if ( screendata - > absolute_x_position < primary_offset_x ) {
primary_offset_x = screendata - > absolute_x_position ;
}
if ( screendata - > absolute_y_position < primary_offset_y ) {
primary_offset_y = screendata - > absolute_y_position ;
}
}
primary_offset_x = primary_offset_x * ( - 1 ) ;
primary_offset_y = primary_offset_y * ( - 1 ) ;
return TQPoint ( primary_offset_x , primary_offset_y ) ;
}
HotPlugRulesList KRandrSimpleAPI : : getHotplugRules ( TQString kde_confdir ) {
int i ;
TQString filename ;
HotPlugRulesList ret ;
filename = " displayglobals " ;
filename . prepend ( kde_confdir . append ( " / " ) ) ;
KSimpleConfig * display_config = new KSimpleConfig ( filename ) ;
TQStringList grouplist = display_config - > groupList ( ) ;
for ( TQStringList : : Iterator it = grouplist . begin ( ) ; it ! = grouplist . end ( ) ; + + it ) {
if ( ! ( * it ) . startsWith ( " Hotplug-Rule " ) ) {
continue ;
}
HotPlugRule rule ;
display_config - > setGroup ( * it ) ;
rule . outputs = display_config - > readListEntry ( " Outputs " ) ;
rule . states = display_config - > readIntListEntry ( " States " ) ;
rule . profileName = display_config - > readEntry ( " Profile " ) ;
ret . append ( rule ) ;
}
delete display_config ;
return ret ;
}
void KRandrSimpleAPI : : saveHotplugRules ( HotPlugRulesList rules , TQString kde_confdir ) {
int i ;
TQString filename ;
filename = " displayglobals " ;
filename . prepend ( kde_confdir . append ( " / " ) ) ;
KSimpleConfig * display_config = new KSimpleConfig ( filename ) ;
TQStringList grouplist = display_config - > groupList ( ) ;
for ( TQStringList : : Iterator it = grouplist . begin ( ) ; it ! = grouplist . end ( ) ; + + it ) {
if ( ! ( * it ) . startsWith ( " Hotplug-Rule " ) ) {
continue ;
}
display_config - > deleteGroup ( * it , true , false ) ;
}
HotPlugRulesList : : Iterator it ;
i = 0 ;
for ( it = rules . begin ( ) ; it ! = rules . end ( ) ; + + it ) {
display_config - > setGroup ( TQString ( " Hotplug-Rule%1 " ) . arg ( i ) ) ;
display_config - > writeEntry ( " Outputs " , ( * it ) . outputs ) ;
display_config - > writeEntry ( " States " , ( * it ) . states ) ;
display_config - > writeEntry ( " Profile " , ( * it ) . profileName ) ;
i + + ;
}
display_config - > sync ( ) ;
delete display_config ;
}
bool KRandrSimpleAPI : : getDisplayConfigurationEnabled ( TQString kde_confdir ) {
TQString filename = " displayglobals " ;
filename . prepend ( kde_confdir . append ( " / " ) ) ;
KSimpleConfig * display_config = new KSimpleConfig ( filename ) ;
display_config - > setGroup ( " General " ) ;
bool enabled = display_config - > readBoolEntry ( " EnableDisplayControl " , false ) ;
delete display_config ;
return enabled ;
}
bool KRandrSimpleAPI : : getDisplayConfigurationStartupAutoApplyEnabled ( TQString kde_confdir ) {
TQString filename = " displayglobals " ;
filename . prepend ( kde_confdir . append ( " / " ) ) ;
KSimpleConfig * display_config = new KSimpleConfig ( filename ) ;
display_config - > setGroup ( " General " ) ;
bool applyonstart = display_config - > readBoolEntry ( " ApplySettingsOnStart " , false ) ;
delete display_config ;
return applyonstart ;
}
TQString KRandrSimpleAPI : : getDisplayConfigurationStartupAutoApplyName ( TQString kde_confdir ) {
TQString filename = " displayglobals " ;
filename . prepend ( kde_confdir . append ( " / " ) ) ;
KSimpleConfig * display_config = new KSimpleConfig ( filename ) ;
display_config - > setGroup ( " General " ) ;
TQString profilename = display_config - > readEntry ( " StartupProfileName " , " " ) ;
delete display_config ;
return profilename ;
}
void KRandrSimpleAPI : : applyHotplugRules ( TQString kde_confdir ) {
bool enabled = getDisplayConfigurationEnabled ( kde_confdir ) ;
if ( ! enabled ) {
return ;
}
HotPlugRulesList rules = getHotplugRules ( kde_confdir ) ;
TQPtrList < SingleScreenData > screenInfoArray = readCurrentDisplayConfiguration ( ) ;
int i ;
int j ;
TQString bestRule ;
int bestRuleMatchCount = 0 ;
SingleScreenData * screendata = NULL ;
HotPlugRulesList : : Iterator it ;
for ( it = rules . begin ( ) ; it ! = rules . end ( ) ; + + it ) {
// Compare each rule against the current display configuration
// It an output matches the state given in the rule, increment matchCount
HotPlugRule rule = * it ;
int matchCount = 0 ;
int numberOfScreens = screenInfoArray . count ( ) ;
for ( i = 0 ; i < numberOfScreens ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
for ( j = 0 ; j < ( * it ) . outputs . count ( ) ; j + + ) {
if ( ( * it ) . outputs [ j ] ! = screendata - > screenUniqueName ) {
continue ;
}
if ( ( * it ) . states [ j ] = = HotPlugRule : : Connected ) {
if ( screendata - > screen_connected ) {
matchCount + + ;
}
}
else if ( ( * it ) . states [ j ] = = HotPlugRule : : Disconnected ) {
if ( ! screendata - > screen_connected ) {
matchCount + + ;
}
}
}
}
if ( matchCount > bestRuleMatchCount ) {
bestRuleMatchCount = matchCount ;
bestRule = rule . profileName ;
}
}
destroyScreenInformationObject ( screenInfoArray ) ;
if ( bestRuleMatchCount > 0 ) {
// At least one rule matched...
// Apply the profile name in bestRule to the display hardware
applyDisplayConfiguration ( bestRule , kde_confdir ) ;
}
}
void KRandrSimpleAPI : : applyDisplayGamma ( TQPtrList < SingleScreenData > screenInfoArray ) {
int i ;
Display * randr_display ;
XRROutputInfo * output_info ;
ScreenInfo * randr_screen_info ;
XRRCrtcGamma * gamma ;
SingleScreenData * screendata ;
if ( isValid ( ) = = true ) {
randr_display = tqt_xdisplay ( ) ;
randr_screen_info = read_screen_info ( randr_display ) ;
for ( i = 0 ; i < screenInfoArray . count ( ) ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
output_info = randr_screen_info - > outputs [ i ] - > info ;
CrtcInfo * current_crtc = randr_screen_info - > outputs [ i ] - > cur_crtc ;
if ( ! current_crtc ) {
continue ;
}
// vvvvvvvvv This chunk of code is borrowed from xrandr vvvvvvvvvv
int size = XRRGetCrtcGammaSize ( randr_display , current_crtc - > id ) ;
if ( ! size ) {
continue ;
}
gamma = XRRAllocGamma ( size ) ;
if ( ! gamma ) {
continue ;
}
for ( i = 0 ; i < size ; i + + ) {
if ( screendata - > gamma_red = = 1.0 )
gamma - > red [ i ] = i < < 8 ;
else
gamma - > red [ i ] = ( pow ( ( double ) i / ( double ) ( size - 1 ) , ( double ) screendata - > gamma_red ) * ( double ) ( size - 1 ) * 256 ) ;
if ( screendata - > gamma_green = = 1.0 )
gamma - > green [ i ] = i < < 8 ;
else
gamma - > green [ i ] = ( pow ( ( double ) i / ( double ) ( size - 1 ) , ( double ) screendata - > gamma_green ) * ( double ) ( size - 1 ) * 256 ) ;
if ( screendata - > gamma_blue = = 1.0 )
gamma - > blue [ i ] = i < < 8 ;
else
gamma - > blue [ i ] = ( pow ( ( double ) i / ( double ) ( size - 1 ) , ( double ) screendata - > gamma_blue ) * ( double ) ( size - 1 ) * 256 ) ;
}
XRRSetCrtcGamma ( randr_display , current_crtc - > id , gamma ) ;
free ( gamma ) ;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
freeScreenInfoStructure ( randr_screen_info ) ;
}
}
void KRandrSimpleAPI : : applyDisplayDPMS ( TQPtrList < SingleScreenData > screenInfoArray ) {
int i ;
Display * randr_display ;
XRROutputInfo * output_info ;
ScreenInfo * randr_screen_info ;
XRRCrtcGamma * gamma ;
SingleScreenData * screendata ;
if ( isValid ( ) = = true ) {
randr_display = tqt_xdisplay ( ) ;
randr_screen_info = read_screen_info ( randr_display ) ;
for ( i = 0 ; i < screenInfoArray . count ( ) ; i + + ) {
screendata = screenInfoArray . at ( i ) ;
output_info = randr_screen_info - > outputs [ i ] - > info ;
CrtcInfo * current_crtc = randr_screen_info - > outputs [ i ] - > cur_crtc ;
if ( ! current_crtc ) {
continue ;
}
if ( ! screendata - > has_dpms ) {
continue ;
}
if ( screendata - > enable_dpms ) {
DPMSSetTimeouts ( randr_display , screendata - > dpms_standby_delay , screendata - > dpms_suspend_delay , screendata - > dpms_off_delay ) ;
DPMSEnable ( randr_display ) ;
}
else {
DPMSDisable ( randr_display ) ;
}
}
freeScreenInfoStructure ( randr_screen_info ) ;
}
}
void KRandrSimpleAPI : : freeScreenInfoStructure ( ScreenInfo * screen_info ) {
int i ;
for ( i = 0 ; i < screen_info - > n_crtc ; i + + ) {
free ( screen_info - > crtcs [ i ] ) ;
}
for ( i = 0 ; i < screen_info - > n_output ; i + + ) {
free ( screen_info - > outputs [ i ] ) ;
}
free ( screen_info - > outputs ) ;
free ( screen_info - > crtcs ) ;
free ( screen_info ) ;
}
TQPtrList < SingleScreenData > KRandrSimpleAPI : : readCurrentDisplayConfiguration ( ) {
// Discover display information
int i ;
int j ;
XRROutputInfo * output_info ;
SingleScreenData * screendata ;
TQPtrList < SingleScreenData > screenInfoArray ;
Display * randr_display ;
ScreenInfo * randr_screen_info ;
// Clear existing info
destroyScreenInformationObject ( screenInfoArray ) ;
int numberOfScreens = 0 ;
if ( isValid ( ) = = true ) {
randr_display = tqt_xdisplay ( ) ;
randr_screen_info = read_screen_info ( randr_display ) ;
for ( i = 0 ; i < randr_screen_info - > n_output ; i + + ) {
output_info = randr_screen_info - > outputs [ i ] - > info ;
CrtcInfo * current_crtc = randr_screen_info - > outputs [ i ] - > cur_crtc ;
// Create new data object
screendata = new SingleScreenData ;
screenInfoArray . append ( screendata ) ;
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?
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?
screendata - > generic_screen_detected = false ;
// Attempt to use KMS to find screen EDID and name
TQString edid = getEDIDMonitorName ( 0 , output_info - > name ) ; // [FIXME] Don't hardwire to card 0!
if ( ! edid . isNull ( ) ) {
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?
}
// Get resolutions
bool screen_active ;
RandRScreen * cur_screen = 0 ;
if ( RR_Disconnected = = randr_screen_info - > outputs [ i ] - > info - > connection ) {
// Output DISCONNECTED
screen_active = false ;
}
else {
if ( randr_screen_info - > outputs [ i ] - > cur_crtc ) {
// Output CONNECTED and ON
screen_active = true ;
cur_screen = new RandRScreen ( i ) ;
}
else {
// Output CONNECTED and OFF
screen_active = false ;
cur_screen = new RandRScreen ( i ) ;
}
}
// Get DPMS information
screendata - > has_dpms = 1 ; // [FIXME] Master Xorg check for global DPMS support should go here if possible
if ( screendata - > has_dpms ) {
CARD16 dpms_standby_delay ;
CARD16 dpms_suspend_delay ;
CARD16 dpms_off_delay ;
screendata - > has_dpms = DPMSGetTimeouts ( randr_display , & dpms_standby_delay , & dpms_suspend_delay , & dpms_off_delay ) ;
screendata - > dpms_standby_delay = dpms_standby_delay ;
screendata - > dpms_suspend_delay = dpms_suspend_delay ;
screendata - > dpms_off_delay = dpms_off_delay ;
if ( screendata - > has_dpms ) {
CARD16 power_level ;
BOOL enable_dpms ;
screendata - > has_dpms = DPMSInfo ( randr_display , & power_level , & enable_dpms ) ;
screendata - > enable_dpms = enable_dpms ;
}
}
if ( ! screendata - > has_dpms ) {
screendata - > enable_dpms = false ;
screendata - > dpms_standby_delay = 0 ;
screendata - > dpms_suspend_delay = 0 ;
screendata - > dpms_off_delay = 0 ;
}
if ( cur_screen ) {
screendata - > screen_connected = true ;
for ( int j = 0 ; j < cur_screen - > numSizes ( ) ; j + + ) {
screendata - > resolutions . append ( i18n ( " %1 x %2 " ) . arg ( cur_screen - > pixelSize ( j ) . width ( ) ) . arg ( cur_screen - > pixelSize ( j ) . height ( ) ) ) ;
}
screendata - > current_resolution_index = 0 ;
if ( current_crtc ) {
screendata - > current_resolution_index = screendata - > resolutions . findIndex ( i18n ( " %1 x %2 " ) . arg ( current_crtc - > info - > width ) . arg ( current_crtc - > info - > height ) ) ;
}
if ( screendata - > current_resolution_index < 0 ) {
screendata - > current_resolution_index = cur_screen - > proposedSize ( ) ;
}
// Get refresh rates
TQStringList rr = cur_screen - > refreshRates ( screendata - > current_resolution_index ) ;
for ( TQStringList : : Iterator it = rr . begin ( ) ; it ! = rr . end ( ) ; + + it ) {
screendata - > refresh_rates . append ( * it ) ;
}
screendata - > current_refresh_rate_index = cur_screen - > proposedRefreshRate ( ) ;
// Get color depths
// [FIXME]
screendata - > color_depths . append ( i18n ( " Default " ) ) ;
screendata - > current_color_depth_index = 0 ;
// Get orientation flags
// RandRScreen::Rotate0
// RandRScreen::Rotate90
// RandRScreen::Rotate180
// RandRScreen::Rotate270
// RandRScreen::ReflectX
// RandRScreen::ReflectY
screendata - > rotations . append ( i18n ( ROTATION_0_DEGREES_STRING ) ) ;
screendata - > rotations . append ( i18n ( ROTATION_90_DEGREES_STRING ) ) ;
screendata - > rotations . append ( i18n ( ROTATION_180_DEGREES_STRING ) ) ;
screendata - > rotations . append ( i18n ( ROTATION_270_DEGREES_STRING ) ) ;
screendata - > supports_transformations = ( cur_screen - > rotations ( ) ! = RandRScreen : : Rotate0 ) ;
if ( screendata - > supports_transformations ) {
screendata - > current_orientation_mask = cur_screen - > proposedRotation ( ) ;
switch ( screendata - > current_orientation_mask & RandRScreen : : RotateMask ) {
case RandRScreen : : Rotate0 :
screendata - > current_rotation_index = 0 ;
break ;
case RandRScreen : : Rotate90 :
screendata - > current_rotation_index = 1 ;
break ;
case RandRScreen : : Rotate180 :
screendata - > current_rotation_index = 2 ;
break ;
case RandRScreen : : Rotate270 :
screendata - > current_rotation_index = 3 ;
break ;
default :
// Shouldn't hit this one
Q_ASSERT ( screendata - > current_orientation_mask & RandRScreen : : RotateMask ) ;
screendata - > current_rotation_index = 0 ;
break ;
}
screendata - > has_x_flip = ( screendata - > current_orientation_mask & RandRScreen : : ReflectX ) ;
screendata - > has_y_flip = ( screendata - > current_orientation_mask & RandRScreen : : ReflectY ) ;
}
else {
screendata - > has_x_flip = false ;
screendata - > has_y_flip = false ;
screendata - > current_rotation_index = 0 ;
}
// Determine if this display is primary and/or extended
RROutput primaryoutput = XRRGetOutputPrimary ( tqt_xdisplay ( ) , DefaultRootWindow ( tqt_xdisplay ( ) ) ) ;
if ( primaryoutput = = randr_screen_info - > outputs [ i ] - > id ) {
screendata - > is_primary = false ;
}
else {
screendata - > is_primary = true ;
}
screendata - > is_extended = screen_active ;
if ( ! screendata - > is_extended ) {
screendata - > is_primary = false ;
}
// Get this screen's absolute position
screendata - > absolute_x_position = 0 ;
screendata - > absolute_y_position = 0 ;
if ( current_crtc ) {
screendata - > absolute_x_position = current_crtc - > info - > x ;
screendata - > absolute_y_position = current_crtc - > info - > y ;
}
// Get this screen's current resolution
screendata - > current_x_pixel_count = cur_screen - > pixelSize ( screendata - > current_resolution_index ) . width ( ) ;
screendata - > current_y_pixel_count = cur_screen - > pixelSize ( screendata - > current_resolution_index ) . height ( ) ;
// Get this screen's current gamma values
// [FIXME]
// This attempts to guess a gamma value based on the LUT settings at 50%
// It may not always be 100% correct, or even anywhere close...
// Essentially it "undoes" the LUT gamma calculation from xrandr
// lut_gamma->green[i] = (pow(i/(size - 1), desired_gamma.green) * (size - 1) * 256);
if ( current_crtc ) {
//int slot = 127;
int slot = 7 ;
int size = XRRGetCrtcGammaSize ( randr_display , current_crtc - > id ) ;
XRRCrtcGamma * gammastruct = XRRGetCrtcGamma ( randr_display , current_crtc - > id ) ;
screendata - > gamma_red = log ( gammastruct - > red [ slot ] / ( ( size - 1.0 ) * 256.0 ) ) / log ( slot / ( size - 1.0 ) ) ;
screendata - > gamma_green = log ( gammastruct - > green [ slot ] / ( ( size - 1.0 ) * 256.0 ) ) / log ( slot / ( size - 1.0 ) ) ;
screendata - > gamma_blue = log ( gammastruct - > blue [ slot ] / ( ( size - 1.0 ) * 256.0 ) ) / log ( slot / ( size - 1.0 ) ) ;
}
else {
screendata - > gamma_red = 2.2 ;
screendata - > gamma_green = 2.2 ;
screendata - > gamma_blue = 2.2 ;
}
// Round off the gamma to one decimal place
screendata - > gamma_red = floorf ( screendata - > gamma_red * 10 + 0.5 ) / 10 ;
screendata - > gamma_green = floorf ( screendata - > gamma_green * 10 + 0.5 ) / 10 ;
screendata - > gamma_blue = floorf ( screendata - > gamma_blue * 10 + 0.5 ) / 10 ;
delete cur_screen ;
}
else {
// Fill in generic data for this disconnected output
screendata - > screenFriendlyName = screendata - > screenFriendlyName + TQString ( " ( " ) + i18n ( " disconnected " ) + TQString ( " ) " ) ;
screendata - > screen_connected = false ;
screendata - > resolutions = i18n ( " Default " ) ;
screendata - > refresh_rates = i18n ( " Default " ) ;
screendata - > color_depths = i18n ( " Default " ) ;
screendata - > rotations = i18n ( " N/A " ) ;
screendata - > current_resolution_index = 0 ;
screendata - > current_refresh_rate_index = 0 ;
screendata - > current_color_depth_index = 0 ;
screendata - > gamma_red = 2.2 ;
screendata - > gamma_green = 2.2 ;
screendata - > gamma_blue = 2.2 ;
screendata - > current_rotation_index = 0 ;
screendata - > current_orientation_mask = 0 ;
screendata - > has_x_flip = false ;
screendata - > has_y_flip = false ;
screendata - > supports_transformations = false ;
screendata - > is_primary = false ;
screendata - > is_extended = false ;
screendata - > absolute_x_position = 0 ;
screendata - > absolute_y_position = 0 ;
screendata - > current_x_pixel_count = 640 ;
screendata - > current_y_pixel_count = 480 ;
}
// Check for more screens...
numberOfScreens + + ;
}
freeScreenInfoStructure ( randr_screen_info ) ;
}
else {
screendata = new SingleScreenData ;
screenInfoArray . append ( screendata ) ;
// Fill in a bunch of generic data
screendata - > screenFriendlyName = i18n ( " Default output on generic video card " ) ;
screendata - > generic_screen_detected = true ;
screendata - > screen_connected = true ;
screendata - > resolutions = i18n ( " Default " ) ;
screendata - > refresh_rates = i18n ( " Default " ) ;
screendata - > color_depths = i18n ( " Default " ) ;
screendata - > rotations = i18n ( " N/A " ) ;
screendata - > current_resolution_index = 0 ;
screendata - > current_refresh_rate_index = 0 ;
screendata - > current_color_depth_index = 0 ;
screendata - > gamma_red = 2.2 ;
screendata - > gamma_green = 2.2 ;
screendata - > gamma_blue = 2.2 ;
screendata - > current_rotation_index = 0 ;
screendata - > current_orientation_mask = 0 ;
screendata - > has_x_flip = false ;
screendata - > has_y_flip = false ;
screendata - > supports_transformations = false ;
screendata - > is_primary = true ;
screendata - > is_extended = true ;
screendata - > absolute_x_position = 0 ;
screendata - > absolute_y_position = 0 ;
screendata - > current_x_pixel_count = 640 ;
screendata - > current_y_pixel_count = 480 ;
numberOfScreens + + ;
}
bool primary_set = false ;
for ( screendata = screenInfoArray . first ( ) ; screendata ; screendata = screenInfoArray . next ( ) ) {
if ( screendata - > is_primary ) {
primary_set = true ;
break ;
}
}
// If there is no primary monitor set, xrandr is probably not functioning correctly!
Q_ASSERT ( primary_set ) ;
if ( ! primary_set ) {
// [FIXME]
// Set this on the real primary monitor only!
screendata = screenInfoArray . at ( 0 ) ;
screendata - > is_primary = true ;
}
return screenInfoArray ;
}
TQString KRandrSimpleAPI : : clearIccConfiguration ( ) {
// Clear ICC settings with XCalib
TQString icc_command ;
FILE * pipe_xcalib ;
char xcalib_result [ 2048 ] ;
int i ;
xcalib_result [ 0 ] = 0 ;
icc_command = TQString ( " xcalib -c " ) ;
if ( ( pipe_xcalib = popen ( icc_command . ascii ( ) , " r " ) ) = = NULL )
{
printf ( " Xcalib pipe error [xcalib clear] \n \r " ) ;
}
else {
if ( fgets ( xcalib_result , 2048 , pipe_xcalib ) ) {
pclose ( pipe_xcalib ) ;
for ( i = 1 ; i < 2048 ; i + + ) {
if ( xcalib_result [ i ] = = 0 ) {
xcalib_result [ i - 1 ] = 0 ;
i = 2048 ;
}
}
if ( strlen ( xcalib_result ) > 2 ) {
return xcalib_result ;
}
}
else {
return " " ;
}
}
return " " ;
}
ScreenInfo * KRandrSimpleAPI : : read_screen_info ( Display * display )
{
return internal_read_screen_info ( display ) ;
}
int KRandrSimpleAPI : : set_screen_size ( ScreenInfo * screen_info )
{
return internal_set_screen_size ( screen_info ) ;
}
void KRandrSimpleAPI : : output_auto ( ScreenInfo * screen_info , OutputInfo * output_info )
{
internal_output_auto ( screen_info , output_info ) ;
}
void KRandrSimpleAPI : : output_off ( ScreenInfo * screen_info , OutputInfo * output )
{
internal_output_off ( screen_info , output ) ;
}
CrtcInfo * KRandrSimpleAPI : : auto_find_crtc ( ScreenInfo * screen_info , OutputInfo * output_info )
{
return internal_auto_find_crtc ( screen_info , output_info ) ;
}
XRRModeInfo * KRandrSimpleAPI : : find_mode_by_xid ( ScreenInfo * screen_info , RRMode mode_id )
{
return internal_find_mode_by_xid ( screen_info , mode_id ) ;
}
int KRandrSimpleAPI : : mode_height ( XRRModeInfo * mode_info , Rotation rotation )
{
return internal_mode_height ( mode_info , rotation ) ;
}
int KRandrSimpleAPI : : mode_width ( XRRModeInfo * mode_info , Rotation rotation )
{
return internal_mode_width ( mode_info , rotation ) ;
}
int KRandrSimpleAPI : : get_width_by_output_id ( ScreenInfo * screen_info , RROutput output_id )
{
return internal_get_width_by_output_id ( screen_info , output_id ) ;
}
int KRandrSimpleAPI : : get_height_by_output_id ( ScreenInfo * screen_info , RROutput output_id )
{
return internal_get_height_by_output_id ( screen_info , output_id ) ;
}
char * KRandrSimpleAPI : : get_output_name ( ScreenInfo * screen_info , RROutput id )
{
return internal_get_output_name ( screen_info , id ) ;
}
Status KRandrSimpleAPI : : crtc_apply ( CrtcInfo * crtc_info )
{
return internal_crtc_apply ( crtc_info ) ;
}
Status KRandrSimpleAPI : : crtc_disable ( CrtcInfo * crtc )
{
return internal_crtc_disable ( crtc ) ;
}
int KRandrSimpleAPI : : main_low_apply ( ScreenInfo * screen_info )
{
return internal_main_low_apply ( screen_info ) ;
}
void KRandrSimpleAPI : : set_primary_output ( ScreenInfo * screen_info , RROutput output_id )
{
internal_output_set_primary ( screen_info , output_id ) ;
}
bool KRandrSimpleAPI : : kRandrHasRandr ( void )
{
return isValid ( ) ;
}
const char * KRandrSimpleAPI : : kRandrVersion ( void )
{
return " 0.9.5 " ;
}
const char * KRandrSimpleAPI : : kRandrCopyright ( void )
{
return " LibKRandr 0.9.5 (C)2010 Timothy Pearson <kb9vqf@pearsoncomputing.net>. U.S.A. " ;
}
/* * * * * *
Under this line ( - - - - - - ) there ' s only a C wrapper for the KRandrSimpleAPI class
* * * * * */
const char * kRandrVersion ( void )
{
return KRandrSimpleAPI : : kRandrVersion ( ) ;
}
const char * kRandrCopyright ( void )
{
return KRandrSimpleAPI : : kRandrCopyright ( ) ;
}