def property_changed(self, widget, event): statelog("%s.property_changed(%s, %s) : %s", self, widget, event, event.atom) if event.atom=="_NET_WM_DESKTOP" and self._been_mapped and not self._override_redirect: self.do_workspace_changed(event) elif event.atom=="XKLAVIER_STATE": #unused for now, but log it: xklavier_state = prop_get(self.get_window(), "XKLAVIER_STATE", ["integer"], ignore_errors=False) keylog("XKLAVIER_STATE=%s", [hex(x) for x in (xklavier_state or [])]) elif event.atom=="_NET_WM_STATE": wm_state_atoms = prop_get(self.get_window(), "_NET_WM_STATE", ["atom"], ignore_errors=False) #code mostly duplicated from gtk_x11/window.py: WM_STATE_NAME = { "fullscreen" : ("_NET_WM_STATE_FULLSCREEN", ), "maximized" : ("_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ"), "shaded" : ("_NET_WM_STATE_SHADED", ), "sticky" : ("_NET_WM_STATE_STICKY", ), "skip-pager" : ("_NET_WM_STATE_SKIP_PAGER", ), "skip-taskbar" : ("_NET_WM_STATE_SKIP_TASKBAR", ), "above" : ("_NET_WM_STATE_ABOVE", ), "below" : ("_NET_WM_STATE_BELOW", ), } state_atoms = set(wm_state_atoms or []) state_updates = {} for state, atoms in WM_STATE_NAME.items(): var = "_" + state.replace("-", "_") #ie: "skip-pager" -> "_skip_pager" cur_state = getattr(self, var) wm_state_is_set = set(atoms).issubset(state_atoms) if wm_state_is_set and not cur_state: state_updates[state] = True elif cur_state and not wm_state_is_set: state_updates[state] = False log("_NET_WM_STATE=%s, state_updates=%s", wm_state_atoms, state_updates) if state_updates: self.update_window_state(state_updates)
def wm_check(display, upgrading=False): #there should only be one screen... but let's check all of them for i in range(display.get_n_screens()): screen = display.get_screen(i) root = screen.get_root_window() wm_prop = "WM_S%s" % i cwm_prop = "_NEW_WM_CM_S%s" % i wm_so = X11Window.XGetSelectionOwner(wm_prop) cwm_so = X11Window.XGetSelectionOwner(cwm_prop) log("ewmh selection owner for %s: %s", wm_prop, wm_so) log("compositing window manager %s: %s", cwm_prop, cwm_so) try: ewmh_wm = prop_get(root, "_NET_SUPPORTING_WM_CHECK", "window", ignore_errors=True, raise_xerrors=False) except: #errors here generally indicate that the window is gone #which is fine: it means the previous window manager is no longer active continue log("_NET_SUPPORTING_WM_CHECK for screen %s: %s", i, ewmh_wm) if ewmh_wm: try: name = prop_get(ewmh_wm, "_NET_WM_NAME", "utf8", ignore_errors=False, raise_xerrors=False) except: name = None if upgrading and name and name==WM_WINDOW_NAME: log.info("found previous Xpra instance") else: log.warn("Warning: found an existing window manager on screen %s using window %#x: %s", i, ewmh_wm.xid, name or "unknown") if (wm_so is None or wm_so==0) and (cwm_so is None or cwm_so==0): log.error("it does not own the selection '%s' or '%s' so we cannot take over and make it exit", wm_prop, cwm_prop) log.error("please stop %s so you can run xpra on this display", name or "the existing window manager") return False return True
def do_dock_tray(self, xid): root = get_default_root_window() window = x11_foreign_new(root.get_display(), xid) if window is None: log.warn("could not find gdk window for tray window %#x", xid) return log("dock_tray: root=%s, window=%s", root, window) w, h = window.get_geometry()[2:4] log("dock_tray: geometry=%s", (w, h)) if w == 0 and h == 0: log("dock_tray: invalid tray geometry, ignoring this request") return event_mask = STRUCTURE_MASK | EXPOSURE_MASK | PROPERTY_CHANGE_MASK window.set_events(event_mask=event_mask) add_event_receiver(window, self) w = max(1, min(MAX_TRAY_SIZE, w)) h = max(1, min(MAX_TRAY_SIZE, h)) title = prop_get(window, "_NET_WM_NAME", "utf8", ignore_errors=True) if title is None: title = prop_get(window, "WM_NAME", "latin1", ignore_errors=True) if title is None: title = "" xid = get_xwindow(root) log("dock_tray(%#x) gdk window=%#x, geometry=%s, title=%s", xid, xid, window.get_geometry(), title) kwargs = {} if not is_gtk3(): colormap = window.get_colormap() if colormap: kwargs["colormap"] = colormap visual = window.get_visual() if visual: kwargs["visual"] = visual tray_window = GDKWindow(root, width=w, height=h, event_mask=event_mask, title=title, x=-200, y=-200, override_redirect=True, **kwargs) log("dock_tray(%#x) setting tray properties", xid) set_tray_window(tray_window, window) tray_window.show() self.tray_windows[window] = tray_window self.window_trays[tray_window] = window log("dock_tray(%#x) resizing and reparenting", xid) window.resize(w, h) xwin = get_xwindow(window) xtray = get_xwindow(tray_window) X11Window.Withdraw(xwin) X11Window.Reparent(xwin, xtray, 0, 0) X11Window.MapRaised(xwin) log("dock_tray(%#x) new tray container window %#x", xid, xtray) tray_window.invalidate_rect(gdk.Rectangle(width=w, height=h), True) X11Window.send_xembed_message(xwin, XEMBED_EMBEDDED_NOTIFY, 0, xtray, XEMBED_VERSION)
def property_changed(self, widget, event): statelog("property_changed(%s, %s) : %s", widget, event, event.atom) if event.atom=="_NET_WM_DESKTOP" and self._been_mapped and not self._override_redirect: self.do_workspace_changed(event) elif event.atom=="_NET_FRAME_EXTENTS": v = prop_get(self.get_window(), "_NET_FRAME_EXTENTS", ["u32"], ignore_errors=False) statelog("_NET_FRAME_EXTENTS: %s", v) if v: if v==self._current_frame_extents: #unchanged return if not self._been_mapped: #map event will take care of sending it return if self.is_OR() or self.is_tray(): #we can't do it: the server can't handle configure packets for OR windows! return if not self._client.window_configure_skip_geometry or not self._client.server_window_frame_extents: #can't send cheap "skip-geometry" packets or frame-extents feature not supported: return #tell server about new value: #TODO: don't bother if unchanged self._current_frame_extents = v statelog("sending configure event to update _NET_FRAME_EXTENTS to %s", v) self._window_state["frame"] = self._client.crect(*v) self.send_configure_event(True) elif event.atom=="XKLAVIER_STATE": #unused for now, but log it: xklavier_state = prop_get(self.get_window(), "XKLAVIER_STATE", ["integer"], ignore_errors=False) keylog("XKLAVIER_STATE=%s", [hex(x) for x in (xklavier_state or [])]) elif event.atom=="_NET_WM_STATE": wm_state_atoms = prop_get(self.get_window(), "_NET_WM_STATE", ["atom"], ignore_errors=False) #code mostly duplicated from gtk_x11/window.py: WM_STATE_NAME = { "fullscreen" : ("_NET_WM_STATE_FULLSCREEN", ), "maximized" : ("_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ"), "shaded" : ("_NET_WM_STATE_SHADED", ), "sticky" : ("_NET_WM_STATE_STICKY", ), "skip-pager" : ("_NET_WM_STATE_SKIP_PAGER", ), "skip-taskbar" : ("_NET_WM_STATE_SKIP_TASKBAR", ), "above" : ("_NET_WM_STATE_ABOVE", ), "below" : ("_NET_WM_STATE_BELOW", ), "focused" : ("_NET_WM_STATE_FOCUSED", ), } state_atoms = set(wm_state_atoms or []) state_updates = {} for state, atoms in WM_STATE_NAME.items(): var = "_" + state.replace("-", "_") #ie: "skip-pager" -> "_skip_pager" cur_state = getattr(self, var) wm_state_is_set = set(atoms).issubset(state_atoms) if wm_state_is_set and not cur_state: state_updates[state] = True elif cur_state and not wm_state_is_set: state_updates[state] = False log("_NET_WM_STATE=%s, state_updates=%s", wm_state_atoms, state_updates) if state_updates: self.update_window_state(state_updates)
def dock_tray(self, xid): log("dock_tray(%#x)", xid) root = gdk.get_default_root_window() window = gdk.window_foreign_new(xid) if window is None: log.warn("could not find gdk window for tray window %#x", xid) return log("dock_tray: root=%s, window=%s", root, window) w, h = window.get_geometry()[2:4] log("dock_tray: geometry=%s", (w, h)) if w == 0 and h == 0: log("dock_tray: invalid tray geometry, ignoring this request") return event_mask = gdk.STRUCTURE_MASK | gdk.EXPOSURE_MASK | gdk.PROPERTY_CHANGE_MASK window.set_events(event_mask=event_mask) add_event_receiver(window, self) w = max(1, min(128, w)) h = max(1, min(128, h)) title = prop_get(window, "_NET_WM_NAME", "utf8", ignore_errors=True) if title is None: title = prop_get(window, "WM_NAME", "latin1", ignore_errors=True) if title is None: title = "" log( "dock_tray(%#x) gdk window=%#x, geometry=%s, title=%s, visual.depth=%s", xid, window.xid, window.get_geometry(), title, window.get_visual().depth) event_mask = gdk.STRUCTURE_MASK | gdk.EXPOSURE_MASK | gdk.PROPERTY_CHANGE_MASK tray_window = gdk.Window(root, width=w, height=h, window_type=gdk.WINDOW_TOPLEVEL, event_mask=event_mask, wclass=gdk.INPUT_OUTPUT, title=title, x=-200, y=-200, override_redirect=True, visual=window.get_visual(), colormap=window.get_colormap()) log("dock_tray(%#x) setting tray properties", xid) set_tray_window(tray_window, window) tray_window.show() self.tray_windows[window] = tray_window self.window_trays[tray_window] = window log("dock_tray(%#x) resizing and reparenting", xid) window.resize(w, h) xwin = window.xid xtray = tray_window.xid X11Window.Withdraw(xwin) X11Window.Reparent(xwin, xtray, 0, 0) X11Window.MapRaised(xwin) log("dock_tray(%#x) new tray container window %#x", xid, xtray) tray_window.invalidate_rect(gdk.Rectangle(width=w, height=h), True) X11Window.send_xembed_message(xwin, XEMBED_EMBEDDED_NOTIFY, 0, xtray, XEMBED_VERSION)
def wm_check(display, wm_name, upgrading=False): # there should only be one screen... but let's check all of them for i in range(display.get_n_screens()): screen = display.get_screen(i) root = screen.get_root_window() wm_prop = "WM_S%s" % i cwm_prop = "_NEW_WM_CM_S%s" % i wm_so = X11Window.XGetSelectionOwner(wm_prop) cwm_so = X11Window.XGetSelectionOwner(cwm_prop) log("ewmh selection owner for %s: %s", wm_prop, wm_so) log("compositing window manager %s: %s", cwm_prop, cwm_so) try: ewmh_wm = prop_get(root, "_NET_SUPPORTING_WM_CHECK", "window", ignore_errors=True, raise_xerrors=False) except: # errors here generally indicate that the window is gone # which is fine: it means the previous window manager is no longer active continue def xid(w): if w: return "%#x" % w.xid return None log("_NET_SUPPORTING_WM_CHECK for screen %i: %s (root=%s)", i, xid(ewmh_wm), xid(root)) if ewmh_wm: try: name = prop_get(ewmh_wm, "_NET_WM_NAME", "utf8", ignore_errors=False, raise_xerrors=False) except: name = None if upgrading and name and name == wm_name: log.info("found previous Xpra instance") else: log.warn( "Warning: found an existing window manager on screen %s using window %#x: %s", i, ewmh_wm.xid, name or "unknown", ) if (wm_so is None or wm_so == 0) and (cwm_so is None or cwm_so == 0): if FORCE_REPLACE_WM: log.warn("XPRA_FORCE_REPLACE_WM is set, replacing it forcibly") else: log.error( "it does not own the selection '%s' or '%s' so we cannot take over and make it exit", wm_prop, cwm_prop, ) log.error( "please stop %s so you can run xpra on this display", name or "the existing window manager" ) log.warn("if you are certain that the window manager is already gone,") log.warn(" you may set XPRA_FORCE_REPLACE_WM=1 to force xpra to continue, at your own risk") return False return True
def get_wm_info(): with xsync: from gi.repository import Gdk #pylint: disable=import-outside-toplevel display = Gdk.Display.get_default() X11Window = X11WindowBindings() screen = display.get_default_screen() root = screen.get_root_window() info = { "display": display.get_name(), "root": root.get_xid(), "WM_S0": X11Window.XGetSelectionOwner(WM_S0) or 0, "_NEW_WM_CM_S0": X11Window.XGetSelectionOwner(_NEW_WM_CM_S0) or 0, } ewmh_xid = raw_prop_get(root, "_NET_SUPPORTING_WM_CHECK", "window", ignore_errors=False, raise_xerrors=False) if ewmh_xid: ewmh_wm = prop_get(root, "_NET_SUPPORTING_WM_CHECK", "window", ignore_errors=True, raise_xerrors=False) if ewmh_wm: info["_NET_SUPPORTING_WM_CHECK"] = ewmh_wm.get_xid() info["wmname"] = prop_get(ewmh_wm, "_NET_WM_NAME", "utf8", ignore_errors=True, raise_xerrors=False) or "" else: info["wmname"] = prop_get(root, "_NET_WM_NAME", "utf8", ignore_errors=True, raise_xerrors=False) or "" for name, prop_name, prop_type in ( ("xpra-server-pid", "XPRA_SERVER_PID", "u32"), ("xpra-vfb-pid", "XPRA_XVFB_PID", "u32"), ("xpra-server-version", "XPRA_SERVER", "latin1"), ("xpra-server-mode", "XPRA_SERVER_MODE", "latin1"), ("dbus-address", "DBUS_SESSION_BUS_ADDRESS", "latin1"), ("dbus-pid", "DBUS_SESSION_BUS_PID", "u32"), ("dbus-window", "DBUS_SESSION_BUS_WINDOW_ID", "u32"), ): v = prop_get(root, prop_name, prop_type, ignore_errors=True, raise_xerrors=False) if v: info[name] = v log("get_wm_info()=%s", info) return info
def wm_check(wm_name, upgrading=False): found_name = False with xsync: from gi.repository import Gdk display = Gdk.Display.get_default() #there should only be one screen... but let's check all of them for i in range(display.get_n_screens()): screen = display.get_screen(i) root = screen.get_root_window() wm_prop = "WM_S%s" % i cwm_prop = "_NEW_WM_CM_S%s" % i wm_so = X11Window.XGetSelectionOwner(wm_prop) cwm_so = X11Window.XGetSelectionOwner(cwm_prop) log("ewmh selection owner for %s: %s", wm_prop, wm_so) log("compositing window manager %s: %s", cwm_prop, cwm_so) ewmh_wm = prop_get(root, "_NET_SUPPORTING_WM_CHECK", "window", ignore_errors=True, raise_xerrors=False) def xid(w): if w: return "%#x" % w.get_xid() return None log("_NET_SUPPORTING_WM_CHECK for screen %i: %s (root=%s)", i, xid(ewmh_wm), xid(root)) if not ewmh_wm: continue name = prop_get(ewmh_wm, "_NET_WM_NAME", "utf8", ignore_errors=True, raise_xerrors=False) if upgrading and name and name==wm_name: log.info("found previous Xpra instance") found_name = True elif not name: log.warn("Warning: no window manager found") log.warn(" on screen %s using window %#x", i, ewmh_wm.get_xid()) else: log.warn("Warning: found an existing window manager") log.warn(" on screen %s using window %#x: %s", i, ewmh_wm.get_xid(), name or "unknown") if (wm_so is None or wm_so==0) and (cwm_so is None or cwm_so==0): if FORCE_REPLACE_WM: log.warn("XPRA_FORCE_REPLACE_WM is set, replacing it forcibly") else: log.error("it does not own the selection '%s' or '%s'", wm_prop, cwm_prop) log.error("so we cannot take over and make it exit") log.error("please stop %s so you can run xpra on this display", name or "the existing window manager") log.warn("if you are certain that the window manager is already gone,") log.warn(" you may set XPRA_FORCE_REPLACE_WM=1 to force xpra to continue") log.warn(" at your own risk") return False if upgrading and not found_name: log.error("Error: xpra server not found") return False return True
def dock_tray(self, xid): root = gtk.gdk.get_default_root_window() window = gtk.gdk.window_foreign_new(xid) w, h = window.get_geometry()[2:4] event_mask = gtk.gdk.STRUCTURE_MASK | gtk.gdk.EXPOSURE_MASK | gtk.gdk.PROPERTY_CHANGE_MASK window.set_events(event_mask=event_mask) add_event_receiver(window, self) w = max(1, min(64, w)) h = max(1, min(64, h)) title = prop_get(window, "_NET_WM_NAME", "utf8", ignore_errors=True) if title is None: title = prop_get(window, "WM_NAME", "latin1", ignore_errors=True) if title is None: title = "" debug( "dock_tray(%s) window=%s, geometry=%s, title=%s, visual.depth=%s", hex(xid), window, window.get_geometry(), title, window.get_visual().depth) event_mask = gtk.gdk.STRUCTURE_MASK | gtk.gdk.EXPOSURE_MASK | gtk.gdk.PROPERTY_CHANGE_MASK tray_window = gtk.gdk.Window(root, width=w, height=h, window_type=gtk.gdk.WINDOW_TOPLEVEL, event_mask=event_mask, wclass=gtk.gdk.INPUT_OUTPUT, title=title, x=-200, y=-200, override_redirect=True, visual=window.get_visual(), colormap=window.get_colormap()) debug("dock_tray(%s) setting tray properties", hex(xid)) set_tray_window(tray_window, window) tray_window.show() self.tray_windows[window] = tray_window self.window_trays[tray_window] = window debug("dock_tray(%s) resizing and reparenting", hex(xid)) window.resize(w, h) xwin = get_xwindow(window) xtray = get_xwindow(tray_window) X11Window.Withdraw(xwin) X11Window.Reparent(xwin, xtray, 0, 0) X11Window.MapRaised(xwin) debug("dock_tray(%s) new tray container window %s", hex(xid), hex(xtray)) tray_window.invalidate_rect(gtk.gdk.Rectangle(width=w, height=h), True) X11Window.send_xembed_message(xwin, XEMBED_EMBEDDED_NOTIFY, 0, xtray, XEMBED_VERSION)
def _get_xresources(): if not is_Wayland(): try: from xpra.x11.gtk_x11.prop import prop_get from xpra.gtk_common.gtk_util import get_default_root_window root = get_default_root_window() value = prop_get(root, "RESOURCE_MANAGER", "latin1", ignore_errors=True) log("RESOURCE_MANAGER=%s", value) if value is None: return None #parse the resources into a dict: values = {} options = value.split("\n") for option in options: if not option: continue parts = option.split(":\t", 1) if len(parts) != 2: log("skipped invalid option: '%s'", option) continue values[parts[0]] = parts[1] return values except Exception as e: log("_get_xresources error: %s", e) return None
def _get_str(prop_name): import gtk from xpra.x11.gtk_x11.prop import prop_get v = prop_get(gtk.gdk.get_default_root_window(), prop_name, "latin1") if v is not None: return v.encode("latin1") return v
def _root_prop_get(prop_name, ptype="u32"): from xpra.gtk_common.gtk_util import get_default_root_window from xpra.x11.gtk_x11.prop import prop_get try: return prop_get(get_default_root_window(), prop_name, ptype) except Exception: return None
def do_xpra_client_message_event(self, event): # FIXME # Need to listen for: # _NET_ACTIVE_WINDOW # _NET_CURRENT_DESKTOP # _NET_WM_PING responses # and maybe: # _NET_RESTACK_WINDOW # _NET_WM_STATE log("do_xpra_client_message_event(%s)", event) if event.message_type == "_NET_SHOWING_DESKTOP": show = bool(event.data[0]) self.emit("show-desktop", show) elif event.message_type == "_NET_REQUEST_FRAME_EXTENTS" and FRAME_EXTENTS: #if we're here, that means the window model does not exist #(or it would have processed the event) #so this must be a an unmapped window frame = (0, 0, 0, 0) with xswallow: if not X11Window.is_override_redirect(get_xwindow( event.window)): #use the global default: frame = prop_get(self._root, "DEFAULT_NET_FRAME_EXTENTS", ["u32"], ignore_errors=True) if not frame: #fallback: frame = (0, 0, 0, 0) framelog( "_NET_REQUEST_FRAME_EXTENTS: setting _NET_FRAME_EXTENTS=%s on %#x", frame, get_xwindow(event.window)) prop_set(event.window, "_NET_FRAME_EXTENTS", ["u32"], frame)
def _get_xresources(): try: from xpra.x11.gtk_x11.prop import prop_get import gtk.gdk root = gtk.gdk.get_default_root_window() v = prop_get(root, "RESOURCE_MANAGER", "latin1", ignore_errors=True) log("RESOURCE_MANAGER=%s", v) if v is None: return None value = v.decode("utf-8") #parse the resources into a dict: values={} options = value.split("\n") for option in options: if not option: continue parts = option.split(":\t", 1) if len(parts)!=2: log("skipped invalid option: '%s'", option) continue values[parts[0]] = parts[1] return values except Exception as e: log("_get_xresources error: %s", e) return None
def init_randr(self): self.randr = RandR.has_randr() screenlog("randr=%s", self.randr) #check the property first, #because we may be inheriting this display, #in which case the screen sizes list may be longer than 1 eprop = prop_get(self.root_window, "_XPRA_RANDR_EXACT_SIZE", "u32", ignore_errors=True, raise_xerrors=False) screenlog("_XPRA_RANDR_EXACT_SIZE=%s", eprop) self.randr_exact_size = eprop == 1 if not self.randr_exact_size: #ugly hackish way of detecting Xvfb with randr, #assume that it has only one resolution pre-defined: sizes = RandR.get_xrr_screen_sizes() if len(sizes) == 1: self.randr_exact_size = True prop_set(self.root_window, "_XPRA_RANDR_EXACT_SIZE", "u32", 1) elif not sizes: #xwayland? self.randr = False self.randr_exact_size = False screenlog("randr=%s, exact size=%s", self.randr, self.randr_exact_size) display = display_get_default() i = 0 while i < display.get_n_screens(): screen = display.get_screen(i) screen.connect("size-changed", self._screen_size_changed) i += 1 screenlog("randr enabled: %s", self.randr) if not self.randr: screenlog.warn("Warning: no X11 RandR support on %s", os.environ.get("DISPLAY"))
def do_xpra_client_message_event(self, event): # FIXME # Need to listen for: # _NET_ACTIVE_WINDOW # _NET_CURRENT_DESKTOP # _NET_WM_PING responses # and maybe: # _NET_RESTACK_WINDOW # _NET_WM_STATE log("do_xpra_client_message_event(%s)", event) if event.message_type=="_NET_SHOWING_DESKTOP": show = bool(event.data[0]) self.emit("show-desktop", show) elif event.message_type=="_NET_REQUEST_FRAME_EXTENTS": #if we're here, that means the window model does not exist #(or it would have processed the event) #so this must be a an unmapped window frame = (0, 0, 0, 0) if not X11Window.is_override_redirect(event.window.xid): #use the global default: frame = prop_get(self._root, "DEFAULT_NET_FRAME_EXTENTS", ["u32"], ignore_errors=True) if not frame: #fallback: frame = (0, 0, 0, 0) log("_NET_REQUEST_FRAME_EXTENTS: setting _NET_FRAME_EXTENTS=%s on %#x", frame, event.window.xid) with xswallow: prop_set(event.window, "_NET_FRAME_EXTENTS", ["u32"], frame)
def wm_check(display, upgrading=False): #there should only be one screen... but let's check all of them for i in range(display.get_n_screens()): screen = display.get_screen(i) root = screen.get_root_window() wm_prop = "WM_S%s" % i cwm_prop = "_NEW_WM_CM_S%s" % i wm_so = X11Window.XGetSelectionOwner(wm_prop) cwm_so = X11Window.XGetSelectionOwner(cwm_prop) log("ewmh selection owner for %s: %s", wm_prop, wm_so) log("compositing window manager %s: %s", cwm_prop, cwm_so) try: ewmh_wm = prop_get(root, "_NET_SUPPORTING_WM_CHECK", "window", ignore_errors=True, raise_xerrors=False) except: #errors here generally indicate that the window is gone #which is fine: it means the previous window manager is no longer active continue log("_NET_SUPPORTING_WM_CHECK for screen %s: %s", i, ewmh_wm) if ewmh_wm: try: name = prop_get(ewmh_wm, "_NET_WM_NAME", "utf8", ignore_errors=False, raise_xerrors=False) except: name = None if upgrading and name and name == WM_WINDOW_NAME: log.info("found previous Xpra instance") else: log.warn( "Warning: found an existing window manager on screen %s using window id %s: %s", i, hex(get_xwindow(ewmh_wm)), name or "unknown") if (wm_so is None or wm_so == 0) and (cwm_so is None or cwm_so == 0): log.error( "it does not own the selection '%s' or '%s' so we cannot take over and make it exit", wm_prop, cwm_prop) log.error("please stop %s so you can run xpra on this display", name or "the existing window manager") return False return True
def do_selection_request_event(self, event): debug("do_selection_request_event(%s)", event) self._selection_request_events += 1 if not self._enabled: gtk.Invisible.do_selection_request_event(self, event) return # Black magic: the superclass default handler for this signal # implements all the hards parts of selection handling, occasionally # calling back to the do_selection_get handler (below) to actually get # the data to be sent. However, it only does this for targets that # have been registered ahead of time; other targets fall through to a # default implementation that cannot be overridden. So, we swoop in # ahead of time and add whatever target was requested to the list of # targets we want to handle! # # Special cases (magic targets defined by ICCCM): # TIMESTAMP: the remote side has a different timeline than us, so # sending TIMESTAMPS across the wire doesn't make any sense. We # ignore TIMESTAMP requests, and let them fall through to GTK+'s # default handler. # TARGET: GTK+ has default handling for this, but we don't want to # use it. Fortunately, if we tell GTK+ that we can handle TARGET # requests, then it will pass them on to us rather than fall # through to the default handler. # MULTIPLE: Ugh. To handle this properly, we need to go out # ourselves and fetch the magic property off the requesting window # (with proper error trapping and all), and interpret its # contents. Probably doable (FIXME), just a pain. # # Another special case is that if an app requests the contents of a # clipboard that it currently owns, then GTK+ will short-circuit the # normal logic and request the contents directly (i.e. it calls # gtk_selection_invoke_handler) -- without giving us a chance to # assert that we can handle the requested sort of target. Fortunately, # Xpra never needs to request the clipboard when it owns it, so that's # okay. assert str(event.selection) == self._selection target = str(event.target) if target == "TIMESTAMP": pass elif target == "MULTIPLE": try: from xpra.x11.gtk_x11.prop import prop_get except ImportError: debug("MULTIPLE for property '%s' not handled due to missing xpra.x11.gtk_x11 bindings", event.property) gtk.Invisible.do_selection_request_event(self, event) return atoms = prop_get(event.window, event.property, ["multiple-conversion"]) debug("MULTIPLE clipboard atoms: %r", atoms) if atoms: targets = atoms[::2] for t in targets: self.selection_add_target(self._selection, t, 0) else: debug("target for %s: %r", self._selection, target) self.selection_add_target(self._selection, target, 0) debug("do_selection_request_event(%s) target=%s, selection=%s", event, target, self._selection) gtk.Invisible.do_selection_request_event(self, event)
def prop_get(self, key, ptype, ignore_errors=None, raise_xerrors=False): """ Get an X11 property from the client window, using the automatic type conversion code from prop.py Ignores property errors during setup_client. """ if ignore_errors is None and (not self._setup_done or not self._managed): ignore_errors = True return prop_get(self.client_window, key, ptype, ignore_errors=bool(ignore_errors), raise_xerrors=raise_xerrors)
def show_current_workspace(self, *args): try: workspace = prop_get(self.window.get_window(), "_NET_WM_DESKTOP", "u32") if workspace is None: workspace = "" self.entry.set_text(str(workspace)) self.warn.set_text("") except Exception as e: self.warn.set_text(str(e))
def _handle_motif_wm_hints_change(self): #motif_hints = self.prop_get("_MOTIF_WM_HINTS", "motif-hints") motif_hints = prop_get(self.client_window, "_MOTIF_WM_HINTS", "motif-hints", ignore_errors=False, raise_xerrors=True) metalog("_MOTIF_WM_HINTS=%s", motif_hints) if motif_hints: if motif_hints.flags & (2**MotifWMHints.DECORATIONS_BIT): self._updateprop("decorations", motif_hints.decorations) if motif_hints.flags & (2**MotifWMHints.INPUT_MODE_BIT): self._updateprop("modal", bool(motif_hints.input_mode))
def get_net_wm_name(self): try: return prop_get(self._ewmh_window, "_NET_WM_NAME", "utf8", ignore_errors=False, raise_xerrors=False) except Exception as e: log.error("error querying _NET_WM_NAME: %s", e)
def print_extents(): v = prop_get(win.get_window(), "_NET_FRAME_EXTENTS", ["u32"], ignore_errors=False) print("_NET_FRAME_EXTENTS: %s" % str(v)) with xsync: event_mask = SubstructureNotifyMask | SubstructureRedirectMask X11Window.sendClientMessage(root.xid, win.get_window().xid, False, event_mask, "_NET_REQUEST_FRAME_EXTENTS") print("sending _NET_REQUEST_FRAME_EXTENTS to %#x for %#x" % (root.xid, win.get_window().xid)) return v is None
def get_settings(self): owner = self.xsettings_owner() log("Fetching current XSettings data, owner=%s", owner) if owner is None: return None try: return prop_get(owner, XSETTINGS, XSETTINGS_TYPE) except XError: log("X error while fetching XSettings data; ignored", exc_info=True) return None
def property_changed(self, widget, event): statelog("%s.property_changed(%s, %s) : %s", self, widget, event, event.atom) if event.atom == "_NET_WM_DESKTOP" and self._been_mapped and not self._override_redirect: self.do_workspace_changed(event) elif event.atom == "XKLAVIER_STATE": #unused for now, but log it: xklavier_state = prop_get(self.get_window(), "XKLAVIER_STATE", ["integer"], ignore_errors=False) keylog("XKLAVIER_STATE=%s", [hex(x) for x in (xklavier_state or [])]) elif event.atom == "_NET_WM_STATE": wm_state_atoms = prop_get(self.get_window(), "_NET_WM_STATE", ["atom"], ignore_errors=False) #code mostly duplicated from gtk_x11/window.py: WM_STATE_NAME = { "fullscreen": ("_NET_WM_STATE_FULLSCREEN", ), "maximized": ("_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ"), "shaded": ("_NET_WM_STATE_SHADED", ), "sticky": ("_NET_WM_STATE_STICKY", ), "skip-pager": ("_NET_WM_STATE_SKIP_PAGER", ), "skip-taskbar": ("_NET_WM_STATE_SKIP_TASKBAR", ), "above": ("_NET_WM_STATE_ABOVE", ), "below": ("_NET_WM_STATE_BELOW", ), } state_atoms = set(wm_state_atoms or []) state_updates = {} for state, atoms in WM_STATE_NAME.items(): var = "_" + state.replace( "-", "_") #ie: "skip-pager" -> "_skip_pager" cur_state = getattr(self, var) wm_state_is_set = set(atoms).issubset(state_atoms) if wm_state_is_set and not cur_state: state_updates[state] = True elif cur_state and not wm_state_is_set: state_updates[state] = False log("_NET_WM_STATE=%s, state_updates=%s", wm_state_atoms, state_updates) if state_updates: self.update_window_state(state_updates)
def dock_tray(self, xid): root = gtk.gdk.get_default_root_window() window = gtk.gdk.window_foreign_new(xid) if window is None: log.warn("could not find gdk window for tray window %#x", xid) return w, h = window.get_geometry()[2:4] event_mask = gtk.gdk.STRUCTURE_MASK | gtk.gdk.EXPOSURE_MASK | gtk.gdk.PROPERTY_CHANGE_MASK window.set_events(event_mask=event_mask) add_event_receiver(window, self) w = max(1, min(64, w)) h = max(1, min(64, h)) title = prop_get(window, "_NET_WM_NAME", "utf8", ignore_errors=True) if title is None: title = prop_get(window, "WM_NAME", "latin1", ignore_errors=True) if title is None: title = "" log("dock_tray(%#x) gdk window=%#x, geometry=%s, title=%s, visual.depth=%s", xid, window.xid, window.get_geometry(), title, window.get_visual().depth) event_mask = gtk.gdk.STRUCTURE_MASK | gtk.gdk.EXPOSURE_MASK | gtk.gdk.PROPERTY_CHANGE_MASK tray_window = gtk.gdk.Window(root, width=w, height=h, window_type=gtk.gdk.WINDOW_TOPLEVEL, event_mask = event_mask, wclass=gtk.gdk.INPUT_OUTPUT, title=title, x=-200, y=-200, override_redirect=True, visual=window.get_visual(), colormap=window.get_colormap()) log("dock_tray(%#x) setting tray properties", xid) set_tray_window(tray_window, window) tray_window.show() self.tray_windows[window] = tray_window self.window_trays[tray_window] = window log("dock_tray(%#x) resizing and reparenting", xid) window.resize(w, h) xwin = window.xid xtray = tray_window.xid X11Window.Withdraw(xwin) X11Window.Reparent(xwin, xtray, 0, 0) X11Window.MapRaised(xwin) log("dock_tray(%#x) new tray container window %#x", xid, xtray) tray_window.invalidate_rect(gtk.gdk.Rectangle(width=w, height=h), True) X11Window.send_xembed_message(xwin, XEMBED_EMBEDDED_NOTIFY, 0, xtray, XEMBED_VERSION)
def wm_check(display, wm_name, upgrading=False): #there should only be one screen... but let's check all of them for i in range(display.get_n_screens()): screen = display.get_screen(i) root = screen.get_root_window() wm_prop = "WM_S%s" % i cwm_prop = "_NEW_WM_CM_S%s" % i wm_so = X11Window.XGetSelectionOwner(wm_prop) cwm_so = X11Window.XGetSelectionOwner(cwm_prop) log("ewmh selection owner for %s: %s", wm_prop, wm_so) log("compositing window manager %s: %s", cwm_prop, cwm_so) try: ewmh_wm = prop_get(root, "_NET_SUPPORTING_WM_CHECK", "window", ignore_errors=True, raise_xerrors=False) except: #errors here generally indicate that the window is gone #which is fine: it means the previous window manager is no longer active continue def xid(w): if w: return "%#x" % w.xid return None log("_NET_SUPPORTING_WM_CHECK for screen %i: %s (root=%s)", i, xid(ewmh_wm), xid(root)) if ewmh_wm: try: name = prop_get(ewmh_wm, "_NET_WM_NAME", "utf8", ignore_errors=False, raise_xerrors=False) except: name = None if upgrading and name and name==wm_name: log.info("found previous Xpra instance") else: log.warn("Warning: found an existing window manager on screen %s using window %#x: %s", i, ewmh_wm.xid, name or "unknown") if (wm_so is None or wm_so==0) and (cwm_so is None or cwm_so==0): if FORCE_REPLACE_WM: log.warn("XPRA_FORCE_REPLACE_WM is set, replacing it forcibly") else: log.error("it does not own the selection '%s' or '%s' so we cannot take over and make it exit", wm_prop, cwm_prop) log.error("please stop %s so you can run xpra on this display", name or "the existing window manager") log.warn("if you are certain that the window manager is already gone,") log.warn(" you may set XPRA_FORCE_REPLACE_WM=1 to force xpra to continue, at your own risk") return False return True
def get_settings(self): owner = self.xsettings_owner() log("Fetching current XSettings data, owner=%s", owner) if owner is None: return None try: with xsync: return prop_get(owner, XSETTINGS, XSETTINGS_TYPE) except XError: log("X error while fetching XSettings data; ignored") return None
def get_resource_manager(self): try: import gtk.gdk root = gtk.gdk.get_default_root_window() from xpra.x11.gtk_x11.prop import prop_get value = prop_get(root, "RESOURCE_MANAGER", "latin1", ignore_errors=True) if value is not None: return value.encode("utf-8") except: log.error("failed to get RESOURCE_MANAGER", exc_info=True) return None
def get_x11_window_value(filter_object, window): xid = get_xid(window) #log("get_x11_window_value(%s, %s) xid=%#x", filter_object, window, xid) with xsync: x11type = window_bindings.GetWindowPropertyType(xid, filter_object.property_name) ptype = get_python_type(x11type) #log("%s: %s (%s)", filter_object.property_name, x11type, ptype) assert ptype, "type '%s' is not handled!" % x11type v = prop_get(window, filter_object.property_name, ptype) log("%s=%s", filter_object.property_name, v) return v
def get_x11_window_value(filter_object, window): xid = get_xid(window) #log("get_x11_window_value(%s, %s) xid=%#x", filter_object, window, xid) with xsync: x11type = window_bindings.GetWindowPropertyType( xid, filter_object.property_name) ptype = get_python_type(x11type) #log("%s: %s (%s)", filter_object.property_name, x11type, ptype) assert ptype, "type '%s' is not handled!" % x11type v = prop_get(window, filter_object.property_name, ptype) log("%s=%s", filter_object.property_name, v) return v
def _sync_frame(self, *args): v = self.get_property("frame") framelog("sync_frame: frame(%#x)=%s", self.xid, v) if not v and (not self.is_OR() and not self.is_tray()): root = self.client_window.get_screen().get_root_window() v = prop_get(root, "DEFAULT_NET_FRAME_EXTENTS", ["u32"], ignore_errors=True) if not v: #default for OR, or if we don't have any other value: v = (0, 0, 0, 0) framelog("sync_frame: setting _NET_FRAME_EXTENTS=%s on %#x", v, self.xid) with xswallow: prop_set(self.client_window, "_NET_FRAME_EXTENTS", ["u32"], v)
def get_resource_manager(self): try: from xpra.gtk_common.gtk_util import get_default_root_window from xpra.x11.gtk_x11.prop import prop_get root = get_default_root_window() value = prop_get(root, "RESOURCE_MANAGER", "latin1", ignore_errors=True) if value is not None: return value.encode("utf-8") except (ImportError, UnicodeEncodeError): log.error("failed to get RESOURCE_MANAGER", exc_info=True) return None
def get_window(filter_object, window): gdkwin = window.get_property("client-window") p = gdkwin log("get_window%s gdkwin=%s, recurse=%s", (filter_object, window), gdkwin, filter_object.recurse) while filter_object.recurse and p: gdkwin = p p = None try: prop = "WM_TRANSIENT_FOR" p = prop_get(gdkwin, prop, "window", ignore_errors=True) log("prop_get(%s, %s)=%s", gdkwin, prop, p) except: log("prop_get(%s, %s)", gdkwin, prop, exc_info=True) break return gdkwin
def _handle_root_prop_changed(self, obj, prop): log("root_prop_changed(%s, %s)", obj, prop) if prop=="RESOURCE_MANAGER": if not self.client.xsettings_tuple: log.warn("xsettings tuple format not supported, update ignored") return root = gtk.gdk.get_default_root_window() from xpra.x11.gtk_x11.prop import prop_get value = prop_get(root, "RESOURCE_MANAGER", "latin1", ignore_errors=True) if value is not None: self.client.send("server-settings", {"resource-manager" : value.encode("utf-8")}) elif prop=="_NET_WORKAREA": self.client.screen_size_changed("from %s event" % self._root_props_watcher) else: log.error("unknown property %s", prop)
def get_frame_extents(self, window): #try native platform code first: x, y = window.get_position() w, h = window.get_size() v = get_window_frame_size(x, y, w, h) framelog("get_window_frame_size%s=%s", (x, y, w, h), v) if v: #(OSX does give us these values via Quartz API) return v if not HAS_X11_BINDINGS: #nothing more we can do! return None from xpra.x11.gtk_x11.prop import prop_get gdkwin = window.get_window() assert gdkwin v = prop_get(gdkwin, "_NET_FRAME_EXTENTS", ["u32"], ignore_errors=False) framelog("get_frame_extents(%s)=%s", window.get_title(), v) return v
def get_x11_window_value(prop, window): with xsync: try: xid = get_xwindow(window) x11type = window_bindings.GetWindowPropertyType(xid, prop) except: log("get_x11_window_value(%s, %s)", prop, window, exc_info=True) x11type = None if x11type: ptype = get_python_type(x11type) #log("%s: %s (%s)", filter_object.property_name, x11type, ptype) assert ptype, "type '%s' is not handled!" % x11type v = prop_get(window, prop, ptype) log("prop_get(%s, %s, %s)=%s", window, prop, ptype, v) if v and isinstance(v, (str, unicode)): v = strtobytes(v).replace("\0", "") else: v = None log("%s=%s (type=%s)", prop, v, x11type) return v
def has_gtk_menu_support(root_window): #figure out if we can handle the "global menu" stuff: try: from xpra.dbus.helper import DBusHelper assert DBusHelper except Exception as e: log("has_menu_support() no dbus: %s", e) return False try: from xpra.x11.gtk_x11.prop import prop_get except Exception as e: log("has_menu_support() no X11 bindings: %s", e) return False v = prop_get(root_window, "_NET_SUPPORTED", ["atom"], ignore_errors=True, raise_xerrors=False) if not v: log("has_menu_support() _NET_SUPPORTED is empty!?") return False show_window_menu = "_GTK_SHOW_WINDOW_MENU" in v log("has_menu_support() _GTK_SHOW_WINDOW_MENU in _NET_SUPPORTED: %s", show_window_menu) return show_window_menu
def _handle_root_prop_changed(self, obj, prop): log("root_prop_changed(%s, %s)", obj, prop) if prop=="RESOURCE_MANAGER": if not self.client.xsettings_tuple: log.warn("xsettings tuple format not supported, update ignored") return import gtk.gdk root = gtk.gdk.get_default_root_window() from xpra.x11.gtk_x11.prop import prop_get value = prop_get(root, "RESOURCE_MANAGER", "latin1", ignore_errors=True) if value is not None: self.client.send("server-settings", {"resource-manager" : value.encode("utf-8")}) elif prop=="_NET_WORKAREA": self.client.screen_size_changed("from %s event" % self._root_props_watcher) elif prop=="_NET_CURRENT_DESKTOP": self.client.workspace_changed("from %s event" % self._root_props_watcher) elif prop in ("_NET_DESKTOP_NAMES", "_NET_NUMBER_OF_DESKTOPS"): self.client.desktops_changed("from %s event" % self._root_props_watcher) else: log.error("unknown property %s", prop)
def _get_settings_blob(self): owner = self._owner() if owner is None: return None return prop_get(owner, XSETTINGS, XSETTINGS_TYPE)
def root_get(self, *args): return prop_get(self._root, *args)
def process_client_message_event(self, event): # FIXME # Need to listen for: # _NET_CURRENT_DESKTOP # _NET_WM_PING responses # and maybe: # _NET_RESTACK_WINDOW # _NET_WM_STATE (more fully) if event.message_type=="_NET_WM_STATE": def update_wm_state(prop): current = self.get_property(prop) mode = event.data[0] if mode==_NET_WM_STATE_ADD: v = True elif mode==_NET_WM_STATE_REMOVE: v = False elif mode==_NET_WM_STATE_TOGGLE: v = not bool(current) else: log.warn("invalid mode for _NET_WM_STATE: %s", mode) return log("process_client_message_event(%s) window %s=%s after %s (current state=%s)", event, prop, v, STATE_STRING.get(mode, mode), current) if v!=current: self.update_wm_state(prop, v) atom1 = get_pyatom(event.window, event.data[1]) log("_NET_WM_STATE: %s", atom1) if atom1=="_NET_WM_STATE_FULLSCREEN": update_wm_state("fullscreen") elif atom1=="_NET_WM_STATE_ABOVE": update_wm_state("above") elif atom1=="_NET_WM_STATE_BELOW": update_wm_state("below") elif atom1=="_NET_WM_STATE_SHADED": update_wm_state("shaded") elif atom1=="_NET_WM_STATE_STICKY": update_wm_state("sticky") elif atom1=="_NET_WM_STATE_SKIP_TASKBAR": update_wm_state("skip-taskbar") elif atom1=="_NET_WM_STATE_SKIP_PAGER": update_wm_state("skip-pager") get_pyatom(event.window, event.data[2]) elif atom1 in ("_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ"): atom2 = get_pyatom(event.window, event.data[2]) #we only have one state for both, so we require both to be set: if atom1!=atom2 and atom2 in ("_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ"): update_wm_state("maximized") elif atom1=="_NET_WM_STATE_HIDDEN": log("ignoring 'HIDDEN' _NET_WM_STATE: %s", event) #we don't honour those because they make little sense, see: #https://mail.gnome.org/archives/wm-spec-list/2005-May/msg00004.html pass elif atom1=="_NET_WM_STATE_MODAL": update_wm_state("modal") else: log.info("process_client_message_event(%s) unhandled atom=%s", event, atom1) return True elif event.message_type=="WM_CHANGE_STATE": log("WM_CHANGE_STATE: %s", event.data[0]) if event.data[0]==IconicState and event.serial>self.last_unmap_serial and not self.is_OR() and not self.is_tray(): self._updateprop("iconic", True) return True elif event.message_type=="_NET_WM_MOVERESIZE": log("_NET_WM_MOVERESIZE: %s", event) self.emit("initiate-moveresize", event) return True elif event.message_type=="_NET_ACTIVE_WINDOW" and event.data[0] in (0, 1): log("_NET_ACTIVE_WINDOW: %s", event) self.set_active() self.emit("raised", event) return True elif event.message_type=="_NET_WM_DESKTOP": workspace = int(event.data[0]) #query the workspace count on the root window #since we cannot access Wm from here.. root = self.client_window.get_screen().get_root_window() ndesktops = prop_get(root, "_NET_NUMBER_OF_DESKTOPS", "u32", ignore_errors=True) workspacelog("received _NET_WM_DESKTOP: workspace=%s, number of desktops=%s", workspacestr(workspace), ndesktops) if ndesktops>0 and (workspace in (WORKSPACE_UNSET, WORKSPACE_ALL) or (workspace>=0 and workspace<ndesktops)): self.move_to_workspace(workspace) else: workspacelog.warn("invalid _NET_WM_DESKTOP request: workspace=%s, number of desktops=%s", workspacestr(workspace), ndesktops) return True elif event.message_type=="_NET_WM_FULLSCREEN_MONITORS": log("_NET_WM_FULLSCREEN_MONITORS: %s", event) #TODO: we should validate the indexes instead of copying them blindly! #TODO: keep track of source indication so we can forward that to the client m1, m2, m3, m4 = event.data[0], event.data[1], event.data[2], event.data[3] N = 16 #FIXME: arbitrary limit if m1<0 or m1>=N or m2<0 or m2>=N or m3<0 or m3>=N or m4<0 or m4>=N: log.warn("invalid list of _NET_WM_FULLSCREEN_MONITORS - ignored") return monitors = [m1, m2, m3, m4] log("_NET_WM_FULLSCREEN_MONITORS: monitors=%s", monitors) prop_set(self.client_window, "_NET_WM_FULLSCREEN_MONITORS", ["u32"], monitors) return True #TODO: maybe we should process _NET_MOVERESIZE_WINDOW here? # it may make sense to apply it to the client_window # whereas the code in WindowModel assumes there is a corral window #not handled: return CoreX11WindowModel.process_client_message_event(self, event)
def pget(key, etype): return prop_get(w, key, etype, ignore_errors=True, raise_xerrors=True)
def _notify(self, prop): v = prop_get(gtk.gdk.get_default_root_window(), prop, "latin1", ignore_errors=True) self.emit("root-prop-changed", prop, str(v))
def window_info(window): from xpra.x11.gtk_x11.prop import prop_get net_wm_name = prop_get(window, "_NET_WM_NAME", "utf8", True) return "%s %s (%s / %s)" % (net_wm_name, window, window.get_geometry(), window.is_visible())
def _get_int(prop_name): import gtk from xpra.x11.gtk_x11.prop import prop_get return prop_get(gtk.gdk.get_default_root_window(), prop_name, "u32")
def xget_u32_property(self, target, name): v = prop_get(target, name, "u32", ignore_errors=True) log("%s.xget_u32_property(%s, %s)=%s", self, target, name, v) if type(v)==int: return v return None
from xpra.x11.bindings.window_bindings import constants, X11WindowBindings, SHAPE_KIND #@UnresolvedImport from xpra.x11.bindings.core_bindings import X11CoreBindings from xpra.gtk_common.error import xsync from xpra.x11.gtk_x11.send_wm import send_wm_workspace X11Window = X11WindowBindings() X11Core = X11CoreBindings() HAS_X11_BINDINGS = True SubstructureNotifyMask = constants["SubstructureNotifyMask"] SubstructureRedirectMask = constants["SubstructureRedirectMask"] CurrentTime = constants["CurrentTime"] try: #TODO: in theory this is not a proper check, meh - that will do root = get_default_root_window() supported = prop_get(root, "_NET_SUPPORTED", ["atom"], ignore_errors=True) CAN_SET_WORKSPACE = bool(supported) and "_NET_WM_DESKTOP" in supported except Exception as e: log.info("failed to setup workspace hooks: %s", e, exc_info=True) except ImportError: pass UNDECORATED_TRANSIENT_IS_OR = int(os.environ.get("XPRA_UNDECORATED_TRANSIENT_IS_OR", "1")) #window types we map to POPUP rather than TOPLEVEL POPUP_TYPE_HINTS = set(( #"DIALOG", #"MENU", #"TOOLBAR", #"SPLASHSCREEN",
def window_name(window): from xpra.x11.gtk_x11.prop import prop_get return prop_get(window, "_NET_WM_NAME", "utf8", True) or "unknown"
def get_xvfb_pid(): import gtk from xpra.x11.gtk_x11.prop import prop_get return prop_get(gtk.gdk.get_default_root_window(), "_XPRA_SERVER_PID", "u32")