def _set_pixmap(self): # The tricky part here is that the pixmap returned by # NameWindowPixmap gets invalidated every time the window's # viewable state changes. ("viewable" here is the X term that # means "mapped, and all ancestors are also mapped".) But # there is no X event that will tell you when a window's # viewability changes! Instead we have to find all ancestors, # and watch all of them for unmap and reparent events. But # what about races? I hear you cry. By doing things in the # exact order: # 1) select for StructureNotify # 2) QueryTree to get parent # 3) repeat 1 & 2 up to the root # 4) call NameWindowPixmap # we are safe. (I think.) listening = [] e = None try: screen = self.client_window.get_screen() if not screen: log("cannot set pixmap on client window - maybe deleted?") return root = screen.get_root_window() gdkworld = None world = get_world_window() if world: gdkworld = world.get_window() win = get_parent(self.client_window) while win not in (None, root, gdkworld) and win.get_parent() is not None: # We have to use a lowlevel function to manipulate the # event selection here, because SubstructureRedirectMask # does not roundtrip through the GDK event mask # functions. So if we used them, here, we would clobber # corral window selection masks, and those don't deserve # clobbering. They are our friends! X is driving me # slowly mad. xid = win.get_xid() X11Window.addXSelectInput(xid, StructureNotifyMask) add_event_receiver(win, self, max_receivers=-1) listening.append(win) win = get_parent(win) handle = XImage.get_xcomposite_pixmap(self.xid) except Exception as e: try: self._cleanup_listening(listening) except Exception: pass raise if handle is None: log("failed to name a window pixmap for %#x: %s", self.xid, e) self._cleanup_listening(listening) else: self._contents_handle = handle # Don't save the listening set until after # NameWindowPixmap has succeeded, to maintain our # invariant: self._listening_to = listening
def set_pixmap(): # The tricky part here is that the pixmap returned by # NameWindowPixmap gets invalidated every time the window's # viewable state changes. ("viewable" here is the X term that # means "mapped, and all ancestors are also mapped".) But # there is no X event that will tell you when a window's # viewability changes! Instead we have to find all ancestors, # and watch all of them for unmap and reparent events. But # what about races? I hear you cry. By doing things in the # exact order: # 1) select for StructureNotify # 2) QueryTree to get parent # 3) repeat 1 & 2 up to the root # 4) call NameWindowPixmap # we are safe. (I think.) listening = [] e = None try: root = self._window.get_screen().get_root_window() world = get_world_window().window win = get_parent(self._window) while win not in (None, root, world) and win.get_parent() is not None: # We have to use a lowlevel function to manipulate the # event selection here, because SubstructureRedirectMask # does not roundtrip through the GDK event mask # functions. So if we used them, here, we would clobber # corral window selection masks, and those don't deserve # clobbering. They are our friends! X is driving me # slowly mad. X11Window.addXSelectInput(win.xid, StructureNotifyMask) add_event_receiver(win, self, max_receivers=-1) listening.append(win) win = get_parent(win) handle = XImage.get_xcomposite_pixmap(self._window.xid) except Exception as e: try: self._cleanup_listening(listening) except: pass raise if handle is None: #avoid race during signal exit, which will clear self._window: win = self._window xid = 0 if win: xid = win.xid log("failed to name a window pixmap for %#x: %s", xid, e) self._cleanup_listening(listening) else: self._contents_handle = handle # Don't save the listening set until after # NameWindowPixmap has succeeded, to maintain our # invariant: self._listening_to = listening
def set_pixmap(): # The tricky part here is that the pixmap returned by # NameWindowPixmap gets invalidated every time the window's # viewable state changes. ("viewable" here is the X term that # means "mapped, and all ancestors are also mapped".) But # there is no X event that will tell you when a window's # viewability changes! Instead we have to find all ancestors, # and watch all of them for unmap and reparent events. But # what about races? I hear you cry. By doing things in the # exact order: # 1) select for StructureNotify # 2) QueryTree to get parent # 3) repeat 1 & 2 up to the root # 4) call NameWindowPixmap # we are safe. (I think.) listening = [] e = None try: root = self._window.get_screen().get_root_window() world = get_world_window().window win = get_parent(self._window) while win not in (None, root, world) and win.get_parent() is not None: # We have to use a lowlevel function to manipulate the # event selection here, because SubstructureRedirectMask # does not roundtrip through the GDK event mask # functions. So if we used them, here, we would clobber # corral window selection masks, and those don't deserve # clobbering. They are our friends! X is driving me # slowly mad. X11Window.addXSelectInput(win.xid, StructureNotifyMask) add_event_receiver(win, self, max_receivers=-1) listening.append(win) win = get_parent(win) handle = XImage.get_xcomposite_pixmap(self._window.xid) except Exception, e: try: self._cleanup_listening(listening) except: pass raise
def do_setup_listening(self): assert self._listening is None add_event_receiver(self._window, self, max_receivers=-1) self._listening = [self._window] #recurse parents: from xpra.x11.gtk_x11.world_window import get_world_window root = self._window.get_screen().get_root_window() world = get_world_window().window win = get_parent(self._window) while win not in (None, root, world) and win.get_parent() is not None: # We have to use a lowlevel function to manipulate the # event selection here, because SubstructureRedirectMask # does not roundtrip through the GDK event mask # functions. So if we used them, here, we would clobber # corral window selection masks, and those don't deserve # clobbering. They are our friends! X is driving me # slowly mad. X11Window.addXSelectInput(win.xid, StructureNotifyMask) add_event_receiver(win, self, max_receivers=-1) self._listening.append(win) win = get_parent(win) log("grab: listening for: %s", [hex(x.xid) for x in self._listening])
def do_setup_listening(self): assert self._listening is None add_event_receiver(self._window, self, max_receivers=-1) self._listening = [self._window] #recurse parents: from xpra.x11.gtk_x11.world_window import get_world_window root = self._window.get_screen().get_root_window() world = get_world_window().window win = get_parent(self._window) while win not in (None, root, world) and win.get_parent() is not None: # We have to use a lowlevel function to manipulate the # event selection here, because SubstructureRedirectMask # does not roundtrip through the GDK event mask # functions. So if we used them, here, we would clobber # corral window selection masks, and those don't deserve # clobbering. They are our friends! X is driving me # slowly mad. X11Window.addXSelectInput(win.xid, StructureNotifyMask) add_event_receiver(win, self, max_receivers=-1) self._listening.append(win) win = get_parent(win) log("grab: listening for: %s", [hex(x.xid) for x in self._listening])