Advertisement
Guest User

BetterLeftUnsaid

a guest
Sep 24th, 2008
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.40 KB | None | 0 0
  1. #!/usr/bin/env python
  2. import subprocess, re, os, sys, Xlib.display, math
  3.  
  4. #TODO: Automatically get the height of the titlebar, maybe using themerc?
  5. #      There's going to be gaps if windows are undecorated.
  6. #      Take over the world!
  7.  
  8. if len(sys.argv) > 1: options = sys.argv[1]
  9. else: options = "-h"
  10.  
  11. screen_x = Xlib.display.Display().screen()["width_in_pixels"]
  12. screen_y = Xlib.display.Display().screen()["height_in_pixels"]
  13. #screen_x, screen_y = 1440, 900
  14. if not screen_x or not screen_y:
  15.     print "Cannot determine screen resolution, exiting."
  16.     sys.exit(1)
  17.  
  18. ob_config = os.path.expanduser("~") + "/.config/openbox/rc.xml"
  19. if os.path.isfile(ob_config):
  20.     ob_config = open(ob_config, "r").read()
  21.     margins = {
  22.         "top" : re.search(r"<top>\s*(\d+)\s*</top>", ob_config, re.M),
  23.         "bottom" : re.search(r"<bottom>\s*(\d+)\s*</bottom>", ob_config, re.M),
  24.         "left" : re.search(r"<left>\s*(\d+)\s*</left>", ob_config, re.M),
  25.         "right" : re.search(r"<right>\s*(\d+)\s*</right>", ob_config, re.M)
  26.         }
  27.     for position, match in margins.iteritems():
  28.         if match: margins[position] = int(match.group(1))
  29.         else:
  30.             print "Warning: Regex fail or margins not defined, defaulting to 0"
  31.             margins[position] = 0
  32. else:
  33.     print "Warning: Openbox config not found, margins defaulting to 0"
  34.     margins["top"] = margins["bottom"] = margins["left"] = margins["right"] = 0
  35. titlebar = 22 #Approximate pixel ammount taken up by the titlebar.
  36.  
  37. #Get current desktop, using the output of wmctrl.  If not found, default to 0
  38. desktops = subprocess.Popen(["wmctrl", "-d"], stdout=subprocess.PIPE).communicate()[0]
  39. current_desk = 0
  40. match = re.search(r"(\d+)\s*\*", desktops)
  41. if match: current_desk = int(match.group(1))
  42.  
  43. all_windows = subprocess.Popen(["wmctrl", "-l"], stdout=subprocess.PIPE).communicate()[0].split("\n") #One window per item in list.
  44. current_wins = []  
  45. for window in all_windows:  #Gets windows on current desktop.  Appends them to current_wins
  46.     match = re.search(r"(0x\w{8})\s*?" + str(current_desk), window) #Assuming that all window ID's are in the form "0x########"
  47.     if match: current_wins.append(match.group(1))
  48. num_of_wins = len(current_wins)
  49.  
  50. if options == "-h":
  51.     #Tile horizontally.  Windows appear next to each other.
  52.     win_x = (screen_x - margins["right"] - margins["left"]) / num_of_wins   #Width per app
  53.     win_y = screen_y - margins["top"] - margins["bottom"] - titlebar    #Height per app
  54.     positions = [win_x*x+margins["right"] for x in range(0, num_of_wins)]   #List of x-value positions
  55.     for i, win in enumerate(current_wins):                  #Resize each window, yay!
  56.         subprocess.Popen(["wmctrl", "-i", "-r", win, "-b", "remove,maximized_vert,maximized_horz"])
  57.         subprocess.Popen(["wmctrl", "-i", "-r", win, "-e", "0,%s,%s,%s,%s" % (positions[i],margins["top"],win_x,win_y)])
  58. elif options == "-v":
  59.     #Tile windows vertically.  Windows stack on top of each other.
  60.     win_x = screen_x - margins["right"] - margins["left"]
  61.     win_y = (screen_y - margins["top"] - margins["bottom"] - (titlebar*num_of_wins)) / num_of_wins
  62.     positions = [((win_y*y)+(titlebar*y)+margins["top"]) for y in range(0, num_of_wins)]
  63.     print positions
  64.     for i, win in enumerate(current_wins):
  65.         subprocess.Popen(["wmctrl", "-i", "-r", win, "-b", "remove,maximized_vert,maximized_horz"])
  66.         subprocess.Popen(["wmctrl", "-i", "-r", win, "-e", "0,%s,%s,%s,%s" % (margins["left"],positions[i],win_x,win_y)])
  67. elif options == "-g":
  68.     #Tiles windows in a grid.
  69.     try: rows = int(sys.argv[2])
  70.     except (ValueError, NameError, IndexError): rows = 2
  71.     cols = int(math.ceil(float(num_of_wins) / rows))
  72.     win_x = (screen_x - margins["right"] - margins["left"]) / cols
  73.     win_y = (screen_y - margins["top"] - margins["bottom"] - (titlebar*rows)) / rows
  74.     pos_x = [win_x*x for x in range(0, cols)]
  75.     pos_y = [win_y*y+(titlebar*y) for y in range(0, rows)]
  76.     grid = []
  77.     for row in pos_x:
  78.         for col in pos_y:
  79.             grid.append((row,col))
  80.     for i, win in enumerate(current_wins):
  81.         subprocess.Popen(["wmctrl", "-i", "-r", win, "-b", "remove,maximized_vert,maximized_horz"])
  82.         subprocess.Popen(["wmctrl", "-i", "-r", win, "-e", "0,%s,%s,%s,%s" % (grid[i][0], grid[i][1], win_x, win_y)])
  83.        
  84. else:
  85.     print """
  86.     Tiles windows in Openbox, either vertically or horizontally.
  87.  
  88.     Usage: tile.py [options]
  89.  
  90.     options:
  91.         -h      Tiles horizontally
  92.         -v      Tiles vertically
  93.         -g [rows]   Tiles in a grid. If unspecified, rows = 2.
  94.         --help      Print this help thingy.
  95.  
  96.     Defaults to horizontal if no options specified
  97.     """
  98.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement