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