scripts/motion.py (raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
############################################################################ ### Functions that provide callbacks for motion events to move and ### ### resize windows. ### ############################################################################ def move(data): """Moves the window interactively. This should only be used with MouseAction.Motion events. If 'Coords Popup for Moving' or 'Rubberband Mode for Moving' is enabled, then the end_move function needs to be bound as well.""" _move(data) def end_move(data): """Complete the interactive move of a window.""" _end_move(data) def resize(data): """Resizes the window interactively. This should only be used with MouseMotion events. If 'Coords Popup for Resizing' or 'Rubberband Mode for Resizing' is enabled, then the end_resize function needs to be bound as well.""" _resize(data) def end_resize(data): """Complete the interactive resize of a window.""" _end_resize(data) export_functions = move, end_move, resize, end_resize ############################################################################# import config config.add('motion', 'edge_resistance', 'Edge Resistance', "The amount of resistance to provide to moving a window past a " + \ "screen boundary. Specify a value of 0 to disable edge resistance.", 'integer', 10, min = 0) config.add('motion', 'popup_in_window', 'Coords Popup In Window', "When this is true, the coordinates popups will be placed " + \ "relative to the window being moved/resized. When false, they " + \ "will appear relative to the entire screen.", 'boolean', 0) config.add('motion', 'popup_centered', 'Coords Popup Centered', "When this is true, the coordinates popups will be centered " + \ "relative to the window or screen (see 'Coords Popup In " + \ "Window'). When false, they will be placed based upon the " + \ "'Coords Popup Position' options.", 'boolean', 1) config.add('motion', 'popup_coords_x', 'Coords Popup Position - X', "When 'Coords Popup Centered' is false, this position will be " + \ "used to place the coordinates popups. The popups will be " + \ "placed relative to the window or the screen (see 'Coords " + \ "Popup In Window'). A value of 0 would place it at the left " + \ "edge, while a value of -1 would place it at the right edge. " + \ "This value behaves similarly to those passed to the -geometry " + \ "flag of many applications.", 'integer', 0) config.add('motion', 'popup_coords_y', 'Coords Popup Position - Y', "When 'Coords Popup Centered' is false, this position will be " + \ "used to place the coordinates popups. The popups will be " + \ "placed relative to the window or the screen (see 'Coords Popup " +\ "In Window'). A value of 0 would place it at the top edge, " + \ "while a value of -1 would place it at the bottom edge. This " + \ "value behaves similarly to those passed to the -geometry flag " + \ "of many applications.", 'integer', 0) config.add('motion', 'move_popup', 'Coords Popup for Moving', "Option to display a coordinates popup when moving windows.", 'boolean', 1) config.add('motion', 'move_rubberband', 'Rubberband Mode for Moving', "NOT IMPLEMENTED (yet?)\n"+\ "Display an outline while moving instead of moving the actual " + \ "window, until the move is completed. Good for slower systems.", 'boolean', 0) config.add('motion', 'resize_popup', 'Coords Popup for Resizing', "Option to display a coordinates popup when resizing windows.", 'boolean', 1) config.add('motion', 'resize_rubberband', 'Rubberband Mode for Resizing', "NOT IMPLEMENTED (yet?)\n"+\ "Display an outline while resizing instead of resizing the " + \ "actual window, until the resize is completed. Good for slower " + \ "systems.", 'boolean', 0) config.add('motion', 'resize_nearest', 'Resize Nearest Corner', "When true, resizing will occur from the corner nearest where " + \ "the mouse is. When false resizing will always occur from the " + \ "bottom right corner.", 'boolean', 1) ########################################################################### ### Internal stuff, should not be accessed outside the module. ### ########################################################################### import ob import otk _popwidget = 0 # motion state _inmove = 0 _inresize = 0 # last motion data _cx = 0 _cy = 0 _cw = 0 _ch = 0 _px = 0 _py = 0 _dx = 0 _dy = 0 _client = 0 _screen = 0 _motion_mask = 0 def _place_popup(): if config.get('motion', 'popup_in_window'): # use the actual client's area, not the frame's area = _client.frame.area() size = _client.frame.size() area = otk.Rect(area.x() + size.left, area.y() + size.top, area.width() - size.left - size.right, area.height() - size.top - size.bottom) else: area = otk.Rect(otk.Point(0, 0), ob.openbox.screen(_screen).size()) size = _popwidget.minSize() if config.get('motion', 'popup_centered'): x = area.position().x() + (area.size().width() - size.width()) / 2 y = area.position().y() + (area.size().height() - size.height()) / 2 else: x = config.get('motion', 'popup_coords_x') y = config.get('motion', 'popup_coords_y') if x < 0: x += area.width() - size.width() + 1 if y < 0: y += area.width() - size.height() + 1 x += area.position().x() y += area.position().y() _popwidget.moveresize(otk.Rect(x, y, size.width(), size.height())) def _motion_grab(data): global _motion_mask, _inmove, _inresize; # are all the modifiers this started with still pressed? if not _motion_mask & data.state: if _inmove: _end_move(data) elif _inresize: _end_resize(data) else: raise RuntimeError _last_x = 0 _last_y = 0 def _do_move(final): global _screen, _client, _cx, _cy, _dx, _dy # get destination x/y for the *frame* x = _cx + _dx + _client.frame.area().x() - _client.area().x() y = _cy + _dy + _client.frame.area().y() - _client.area().y() global _last_x, _last_y resist = config.get('motion', 'edge_resistance') if resist: fs = _client.frame.size() w = _client.area().width() + fs.left + fs.right h = _client.area().height() + fs.top + fs.bottom # use the area based on the struts area = ob.openbox.screen(_screen).area(_client.desktop()) l = area.left() r = area.right() - w + 1 t = area.top() b = area.bottom() - h + 1 # left screen edge if _last_x > x and x < l and x >= l - resist: x = l # right screen edge if _last_x < x and x > r and x <= r + resist: x = r # top screen edge if _last_y > y and y < t and y >= t - resist: y = t # right screen edge if _last_y < y and y > b and y <= b + resist: y = b global _inmove if not _inmove: _last_x = 0 _last_y = 0 else: _last_x = x _last_y = y if not final and config.get('motion', 'move_rubberband'): # XXX draw the outline ... pass else: _client.move(x, y, final) if config.get('motion', 'move_popup'): global _popwidget text = "X: " + str(x) + " Y: " + str(y) if not _popwidget: _popwidget = otk.Label(_screen, ob.openbox) _popwidget.setHighlighted(1) _popwidget.setText(text) _place_popup() _popwidget.show() def _move(data): if not data.client: return # not-normal windows dont get moved if not data.client.normal(): return global _screen, _client, _cx, _cy, _dx, _dy, _motion_mask _screen = data.screen _client = data.client _cx = data.press_clientx _cy = data.press_clienty _dx = data.xroot - data.pressx _dy = data.yroot - data.pressy _motion_mask = data.state _do_move(0) global _inmove if not _inmove: ob.kgrab(_screen, _motion_grab) _inmove = 1 def _end_move(data): global _inmove, _popwidget if _inmove: _do_move(1) _inmove = 0 _popwidget = 0 ob.kungrab() def _do_resize(final): global _screen, _client, _cx, _cy, _cw, _ch, _px, _py, _dx, _dy dx = _dx dy = _dy # pick a corner to anchor if not (config.get('motion', 'resize_nearest') or _context == ob.MouseContext.Grip): corner = ob.Client.TopLeft else: x = _px - _cx y = _py - _cy if y < _ch / 2: if x < _cw / 2: corner = ob.Client.BottomRight dx *= -1 else: corner = ob.Client.BottomLeft dy *= -1 else: if x < _cw / 2: corner = ob.Client.TopRight dx *= -1 else: corner = ob.Client.TopLeft w = _cw + dx h = _ch + dy if not final and config.get('motion', 'resize_rubberband'): # XXX draw the outline ... pass else: _client.resize(corner, w, h) if config.get('motion', 'resize_popup'): global _popwidget ls = _client.logicalSize() text = "W: " + str(ls.width()) + " H: " + str(ls.height()) if not _popwidget: _popwidget = otk.Label(_screen, ob.openbox) _popwidget.setHighlighted(1) _popwidget.setText(text) _place_popup() _popwidget.show() def _resize(data): if not data.client: return # not-normal windows dont get resized if not data.client.normal(): return global _screen, _client, _cx, _cy, _cw, _ch, _px, _py, _dx, _dy global _motion_mask _screen = data.screen _client = data.client _cx = data.press_clientx _cy = data.press_clienty _cw = data.press_clientwidth _ch = data.press_clientheight _px = data.pressx _py = data.pressy _dx = data.xroot - _px _dy = data.yroot - _py _motion_mask = data.state _do_resize(0) global _inresize if not _inresize: ob.kgrab(_screen, _motion_grab) _inresize = 1 def _end_resize(data): global _inresize, _popwidget if _inresize: _do_resize(1) _inresize = 0 _popwidget = 0 ob.kungrab() |