summaryrefslogtreecommitdiffstats
path: root/displayconfig/displayconfig-restore.py
diff options
context:
space:
mode:
Diffstat (limited to 'displayconfig/displayconfig-restore.py')
-rwxr-xr-xdisplayconfig/displayconfig-restore.py324
1 files changed, 324 insertions, 0 deletions
diff --git a/displayconfig/displayconfig-restore.py b/displayconfig/displayconfig-restore.py
new file mode 100755
index 0000000..8c44a48
--- /dev/null
+++ b/displayconfig/displayconfig-restore.py
@@ -0,0 +1,324 @@
+#!/usr/bin/python
+###########################################################################
+# displayconfig-restore.py - description #
+# ------------------------------ #
+# begin : Wed Dec 15 2004 #
+# copyright : (C) 2004-2006 by Simon Edwards #
+# email : [email protected] #
+# #
+###########################################################################
+# #
+# This program is free software; you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation; either version 2 of the License, or #
+# (at your option) any later version. #
+# #
+###########################################################################
+import os
+import os.path
+import subprocess
+import ixf86misc
+import xf86misc
+
+from execwithcapture import *
+
+############################################################################
+def FindXorgConfig(self):
+ # Lookup location of X configfile
+ for line in ExecWithCapture("xset", ["xset","q"],True).split('\n'):
+ if line.strip().startswith("Config file"):
+ return line.split(":")[1].strip()
+ # Sometimes, xset doesn't know about the configfile location, hence ...
+ if os.path.isfile("/etc/X11/xorg.conf"):
+ return "/etc/X11/xorg.conf"
+ return None
+
+############################################################################
+# FixXorgDPI
+# ==========
+# The idea here is to ensure that applications use a sensible DPI setting
+# for fonts. When Xorg starts up it tries to detect the size of the attached
+# monitor and calculate the real DPI from there and use that. Problems are:
+#
+# * if the monitor size can not be detect then Xorg uses 75dpi. This is
+# usually far too low.
+#
+# * if the monitor size is not accurately detected then you get bad a DPI.
+#
+# * most fonts are optimised to work at a handful of standard DPIs. 96dpi,
+# 120dpi and printer resolution 300dpi and 600dpi. Fonts rendered in
+# non-standard DPIs often look bad and jagged. This is a real problem
+# when rendering fonts on low resolution devices. (i.e. a computer
+# monitor).
+#
+# Although it is desirable in theory to use the real DPI of the monitor, in
+# practice it is more important to ensure that fonts are well rendered even
+# if the DPI in use is not correct.
+#
+# What this function does is read the display size from the X server and
+# if it is lower than 140dpi then 'round' it to either 96dpi or 120dpi.
+# (A dpi greater or equal to 140 is assumed to be high enough to render fonts
+# well.) The new dpi is then loaded with the xrdb command into the X server
+# resource database. Most X applications (Qt and GTK apps at least) will then
+# use this DPI for font rendering.
+#
+def FixXorgDPI(desiredDPI):
+ # dpi is:
+ # None - round the DPI.
+ # xserver - Use the X server's DPI.
+ # <number> - DPI to use.
+ if desiredDPI=="xserver":
+ return
+
+ dpi = 96
+ try:
+ if desiredDPI is not None:
+ dpi = int(desiredDPI)
+ except ValueError:
+ desiredDPI = None
+
+ if desiredDPI is None:
+ xserver = xf86misc.XF86Server()
+ if len(xserver.getScreens())!=0:
+ (width,height,width_mm,height_mm) = xserver.getScreens()[0].getDimensions()
+ if not float(width_mm) == 0:
+ w_dpi = float(width)/(float(width_mm)/25.4)
+ else:
+ w_dpi = 96
+ if not float(height_mm) == 0:
+ h_dpi = float(height)/(float(height_mm)/25.4)
+ else:
+ h_dpi = 96
+ dpi = (w_dpi+h_dpi)/2.0 # Average the two possible DPIs.
+
+ if dpi >= 140: # Anything above 140 is ok.
+ dpi = int(dpi)
+ else:
+ if abs(96-dpi) < abs(120-dpi): # Rounding to 96 is best.
+ dpi = 96
+ else:
+ dpi = 120
+
+ # work around for LP beastie 151311
+ if ((w_dpi < 200) and (h_dpi > 900)):
+ dpi = 96
+
+ try:
+ xrdb = subprocess.Popen(["xrdb","-nocpp","-merge"],stdin=subprocess.PIPE)
+ xrdb.communicate("Xft.dpi: %i\n" % dpi)
+ xrdb.wait()
+ except OSError:
+ pass
+
+ # Other common, but now used settingsfor xrdb:
+ # Xft.antialias:
+ # Xft.hinting:
+ # Xft.hintstyle:
+ # Xft.rgba:
+
+############################################################################
+def ReadDisplayConfigRC():
+ screens = None
+ dpi = None
+ dpms_seconds = None
+ dpms_enabled = None
+
+ configpath = ExecWithCapture("kde-config",['kde-config','--path','config'],True)
+
+ # Hunt down the user's displayconfigrc file and adjust the resolution
+ # on the fly to match. (Non-root Users can independantly specify their own settings.)
+ dirs = configpath.strip().split(":")
+ for dir in dirs:
+ if dir!="":
+ configpath = os.path.join(dir,"displayconfigrc")
+ if os.path.exists(configpath):
+ # Parse the config file.
+ fhandle = open(configpath)
+ screens = []
+ currentscreen = None
+ for line in fhandle.readlines():
+ line = line.strip()
+ if line.startswith("[Screen"):
+ # Screen, width, height, refresh, reflectx, reflecty, rotate, redgamma, greengamma,bluegamma
+ currentscreen = [int(line[7:-1]), None, None, None, False, False, "0", None, None, None]
+ screens.append(currentscreen)
+ elif line.startswith("["):
+ currentscreen = None
+ elif line.startswith("dpi="):
+ dpi = line[4:]
+ elif currentscreen is not None:
+ if line.startswith("width="):
+ currentscreen[1] = int(line[6:])
+ elif line.startswith("height="):
+ currentscreen[2] = int(line[7:])
+ elif line.startswith("refresh="):
+ currentscreen[3] = int(line[8:])
+ elif line.startswith("reflectX="):
+ currentscreen[4] = line[9:]=="1"
+ elif line.startswith("reflectY="):
+ currentscreen[5] = line[9:]=="1"
+ elif line.startswith("rotate="):
+ currentscreen[6] = line[7:]
+ elif line.startswith("redgamma="):
+ currentscreen[7] = line[9:]
+ elif line.startswith("greengamma="):
+ currentscreen[8] = line[11:]
+ elif line.startswith("bluegamma="):
+ currentscreen[9] = line[10:]
+ elif line.startswith("dpmsEnabled"):
+ dpms_enabled = line.split("=")[1]
+ elif line.startswith("dpmsSeconds"):
+ dpms_seconds = int(line.split("=")[1])
+ fhandle.close()
+ break
+
+ return (screens,dpi,dpms_enabled,dpms_seconds)
+
+############################################################################
+def main():
+ (screens,dpi,dpms_enabled,dpms_seconds) = ReadDisplayConfigRC()
+
+ if dpms_enabled:
+ if dpms_enabled == "on":
+ if not dpms_seconds:
+ dpms_seconds = 900
+ cmd = "xset dpms %i %i %i" % (dpms_seconds,dpms_seconds,dpms_seconds)
+ os.system(cmd)
+ else:
+ cmd = "xset -dpms"
+ os.system(cmd)
+
+ if screens is not None:
+ # Set the X server.
+ try:
+ xserver = xf86misc.XF86Server()
+ if len(screens)!=0:
+
+ for screen in screens:
+ (id,width,height,refresh,reflectx,reflecty,rotate,redgamma,greengamma,bluegamma) = screen
+
+ # Convert the stuff into RandR's rotation bitfield thingy.
+ if rotate=="0":
+ rotation = xf86misc.XF86Screen.RR_Rotate_0
+ elif rotate=="90":
+ rotation = xf86misc.XF86Screen.RR_Rotate_90
+ elif rotate=="180":
+ rotation = xf86misc.XF86Screen.RR_Rotate_180
+ elif rotate=="270":
+ rotation = xf86misc.XF86Screen.RR_Rotate_270
+ if reflectx:
+ rotation |= xf86misc.XF86Screen.RR_Reflect_X
+ if reflecty:
+ rotation |= xf86misc.XF86Screen.RR_Reflect_Y
+
+ if id<len(xserver.getScreens()):
+ xscreen = xserver.getScreens()[id]
+
+ if xscreen.resolutionSupportAvailable():
+ available_sizes = xscreen.getAvailableSizes()
+
+ # Find the closest matching resolution
+ best_score = 1000000
+ best_size_id = 0
+ for size_id in range(len(available_sizes)):
+ size = available_sizes[size_id]
+ score = abs(size[0]-width)+abs(size[1]-height)
+ if score < best_score:
+ best_size_id = size_id
+ best_score = score
+
+ # Now find the best refresh for this resolution
+ best_score = 1000000
+ best_refresh = 50
+ for available_refresh in xscreen.getAvailableRefreshRates(best_size_id):
+ score = abs(refresh-available_refresh)
+ if score < best_score:
+ best_refresh = available_refresh
+ best_score = score
+
+ # Mask out any unsupported rotations.
+ rotation &= xscreen.getAvailableRotations()
+ xscreen.setScreenConfigAndRate(best_size_id, rotation, best_refresh)
+
+ # Restore the gamma settings.
+ if redgamma is not None and greengamma is not None and bluegamma is not None:
+ try:
+ xscreen.setGamma( (float(redgamma), float(greengamma), float(bluegamma)) )
+ except ValueError,e:
+ pass
+
+ FixXorgDPI(dpi)
+ except xf86misc.XF86Error,err:
+ print err
+
+ return
+
+ else:
+ # Ensure that the xorgs virtual screen size matches the default resolution
+ # of the server. Why does this matter? When Xorg starts up it reads its
+ # config file chooses the first mode in the "modes" line of the active
+ # Screen section and uses it as the virtual screen size and as the
+ # screen resolution (ie 1024x768 resolution screen showing a 1024x768 gfx
+ # buffer). But, this means that you can't use RandR to get to any higher
+ # screen resolutions (ie 1280x1024) because Xorg requires that the virtual
+ # screen size 'cover' the screen resolution being displayed.
+ #
+ # So, to get around this problem and make it possible for people to select
+ # a lower resolution screen *and* still have the option later to use
+ # RandR/displayconfig to switch to higher resolution, displayconfig
+ # explicitly sets the virtual screen size in xorg.conf to the largest
+ # resoluution that the monitor/gfx card can support. The down side to
+ # this is that the X server and kdm get the correct resolution but the
+ # wrong (virtual) screen size. The user can now scroll around on the
+ # greater virtual screen. Kind of annoying for kdm, unacceptable once
+ # the user has logged in.
+ #
+ # What we do now as the user's KDE session is being started up is check
+ # what the real virtual screen size is meant to be (=same as the real
+ # resolution being used) and then use the RandR extension to explicitly
+ # set the correct resolution. This has the effect of changing the virtual
+ # screeen size to what we really want. (RandR can change the virtual
+ # screen size, thankfully)
+ import displayconfigabstraction
+
+ try:
+ xserver = xf86misc.XF86Server()
+
+ for xscreen in xserver.getScreens():
+ if xscreen.resolutionSupportAvailable():
+ mode_line = ixf86misc.XF86VidModeGetModeLine(xserver.getDisplay(),xscreen.getScreenId())
+
+ hdisplay = mode_line[1]
+ vdisplay = mode_line[5]
+
+ live_refresh_rate = xscreen.getRefreshRate()
+ try:
+ (live_width,live_height,x,x) = xscreen.getAvailableSizes()[xscreen.getSizeID()]
+ except IndexError, errmsg:
+ print "IndexError:", errmsg, "in displayconfig-restore getting live screen size - trying screen 0."
+ (live_width,live_height,x,x) = xscreen.getAvailableSizes()[0]
+
+ if (hdisplay,vdisplay) != (live_width,live_height):
+ # The screen resolution doesn't match the virtual screen size.
+ screen_sizes = xscreen.getAvailableSizes()
+ for size_id in range(len(screen_sizes)):
+ screen_size = screen_sizes[size_id]
+ if screen_size[0]==hdisplay and screen_size[1]==vdisplay:
+
+ # Find the closest matching refresh rate.
+ best_refresh = 0
+ best_score = 1000000
+ for rate in xscreen.getAvailableRefreshRates(size_id):
+ score = abs(rate-live_refresh_rate)
+ if score < best_score:
+ best_refresh = rate
+ best_score = score
+
+ # Reset the screen mode and virtual screen size.
+ xscreen.setScreenConfigAndRate(size_id,xscreen.getRotation(),best_refresh)
+ break
+ FixXorgDPI(dpi)
+ except (xf86misc.XF86Error,TypeError),err:
+ print err
+
+main()