]> Dogcows Code - chaz/openbox/blob - scripts/motion.py
bf52bd9634698a7f5b5a87edfd12b5e87d77267d
[chaz/openbox] / scripts / motion.py
1 ############################################################################
2 ### Functions that provide callbacks for motion events to move and ###
3 ### resize windows. ###
4 ############################################################################
5
6 #############################################################################
7 ### Options that can be modified to change the functions' behaviors. ###
8 #############################################################################
9 EDGE_RESISTANCE = 10
10 """The amount of resistance to provide to moving a window past a screen
11 boundary. Specify a value of 0 to disable edge resistance."""
12 POPUP_IN_WINDOW = 0
13 """When this is non-zero, the coordinates popups will be placed relative to
14 the window being moved/resized. When zero, they will appear relative to the
15 entire screen."""
16 POPUP_CENTERED = 1
17 """When this is non-zero, the coordinates popups will be centered relative to
18 the window or screen (see POPUP_IN_WINDOW). When zero, they will be placed
19 at based upon POPUP_COORDS."""
20 POPUP_COORDS = 0, 0
21 """When POPUP_CENTERED is zero, these coordinates will be used to place the
22 coordinates popup. The popup will be placed relative to the window or the
23 screen (see POPUP_IN_WINDOW). A value of 0, 0 would place it in the top
24 left corner, while a value of -1, -1 would place it in the bottom right.
25 These values behave simmilarly to those passed to the -geometry flag of many
26 applications."""
27 MOVE_POPUP = 1
28 """Display a coordinates popup when moving windows."""
29 MOVE_RUBBERBAND = 0
30 """NOT IMPLEMENTED (yet?)
31 Display an outline while moving instead of moving the actual window,
32 until the move is completed. Good for slower systems."""
33 RESIZE_POPUP = 1
34 """Display a size popup when resizing windows."""
35 RESIZE_RUBBERBAND = 0
36 """NOT IMPLEMENTED (yet?)
37 Display an outline while resizing instead of resizing the actual
38 window, until the resize is completed. Good for slower systems."""
39 RESIZE_NEAREST = 1
40 """Non-zero to resize from the corner nearest where the mouse is, 0 to
41 resize always from the bottom right corner."""
42 #############################################################################
43
44 def move(data):
45 """Moves the window interactively. This should only be used with
46 MouseAction.Motion events. If MOVE_POPUP or MOVE_RUBBERBAND is enabled,
47 then the end_move function needs to be bound as well."""
48 _move(data)
49
50 def end_move(data):
51 """Complete the interactive move of a window."""
52 _end_move(data)
53
54 def resize(data):
55 """Resizes the window interactively. This should only be used with
56 MouseMotion events. If RESIZE_POPUP or RESIZE_RUBBERBAND is enabled,
57 then the end_resize function needs to be bound as well."""
58 _resize(data)
59
60 def end_resize(data):
61 """Complete the interactive resize of a window."""
62 _end_resize(data)
63
64 ###########################################################################
65 ###########################################################################
66
67 ###########################################################################
68 ### Internal stuff, should not be accessed outside the module. ###
69 ###########################################################################
70
71 import ob
72 import otk
73
74 _popwidget = 0
75
76 # motion state
77 _inmove = 0
78 _inresize = 0
79
80 # last motion data
81 _cx = 0
82 _cy = 0
83 _cw = 0
84 _ch = 0
85 _px = 0
86 _py = 0
87 _dx = 0
88 _dy = 0
89 _client = 0
90 _screen = 0
91
92 _motion_mask = 0
93
94 def _place_popup():
95 if POPUP_IN_WINDOW:
96 area = _client.frame.area()
97 else:
98 area = otk.Rect(otk.Point(0, 0), ob.openbox.screen(_screen).size())
99 size = _popwidget.minSize()
100 if POPUP_CENTERED:
101 x = area.position().x() + (area.size().width() - size.width()) / 2
102 y = area.position().y() + (area.size().height() - size.height()) / 2
103 else:
104 try: x, y = POPUP_COORDS
105 except: x = y = 0
106 if x < 0: x += area.right() - size.width() + 2
107 if y < 0: y += area.bottom() - size.height() + 2
108 _popwidget.moveresize(otk.Rect(x, y, size.width(), size.height()))
109
110 def _motion_grab(data):
111 global _motion_mask, _inmove, _inresize;
112
113 # are all the modifiers this started with still pressed?
114 if not _motion_mask & data.state:
115 if _inmove:
116 _end_move(data)
117 elif _inresize:
118 _end_resize(data)
119 else:
120 raise RuntimeError
121
122 _last_x = 0
123 _last_y = 0
124
125 def _do_move(final):
126 global _screen, _client, _cx, _cy, _dx, _dy
127
128 # get destination x/y for the *frame*
129 x = _cx + _dx + _client.frame.area().x() - _client.area().x()
130 y = _cy + _dy + _client.frame.area().y() - _client.area().y()
131
132 global _last_x, _last_y
133 if EDGE_RESISTANCE:
134 fs = _client.frame.size()
135 w = _client.area().width() + fs.left + fs.right
136 h = _client.area().height() + fs.top + fs.bottom
137 # use the area based on the struts
138 area = ob.openbox.screen(_screen).area(_client.desktop())
139 l = area.left()
140 r = area.right() - w + 1
141 t = area.top()
142 b = area.bottom() - h + 1
143 # left screen edge
144 if _last_x > x and x < l and x >= l - EDGE_RESISTANCE:
145 x = l
146 # right screen edge
147 if _last_x < x and x > r and x <= r + EDGE_RESISTANCE:
148 x = r
149 # top screen edge
150 if _last_y > y and y < t and y >= t - EDGE_RESISTANCE:
151 y = t
152 # right screen edge
153 if _last_y < y and y > b and y <= b + EDGE_RESISTANCE:
154 y = b
155
156 global _inmove
157 if not _inmove:
158 _last_x = 0
159 _last_y = 0
160 else:
161 _last_x = x
162 _last_y = y
163
164 if MOVE_RUBBERBAND:
165 # draw the outline ...
166 f=0
167 else:
168 _client.move(x, y, final)
169
170 if MOVE_POPUP:
171 global _popwidget
172 text = "X: " + str(x) + " Y: " + str(y)
173 if not _popwidget:
174 _popwidget = otk.Label(_screen, ob.openbox)
175 _popwidget.setHighlighted(1)
176 _popwidget.setText(text)
177 _place_popup()
178 _popwidget.show()
179
180 def _move(data):
181 if not data.client: return
182
183 # not-normal windows dont get moved
184 if not data.client.normal(): return
185
186 global _screen, _client, _cx, _cy, _dx, _dy, _motion_mask
187 _screen = data.screen
188 _client = data.client
189 _cx = data.press_clientx
190 _cy = data.press_clienty
191 _dx = data.xroot - data.pressx
192 _dy = data.yroot - data.pressy
193 _motion_mask = data.state
194 _do_move(0)
195 global _inmove
196 if not _inmove:
197 ob.kgrab(_screen, _motion_grab)
198 _inmove = 1
199
200 def _end_move(data):
201 global MOVE_RUBBERBAND
202 global _inmove, _popwidget
203 if _inmove:
204 r = MOVE_RUBBERBAND
205 MOVE_RUBBERBAND = 0
206 _do_move(1)
207 MOVE_RUBBERBAND = r
208 _inmove = 0
209 _popwidget = 0
210 ob.kungrab()
211
212 def _do_resize():
213 global _screen, _client, _cx, _cy, _cw, _ch, _px, _py, _dx, _dy
214
215 dx = _dx
216 dy = _dy
217
218 # pick a corner to anchor
219 if not (RESIZE_NEAREST or _context == ob.MouseContext.Grip):
220 corner = ob.Client.TopLeft
221 else:
222 x = _px - _cx
223 y = _py - _cy
224 if y < _ch / 2:
225 if x < _cw / 2:
226 corner = ob.Client.BottomRight
227 dx *= -1
228 else:
229 corner = ob.Client.BottomLeft
230 dy *= -1
231 else:
232 if x < _cw / 2:
233 corner = ob.Client.TopRight
234 dx *= -1
235 else:
236 corner = ob.Client.TopLeft
237
238 w = _cw + dx
239 h = _ch + dy
240
241 if RESIZE_RUBBERBAND:
242 # draw the outline ...
243 f=0
244 else:
245 _client.resize(corner, w, h)
246
247 if RESIZE_POPUP:
248 global _popwidget
249 ls = _client.logicalSize()
250 text = "W: " + str(ls.width()) + " H: " + str(ls.height())
251 if not _popwidget:
252 _popwidget = otk.Label(_screen, ob.openbox)
253 _popwidget.setHighlighted(1)
254 _popwidget.setText(text)
255 _place_popup()
256 _popwidget.show()
257
258 def _resize(data):
259 if not data.client: return
260
261 # not-normal windows dont get resized
262 if not data.client.normal(): return
263
264 global _screen, _client, _cx, _cy, _cw, _ch, _px, _py, _dx, _dy
265 global _motion_mask
266 _screen = data.screen
267 _client = data.client
268 _cx = data.press_clientx
269 _cy = data.press_clienty
270 _cw = data.press_clientwidth
271 _ch = data.press_clientheight
272 _px = data.pressx
273 _py = data.pressy
274 _dx = data.xroot - _px
275 _dy = data.yroot - _py
276 _motion_mask = data.state
277 _do_resize()
278 global _inresize
279 if not _inresize:
280 ob.kgrab(_screen, _motion_grab)
281 _inresize = 1
282
283 def _end_resize(data):
284 global RESIZE_RUBBERBAND, _inresize
285 global _popwidget
286 if _inresize:
287 r = RESIZE_RUBBERBAND
288 RESIZE_RUBBERBAND = 0
289 _do_resize()
290 RESIZE_RUBBERBAND = r
291 _inresize = 0
292 _popwidget = 0
293 ob.kungrab()
This page took 0.053968 seconds and 3 git commands to generate.