add missing include, pass right args to font_draw
[openbox.git] / scripts / historyplacement.py
blobfb1dd35b4d4cb55d70dce4a963d0d0f780973b39
1 ##############################################################################
2 ### The history window placement algorithm. ebind historyplacement.place ###
3 ### to the ob.EventAction.PlaceWindow event to use it. ###
4 ##############################################################################
6 import windowplacement, config
8 def place(data):
9 """Place a window usingthe history placement algorithm."""
10 _place(data)
12 export_functions = place
14 ##############################################################################
16 config.add('historyplacement',
17 'ignore_requested_positions',
18 'Ignore Requested Positions',
19 "When true, the placement algorithm will attempt to place " + \
20 "windows even when they request a position (like XMMS can)." + \
21 "Note this only applies to 'normal' windows, not to special " + \
22 "cases like desktops and docks.",
23 'boolean',
25 config.add('historyplacement',
26 'dont_duplicate',
27 "Don't Diplicate",
28 "When true, if 2 copies of the same match in history are to be " + \
29 "placed before one of them is closed (so it would be placed " + \
30 "over-top of the last one), this will cause the second window to "+\
31 "not be placed via history, and the 'Fallback Algorithm' will be "+\
32 "used instead.",
33 'boolean',
35 config.add('historyplacement',
36 'filename',
37 'History Database Filename',
38 "The name of the file where history data will be stored. The " + \
39 "number of the screen is appended onto this name. The file will " +\
40 "be placed in ~/.openbox/.",
41 'string',
42 'historydb')
43 config.add('historyplacement',
44 'fallback',
45 'Fallback Algorithm',
46 "The window placement algorithm that will be used when history " + \
47 "placement does not have a place for the window.",
48 'enum',
49 windowplacement.random,
50 options = windowplacement.export_functions)
52 ###########################################################################
54 ###########################################################################
55 ### Internal stuff, should not be accessed outside the module. ###
56 ###########################################################################
58 import otk
59 import ob
60 import os
61 import string
63 _data = []
65 class _state:
66 def __init__(self, appname, appclass, role, x, y):
67 self.appname = appname
68 self.appclass = appclass
69 self.role = role
70 self.x = x
71 self.y = y
72 self.placed = 0
73 def __eq__(self, other):
74 if self.appname == other.appname and \
75 self.appclass == other.appclass and \
76 self.role == other.role:
77 return 1
78 return 0
80 def _load(data):
81 global _data
82 try:
83 file = open(os.environ['HOME'] + '/.openbox/' + \
84 config.get('historyplacement', 'filename') + \
85 "." + str(data.screen), 'r')
86 # read data
87 for line in file.readlines():
88 line = line[:-1] # drop the '\n'
89 try:
90 s = string.split(line, '\0')
91 state = _state(s[0], s[1], s[2],
92 string.atoi(s[3]), string.atoi(s[4]))
94 while len(_data)-1 < data.screen:
95 _data.append([])
96 _data[data.screen].append(state)
98 except ValueError: pass
99 except IndexError: pass
100 file.close()
101 except IOError: pass
103 def _save(data):
104 global _data
105 file = open(os.environ['HOME']+'/.openbox/'+ \
106 config.get('historyplacement', 'filename') + \
107 "." + str(data.screen), 'w')
108 if file:
109 while len(_data)-1 < data.screen:
110 _data.append([])
111 for i in _data[data.screen]:
112 file.write(i.appname + '\0' +
113 i.appclass + '\0' +
114 i.role + '\0' +
115 str(i.x) + '\0' +
116 str(i.y) + '\n')
117 file.close()
119 def _create_state(data):
120 global _data
121 area = data.client.area()
122 return _state(data.client.appName(), data.client.appClass(),
123 data.client.role(), area.x(), area.y())
125 def _find(screen, state):
126 global _data
127 try:
128 return _data[screen].index(state)
129 except ValueError:
130 return -1
131 except IndexError:
132 while len(_data)-1 < screen:
133 _data.append([])
134 return _find(screen, state) # try again
136 def _place(data):
137 global _data
138 if data.client:
139 if not (config.get('historyplacement', 'ignore_requested_positions') \
140 and data.client.normal()):
141 if data.client.positionRequested(): return
142 state = _create_state(data)
143 try:
144 print "looking for : " + state.appname + " : " + \
145 state.appclass + " : " + state.role
147 i = _find(data.screen, state)
148 if i >= 0:
149 coords = _data[data.screen][i]
150 print "Found in history ("+str(coords.x)+","+\
151 str(coords.y)+")"
152 if not (config.get('historyplacement', 'dont_duplicate') \
153 and coords.placed):
154 data.client.move(coords.x, coords.y)
155 coords.placed = 1
156 return
157 else:
158 print "Already placed another window there"
159 else:
160 print "No match in history"
161 except TypeError:
162 pass
163 fallback = config.get('historyplacement', 'fallback')
164 if fallback: fallback(data)
166 def _save_window(data):
167 global _data
168 if data.client:
169 state = _create_state(data)
170 print "looking for : " + state.appname + " : " + state.appclass + \
171 " : " + state.role
173 i = _find(data.screen, state)
174 if i >= 0:
175 print "replacing"
176 _data[data.screen][i] = state # replace it
177 else:
178 print "appending"
179 _data[data.screen].append(state)
181 ob.ebind(ob.EventAction.CloseWindow, _save_window)
182 ob.ebind(ob.EventAction.Startup, _load)
183 ob.ebind(ob.EventAction.Shutdown, _save)
185 print "Loaded historyplacement.py"