def do_unmanaged(self, wm_exiting): log("unmanaging window: %s (%s - %s)", self, self.corral_window, self.client_window) self._internal_set_property("owner", None) if self.corral_window: remove_event_receiver(self.corral_window, self) with xswallow: for prop in WindowModel.SCRUB_PROPERTIES: X11Window.XDeleteProperty(self.xid, prop) if self.client_reparented: self.client_window.reparent(gtk.gdk.get_default_root_window(), 0, 0) self.client_reparented = False self.client_window.set_events(self.client_window_saved_events) #it is now safe to destroy the corral window: self.corral_window.destroy() self.corral_window = None # It is important to remove from our save set, even after # reparenting, because according to the X spec, windows that are # in our save set are always Mapped when we exit, *even if those # windows are no longer inferior to any of our windows!* (see # section 10. Connection Close). This causes "ghost windows", see # bug #27: if self.in_save_set: with xswallow: X11Window.XRemoveFromSaveSet(self.xid) self.in_save_set = False with xswallow: X11Window.sendConfigureNotify(self.xid) if wm_exiting: self.client_window.show_unraised() BaseWindowModel.do_unmanaged(self, wm_exiting)
def do_unmanaged(self, wm_exiting): log("unmanaging window: %s (%s - %s)", self, self.corral_window, self.client_window) self._internal_set_property("owner", None) if self.corral_window: remove_event_receiver(self.corral_window, self) geom = None #use a new context so we will XSync right here #and detect if the window is already gone: with XSwallowContext(): geom = X11Window.getGeometry(self.xid) if geom is not None: if self.client_reparented: self.client_window.reparent(get_default_root_window(), 0, 0) self.client_window.set_events(self.client_window_saved_events) self.client_reparented = False #it is now safe to destroy the corral window: self.corral_window.destroy() self.corral_window = None # It is important to remove from our save set, even after # reparenting, because according to the X spec, windows that are # in our save set are always Mapped when we exit, *even if those # windows are no longer inferior to any of our windows!* (see # section 10. Connection Close). This causes "ghost windows", see # bug #27: if self.in_save_set: with xswallow: X11Window.XRemoveFromSaveSet(self.xid) self.in_save_set = False with xswallow: X11Window.sendConfigureNotify(self.xid) if wm_exiting: self.client_window.show_unraised() BaseWindowModel.do_unmanaged(self, wm_exiting)
def cleanup(self): log("SystemTray.cleanup()") root = gtk.gdk.get_default_root_window() owner = X11Window.XGetSelectionOwner(SELECTION) if owner == self.tray_window.xid: X11Window.XSetSelectionOwner(0, SELECTION) log("SystemTray.cleanup() reset %s selection owner to %#x", SELECTION, X11Window.XGetSelectionOwner(SELECTION)) else: log.warn( "SystemTray.cleanup() we were no longer the selection owner") remove_event_receiver(self.tray_window, self) def undock(window): log("undocking %s", window) X11Window.Unmap(window.xid) X11Window.Reparent(window.xid, root.xid, 0, 0) for window, tray_window in self.tray_windows.items(): with xswallow: undock(window) tray_window.destroy() self.tray_window.destroy() self.tray_window = None log("SystemTray.cleanup() done")
def call_setup(self): """ Call this method to prepare the window: * makes sure it still exists (by querying its geometry which may raise an XError) * setup composite redirection * calls setup The difficulty comes from X11 errors and synchronization: we want to catch errors and undo what we've done. The mix of GTK and pure-X11 calls is not helping. """ try: with xsync: geom = X11Window.geometry_with_border(self.xid) if geom is None: raise Unmanageable("window %#x disappeared already" % self.xid) self._internal_set_property("geometry", geom[:4]) self._read_initial_X11_properties() except XError as e: raise Unmanageable(e) add_event_receiver(self.client_window, self) # Keith Packard says that composite state is undefined following a # reparent, so I'm not sure doing this here in the superclass, # before we reparent, actually works... let's wait and see. try: self._composite = CompositeHelper(self.client_window) with xsync: self._composite.setup() if X11Window.displayHasXShape(): X11Window.XShapeSelectInput(self.xid) except Exception as e: remove_event_receiver(self.client_window, self) log("%s %#x does not support compositing: %s", self._MODELTYPE, self.xid, e) with xswallow: self._composite.destroy() self._composite = None if isinstance(e, Unmanageable): raise raise Unmanageable(e) #compositing is now enabled, #from now on we must call setup_failed to clean things up self._managed = True try: with xsync: self.setup() except XError as e: try: with xsync: self.setup_failed(e) except Exception as ex: log.error("error in cleanup handler: %s", ex) raise Unmanageable(e) self._setup_done = True
def do_unmanaged(self, wm_exiting): if not self._managed: return self._managed = False log("%s.do_unmanaged(%s) damage_forward_handle=%s, composite=%s", self._MODELTYPE, wm_exiting, self._damage_forward_handle, self._composite) remove_event_receiver(self.client_window, self) glib.idle_add(self.managed_disconnect) if self._composite: if self._damage_forward_handle: self._composite.disconnect(self._damage_forward_handle) self._damage_forward_handle = None self._composite.destroy() self._composite = None self._scrub_x11()
def cleanup(self): #this must be called from the UI thread! remove_event_receiver(self._root, self) self._root.set_events(self._saved_event_mask) #try a few times: #errors happen because windows are being destroyed #(even more so when we cleanup) #and we don't really care too much about this for l in (log, log, log, log, log.warn): try: with xsync: cleanup_all_event_receivers() #all went well, we're done return except Exception as e: l("failed to remove event receivers: %s", e)
def cleanup(self): log("SystemTray.cleanup()") root = gtk.gdk.get_default_root_window() owner = X11Window.XGetSelectionOwner(SELECTION) if owner==self.tray_window.xid: X11Window.XSetSelectionOwner(0, SELECTION) log("SystemTray.cleanup() reset %s selection owner to %#x", SELECTION, X11Window.XGetSelectionOwner(SELECTION)) else: log.warn("Warning: we were no longer the tray selection owner") remove_event_receiver(self.tray_window, self) def undock(window): log("undocking %s", window) X11Window.Unmap(window.xid) X11Window.Reparent(window.xid, root.xid, 0, 0) for window, tray_window in self.tray_windows.items(): with xswallow: undock(window) tray_window.destroy() self.tray_window.destroy() self.tray_window = None log("SystemTray.cleanup() done")
def destroy(self): if self._window is None: log.warn("composite window %s already destroyed!", self) return #clear the reference to the window early: win = self._window xwin = self._window.xid #Note: invalidate_pixmap()/_cleanup_listening() use self._window, but won't care if it's None self._window = None remove_event_receiver(win, self) self.invalidate_pixmap() if not self._already_composited: trap.swallow_synced(X11Window.XCompositeUnredirectWindow, xwin) if self._damage_handle: trap.swallow_synced(X11Window.XDamageDestroy, self._damage_handle) self._damage_handle = None if self._shm_handle: self._shm_handle.cleanup() self._shm_handle = None #note: this should be redundant since we cleared the #reference to self._window and shortcut out in do_get_property_contents_handle #but it's cheap anyway self.invalidate_pixmap()
def cleanup(self): #this must be called from the UI thread! remove_event_receiver(self._root, self) self._root.set_events(self._saved_event_mask) if self._own_x11_filter: #only remove the x11 filter if we initialized it (ie: when running in client) try: with xsync: cleanup_x11_filter() except Exception as e: log.error("failed to remove x11 event filter: %s", e) #try a few times: #errors happen because windows are being destroyed #(even more so when we cleanup) #and we don't really care too much about this for l in (log, log, log, log, log.warn): try: with xsync: cleanup_all_event_receivers() #all went well, we're done return except Exception as e: l("failed to remove event receivers: %s", e)
def cleanup(self): remove_event_receiver(self._root, self)
def do_destroy(self, win): remove_event_receiver(win, self) self.destroy_damage_handle()
def do_xpra_destroy_event(self, event): remove_event_receiver(event.window, self) gtk.main_quit()
def _cleanup_listening(self, listening): if listening: # Don't want to stop listening to self.client_window!: assert self.client_window is None or self.client_window not in listening for w in listening: remove_event_receiver(w, self)