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: log("failed to manage %#x", self.xid, exc_info=True) raise Unmanageable(e) from 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) from 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: log("failed to setup %#x", self.xid, exc_info=True) try: with xsync: self.setup_failed(e) except Exception as ex: log.error("error in cleanup handler: %s", ex) raise Unmanageable(e) from None self._setup_done = True
def setup(self): super(WindowModel, self).setup() x, y, w, h, _ = self.client_window.get_geometry() # We enable PROPERTY_CHANGE_MASK so that we can call # x11_get_server_time on this window. # clamp this window to the desktop size: x, y = self._clamp_to_desktop(x, y, w, h) self.corral_window = gdk.Window(self.parking_window, x=x, y=y, width=w, height=h, window_type=gdk.WINDOW_CHILD, wclass=gdk.INPUT_OUTPUT, event_mask=gdk.PROPERTY_CHANGE_MASK, title = "CorralWindow-%#x" % self.xid) log("setup() corral_window=%#x", self.corral_window.xid) prop_set(self.corral_window, "_NET_WM_NAME", "utf8", u"Xpra-CorralWindow-%#x" % self.xid) X11Window.substructureRedirect(self.corral_window.xid) add_event_receiver(self.corral_window, self) # The child might already be mapped, in case we inherited it from # a previous window manager. If so, we unmap it now, and save the # serial number of the request -- this way, when we get an # UnmapNotify later, we'll know that it's just from us unmapping # the window, not from the client withdrawing the window. if X11Window.is_mapped(self.xid): log("hiding inherited window") self.last_unmap_serial = X11Window.Unmap(self.xid) log("setup() adding to save set") X11Window.XAddToSaveSet(self.xid) self.in_save_set = True log("setup() reparenting") X11Window.Reparent(self.xid, self.corral_window.xid, 0, 0) self.client_reparented = True geomlog("setup() geometry") geom = X11Window.geometry_with_border(self.xid) if geom is None: raise Unmanageable("window %#x disappeared already" % self.xid) w, h = geom[2:4] hints = self.get_property("size-hints") geomlog("setup() hints=%s size=%ix%i", hints, w, h) nw, nh = calc_constrained_size(w, h, hints) if nw>=MAX_WINDOW_SIZE or nh>=MAX_WINDOW_SIZE: #we can't handle windows that big! raise Unmanageable("window constrained size is too large: %sx%s (from client geometry: %s,%s with size hints=%s)" % (nw, nh, w, h, hints)) self._updateprop("geometry", (x, y, nw, nh)) geomlog("setup() resizing windows to %sx%s", nw, nh) self.corral_window.resize(nw, nh) self.client_window.resize(nw, nh) self.client_window.show_unraised() #this is here to trigger X11 errors if any are pending #or if the window is deleted already: self.client_window.get_geometry()
def setup(self): super(OverrideRedirectWindowModel, self).setup() # So now if the window becomes unmapped in the future then we will # notice... but it might be unmapped already, and any event # already generated, and our request for that event is too late! # So double check now, *after* putting in our request: if not X11Window.is_mapped(self.xid): raise Unmanageable("window already unmapped") ch = self._composite.get_contents_handle() if ch is None: raise Unmanageable("failed to get damage handle")
def setup(self): super().setup() ox, oy, ow, oh = self.client_window.get_geometry()[:4] # We enable PROPERTY_CHANGE_MASK so that we can call # x11_get_server_time on this window. # clamp this window to the desktop size: x, y = self._clamp_to_desktop(ox, oy, ow, oh) self.corral_window = GDKX11Window( self.parking_window, x=x, y=y, width=ow, height=oh, window_type=Gdk.WindowType.CHILD, event_mask=Gdk.EventMask.PROPERTY_CHANGE_MASK, title="CorralWindow-%#x" % self.xid) cxid = self.corral_window.get_xid() log("setup() corral_window=%#x", cxid) prop_set(self.corral_window, "_NET_WM_NAME", "utf8", "Xpra-CorralWindow-%#x" % self.xid) X11Window.substructureRedirect(cxid) add_event_receiver(self.corral_window, self) # The child might already be mapped, in case we inherited it from # a previous window manager. If so, we unmap it now, and save the # serial number of the request -- this way, when we get an # UnmapNotify later, we'll know that it's just from us unmapping # the window, not from the client withdrawing the window. if X11Window.is_mapped(self.xid): log("hiding inherited window") self.last_unmap_serial = X11Window.Unmap(self.xid) log("setup() adding to save set") X11Window.XAddToSaveSet(self.xid) self.in_save_set = True log("setup() reparenting") X11Window.Reparent(self.xid, cxid, 0, 0) self.client_reparented = True geomlog("setup() geometry") geom = X11Window.geometry_with_border(self.xid) if geom is None: raise Unmanageable("window %#x disappeared already" % self.xid) w, h = geom[2:4] hints = self.get_property("size-hints") geomlog("setup() hints=%s size=%ix%i", hints, w, h) nw, nh = self.calc_constrained_size(w, h, hints) self._updateprop("geometry", (x, y, nw, nh)) geomlog("setup() resizing windows to %sx%s", nw, nh) #don't trigger a resize unless we have to: if ow != nw or oh != nh: self.corral_window.resize(nw, nh) if w != nw or h != nh: self.client_window.resize(nw, nh) self.client_window.show_unraised() #this is here to trigger X11 errors if any are pending #or if the window is deleted already: self.client_window.get_geometry()
def setup(self): self.invalidate_pixmap() geom = X11Window.geometry_with_border(self.xid) if geom is None: raise Unmanageable("window %#x disappeared already" % self.xid) self._border_width = geom[-1] self.create_damage_handle() add_event_receiver(self.client_window, self)
def _read_initial_X11_properties(self): metalog("read_initial_X11_properties() window") # WARNING: have to handle _NET_WM_STATE before we look at WM_HINTS; # WM_HINTS assumes that our "state" property is already set. This is # because there are four ways a window can get its urgency # ("attention-requested") bit set: # 1) _NET_WM_STATE_DEMANDS_ATTENTION in the _initial_ state hints # 2) setting the bit WM_HINTS, at _any_ time # 3) sending a request to the root window to add # _NET_WM_STATE_DEMANDS_ATTENTION to their state hints # 4) if we (the wm) decide they should be and set it # To implement this, we generally track the urgency bit via # _NET_WM_STATE (since that is under our sole control during normal # operation). Then (1) is accomplished through the normal rule that # initial states are read off from the client, and (2) is accomplished # by having WM_HINTS affect _NET_WM_STATE. But this means that # WM_HINTS and _NET_WM_STATE handling become intertangled. def set_if_unset(propname, value): #the property may not be initialized yet, #if that's the case then calling get_property throws an exception: try: if self.get_property(propname) not in (None, ""): return except TypeError: pass self._internal_set_property(propname, value) #"decorations" needs to be set before reading the X11 properties #because handle_wm_normal_hints_change reads it: set_if_unset("decorations", -1) super()._read_initial_X11_properties() net_wm_state = self.get_property("state") assert net_wm_state is not None, "_NET_WM_STATE should have been read already" geom = X11Window.getGeometry(self.xid) if not geom: raise Unmanageable("failed to get geometry for %#x" % self.xid) #initial position and size, from the Window object, #but allow size hints to override it if specified x, y, w, h = geom[:4] size_hints = self.get_property("size-hints") ax, ay = size_hints.get("position", (0, 0)) if ax==ay==0 and (x!=0 or y!=0): #don't override with 0,0 size_hints.pop("position", None) ax, ay = x, y aw, ah = size_hints.get("size", (w, h)) geomlog("initial X11 position and size: requested(%s, %s, %s)=%s", (x, y, w, h), size_hints, geom, (ax, ay, aw, ah)) set_if_unset("modal", "_NET_WM_STATE_MODAL" in net_wm_state) set_if_unset("requested-position", (ax, ay)) set_if_unset("requested-size", (aw, ah)) #it may have been set already: sip = self.get_property("set-initial-position") if not sip and ("position" in size_hints): self._internal_set_property("set-initial-position", True) elif sip is None: self._internal_set_property("set-initial-position", False) self.update_children()