| 1 |  |  | """Wrapper around libwnck for interacting with the window manager""" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | __author__ = "Stephan Sokolow (deitarion/SSokolow)" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  | __license__ = "GNU GPL 2.0 or later" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  | import logging | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | import gtk.gdk, wnck  # pylint: disable=import-error | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  | from .util import EnumSafeDict, XInitError | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | #: Lookup table for internal window gravity support. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  | #: (libwnck's support is either unreliable or broken) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  | GRAVITY = EnumSafeDict({ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  |     'NORTH_WEST': (0.0, 0.0), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  |     'NORTH': (0.5, 0.0), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  |     'NORTH_EAST': (1.0, 0.0), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  |     'WEST': (0.0, 0.5), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  |     'CENTER': (0.5, 0.5), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  |     'EAST': (1.0, 0.5), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  |     'SOUTH_WEST': (0.0, 1.0), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  |     'SOUTH': (0.5, 1.0), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |     'SOUTH_EAST': (1.0, 1.0), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  | }) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  | key, val = None, None  # Safety cushion for the "del" line. | 
                            
                    |  |  |  | 
                                                                                        
                                                                                            
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  | for key, val in GRAVITY.items(): | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  |     # Support GDK gravity constants | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  |     GRAVITY[getattr(gtk.gdk, 'GRAVITY_%s' % key)] = val | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |     # Support libwnck gravity constants | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |     _name = 'WINDOW_GRAVITY_%s' % key.replace('_', '') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |     GRAVITY[getattr(wnck, _name)] = val | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  | # Prevent these temporary variables from showing up in the apidocs | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  | del _name, key, val | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  | # --- | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  | class WorkArea(object): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |     """Helper to calculate and query available workarea on the desktop.""" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |     def __init__(self, gdk_screen, ignore_struts=False): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  |         self.gdk_screen = gdk_screen | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  |         self.ignore_struts = ignore_struts | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |     def get_monitor_rect(self, monitor): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |         """Helper to normalize various monitor identifiers.""" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  |         if isinstance(monitor, int): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |             usable_rect = self.gdk_screen.get_monitor_geometry(monitor) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  |             logging.debug("Retrieved geometry %s for monitor #%s", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  |                           usable_rect, monitor) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |         elif not isinstance(monitor, gtk.gdk.Rectangle): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |             logging.debug("Converting geometry %s to gtk.gdk.Rectangle", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |                           monitor) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |             usable_rect = gtk.gdk.Rectangle(monitor) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |         else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |             usable_rect = monitor | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |         usable_region = gtk.gdk.region_rectangle(usable_rect) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |         if not usable_region.get_rectangles(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |             logging.error("WorkArea.get_monitor_rect received " | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |                           "an empty monitor region!") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  |             return None, None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |         return usable_rect, usable_region | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 65 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 66 |  |  |     def get_struts(self, root_win): | 
            
                                                                        
                            
            
                                    
            
            
                | 67 |  |  |         """Retrieve the struts from the root window if supported.""" | 
            
                                                                        
                            
            
                                    
            
            
                | 68 |  |  |         if not self.gdk_screen.supports_net_wm_hint("_NET_WM_STRUT_PARTIAL"): | 
            
                                                                        
                            
            
                                    
            
            
                | 69 |  |  |             return [] | 
            
                                                                        
                            
            
                                    
            
            
                | 70 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 71 |  |  |         # Gather all struts | 
            
                                                                        
                            
            
                                    
            
            
                | 72 |  |  |         struts = [root_win.property_get("_NET_WM_STRUT_PARTIAL")] | 
            
                                                                        
                            
            
                                    
            
            
                | 73 |  |  |         if self.gdk_screen.supports_net_wm_hint("_NET_CLIENT_LIST"): | 
            
                                                                        
                            
            
                                    
            
            
                | 74 |  |  |             # Source: http://stackoverflow.com/a/11332614/435253 | 
            
                                                                        
                            
            
                                    
            
            
                | 75 |  |  |             for wid in root_win.property_get('_NET_CLIENT_LIST')[2]: | 
            
                                                                        
                            
            
                                    
            
            
                | 76 |  |  |                 w = gtk.gdk.window_foreign_new(wid) | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                        
                            
            
                                    
            
            
                | 77 |  |  |                 struts.append(w.property_get("_NET_WM_STRUT_PARTIAL")) | 
            
                                                                        
                            
            
                                    
            
            
                | 78 |  |  |         struts = [x[2] for x in struts if x] | 
            
                                                                        
                            
            
                                    
            
            
                | 79 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 80 |  |  |         logging.debug("Gathered _NET_WM_STRUT_PARTIAL values:\n\t%s", | 
            
                                                                        
                            
            
                                    
            
            
                | 81 |  |  |                       struts) | 
            
                                                                        
                            
            
                                    
            
            
                | 82 |  |  |         return struts | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |     def subtract_struts(self, usable_region, struts): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |         """Subtract the given struts from the given region.""" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |         # Subtract the struts from the usable region | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |         _Sub = lambda *g: usable_region.subtract( | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |             gtk.gdk.region_rectangle(g)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |         _w, _h = self.gdk_screen.get_width(), self.gdk_screen.get_height() | 
                            
                    |  |  |  | 
                                                                                        
                                                                                            
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |         for g in struts:  # pylint: disable=invalid-name | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |             # http://standards.freedesktop.org/wm-spec/1.5/ar01s05.html | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |             # XXX: Must not cache unless watching for notify events. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |             _Sub(0, g[4], g[0], g[5] - g[4] + 1)             # left | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |             _Sub(_w - g[1], g[6], g[1], g[7] - g[6] + 1)     # right | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |             _Sub(g[8], 0, g[9] - g[8] + 1, g[2])             # top | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |             _Sub(g[10], _h - g[3], g[11] - g[10] + 1, g[3])  # bottom | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |         # Generate a more restrictive version used as a fallback | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |         usable_rect = usable_region.copy() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |         _Sub = lambda *g: usable_rect.subtract(gtk.gdk.region_rectangle(g)) | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |         for geom in struts: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |             # http://standards.freedesktop.org/wm-spec/1.5/ar01s05.html | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |             # XXX: Must not cache unless watching for notify events. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |             _Sub(0, geom[4], geom[0], _h)             # left | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  |             _Sub(_w - geom[1], geom[6], geom[1], _h)  # right | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |             _Sub(0, 0, _w, geom[2])                   # top | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |             _Sub(0, _h - geom[3], _w, geom[3])        # bottom | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |             # TODO: The required "+ 1" in certain spots confirms that we're | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |             #       going to need unit tests which actually check that the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |             #       WM's code for constraining windows to the usable area | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |             #       doesn't cause off-by-one bugs. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |             # TODO: Share this on http://stackoverflow.com/q/2598580/435253 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |         return usable_rect.get_clipbox(), usable_region | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |     def get(self, monitor, ignore_struts=None): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |         """Retrieve the usable area of the specified monitor using | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |         the most expressive method the window manager supports. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |         @param monitor: The number or dimensions of the desired monitor. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |         @param ignore_struts: If C{True}, just return the size of the whole | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |             monitor, allowing windows to overlap panels. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |         @type monitor: C{int} or C{gtk.gdk.Rectangle} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |         @type ignore_struts: C{bool} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |         @returns: The usable region and its largest rectangular subset. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |         @rtype: C{gtk.gdk.Region}, C{gtk.gdk.Rectangle} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |         usable_rect, usable_region = self.get_monitor_rect(monitor) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |         if ignore_struts or (ignore_struts is None and self.ignore_struts): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |             logging.debug("Panels ignored. Reported monitor geometry is:\n%s", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |                           usable_rect) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |             return usable_region, usable_rect | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |         root_win = self.gdk_screen.get_root_window() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |         struts = self.get_struts(root_win) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |         if struts: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  |             usable_rect, usable_region = self.subtract_struts(usable_region, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |                                                               struts) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  |         elif self.gdk_screen.supports_net_wm_hint("_NET_WORKAREA"): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 |  |  |             desktop_geo = tuple(root_win.property_get('_NET_WORKAREA')[2][0:4]) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |             logging.debug("Falling back to _NET_WORKAREA: %s", desktop_geo) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  |             usable_region.intersect(gtk.gdk.region_rectangle(desktop_geo)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  |             usable_rect = usable_region.get_clipbox() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  |         # FIXME: Only call get_rectangles if --debug | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |         logging.debug("Usable region of monitor calculated as:\n" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  |                       "\tRegion: %r\n\tRectangle: %r", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  |                       usable_region.get_rectangles(), usable_rect) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 |  |  |         return usable_region, usable_rect | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  | class WindowManager(object): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  |     """A simple API-wrapper class for manipulating window positioning.""" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  |     def __init__(self, screen=None, ignore_workarea=False): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 |  |  |         Initializes C{WindowManager}. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 |  |  |         @param screen: The X11 screen to operate on. If C{None}, the default | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 |  |  |             screen as retrieved by C{gtk.gdk.screen_get_default} will be used. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 |  |  |         @type screen: C{gtk.gdk.Screen} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 |  |  |         @todo: Confirm that the root window only changes on X11 server | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 |  |  |                restart. (Something which will crash QuickTile anyway since | 
            
                                                                                                            
                            
            
                                    
            
            
                | 169 |  |  |                PyGTK makes X server disconnects uncatchable.) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 170 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 171 |  |  |                It could possibly change while toggling "allow desktop icons" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 172 |  |  |                in KDE 3.x. (Not sure what would be equivalent elsewhere) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 173 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 174 |  |  |         self.gdk_screen = screen or gtk.gdk.screen_get_default() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 175 |  |  |         if self.gdk_screen is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 176 |  |  |             raise XInitError("GTK+ could not open a connection to the X server" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 177 |  |  |                              " (bad DISPLAY value?)") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 178 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 179 |  |  |         # pylint: disable=no-member | 
            
                                                                                                            
                            
            
                                    
            
            
                | 180 |  |  |         self.screen = wnck.screen_get(self.gdk_screen.get_number()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 181 |  |  |         self.workarea = WorkArea(self.gdk_screen, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 182 |  |  |                                  ignore_struts=ignore_workarea) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 183 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 184 |  |  |     @classmethod | 
            
                                                                                                            
                            
            
                                    
            
            
                | 185 |  |  |     def calc_win_gravity(cls, geom, gravity): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 186 |  |  |         """Calculate the X and Y coordinates necessary to simulate non-topleft | 
            
                                                                                                            
                            
            
                                    
            
            
                | 187 |  |  |         gravity on a window. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 188 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 189 |  |  |         @param geom: The window geometry to which to apply the corrections. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 190 |  |  |         @param gravity: A desired gravity chosen from L{GRAVITY}. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 191 |  |  |         @type geom: C{gtk.gdk.Rectangle} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 192 |  |  |         @type gravity: C{wnck.WINDOW_GRAVITY_*} or C{gtk.gdk.GRAVITY_*} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 193 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 194 |  |  |         @returns: The coordinates to be used to achieve the desired position. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 195 |  |  |         @rtype: C{(x, y)} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 196 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 197 |  |  |         grav_x, grav_y = GRAVITY[gravity] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 198 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 199 |  |  |         return ( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 200 |  |  |             int(geom.x - (geom.width * grav_x)), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 201 |  |  |             int(geom.y - (geom.height * grav_y)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 202 |  |  |         ) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 203 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 204 |  |  |     @staticmethod | 
            
                                                                                                            
                            
            
                                    
            
            
                | 205 |  |  |     def get_geometry_rel(window, monitor_geom): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 206 |  |  |         """Get window position relative to the monitor rather than the desktop. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 207 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 208 |  |  |         @param monitor_geom: The rectangle returned by | 
            
                                                                                                            
                            
            
                                    
            
            
                | 209 |  |  |             C{gdk.Screen.get_monitor_geometry} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 210 |  |  |         @type window: C{wnck.Window} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 211 |  |  |         @type monitor_geom: C{gtk.gdk.Rectangle} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 212 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 213 |  |  |         @rtype: C{gtk.gdk.Rectangle} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 214 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 215 |  |  |         win_geom = gtk.gdk.Rectangle(*window.get_geometry()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 216 |  |  |         win_geom.x -= monitor_geom.x | 
            
                                                                                                            
                            
            
                                    
            
            
                | 217 |  |  |         win_geom.y -= monitor_geom.y | 
            
                                                                                                            
                            
            
                                    
            
            
                | 218 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 219 |  |  |         return win_geom | 
            
                                                                                                            
                            
            
                                    
            
            
                | 220 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 221 |  |  |     def get_monitor(self, win): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 222 |  |  |         """Given a Window (Wnck or GDK), retrieve the monitor ID and geometry. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 223 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 224 |  |  |         @type win: C{wnck.Window} or C{gtk.gdk.Window} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 225 |  |  |         @returns: A tuple containing the monitor ID and geometry. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 226 |  |  |         @rtype: C{(int, gtk.gdk.Rectangle)} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 227 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 228 |  |  |         # TODO: Look for a way to get the monitor ID without having | 
            
                                                                                                            
                            
            
                                    
            
            
                | 229 |  |  |         #       to instantiate a gtk.gdk.Window | 
            
                                                                                                            
                            
            
                                    
            
            
                | 230 |  |  |         if not isinstance(win, gtk.gdk.Window): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 231 |  |  |             win = gtk.gdk.window_foreign_new(win.get_xid()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 232 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 233 |  |  |         # TODO: How do I retrieve the root window from a given one? | 
            
                                                                                                            
                            
            
                                    
            
            
                | 234 |  |  |         monitor_id = self.gdk_screen.get_monitor_at_window(win) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 235 |  |  |         monitor_geom = self.gdk_screen.get_monitor_geometry(monitor_id) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 236 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 237 |  |  |         logging.debug(" Window is on monitor %s, which has geometry %s", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 238 |  |  |                       monitor_id, monitor_geom) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 239 |  |  |         return monitor_id, monitor_geom | 
            
                                                                                                            
                            
            
                                    
            
            
                | 240 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 241 |  |  |     def get_workspace(self, window=None, direction=None): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 242 |  |  |         """Get a workspace relative to either a window or the active one. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 243 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 244 |  |  |         @param window: The point of reference. C{None} for the active workspace | 
            
                                                                                                            
                            
            
                                    
            
            
                | 245 |  |  |         @param direction: The direction in which to look, relative to the point | 
            
                                                                                                            
                            
            
                                    
            
            
                | 246 |  |  |             of reference. Accepts the following types: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 247 |  |  |              - C{wnck.MotionDirection}: Non-cycling direction | 
            
                                                                                                            
                            
            
                                    
            
            
                | 248 |  |  |              - C{int}: Relative index in the list of workspaces | 
            
                                                                                                            
                            
            
                                    
            
            
                | 249 |  |  |              - C{None}: Just get the workspace object for the point of | 
            
                                                                                                            
                            
            
                                    
            
            
                | 250 |  |  |                reference | 
            
                                                                                                            
                            
            
                                    
            
            
                | 251 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 252 |  |  |         @type window: C{wnck.Window} or C{None} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 253 |  |  |         @rtype: C{wnck.Workspace} or C{None} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 254 |  |  |         @returns: The workspace object or C{None} if no match could be found. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 255 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 256 |  |  |         if window: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 257 |  |  |             cur = window.get_workspace() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 258 |  |  |         else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 259 |  |  |             cur = self.screen.get_active_workspace() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 260 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 261 |  |  |         if not cur: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 262 |  |  |             return None  # It's either pinned or on no workspaces | 
            
                                                                                                            
                            
            
                                    
            
            
                | 263 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 264 |  |  |         # pylint: disable=no-member | 
            
                                                                                                            
                            
            
                                    
            
            
                | 265 |  |  |         if isinstance(direction, wnck.MotionDirection): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 266 |  |  |             nxt = cur.get_neighbor(direction) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 267 |  |  |         elif isinstance(direction, int): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 268 |  |  |             nxt = self.screen.get_workspace((cur.get_number() + direction) % | 
            
                                                                                                            
                            
            
                                    
            
            
                | 269 |  |  |                     self.screen.get_workspace_count()) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 270 |  |  |         elif direction is None: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 271 |  |  |             nxt = cur | 
            
                                                                                                            
                            
            
                                    
            
            
                | 272 |  |  |         else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 273 |  |  |             nxt = None | 
            
                                                                                                            
                            
            
                                    
            
            
                | 274 |  |  |             logging.warn("Unrecognized direction: %r", direction) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 275 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 276 |  |  |         return nxt | 
            
                                                                                                            
                            
            
                                    
            
            
                | 277 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 278 |  |  |     def reposition(self, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 279 |  |  |             win, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 280 |  |  |             geom=None, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 281 |  |  |             monitor=gtk.gdk.Rectangle(0, 0, 0, 0), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 282 |  |  |             keep_maximize=False, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 283 |  |  |             gravity=wnck.WINDOW_GRAVITY_NORTHWEST, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 284 |  |  |             geometry_mask=wnck.WINDOW_CHANGE_X | wnck.WINDOW_CHANGE_Y | | 
            
                                                                                                            
                            
            
                                    
            
            
                | 285 |  |  |                 wnck.WINDOW_CHANGE_WIDTH | wnck.WINDOW_CHANGE_HEIGHT | 
            
                                                                                                            
                            
            
                                    
            
            
                | 286 |  |  |                    ):  # pylint: disable=no-member,too-many-arguments | 
            
                                                                                                            
                            
            
                                    
            
            
                | 287 |  |  |         # pylint:disable=line-too-long | 
            
                                                                                                            
                            
            
                                    
            
            
                | 288 |  |  |         """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 289 |  |  |         Position and size a window, decorations inclusive, according to the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 290 |  |  |         provided target window and monitor geometry rectangles. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 291 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 292 |  |  |         If no monitor rectangle is specified, position relative to the desktop | 
            
                                                                                                            
                            
            
                                    
            
            
                | 293 |  |  |         as a whole. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 294 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 295 |  |  |         @param win: The C{wnck.Window} to operate on. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 296 |  |  |         @param geom: The new geometry for the window. Can be left unspecified | 
            
                                                                                                            
                            
            
                                    
            
            
                | 297 |  |  |             if the intent is to move the window to another monitor without | 
            
                                                                                                            
                            
            
                                    
            
            
                | 298 |  |  |             repositioning it. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 299 |  |  |         @param monitor: The frame relative to which C{geom} should be | 
            
                                                                                                            
                            
            
                                    
            
            
                | 300 |  |  |             interpreted. The whole desktop if unspecified. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 301 |  |  |         @param keep_maximize: Whether to re-maximize a maximized window after | 
            
                                                                                                            
                            
            
                                    
            
            
                | 302 |  |  |             un-maximizing it to move it. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 303 |  |  |         @param gravity: A constant specifying which point on the window is | 
            
                                                                                                            
                            
            
                                    
            
            
                | 304 |  |  |             referred to by the X and Y coordinates in C{geom}. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 305 |  |  |         @param geometry_mask: A set of flags determining which aspects of the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 306 |  |  |             requested geometry should actually be applied to the window. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 307 |  |  |             (Allows the same geometry definition to easily be shared between | 
            
                                                                                                            
                            
            
                                    
            
            
                | 308 |  |  |             operations like move and resize.) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 309 |  |  |         @type win: C{gtk.gdk.Window} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 310 |  |  |         @type geom: C{gtk.gdk.Rectangle} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 311 |  |  |         @type monitor: C{gtk.gdk.Rectangle} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 312 |  |  |         @type keep_maximize: C{bool} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 313 |  |  |         @type gravity: U{WnckWindowGravity<https://developer.gnome.org/libwnck/stable/WnckWindow.html#WnckWindowGravity>} or U{GDK Gravity Constant<http://www.pygtk.org/docs/pygtk/gdk-constants.html#gdk-gravity-constants>} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 314 |  |  |         @type geometry_mask: U{WnckWindowMoveResizeMask<https://developer.gnome.org/libwnck/2.30/WnckWindow.html#WnckWindowMoveResizeMask>} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 315 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 316 |  |  |         @todo 1.0.0: Look for a way to accomplish this with a cleaner method | 
            
                                                                                                            
                            
            
                                    
            
            
                | 317 |  |  |             signature. This is getting a little hairy. (API-breaking change) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 318 |  |  |         """  # NOQA | 
            
                                                                                                            
                            
            
                                    
            
            
                | 319 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 320 |  |  |         # We need to ensure that ignored values are still present for | 
            
                                                                                                            
                            
            
                                    
            
            
                | 321 |  |  |         # gravity calculations. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 322 |  |  |         old_geom = self.get_geometry_rel(win, self.get_monitor(win)[1]) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 323 |  |  |         if geom: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 324 |  |  |             for attr in ('x', 'y', 'width', 'height'): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 325 |  |  |                 if not geometry_mask & getattr(wnck, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 326 |  |  |                         'WINDOW_CHANGE_%s' % attr.upper()): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 327 |  |  |                     setattr(geom, attr, getattr(old_geom, attr)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 328 |  |  |         else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 329 |  |  |             geom = old_geom | 
            
                                                                                                            
                            
            
                                    
            
            
                | 330 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 331 |  |  |         # Unmaximize and record the types we may need to restore | 
            
                                                                                                            
                            
            
                                    
            
            
                | 332 |  |  |         max_types, maxed = ['', '_horizontally', '_vertically'], [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 333 |  |  |         for maxtype in max_types: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 334 |  |  |             if getattr(win, 'is_maximized' + maxtype)(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 335 |  |  |                 maxed.append(maxtype) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 336 |  |  |                 getattr(win, 'unmaximize' + maxtype)() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 337 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 338 |  |  |         # Apply gravity and resolve to absolute desktop coordinates. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 339 |  |  |         new_x, new_y = self.calc_win_gravity(geom, gravity) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 340 |  |  |         new_x += monitor.x | 
            
                                                                                                            
                            
            
                                    
            
            
                | 341 |  |  |         new_y += monitor.y | 
            
                                                                                                            
                            
            
                                    
            
            
                | 342 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 343 |  |  |         logging.debug(" Repositioning to (%d, %d, %d, %d)\n", | 
            
                                                                                                            
                            
            
                                    
            
            
                | 344 |  |  |                 new_x, new_y, geom.width, geom.height) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 345 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 346 |  |  |         # XXX: I'm not sure whether wnck, Openbox, or both are at fault, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 347 |  |  |         #      but window gravities seem to have no effect beyond double- | 
            
                                                                                                            
                            
            
                                    
            
            
                | 348 |  |  |         #      compensating for window border thickness unless using | 
            
                                                                                                            
                            
            
                                    
            
            
                | 349 |  |  |         #      WINDOW_GRAVITY_STATIC. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 350 |  |  |         # | 
            
                                                                                                            
                            
            
                                    
            
            
                | 351 |  |  |         #      My best guess is that the gravity modifiers are being applied | 
            
                                                                                                            
                            
            
                                    
            
            
                | 352 |  |  |         #      to the window frame rather than the window itself, hence why | 
            
                                                                                                            
                            
            
                                    
            
            
                | 353 |  |  |         #      static gravity would position correctly and north-west gravity | 
            
                                                                                                            
                            
            
                                    
            
            
                | 354 |  |  |         #      would double-compensate for the titlebar and border dimensions. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 355 |  |  |         # | 
            
                                                                                                            
                            
            
                                    
            
            
                | 356 |  |  |         #      ...however, that still doesn't explain why the non-topleft | 
            
                                                                                                            
                            
            
                                    
            
            
                | 357 |  |  |         #      gravities have no effect. I'm guessing something's just broken. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 358 |  |  |         win.set_geometry(wnck.WINDOW_GRAVITY_STATIC, geometry_mask, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 359 |  |  |                 new_x, new_y, geom.width, geom.height) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 360 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 361 |  |  |         # Restore maximization if asked | 
            
                                                                                                            
                            
            
                                    
            
            
                | 362 |  |  |         if maxed and keep_maximize: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 363 |  |  |             for maxtype in maxed: | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 364 |  |  |                 getattr(win, 'maximize' + maxtype)() | 
            
                                                        
            
                                    
            
            
                | 365 |  |  |  | 
            
                        
This check looks for invalid names for a range of different identifiers.
You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.
If your project includes a Pylint configuration file, the settings contained in that file take precedence.
To find out more about Pylint, please refer to their site.