support pseudocolor and greyscale displays by, using solid colors instead of gradients
[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 _last_x = 0
90 _last_y = 0
91
92 def _do_move():
93     global _screen, _client, _cx, _cy, _dx, _dy
94
95     # get destination x/y for the *frame*
96     x = _cx + _dx + _client.frame.rect().x() - _client.area().x()
97     y = _cy + _dy + _client.frame.rect().y() - _client.area().y()
98
99     global edge_resistance
100     global _last_x, _last_y
101     if edge_resistance:
102         fs = _client.frame.size()
103         w = _client.area().width() + fs.left + fs.right
104         h = _client.area().height() + fs.top + fs.bottom
105         # use the area based on the struts
106         area = ob.openbox.screen(_screen).area()
107         l = area.left()
108         r = area.right() - w + 1
109         t = area.top()
110         b = area.bottom() - h + 1
111         # left screen edge
112         if _last_x > x and x < l and x >= l - edge_resistance:
113             x = l
114         # right screen edge
115         if _last_x < x and x > r and x <= r + edge_resistance:
116             x = r
117         # top screen edge
118         if _last_y > y and y < t and y >= t - edge_resistance:
119             y = t
120         # right screen edge
121         if _last_y < y and y > b and y <= b + edge_resistance:
122             y = b
123
124     global _inmove
125     if not _inmove:
126         _last_x = 0
127         _last_y = 0
128     else:
129         _last_x = x
130         _last_y = y
131
132     global move_rubberband
133     if move_rubberband:
134         # draw the outline ...
135         f=0
136     else:
137         _client.move(x, y)
138
139     global move_popup
140     if move_popup:
141         global _popwidget, _poplabel
142         style = ob.openbox.screen(_screen).style()
143         font = style.labelFont()
144         text = "X: " + str(x) + " Y: " + str(y)
145         length = font.measureString(text)
146         if not _popwidget:
147             _popwidget = otk.Widget(ob.openbox, style,
148                                     otk.Widget.Horizontal, 0,
149                                     style.bevelWidth(), 1)
150             _popwidget.setTexture(style.titlebarFocusBackground())
151             _poplabel = otk.Label(_popwidget)
152             _poplabel.setTexture(style.labelFocusBackground())
153         _poplabel.fitString(text)
154         _poplabel.setText(text)
155         _popwidget.update() 
156         area = otk.display.screenInfo(_screen).rect()
157         _popwidget.move(area.x() + (area.width() -
158                                     _popwidget.width()) / 2,
159                         area.y() + (area.height() -
160                                     _popwidget.height()) / 2)
161         _popwidget.show(1)
162
163 def move(data):
164     """Moves the window interactively. This should only be used with
165        MouseMotion events. If move_popup or move_rubberband is enabled, then
166        the end_move function needs to be bound as well."""
167     if not data.client: return
168
169     # not-normal windows dont get moved
170     if not data.client.normal(): return
171
172     global _screen, _client, _cx, _cy, _dx, _dy
173     _screen = data.screen
174     _client = data.client
175     _cx = data.press_clientx
176     _cy = data.press_clienty
177     _dx = data.xroot - data.pressx
178     _dy = data.yroot - data.pressy
179     _do_move()
180     global _inmove
181     if not _inmove:
182         ob.kgrab(_screen, _motion_grab)
183         _inmove = 1
184
185 def end_move(data):
186     """Complete the interactive move of a window."""
187     global move_rubberband, _inmove
188     global _popwidget, _poplabel
189     if _inmove:
190         r = move_rubberband
191         move_rubberband = 0
192         _do_move()
193         move_rubberband = r
194         _inmove = 0
195     _poplabel = 0
196     _popwidget = 0
197     ob.kungrab()
198
199 def _do_resize():
200     global _screen, _client, _cx, _cy, _cw, _ch, _px, _py, _dx, _dy
201
202     dx = _dx
203     dy = _dy
204     
205     # pick a corner to anchor
206     if not (resize_nearest or _context == ob.MouseContext.Grip):
207         corner = ob.Client.TopLeft
208     else:
209         x = _px - _cx
210         y = _py - _cy
211         if y < _ch / 2:
212             if x < _cw / 2:
213                 corner = ob.Client.BottomRight
214                 dx *= -1
215             else:
216                 corner = ob.Client.BottomLeft
217             dy *= -1
218         else:
219             if x < _cw / 2:
220                 corner = ob.Client.TopRight
221                 dx *= -1
222             else:
223                 corner = ob.Client.TopLeft
224
225     w = _cw + dx
226     h = _ch + dy
227
228     global resize_popup
229     if resize_rubberband:
230         # draw the outline ...
231         f=0
232     else:
233         _client.resize(corner, w, h)
234
235     global resize_popup
236     if resize_popup:
237         global _popwidget, _poplabel
238         style = ob.openbox.screen(_screen).style()
239         ls = _client.logicalSize()
240         text = "W: " + str(ls.x()) + " H: " + str(ls.y())
241         if not _popwidget:
242             _popwidget = otk.Widget(ob.openbox, style,
243                                     otk.Widget.Horizontal, 0,
244                                     style.bevelWidth(), 1)
245             _popwidget.setTexture(style.titlebarFocusBackground())
246             _poplabel = otk.Label(_popwidget)
247             _poplabel.setTexture(style.labelFocusBackground())
248         _poplabel.fitString(text)
249         _poplabel.setText(text)
250         area = otk.display.screenInfo(_screen).rect()
251         _popwidget.update() 
252         _popwidget.move(area.x() + (area.width() -
253                                     _popwidget.width()) / 2,
254                         area.y() + (area.height() -
255                                     _popwidget.height()) / 2)
256         _popwidget.show(1)
257
258 def resize(data):
259     """Resizes the window interactively. This should only be used with
260        MouseMotion events"""
261     if not data.client: return
262
263     # not-normal windows dont get resized
264     if not data.client.normal(): return
265
266     global _screen, _client, _cx, _cy, _cw, _ch, _px, _py, _dx, _dy
267     _screen = data.screen
268     _client = data.client
269     _cx = data.press_clientx
270     _cy = data.press_clienty
271     _cw = data.press_clientwidth
272     _ch = data.press_clientheight
273     _px = data.pressx
274     _py = data.pressy
275     _dx = data.xroot - _px
276     _dy = data.yroot - _py
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     """Complete the interactive resize of a window."""
285     global resize_rubberband, _inresize
286     global _popwidget, _poplabel
287     if _inresize:
288         r = resize_rubberband
289         resize_rubberband = 0
290         _do_resize()
291         resize_rubberband = r
292         _inresize = 0
293     _poplabel = 0
294     _popwidget = 0
295     ob.kungrab()