From 1e457b6910a3db354724133acf6259518e365e8e Mon Sep 17 00:00:00 2001 From: totaam Date: Tue, 16 May 2023 21:54:02 +0700 Subject: [PATCH] #1995 use xid for damage, composite and event routing --- .../client/gtk_base/gtk_client_window_base.py | 3 +- xpra/x11/desktop/desktop_server_base.py | 2 +- xpra/x11/desktop/model_base.py | 9 ++- xpra/x11/gtk3/gdk_bindings.pyx | 65 ++++++++++--------- xpra/x11/gtk_x11/clipboard.py | 4 +- xpra/x11/gtk_x11/composite.py | 38 +++++------ xpra/x11/gtk_x11/selection.py | 6 +- xpra/x11/gtk_x11/tray.py | 9 +-- xpra/x11/gtk_x11/window_damage.py | 31 ++++----- xpra/x11/gtk_x11/wm.py | 31 ++++++--- xpra/x11/models/core.py | 16 ++--- xpra/x11/models/window.py | 7 +- xpra/x11/server.py | 8 +-- xpra/x11/window_info.py | 31 ++++++--- xpra/x11/xroot_props.py | 4 +- xpra/x11/xsettings.py | 6 +- 16 files changed, 147 insertions(+), 123 deletions(-) diff --git a/xpra/client/gtk_base/gtk_client_window_base.py b/xpra/client/gtk_base/gtk_client_window_base.py index 42fc77bf37..1e172c188c 100644 --- a/xpra/client/gtk_base/gtk_client_window_base.py +++ b/xpra/client/gtk_base/gtk_client_window_base.py @@ -480,7 +480,8 @@ def do_init_focus(self): log.warn(" you may experience window focus issues") else: grablog("adding event receiver so we can get FocusIn and FocusOut events whilst grabbing the keyboard") - add_event_receiver(self.get_window(), self) + xid = self.get_window().get_xid() + add_event_receiver(xid, self) #other platforms should bet getting regular focus events instead: def focus_in(_window, event): focuslog("focus-in-event for wid=%s", self._id) diff --git a/xpra/x11/desktop/desktop_server_base.py b/xpra/x11/desktop/desktop_server_base.py index df5d137d46..bb5a1ddb62 100644 --- a/xpra/x11/desktop/desktop_server_base.py +++ b/xpra/x11/desktop/desktop_server_base.py @@ -77,7 +77,7 @@ def x11_init(self): assert display.get_n_screens()==1 screen = display.get_screen(0) root = screen.get_root_window() - add_event_receiver(root, self) + add_event_receiver(root.get_xid(), self) add_catchall_receiver("xpra-motion-event", self) add_catchall_receiver("xpra-xkb-event", self) with xlog: diff --git a/xpra/x11/desktop/model_base.py b/xpra/x11/desktop/model_base.py index 83f929a560..c678e09617 100644 --- a/xpra/x11/desktop/model_base.py +++ b/xpra/x11/desktop/model_base.py @@ -82,13 +82,12 @@ def __init__(self): def setup(self): WindowDamageHandler.setup(self) - xid = self.client_window.get_xid() - self._depth = X11Window.get_depth(xid) - X11Window.addDefaultEvents(xid) + self._depth = X11Window.get_depth(self.xid) + X11Window.addDefaultEvents(self.xid) self._managed = True self._setup_done = True #listen for property changes on the root window: - add_event_receiver(self.client_window, self) + add_event_receiver(self.xid, self) def do_xpra_property_notify_event(self, event): eventlog(f"do_xpra_property_notify_event: {event.atom}") @@ -101,7 +100,7 @@ def do_xpra_property_notify_event(self, event): return True def unmanage(self, exiting=False): - remove_event_receiver(self.client_window, self) + remove_event_receiver(self.xid, self) WindowDamageHandler.destroy(self) WindowModelStub.unmanage(self, exiting) self.cancel_resize_timer() diff --git a/xpra/x11/gtk3/gdk_bindings.pyx b/xpra/x11/gtk3/gdk_bindings.pyx index 7927ea14e5..1f8e72eb0b 100644 --- a/xpra/x11/gtk3/gdk_bindings.pyx +++ b/xpra/x11/gtk3/gdk_bindings.pyx @@ -263,9 +263,6 @@ cdef extern from "gtk-3.0/gdk/gdktypes.h": # Basic utilities: -cdef int get_xwindow(pywindow): - return GDK_WINDOW_XID(unwrap(pywindow, Gdk.Window)) - def get_pywindow(xwindow): display = Gdk.get_default_root_window().get_display() return _get_pywindow(display, xwindow) @@ -332,34 +329,40 @@ cdef _get_pyatom(display, int xatom): # Children listing -cdef _query_tree(pywindow): +def get_children(xid : int): cdef Window root = 0, parent = 0 cdef Window * children = 0 cdef unsigned int i, nchildren = 0 - if not XQueryTree(get_xdisplay_for(pywindow), - get_xwindow(pywindow), + display = Gdk.get_default_root_window().get_display() + cdef Display *xdisplay = get_xdisplay_for(display) + if not XQueryTree(xdisplay, xid, &root, &parent, &children, &nchildren): return (None, []) cdef object pychildren = [] - for i from 0 <= i < nchildren: + for i in range(nchildren): #we cannot get the gdk window for wid=0 if children[i]>0: - pychildren.append(_get_pywindow(pywindow, children[i])) + pychildren.append(children[i]) # Apparently XQueryTree sometimes returns garbage in the 'children' # pointer when 'nchildren' is 0, which then leads to a segfault when we # try to XFree the non-NULL garbage. if nchildren > 0 and children != NULL: XFree(children) - cdef object pyparent = None - if parent != XNone: - pyparent = _get_pywindow(pywindow, parent) - return (pyparent, pychildren) - -def get_children(pywindow): - return _query_tree(pywindow)[1] + return pychildren -def get_parent(pywindow): - return _query_tree(pywindow)[0] +def get_parent(xid : int) -> int: + cdef Window root = 0, parent = 0 + cdef Window * children = 0 + cdef unsigned int i, nchildren = 0 + display = Gdk.get_default_root_window().get_display() + cdef Display *xdisplay = get_xdisplay_for(display) + if not XQueryTree(xdisplay, xid, &root, &parent, &children, &nchildren): + return None + if nchildren > 0 and children != NULL: + XFree(children) + if parent==XNone: + return None + return int(parent) ################################### @@ -429,32 +432,33 @@ cdef extern from "gtk-3.0/gdk/gdkevents.h": # client that owns the window they are sent to, otherwise they go to any # clients that are selecting for that mask they are sent with. -event_receivers_map = WeakKeyDictionary() +event_receivers_map : dict = dict() -def add_event_receiver(window, receiver, max_receivers=3): - receivers = event_receivers_map.get(window) +def add_event_receiver(xid:int, receiver:callable, max_receivers:int=3): + receivers = event_receivers_map.get(xid) if receivers is None: receivers = set() - event_receivers_map[window] = receivers + event_receivers_map[xid] = receivers if max_receivers>0 and len(receivers)>max_receivers: log.warn("Warning: already too many event receivers") - log.warn(" for window %s: %s, adding %s to %s", window, len(receivers), receiver, receivers) + log.warn(f" for window {xid:x}: {len(receivers)}") + log.warn(f" adding {receiver!r} to {receivers}") traceback.print_stack() receivers.add(receiver) -def remove_event_receiver(window, receiver): - receivers = event_receivers_map.get(window) +def remove_event_receiver(xid:int, receiver:callable): + receivers = event_receivers_map.get(xid) if receivers is None: return receivers.discard(receiver) if not receivers: - event_receivers_map.pop(window) + event_receivers_map.pop(xid) #only used for debugging: -def get_event_receivers(window): - return event_receivers_map.get(window) +def get_event_receivers(xid:int): + return event_receivers_map.get(xid) -def cleanup_all_event_receivers(): +def cleanup_all_event_receivers() -> None: event_receivers_map.clear() @@ -753,7 +757,8 @@ cdef _route_event(int etype, event, signal, parent_signal): window = event.window if DEBUG: log.info(" delivering event to window itself: %#x (signal=%s)", window.get_xid(), signal) - handlers = get_event_receivers(window) + if window: + handlers = get_event_receivers(window.get_xid()) _maybe_send_event(DEBUG, handlers, signal, event, "window %#x" % window.get_xid()) elif DEBUG: log.info(" received event on window itself but have no signal for that") @@ -766,7 +771,7 @@ cdef _route_event(int etype, event, signal, parent_signal): else: if DEBUG: log.info(" delivering event to parent window: %#x (signal=%s)", window.get_xid(), parent_signal) - handlers = get_event_receivers(window) + handlers = get_event_receivers(window.get_xid()) _maybe_send_event(DEBUG, handlers, parent_signal, event, "parent window %#x" % window.get_xid()) else: if DEBUG: diff --git a/xpra/x11/gtk_x11/clipboard.py b/xpra/x11/gtk_x11/clipboard.py index e3d753a603..8bd1be33a8 100644 --- a/xpra/x11/gtk_x11/clipboard.py +++ b/xpra/x11/gtk_x11/clipboard.py @@ -121,13 +121,13 @@ def init_window(self): xid = self.window.get_xid() with xsync: X11Window.selectSelectionInput(xid) - add_event_receiver(self.window, self) + add_event_receiver(xid, self) def cleanup_window(self): w = self.window if w: self.window = None - remove_event_receiver(w, self) + remove_event_receiver(w.get_xid(), self) w.destroy() def cleanup(self): diff --git a/xpra/x11/gtk_x11/composite.py b/xpra/x11/gtk_x11/composite.py index 41fd14f7d1..b6c918cbe4 100644 --- a/xpra/x11/gtk_x11/composite.py +++ b/xpra/x11/gtk_x11/composite.py @@ -4,7 +4,7 @@ # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. -from gi.repository import GObject +from gi.repository import GObject, Gdk from xpra.x11.gtk_x11.window_damage import WindowDamageHandler from xpra.gtk_common.gobject_util import one_arg_signal @@ -37,8 +37,8 @@ class CompositeHelper(WindowDamageHandler, GObject.GObject): }) # This may raise XError. - def __init__(self, window): - WindowDamageHandler.__init__(self, window) + def __init__(self, xid): + WindowDamageHandler.__init__(self, xid) GObject.GObject.__init__(self) self._listening_to = None @@ -49,10 +49,10 @@ def setup(self): X11Window.XCompositeRedirectWindow(self.xid) WindowDamageHandler.setup(self) - def do_destroy(self, win): + def do_destroy(self): with xlog: X11Window.XCompositeUnredirectWindow(self.xid) - WindowDamageHandler.do_destroy(self, win) + WindowDamageHandler.do_destroy(self) def invalidate_pixmap(self): lt = self._listening_to @@ -63,10 +63,10 @@ def invalidate_pixmap(self): 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) + # Don't want to stop listening to our xid!: + if w!=self.xid: + remove_event_receiver(w, self) def _set_pixmap(self): # The tricky part here is that the pixmap returned by @@ -86,17 +86,13 @@ def _set_pixmap(self): 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() + gdkworld = None 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: + root = Gdk.Screen.get_default().get_root_window() + xid = get_parent(self.xid) + while xid not in (None, root, gdkworld): # We have to use a lowlevel function to manipulate the # event selection here, because SubstructureRedirectMask # does not roundtrip through the GDK event mask @@ -104,11 +100,13 @@ def _set_pixmap(self): # corral window selection masks, and those don't deserve # clobbering. They are our friends! X is driving me # slowly mad. - xid = win.get_xid() + parent = get_parent(xid) + if not parent: + break X11Window.addXSelectInput(xid, StructureNotifyMask) - add_event_receiver(win, self, max_receivers=-1) - listening.append(win) - win = get_parent(win) + add_event_receiver(xid, self, max_receivers=-1) + listening.append(xid) + xid = parent handle = XImage.get_xcomposite_pixmap(self.xid) except Exception: try: diff --git a/xpra/x11/gtk_x11/selection.py b/xpra/x11/gtk_x11/selection.py index f23949349d..2ccda3fe2f 100644 --- a/xpra/x11/gtk_x11/selection.py +++ b/xpra/x11/gtk_x11/selection.py @@ -139,7 +139,7 @@ def acquire(self, when): log("Previous owner is already gone? not blocking", exc_info=True) else: log("Waiting for previous owner to exit...") - add_event_receiver(window, self) + add_event_receiver(window.get_xid(), self) self.exit_timer = GLib.timeout_add(SELECTION_EXIT_TIMEOUT*1000, self.exit_timeout) Gtk.main() if self.exit_timer: @@ -171,7 +171,9 @@ def _owner_change(self, clipboard, event): self.emit("selection-lost") def do_xpra_destroy_event(self, event): - remove_event_receiver(event.window, self) + w = event.window + if w: + remove_event_receiver(w.get_xid(), self) Gtk.main_quit() def window(self): diff --git a/xpra/x11/gtk_x11/tray.py b/xpra/x11/gtk_x11/tray.py index 0feda7186b..63222b8ad0 100644 --- a/xpra/x11/gtk_x11/tray.py +++ b/xpra/x11/gtk_x11/tray.py @@ -117,15 +117,16 @@ def undock(window): rxid = root.get_xid() X11Window.Unmap(wxid) X11Window.Reparent(wxid, rxid, 0, 0) + tray_xid = self.tray_window.get_xid() with xlog: owner = X11Window.XGetSelectionOwner(SELECTION) - if owner==self.tray_window.get_xid(): + if owner==tray_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) + remove_event_receiver(tray_xid, self) tray_windows = self.tray_windows self.tray_windows = {} for window, tray_window in tray_windows.items(): @@ -171,7 +172,7 @@ def setup_tray_window(self): CurrentTime, SELECTION, xtray) owner = X11Window.XGetSelectionOwner(SELECTION) assert owner==xtray, "we failed to get ownership of the tray selection" - add_event_receiver(self.tray_window, self) + add_event_receiver(xtray, self) log("setup tray: done") except Exception: log("setup_tray failure", exc_info=True) @@ -231,7 +232,7 @@ def do_dock_tray(self, xid): em = Gdk.EventMask event_mask = em.STRUCTURE_MASK | em.EXPOSURE_MASK | em.PROPERTY_CHANGE_MASK window.set_events(event_mask=event_mask) - add_event_receiver(window, self) + add_event_receiver(xid, self) w = max(1, min(MAX_TRAY_SIZE, w)) h = max(1, min(MAX_TRAY_SIZE, h)) title = prop_get(xid, "_NET_WM_NAME", "utf8", ignore_errors=True) diff --git a/xpra/x11/gtk_x11/window_damage.py b/xpra/x11/gtk_x11/window_damage.py index 6639dc006f..b4a8aa4d5b 100644 --- a/xpra/x11/gtk_x11/window_damage.py +++ b/xpra/x11/gtk_x11/window_damage.py @@ -42,9 +42,8 @@ class WindowDamageHandler: } # This may raise XError. - def __init__(self, client_window, use_xshm=USE_XSHM): - self.client_window = client_window - self.xid = client_window.get_xid() + def __init__(self, xid : int, use_xshm : bool=USE_XSHM): + self.xid : int = xid log("WindowDamageHandler.__init__(%#x, %s)", self.xid, use_xshm) self._use_xshm = use_xshm self._damage_handle = None @@ -62,24 +61,21 @@ def setup(self): raise Unmanageable(f"window {self.xid:x} disappeared already") self._border_width = geom[-1] self.create_damage_handle() - add_event_receiver(self.client_window, self, self.MAX_RECEIVERS) + add_event_receiver(self.xid, self, self.MAX_RECEIVERS) def create_damage_handle(self): - if self.client_window: + if self.xid: self._damage_handle = X11Window.XDamageCreate(self.xid) log("damage handle(%#x)=%#x", self.xid, self._damage_handle) def destroy(self): - if self.client_window is None: + if not self.xid: log.error(f"Error: damage window handler for {self.xid:x} already cleaned up!") return - #clear the reference to the window early: - win = self.client_window - self.client_window = None - self.do_destroy(win) - def do_destroy(self, win): - remove_event_receiver(win, self) + def do_destroy(self): + remove_event_receiver(self.xid, self) + self.xid = 0 self.destroy_damage_handle() def destroy_damage_handle(self): @@ -95,9 +91,7 @@ def destroy_damage_handle(self): self._xshm_handle = None with xlog: sh.cleanup() - #note: this should be redundant since we cleared the - #reference to self.client_window and shortcut out in do_get_property_contents_handle - #but it's cheap anyway + #note: this should be redundant, but it's cheap and safer self.invalidate_pixmap() def acknowledge_changes(self): @@ -106,7 +100,7 @@ def acknowledge_changes(self): log("acknowledge_changes() xshm handle=%s, damage handle=%s", sh, dh) if sh: sh.discard() - if dh and self.client_window: + if dh and self.xid: #"Synchronously modifies the regions..." so unsynced? with xlog: X11Window.XDamageSubtract(dh) @@ -128,7 +122,8 @@ def get_xshm_handle(self): return None if self._xshm_handle: sw, sh = self._xshm_handle.get_size() - ww, wh = self.client_window.get_geometry()[2:4] + with xsync: + ww, wh = X11Window.getGeometry(self.xid)[2:4] if sw!=ww or sh!=wh: #size has changed! #make sure the current wrapper gets garbage collected: @@ -156,7 +151,7 @@ def _set_pixmap(self): self._contents_handle = XImage.get_xwindow_pixmap_wrapper(self.xid) def get_contents_handle(self): - if not self.client_window: + if not self.xid: #shortcut out return None if self._contents_handle is None: diff --git a/xpra/x11/gtk_x11/wm.py b/xpra/x11/gtk_x11/wm.py index 0553fc9149..dec2136797 100644 --- a/xpra/x11/gtk_x11/wm.py +++ b/xpra/x11/gtk_x11/wm.py @@ -23,6 +23,7 @@ add_event_receiver, #@UnresolvedImport add_fallback_receiver, remove_fallback_receiver, #@UnresolvedImport get_children, #@UnresolvedImport + get_pywindow, #@UnresolvedImport ) from xpra.x11.bindings.window_bindings import constants, X11WindowBindings #@UnresolvedImport from xpra.x11.bindings.keyboard_bindings import X11KeyboardBindings #@UnresolvedImport @@ -229,25 +230,37 @@ def __init__(self, replace_other_wm, wm_name, display=None): # Okay, ready to select for SubstructureRedirect and then load in all # the existing clients. - add_event_receiver(self._root, self) + rxid = self._root.get_xid() + add_event_receiver(rxid, self) add_fallback_receiver("xpra-client-message-event", self) #when reparenting, the events may get sent #to a window that is already destroyed #and we don't want to miss those events, so: add_fallback_receiver("child-map-request-event", self) - rxid = self._root.get_xid() X11Window.substructureRedirect(rxid) - for w in get_children(self._root): + children = get_children(rxid) + log(f"root window children: {children}") + for xid in children: # Checking for FOREIGN here filters out anything that we've # created ourselves (like, say, the world window), and checking # for mapped filters out any withdrawn windows. - xid = w.get_xid() - if (w.get_window_type() == Gdk.WindowType.FOREIGN - and not X11Window.is_override_redirect(xid) - and X11Window.is_mapped(xid)): - log("Wm managing pre-existing child window %#x", xid) - self._manage_client(w) + w = get_pywindow(xid) + log(f"pywindow({xid:x})={w}") + if not w: + continue + wtype = w.get_window_type() + if wtype!=Gdk.WindowType.FOREIGN: + log(f"skipping non foreign window %s", window_info(xid)) + continue + if X11Window.is_override_redirect(xid): + log(f"skipping override redirect window %s", window_info(xid)) + continue + if not X11Window.is_mapped(xid): + log(f"skipping unmapped window %s", window_info(xid)) + continue + log(f"Wm managing pre-existing child window {xid:x}") + self._manage_client(w) # Also watch for focus change events on the root window X11Window.selectFocusChange(rxid) diff --git a/xpra/x11/models/core.py b/xpra/x11/models/core.py index 06c04cb042..3fba1c4a55 100644 --- a/xpra/x11/models/core.py +++ b/xpra/x11/models/core.py @@ -288,18 +288,18 @@ def call_setup(self): 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) + add_event_receiver(self.xid, 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) + self._composite = CompositeHelper(self.xid) with xsync: self._composite.setup() if X11Window.displayHasXShape(): X11Window.XShapeSelectInput(self.xid) except Exception as e: - remove_event_receiver(self.client_window, self) + remove_event_receiver(self.xid, self) log("%s %#x does not support compositing: %s", self._MODELTYPE, self.xid, e) with xswallow: self._composite.destroy() @@ -344,7 +344,7 @@ def do_unmanaged(self, wm_exiting): 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) + remove_event_receiver(self.xid, self) GLib.idle_add(self.managed_disconnect) if self._composite: if self._damage_forward_handle: @@ -562,7 +562,7 @@ def _handle_property_change(self, name): if X11PROPERTY_SYNC and not any (name.startswith(x) for x in X11PROPERTY_SYNC_BLACKLIST): try: with xsync: - prop_type = prop_type_get(self.client_window, name) + prop_type = prop_type_get(self.xid, name) metalog("_handle_property_change(%s) property type=%s", name, prop_type) if prop_type: dtype, dformat = prop_type @@ -667,11 +667,11 @@ def _handle_opaque_region_change(self): ######################################### def do_xpra_unmap_event(self, event): - log("do_xpra_unmap_event(%s) corral_window=%s, ", event, self.client_window) + log("do_xpra_unmap_event(%s) client_window=%s, ", event, self.client_window) self.unmanage() def do_xpra_destroy_event(self, event): - log("do_xpra_destroy_event(%s) corral_window=%s, ", event, self.client_window) + log("do_xpra_destroy_event(%s) client_window=%s, ", event, self.client_window) if event.delivered_to is self.client_window: # This is somewhat redundant with the unmap signal, because if you # destroy a mapped window, then a UnmapNotify is always generated. @@ -800,7 +800,7 @@ def do_xpra_motion_event(self, event): ################################ def raise_window(self): - X11Window.XRaiseWindow(self.client_window.get_xid()) + X11Window.XRaiseWindow(self.xid) def set_active(self): self.root_prop_set("_NET_ACTIVE_WINDOW", "u32", self.xid) diff --git a/xpra/x11/models/window.py b/xpra/x11/models/window.py index 97782abca8..ec5f54bc21 100644 --- a/xpra/x11/models/window.py +++ b/xpra/x11/models/window.py @@ -204,7 +204,7 @@ def setup(self): log("setup() corral_window=%#x", cxid) prop_set(cxid, "_NET_WM_NAME", "utf8", "Xpra-CorralWindow-%#x" % self.xid) X11Window.substructureRedirect(cxid) - add_event_receiver(self.corral_window, self) + add_event_receiver(cxid, 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 @@ -349,7 +349,7 @@ def do_unmanaged(self, wm_exiting): cwin = self.corral_window if cwin: self.corral_window = None - remove_event_receiver(cwin, self) + remove_event_receiver(cwin.get_xid(), self) geom = None #use a new context so we will XSync right here #and detect if the window is already gone: @@ -532,8 +532,7 @@ def do_xpra_configure_event(self, event): def update_children(self): ww, wh = self.client_window.get_geometry()[2:4] children = [] - for w in get_children(self.client_window): - xid = w.get_xid() + for xid in get_children(self.xid): if X11Window.is_inputonly(xid): continue geom = X11Window.getGeometry(xid) diff --git a/xpra/x11/server.py b/xpra/x11/server.py index f5b4fb87f6..72175b3846 100644 --- a/xpra/x11/server.py +++ b/xpra/x11/server.py @@ -402,16 +402,16 @@ def load_existing_windows(self): self._add_new_window(window) root = get_default_root_window() + rxid = root.get_xid() try: with xsync: - children = get_children(root) + children = get_children(rxid) except XError: log("load_existing_windows()", exc_info=True) log("trying again") with xsync: - children = get_children(root) - for window in children: - xid = window.get_xid() + children = get_children(rxid) + for xid in children: can_add = False with xlog: can_add = X11Window.is_override_redirect(xid) and X11Window.is_mapped(xid) diff --git a/xpra/x11/window_info.py b/xpra/x11/window_info.py index e87cddd956..82c25becb2 100644 --- a/xpra/x11/window_info.py +++ b/xpra/x11/window_info.py @@ -5,14 +5,22 @@ # later version. See the file COPYING for details. -def window_name(window): +def window_name(xid): from xpra.x11.gtk_x11.prop import prop_get - return prop_get(window.get_xid(), "_NET_WM_NAME", "utf8", True) or "unknown" + return prop_get(xid, "_NET_WM_NAME", "utf8", True) or "unknown" -def window_info(window): +def window_info(xid): from xpra.x11.gtk_x11.prop import prop_get - net_wm_name = prop_get(window.get_xid(), "_NET_WM_NAME", "utf8", True) - return "%s %s visible=%s" % (net_wm_name, window.get_geometry(), window.is_visible()) + net_wm_name = prop_get(xid, "_NET_WM_NAME", "utf8", True) + from xpra.x11.bindings.window_bindings import X11WindowBindings + X11Window = X11WindowBindings() + from xpra.gtk_common.error import xlog + geom = None # @UnusedVariable + mapped = False # @UnusedVariable + with xlog: + geom = X11Window.getGeometry(xid) + mapped = X11Window.is_mapped(xid) + return "%s %s mapped=%s" % (net_wm_name, geom, mapped) def dump_windows(): @@ -20,13 +28,16 @@ def dump_windows(): log = Logger("x11", "window") from xpra.gtk_common.gtk_util import get_default_root_window root = get_default_root_window() - log("root window: %s" % root) + xid = root.get_xid() + log(f"root window: {xid:x}") try: from xpra.x11.gtk_x11.gdk_bindings import get_children #@UnresolvedImport + from xpra.gtk_common.error import xlog except ImportError: pass else: - children = get_children(root) - log("%s windows" % len(children)) - for window in get_children(root): - log("found window: %s", window_info(window)) + with xlog: + children = get_children(xid) + log("%s windows" % len(xid)) + for cxid in children: + log("found window: %s", window_info(cxid)) diff --git a/xpra/x11/xroot_props.py b/xpra/x11/xroot_props.py index d12c704826..396f49fead 100644 --- a/xpra/x11/xroot_props.py +++ b/xpra/x11/xroot_props.py @@ -27,11 +27,11 @@ def __init__(self, props, root_window): self._root = root_window self._saved_event_mask = self._root.get_events() self._root.set_events(self._saved_event_mask | Gdk.EventMask.PROPERTY_CHANGE_MASK) - add_event_receiver(self._root, self) + add_event_receiver(self._root.get_xid(), self) def cleanup(self): #this must be called from the UI thread! - remove_event_receiver(self._root, self) + remove_event_receiver(self._root.get_xid(), self) self._root.set_events(self._saved_event_mask) diff --git a/xpra/x11/xsettings.py b/xpra/x11/xsettings.py index d363cee1d3..d82d15ebed 100644 --- a/xpra/x11/xsettings.py +++ b/xpra/x11/xsettings.py @@ -98,16 +98,16 @@ def __init__(self, screen_number=0): GObject.GObject.__init__(self) XSettingsHelper.__init__(self, screen_number) self._root = self._clipboard.get_display().get_default_screen().get_root_window() - add_event_receiver(self._root, self) + add_event_receiver(self._root.get_xid(), self) self._add_watch() def cleanup(self): - remove_event_receiver(self._root, self) + remove_event_receiver(self._root.get_xid(), self) def _add_watch(self): owner = self.xsettings_owner() if owner is not None: - add_event_receiver(owner, self) + add_event_receiver(owner.get_xid(), self) def do_xpra_client_message_event(self, event): if (event.window is self._root