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