Guest User

Untitled

a guest
Jul 21st, 2015
269
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 14.02 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # coding: utf-8
  3. # vim: ai ts=4 sts=4 et sw=4
  4.   
  5. import os, sys, re, logging
  6. from functools import wraps, partial
  7. from optparse import OptionParser
  8. import gtk, gobject
  9. from gtk import gdk
  10. import wnck
  11.   
  12. __doc__ = """
  13. #.rules.py example
  14.   
  15. #@opened(name='gvim')
  16. #def move_gvim(win):
  17. #    " resize and move gvim when it's started "
  18. #    win.move(0,54)
  19. #    win.resize(1124,689)
  20.   
  21. #@opened(app_name='chromium-browser')
  22. #def maximize_chrominum(win):
  23. #    win.maximize()
  24.   
  25. #@moved(name='gvim')
  26. #def gvim_moved(win):
  27. #    " print gvim position when it's moved "
  28. #    print win.get_position()
  29.   
  30. #@opened(name='Buddy List')
  31. #def fix_pidgin(window):
  32. #    " fix pidgin window in the right corner "
  33. #    window.move(1072, 0)
  34. #    window.resize(208, 745)
  35. #    #window.set_functions(gdk.FUNC_ALL ^ gdk.FUNC_MOVE ^ gdk.FUNC_RESIZE)
  36. #    window.set_functions(gdk.FUNC_CLOSE)
  37.   
  38. #@focused(app_name='mplayer')
  39. #def mplayer_tomon1(window):
  40. #    " move mplayer to second monitor "
  41. #    window.to_monitor(1)
  42. #    window.fullscreen()
  43. """
  44.   
  45. #class Window(object):
  46. #    def __init__(self, w):
  47. #        gw = gdk.window_foreign_new(w.get_xid())
  48. #        for k,v in w.__class__.__dict__.items():
  49. #            if callable(v) and not k.startswith('_'):
  50. #                setattr(self, k, partial(v, w))
  51. #        for k,v in gw.__class__.__dict__.items():
  52. #            if callable(v) and not k.startswith('_'):
  53. #                setattr(self, k, partial(v, gw))
  54. #STATE_NORMAL = 0
  55. #STATE_MINIMIZED = 129
  56. #STATE_MAXIMIZED = 6
  57. #STATE_FULLSCREEN = 256
  58.   
  59. class Window(object):
  60.     """
  61.     own methods:
  62.     to_monitor
  63.     methods from wnck.Window:
  64.     activate activate_transient close get_actions get_application get_class_group get_client_window_geometry get_geometry get_group_leader get_icon get_icon_is_fallback get_icon_name get_mini_icon get_name get_pid get_screen get_session_id get_session_id_utf8 get_sort_order get_state get_transient get_window_type get_workspace get_xid has_icon_name has_name is_above is_active is_below is_fullscreen is_in_viewport is_maximized is_maximized_horizontally is_maximized_vertically is_minimized is_most_recently_activated is_on_workspace is_pinned is_shaded is_skip_pager is_skip_tasklist is_sticky is_visible_on_workspace keyboard_move keyboard_size make_above make_below maximize maximize_horizontally maximize_vertically minimize move_to_workspace needs_attention or_transient_needs_attention pin set_fullscreen set_geometry set_icon_geometry set_skip_pager set_skip_tasklist set_sort_order set_window_type shade stick transient_is_most_recently_activated unmake_above unmake_below unmaximize unmaximize_horizontally unmaximize_vertically unminimize unpin unshade unstick
  65.     methods from gtk.gdk.Window:
  66.     add_filter beep begin_move_drag begin_paint_rect begin_paint_region begin_resize_drag clear clear_area clear_area_e configure_finished deiconify destroy destroy_notify drag_begin enable_synchronized_configure end_paint focus freeze_updates fullscreen get_children get_decorations get_deskrelative_origin get_events get_frame_extents get_geometry get_group get_origin get_parent get_pointer get_position get_root_origin get_state get_toplevel get_type_hint get_update_area get_user_data get_window_type hide iconify input_set_extension_events input_shape_combine_mask input_shape_combine_region invalidate_rect invalidate_region is_viewable is_visible lower maximize merge_child_input_shapes merge_child_shapes move move_region move_resize move_to_current_desktop process_updates property_change property_delete property_get raise_ redirect_to_drawable register_dnd remove_redirection reparent resize scroll selection_convert set_accept_focus set_back_pixmap set_background set_child_input_shapes set_child_shapes set_composited set_cursor set_decorations set_events set_focus_on_map set_functions set_geometry_hints set_group set_hints set_icon set_icon_list set_icon_name set_keep_above set_keep_below set_modal_hint set_opacity set_override_redirect set_role set_skip_pager_hint set_skip_taskbar_hint set_startup_id set_static_gravities set_title set_transient_for set_type_hint set_urgency_hint set_user_data set_user_time shape_combine_mask shape_combine_region show show_unraised stick thaw_updates unfullscreen unmaximize unstick withdraw
  67.     """
  68.   
  69.     def __init__(self, wnck_window):
  70.         self.wnck_window = wnck_window
  71.         self.gdk_window = gdk.window_foreign_new(wnck_window.get_xid())
  72.   
  73.     def __getattr__(self, k):
  74.         if k in ['above', 'active', 'below', 'fullscreen', 'maximized', 'maximized_horizontally', 'maximized_vertically', 'minimized', 'most_recently_activated', 'pinned', 'shaded', 'skip_pager', 'skip_tasklist', 'sticky']:
  75.             return getattr(self.wnck_window,'is_%s' % k)()
  76.         if k in ['geometry', 'state', 'pid', 'xid', 'actions', 'window_type', 'client_window_geometry', 'name']:
  77.             return getattr(self.wnck_window,'get_%s' % k)()
  78.         if k in ['decorations', 'frame_extents', 'geometry', 'origin', 'position', 'root_origin', 'size', 'type_hint', 'window_type']:
  79.             return getattr(self.gdk_window,'get_%s' % k)()
  80.   
  81.         if hasattr(self.wnck_window, k):
  82.             return getattr(self.wnck_window, k)
  83.         elif hasattr(self.gdk_window, k):
  84.             return getattr(self.gdk_window, k)
  85.         else:
  86.             raise AttributeError("Window has no attribute '%s'" % k)
  87.   
  88.     def __dir__(self):
  89.         return [k for k in dir(wnck.Window)+dir(gdk.Window) if not k.startswith('_')]+dir(Window)
  90.   
  91.     def to_monitor(self, monitor_number):
  92.         was_max = self.wnck_window.is_maximized()
  93.         was_fs = self.wnck_window.is_fullscreen()
  94.         self.wnck_window.unmaximize()
  95.         self.wnck_window.set_fullscreen(False)
  96.         s = self.gdk_window.get_screen()
  97.         cur = s.get_monitor_at_window(self.gdk_window)
  98.         if cur == monitor_number:
  99.             return
  100.         mong = s.get_monitor_geometry(monitor_number)
  101.         curmong = s.get_monitor_geometry(cur)
  102.         pos = list(self.gdk_window.get_root_origin())
  103.         pos[0] += mong[0] - curmong[0]
  104.         pos[1] += mong[1] - curmong[1]
  105.         self.gdk_window.move(*pos)
  106.         if was_max:
  107.             self.wnck_window.maximize()
  108.         self.wnck_window.set_fullscreen(was_fs)
  109.   
  110.     def focus(self):
  111.         self.wnck_window.activate(int(gobject.get_current_time()))
  112.   
  113.     @property
  114.     def name(self):
  115.         return self.wnck_window.get_name()
  116.   
  117.   
  118. #def _event_decorator(event_name, event, f):
  119. #    screen.connect(event, f)
  120. #    f.event = event_name
  121. #    if event_name not in connected:
  122. #        connected[event_name] = []
  123. #    connected[event_name].append(f)
  124. #    return f
  125.   
  126. def _event_decorator(event_name, event, **kargs):
  127.     def wrap(f):
  128.         for _name, _func in functions:
  129.             if _name in kargs:
  130.                 f = _decorator(_func, _name, kargs[_name])(f)
  131.         screen.connect(event, f)
  132.         f.event = event_name
  133.         if event_name not in connected:
  134.             connected[event_name] = []
  135.         connected[event_name].append(f)
  136.         return f
  137.     wrap.event = event_name
  138.     return wrap
  139.   
  140. #def _window_event(event_name, event, f):
  141. #    f.event = event_name
  142.   
  143. #    if event_name not in connected:
  144. #        connected[event_name] = []
  145. #    connected[event_name].append(f)
  146. #    return f
  147.   
  148. def _window_event(event_name, event, **kargs):
  149.     def wrap(f):
  150.         for _name, _func in functions:
  151.             if _name in kargs:
  152.                 f = _decorator(_func, _name, kargs[_name])(f)
  153.         f.event = event_name
  154.         if event_name not in connected:
  155.             connected[event_name] = []
  156.         connected[event_name].append(f)
  157.         return f
  158.     wrap.event = event_name
  159.     return wrap
  160.   
  161.   
  162.   
  163. def _decorator(attr, attr_title, match):
  164.     src = repr(match)
  165.     if isinstance(match, basestring):
  166.         match = re.compile('.*%s.*' % match, re.IGNORECASE).match
  167.     elif hasattr(match, 'match'):
  168.         match = match.match
  169.     def dec(f):
  170.         @wraps(f)
  171.         def wrap(w, *args):
  172.             if isinstance(w, wnck.Screen):
  173.                 args = list(args)
  174.                 w = args.pop(0)
  175.             if wrap.event == 'focused':
  176.                 w = screen.get_active_window()
  177.             if match(attr(w)):
  178.                 if opts.verbose:
  179.                     print wrap.event, attr_title, repr(attr(w)), 'match', src, 'function: %r' % f.__name__
  180.                 return f(Window(w), *args)
  181.             return True
  182.         wrap.src = src
  183.         #wrap.match = match
  184.         #wrap.attr = attr
  185.         return wrap
  186.     return dec
  187.   
  188. screen_events = (
  189.     ('focused', 'active-window-changed'),
  190.     ('opened', 'window-opened'),
  191.     #('app_opened', 'application-opened'),
  192. )
  193. window_events = (
  194.     ('moved', 'geometry-changed'),
  195.     ('state_changed', 'state-changed'),
  196.     ('workspace_changed', 'workspace-changed'),
  197.     ('actions_changed', 'actions-changed'),
  198. )
  199.   
  200. functions = (
  201.     ('name', lambda w: w and w.get_name() or ''),
  202.     #('icon_name', lambda w: w.get_icon_name()),
  203.     ('app_name', lambda w: w and w.get_application() and w.get_application().get_name() or ''),
  204.     #('app_icon_name', lambda w: w.get_application() and w.get_application().get_icon_name() or ''),
  205. )
  206.   
  207. for _name, _func in functions:
  208.     globals()[_name] = partial(_decorator, _func, _name)
  209.   
  210. for _name, _event in screen_events:
  211.     globals()[_name] = partial(_event_decorator, _name, _event)
  212.   
  213. for _name, _event in window_events:
  214.     globals()[_name] = partial(_window_event, _name, _event)
  215.   
  216. #|  Signals from WnckScreen:
  217. #|    window-manager-changed ()
  218. #|    active-workspace-changed (WnckWorkspace)
  219. #|    window-stacking-changed ()
  220. #|    window-closed (WnckWindow)
  221. #|    workspace-created (WnckWorkspace)
  222. #|    workspace-destroyed (WnckWorkspace)
  223. #|    application-opened (WnckApplication)
  224. #|    application-closed (WnckApplication)
  225. #|    class-group-opened (WnckClassGroup)
  226. #|    class-group-closed (WnckClassGroup)
  227. #|    background-changed ()
  228. #|    showing-desktop-changed ()
  229. #|    viewports-changed ()
  230. #|  Signals from WnckWindow:
  231. #|    name-changed ()
  232. #|    workspace-changed ()
  233. #|    icon-changed ()
  234.   
  235. def connect_to_window(scr, window):
  236.     for _name, _event in window_events:
  237.         for v in connected.get(_name, []):
  238.             window.connect(_event, v)
  239.   
  240. def connect_to_windows():
  241.     screen.connect('window-opened', connect_to_window)
  242.   
  243. def setup_debug():
  244.     def get_debug():
  245.         def debug(s, w):
  246.             if debug.event == 'focused':
  247.                 w = s.get_active_window()
  248.             if w:
  249.                 print '[%s]' % debug.event, ' '.join('%s: %r' % (_name, _func(w)) for _name, _func in functions)
  250.                 print '', ' '.join('%s:%r' % (_name, getattr(w,'get_%s' % _name)()) for _name in \
  251.                     ('geometry', 'client_window_geometry', 'pid', 'xid', 'window_type'))
  252.             return True
  253.         return debug
  254.     debug_focused = focused()(get_debug())
  255.     debug_opened = opened()(get_debug())
  256.   
  257.   
  258. if __name__ == '__main__':
  259.   
  260.     connected = {}
  261.     screen = wnck.screen_get_default()
  262.   
  263.     opts = OptionParser()
  264.     opts.add_option("-q", "--quiet",
  265.                   action="store_false", dest="verbose", default=True,
  266.                   help="don't print status messages to stdout")
  267.     opts.add_option("-d", "--debug",
  268.                   action="store_true", dest="debug", default=False,
  269.                   help="print all events and window information to stdout")
  270.     opts.add_option("-f", "--file",
  271.                   dest="filename", default='~/.rules.py',
  272.                   help="read rules from file(default: ~/.rules.py)")
  273.     opts, args = opts.parse_args()
  274.   
  275.     default_path = opts.filename == '~/.rules.py'
  276.     opts.filename = os.path.expanduser(opts.filename)
  277.     if not os.path.exists(opts.filename):
  278.         print >>sys.stderr, "%s not found" % opts.filename
  279.         if default_path:
  280.             open(opts.filename, "w").write(__doc__)
  281.             print >>sys.stderr, "%s was created, check it out" % opts.filename
  282.         sys.exit(1)
  283.     exec(compile(open(opts.filename).read(),'rules','exec'))
  284.   
  285.     if opts.verbose:
  286.         for k,v in connected.items():
  287.             print '%s:' % k
  288.             for _func in v:
  289.                 print '',getattr(_func,'src','*'),_func
  290.   
  291.     if opts.debug:
  292.         setup_debug()
  293.   
  294.     if not connected:
  295.         print >>sys.stderr, "no rules defined in %s" % opts.filename
  296.         sys.exit(1)
  297.     connect_to_windows()
  298.   
  299.     gtk.main()
Advertisement
Add Comment
Please, Sign In to add comment