merge the C branch into HEAD
[openbox.git] / python / historyplacement.py
blob0421a223e07452fe06b85f8dda99f76a0c29ba64
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, hooks
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 ob, os, string
60 _data = []
62 class _State:
63 def __init__(self, resname, resclass, role, x, y):
64 self.resname = resname
65 self.resclass = resclass
66 self.role = role
67 self.x = x
68 self.y = y
69 self.placed = 0
70 def __eq__(self, other):
71 if self.resname == other.resname and \
72 self.resclass == other.resclass and \
73 self.role == other.role:
74 return 1
75 return 0
77 def _load():
78 global _data
79 try:
80 file = open(os.environ['HOME'] + '/.openbox/' + \
81 config.get('historyplacement', 'filename') + \
82 "." + str(ob.Openbox.screenNumber()), 'r')
83 # read data
84 for line in file.readlines():
85 line = line[:-1] # drop the '\n'
86 try:
87 s = string.split(line, '\0')
88 state = _State(s[0], s[1], s[2],
89 int(s[3]), int(s[4]))
91 _data.append(state)
93 except ValueError: pass
94 except IndexError: pass
95 file.close()
96 except IOError: pass
98 def _save():
99 file = open(os.environ['HOME'] + '/.openbox/'+ \
100 config.get('historyplacement', 'filename') + \
101 "." + str(ob.Openbox.screenNumber()), 'w')
102 if file:
103 for i in _data:
104 file.write(i.resname + '\0' +
105 i.resclass + '\0' +
106 i.role + '\0' +
107 str(i.x) + '\0' +
108 str(i.y) + '\n')
109 file.close()
111 def _create_state(client):
112 area = client.area()
113 return _State(client.resName(), client.resClass(),
114 client.role(), area[0], area[1])
116 def _place(client):
117 state = _create_state(client)
118 try:
119 print "looking for : " + state.resname + " : " + \
120 state.resclass + " : " + state.role
121 try:
122 i = _data.index(state)
123 except ValueError:
124 print "No match in history"
125 else:
126 coords = _data[i] # get the equal element
127 print "Found in history ("+str(coords.x)+","+\
128 str(coords.y)+")"
129 if not (config.get('historyplacement', 'dont_duplicate') \
130 and coords.placed):
131 coords.placed = 1
132 if ob.Openbox.state() != ob.State.Starting:
133 # if not (config.get('historyplacement', 'ignore_requested_positions') \
134 # and data.client.normal()):
135 # if data.client.positionRequested(): return
136 ca = client.area()
137 client.setArea((coords.x, coords.y, ca[2], ca[3]))
138 return
139 else:
140 print "Already placed another window there"
141 except TypeError:
142 pass
143 fallback = config.get('historyplacement', 'fallback')
144 if fallback: fallback(client)
146 def _save_window(client):
147 global _data
148 state = _create_state(client)
149 print "looking for : " + state.resname + " : " + state.resclass + \
150 " : " + state.role
152 try:
153 print "replacing"
154 i = _data.index(state)
155 _data[i] = state # replace it
156 except ValueError:
157 print "appending"
158 _data.append(state)
160 hooks.startup.append(_load)
161 hooks.shutdown.append(_save)
162 hooks.closed.append(_save_window)
164 print "Loaded historyplacement.py"