]> Dogcows Code - chaz/openbox/blob - scripts/historyplacement.py
cb9fb96cc77877b4528b012722ef008659708193
[chaz/openbox] / scripts / historyplacement.py
1 ##############################################################################
2 ### The history window placement algorithm. ebind historyplacement.place ###
3 ### to the ob.EventAction.PlaceWindow event to use it. ###
4 ##############################################################################
5
6 import windowplacement, config
7
8 def place(data):
9 """Place a window usingthe history placement algorithm."""
10 _place(data)
11
12 export_functions = place
13
14 ##############################################################################
15
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',
24 0)
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',
34 1)
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)
51 config.add('historyplacement',
52 'confirm_callback',
53 'Confirm Placement Callback',
54 "A function which will be called before attempting to place a " + \
55 "window via history. If the function returns true, then an " + \
56 "attempt will be made to place the window. If it returns false, " +\
57 "the 'Fallback Algorithm' will be directly applied instead. The " +\
58 "function must take 1 argument, which will be the callback data " +\
59 "which was passed to invoke the window placement.",
60 'function',
61 None)
62
63 ###########################################################################
64
65 ###########################################################################
66 ### Internal stuff, should not be accessed outside the module. ###
67 ###########################################################################
68
69 import otk
70 import ob
71 import os
72 import string
73
74 _data = []
75
76 class _state:
77 def __init__(self, appname, appclass, role, x, y):
78 self.appname = appname
79 self.appclass = appclass
80 self.role = role
81 self.x = x
82 self.y = y
83 self.placed = 0
84 def __eq__(self, other):
85 if self.appname == other.appname and \
86 self.appclass == other.appclass and \
87 self.role == other.role:
88 return 1
89 return 0
90
91 def _load(data):
92 global _data
93 try:
94 file = open(os.environ['HOME'] + '/.openbox/' + \
95 config.get('historyplacement', 'filename') + \
96 "." + str(data.screen), 'r')
97 # read data
98 for line in file.readlines():
99 line = line[:-1] # drop the '\n'
100 try:
101 s = string.split(line, '\0')
102 state = _state(s[0], s[1], s[2],
103 string.atoi(s[3]), string.atoi(s[4]))
104
105 while len(_data)-1 < data.screen:
106 _data.append([])
107 _data[data.screen].append(state)
108
109 except ValueError: pass
110 except IndexError: pass
111 file.close()
112 except IOError: pass
113
114 def _save(data):
115 global _data
116 file = open(os.environ['HOME']+'/.openbox/'+ \
117 config.get('historyplacement', 'filename') + \
118 "." + str(data.screen), 'w')
119 if file:
120 while len(_data)-1 < data.screen:
121 _data.append([])
122 for i in _data[data.screen]:
123 file.write(i.appname + '\0' +
124 i.appclass + '\0' +
125 i.role + '\0' +
126 str(i.x) + '\0' +
127 str(i.y) + '\n')
128 file.close()
129
130 def _create_state(data):
131 global _data
132 area = data.client.area()
133 return _state(data.client.appName(), data.client.appClass(),
134 data.client.role(), area.x(), area.y())
135
136 def _find(screen, state):
137 global _data
138 try:
139 return _data[screen].index(state)
140 except ValueError:
141 return -1
142 except IndexError:
143 while len(_data)-1 < screen:
144 _data.append([])
145 return _find(screen, state) # try again
146
147 def _place(data):
148 global _data
149 if data.client:
150 if not (config.get('historyplacement', 'ignore_requested_positions') \
151 and data.client.normal()):
152 if data.client.positionRequested(): return
153 state = _create_state(data)
154 try:
155 confirm = config.get('historyplacement', 'confirm_callback')
156 if not confirm or confirm(data):
157 print "looking for : " + state.appname + " : " + \
158 state.appclass + " : " + state.role
159
160 i = _find(data.screen, state)
161 if i >= 0:
162 coords = _data[data.screen][i]
163 print "Found in history ("+str(coords.x)+","+\
164 str(coords.y)+")"
165 if not (config.get('historyplacement', 'dont_duplicate') \
166 and coords.placed):
167 data.client.move(coords.x, coords.y)
168 coords.placed = 1
169 return
170 else:
171 print "Already placed another window there"
172 else:
173 print "No match in history"
174 except TypeError:
175 pass
176 fallback = config.get('historyplacement', 'fallback')
177 if fallback: fallback(data)
178
179 def _save_window(data):
180 global _data
181 if data.client:
182 state = _create_state(data)
183 print "looking for : " + state.appname + " : " + state.appclass + \
184 " : " + state.role
185
186 i = _find(data.screen, state)
187 if i >= 0:
188 print "replacing"
189 _data[data.screen][i] = state # replace it
190 else:
191 print "appending"
192 _data[data.screen].append(state)
193
194 ob.ebind(ob.EventAction.CloseWindow, _save_window)
195 ob.ebind(ob.EventAction.Startup, _load)
196 ob.ebind(ob.EventAction.Shutdown, _save)
197
198 print "Loaded historyplacement.py"
This page took 0.040874 seconds and 3 git commands to generate.