def x11_init(self): X11ServerBase.x11_init(self) init_x11_filter() self._has_focus = 0 # Do this before creating the Wm object, to avoid clobbering its # selecting SubstructureRedirect. root = gtk.gdk.get_default_root_window() root.set_events(root.get_events() | gtk.gdk.SUBSTRUCTURE_MASK) root.property_change(gtk.gdk.atom_intern("XPRA_SERVER", False), gtk.gdk.atom_intern("STRING", False), 8, gtk.gdk.PROP_MODE_REPLACE, xpra.__version__) add_event_receiver(root, self) ### Create the WM object self._wm = Wm(self.clobber) self._wm.connect("new-window", self._new_window_signaled) self._wm.connect("bell", self._bell_signaled) self._wm.connect("quit", lambda _: self.quit(True)) self.default_cursor_data = None self.last_cursor_serial = None self.send_cursor_pending = False self.cursor_data = None self.cursor_sizes = None def get_default_cursor(): self.default_cursor_data = X11Keyboard.get_cursor_image() log("get_default_cursor=%s", self.default_cursor_data) trap.swallow_synced(get_default_cursor) self._wm.enableCursors(True)
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 __init__(self, props, root_window): gobject.GObject.__init__(self) self._props = props self._root = root_window self._saved_event_mask = self._root.get_events() self._root.set_events(self._saved_event_mask | PROPERTY_CHANGE_MASK) add_event_receiver(self._root, self)
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)) debug("dock_tray(%s) window=%s, geometry=%s, visual.depth=%s", hex(xid), window, window.get_geometry(), 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="TrayWindow", 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 __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) self._add_watch()
def __init__(self, props, root_window): super().__init__() self._props = props 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)
def __init__(self, props): gobject.GObject.__init__(self) self._props = props self._root = gtk.gdk.get_default_root_window() self._saved_event_mask = self._root.get_events() self._root.set_events(self._saved_event_mask | gtk.gdk.PROPERTY_CHANGE_MASK) self._own_x11_filter = init_x11_filter() add_event_receiver(self._root, self)
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 __init__(self, screen_number=0): gobject.GObject.__init__(self) self._selection = "_XSETTINGS_S%s" % screen_number self._clipboard = gtk.Clipboard(gtk.gdk.display_get_default(), self._selection) self._current = None self._root = self._clipboard.get_display().get_default_screen().get_root_window() add_event_receiver(self._root, self) self._add_watch()
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 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 setup(self): xwin = get_xwindow(self._window) if not self._already_composited: X11Window.XCompositeRedirectWindow(xwin) _, _, _, _, self._border_width = X11Window.geometry_with_border(xwin) self.invalidate_pixmap() self._damage_handle = X11Window.XDamageCreate(xwin) log("CompositeHelper.setup() damage handle(%s)=%s", hex(xwin), hex(self._damage_handle)) add_event_receiver(self._window, self)
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): xwin = self._window.xid if not self._already_composited: X11Window.XCompositeRedirectWindow(xwin) _, _, _, _, self._border_width = X11Window.geometry_with_border(xwin) self.invalidate_pixmap() self._damage_handle = X11Window.XDamageCreate(xwin) log("CompositeHelper.setup() damage handle(%#x)=%#x", xwin, self._damage_handle) add_event_receiver(self._window, self)
def setup_tray_window(self): display = display_get_default() root = get_default_root_window() screen = root.get_screen() owner = X11Window.XGetSelectionOwner(SELECTION) log("setup tray: current selection owner=%#x", owner) if owner != XNone: raise Exception("%s already owned by %s" % (SELECTION, owner)) kwargs = {} visual = screen.get_system_visual() if TRANSPARENCY: visual = screen.get_rgba_visual() if visual is None: log.warn("setup tray: using rgb visual fallback") visual = screen.get_rgb_visual() #only GTK2 uses colormap: if not is_gtk3(): if TRANSPARENCY: colormap = screen.get_rgba_colormap() else: colormap = screen.get_rgb_colormap() kwargs["colormap"] = colormap assert visual is not None, "failed to obtain visual" self.tray_window = GDKWindow(root, width=1, height=1, title="Xpra-SystemTray", visual=visual, **kwargs) xtray = get_xwindow(self.tray_window) set_tray_visual(self.tray_window, visual) set_tray_orientation(self.tray_window, TRAY_ORIENTATION_HORZ) log("setup tray: tray window %#x", xtray) if is_gtk3(): display.request_selection_notification( gdk.Atom.intern(SELECTION, False)) else: display.request_selection_notification(SELECTION) try: with xsync: setsel = X11Window.XSetSelectionOwner(xtray, SELECTION) log("setup tray: set selection owner returned %s, owner=%#x", setsel, X11Window.XGetSelectionOwner(SELECTION)) event_mask = StructureNotifyMask log("setup tray: sending client message") xid = get_xwindow(root) X11Window.sendClientMessage(xid, xid, False, event_mask, "MANAGER", 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) log("setup tray: done") except Exception: log("setup_tray failure", exc_info=True) self.cleanup() raise
def init_window(self): root = get_default_root_window() self.window = GDKX11Window(root, width=1, height=1, title="Xpra-Clipboard", wclass=Gdk.WindowWindowClass.INPUT_ONLY) self.window.set_events(Gdk.EventMask.PROPERTY_CHANGE_MASK | self.window.get_events()) xid = self.window.get_xid() with xsync: X11Window.selectSelectionInput(xid) add_event_receiver(self.window, self)
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 x11_init(self): X11ServerBase.x11_init(self) assert init_x11_filter() is True display = display_get_default() screens = display.get_n_screens() for n in range(screens): screen = display.get_screen(n) root = screen.get_root_window() add_event_receiver(root, self) add_catchall_receiver("xpra-motion-event", self) add_catchall_receiver("xpra-xkb-event", self) X11Keyboard.selectBellNotification(True)
def init_window(self): root = get_default_root_window() self.window = GDKWindow(root, width=1, height=1, title="Xpra-Clipboard", wclass=CLASS_INPUT_ONLY) self.window.set_events(PROPERTY_CHANGE_MASK | self.window.get_events()) xid = get_xwindow(self.window) with xsync: X11Window.selectSelectionInput(xid) add_event_receiver(self.window, self)
def x11_init(self): X11ServerBase.x11_init(self) display = Gdk.Display.get_default() screens = display.get_n_screens() for n in range(screens): screen = display.get_screen(n) root = screen.get_root_window() add_event_receiver(root, self) add_catchall_receiver("xpra-motion-event", self) add_catchall_receiver("xpra-xkb-event", self) with xlog: X11Keyboard.selectBellNotification(True) if MODIFY_GSETTINGS: self.modify_gsettings()
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 x11_init(self): X11ServerBase.x11_init(self) assert init_x11_filter() is True self._has_grab = 0 self._has_focus = 0 # Do this before creating the Wm object, to avoid clobbering its # selecting SubstructureRedirect. root = gtk.gdk.get_default_root_window() root.set_events(root.get_events() | gtk.gdk.SUBSTRUCTURE_MASK) root.property_change(gtk.gdk.atom_intern("XPRA_SERVER", False), gtk.gdk.atom_intern("STRING", False), 8, gtk.gdk.PROP_MODE_REPLACE, xpra.__version__) add_event_receiver(root, self) ### Create the WM object self._wm = Wm(self.clobber, self.wm_name) self._wm.connect("new-window", self._new_window_signaled) self._wm.connect("bell", self._bell_signaled) self._wm.connect("quit", lambda _: self.clean_quit(True)) self._wm.connect("show-desktop", self._show_desktop) #save default xsettings: self.default_xsettings = XSettingsHelper().get_settings() settingslog("default_xsettings=%s", self.default_xsettings) self._settings = {} self._xsettings_manager = None #for handling resize synchronization between client and server (this is not xsync!): self.last_client_configure_event = 0 self.snc_timer = 0 #cursor: self.default_cursor_data = None self.last_cursor_serial = None self.last_cursor_data = None self.send_cursor_pending = False def get_default_cursor(): self.default_cursor_data = X11Keyboard.get_cursor_image() cursorlog("get_default_cursor=%s", self.default_cursor_data) trap.swallow_synced(get_default_cursor) self._wm.enableCursors(True)
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: win = get_parent(self._window) while win is not None 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(get_xwindow(win), constants["StructureNotifyMask"]) add_event_receiver(win, self, max_receivers=-1) self._listening.append(win) win = get_parent(win) debug("grab: listening for: %s", self._listening)
def setup_tray_window(self): display = gtk.gdk.display_get_default() root = gtk.gdk.get_default_root_window() screen = root.get_screen() if TRANSPARENCY: colormap, visual = screen.get_rgba_colormap( ), screen.get_rgba_visual() if colormap is None or visual is None: log.warn("setup tray: using rgb visual fallback") colormap, visual = screen.get_rgb_colormap( ), screen.get_rgb_visual() assert colormap is not None and visual is not None, "failed to obtain visual or colormap" owner = X11Window.XGetSelectionOwner(SELECTION) log("setup tray: current selection owner=%#x", owner) if owner != XNone: raise Exception("%s already owned by %s" % (SELECTION, owner)) self.tray_window = gtk.gdk.Window(root, width=1, height=1, window_type=gtk.gdk.WINDOW_TOPLEVEL, event_mask=0, wclass=gtk.gdk.INPUT_OUTPUT, title="Xpra-SystemTray", visual=visual, colormap=colormap) xtray = self.tray_window.xid set_tray_visual(self.tray_window, visual) set_tray_orientation(self.tray_window, TRAY_ORIENTATION_HORZ) log("setup tray: tray window %#x", xtray) display.request_selection_notification(SELECTION) setsel = X11Window.XSetSelectionOwner(xtray, SELECTION) log("setup tray: set selection owner returned %s, owner=%#x", setsel, X11Window.XGetSelectionOwner(SELECTION)) event_mask = StructureNotifyMask log("setup tray: sending client message") X11Window.sendClientMessage(root.xid, root.xid, False, event_mask, "MANAGER", CurrentTime, SELECTION, xtray, 0, 0) owner = X11Window.XGetSelectionOwner(SELECTION) #FIXME: cleanup if we fail! assert owner == xtray, "we failed to get ownership of the tray selection" add_event_receiver(self.tray_window, self) log("setup tray: done")
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 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)) debug("dock_tray(%s) window=%s, geometry=%s, visual.depth=%s", hex(xid), window, window.get_geometry(), 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="TrayWindow", 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 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 setup_tray_window(self): display = gtk.gdk.display_get_default() root = gtk.gdk.get_default_root_window() screen = root.get_screen() if TRANSPARENCY: colormap, visual = screen.get_rgba_colormap(), screen.get_rgba_visual() if colormap is None or visual is None: log.warn("setup tray: using rgb visual fallback") colormap, visual = screen.get_rgb_colormap(), screen.get_rgb_visual() assert colormap is not None and visual is not None, "failed to obtain visual or colormap" owner = X11Window.XGetSelectionOwner(SELECTION) log("setup tray: current selection owner=%#x", owner) if owner!=XNone: raise Exception("%s already owned by %s" % (SELECTION, owner)) self.tray_window = gtk.gdk.Window(root, width=1, height=1, window_type=gtk.gdk.WINDOW_TOPLEVEL, event_mask = 0, wclass=gtk.gdk.INPUT_OUTPUT, title="Xpra-SystemTray", visual=visual, colormap=colormap) xtray = self.tray_window.xid set_tray_visual(self.tray_window, visual) set_tray_orientation(self.tray_window, TRAY_ORIENTATION_HORZ) log("setup tray: tray window %#x", xtray) display.request_selection_notification(SELECTION) setsel = X11Window.XSetSelectionOwner(xtray, SELECTION) log("setup tray: set selection owner returned %s, owner=%#x", setsel, X11Window.XGetSelectionOwner(SELECTION)) event_mask = StructureNotifyMask log("setup tray: sending client message") X11Window.sendClientMessage(root.xid, root.xid, False, event_mask, "MANAGER", CurrentTime, SELECTION, xtray, 0, 0) owner = X11Window.XGetSelectionOwner(SELECTION) #FIXME: cleanup if we fail! assert owner==xtray, "we failed to get ownership of the tray selection" add_event_receiver(self.tray_window, self) log("setup tray: done")
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: win = get_parent(self._window) while win is not None 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(get_xwindow(win), constants["StructureNotifyMask"]) add_event_receiver(win, self, max_receivers=-1) listening.append(win) win = get_parent(win) handle = XImage.get_xcomposite_pixmap(get_xwindow(self._window)) except Exception, e: try: self._cleanup_listening(listening) except: pass raise
def __init__(self, replace_other_wm, wm_name, display=None): gobject.GObject.__init__(self) if display is None: display = display_get_default() self._display = display self._root = self._display.get_default_screen().get_root_window() self._wm_name = wm_name self._ewmh_window = None self._windows = {} # EWMH says we have to know the order of our windows oldest to # youngest... self._windows_in_order = [] # Become the Official Window Manager of this year's display: self._wm_selection = ManagerSelection(self._display, "WM_S0") self._cm_wm_selection = ManagerSelection(self._display, "_NET_WM_CM_S0") self._wm_selection.connect("selection-lost", self._lost_wm_selection) self._cm_wm_selection.connect("selection-lost", self._lost_wm_selection) # May throw AlreadyOwned: if replace_other_wm: mode = self._wm_selection.FORCE else: mode = self._wm_selection.IF_UNOWNED self._wm_selection.acquire(mode) self._cm_wm_selection.acquire(mode) # Set up the necessary EWMH properties on the root window. self._setup_ewmh_window() # Start with just one desktop: self.set_desktop_list((u"Main", )) self.set_current_desktop(0) # Start with the full display as workarea: root_w, root_h = get_default_root_window().get_geometry()[2:4] self.root_set("_NET_SUPPORTED", ["atom"], NET_SUPPORTED) self.set_workarea(0, 0, root_w, root_h) self.set_desktop_geometry(root_w, root_h) self.root_set("_NET_DESKTOP_VIEWPORT", ["u32"], [0, 0]) self.size_constraints = DEFAULT_SIZE_CONSTRAINTS # Load up our full-screen widget self._world_window = None if not is_gtk3(): self._world_window = WorldWindow( self._display.get_default_screen()) self.notify("toplevel") self._world_window.show_all() # Okay, ready to select for SubstructureRedirect and then load in all # the existing clients. add_event_receiver(self._root, 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 = get_xwindow(self._root) X11Window.substructureRedirect(rxid) for w in get_children(self._root): # 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 = get_xwindow(w) if (w.get_window_type() == GDKWINDOW_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) # Also watch for focus change events on the root window X11Window.selectFocusChange(rxid) X11Keyboard.selectBellNotification(True)
def acquire(self, when): old_owner = self._owner() if when is self.IF_UNOWNED and old_owner != XNone: raise AlreadyOwned self.clipboard.set_with_data([("VERSION", 0, 0)], self._get, self._clear, None) # Having acquired the selection, we have to announce our existence # (ICCCM 2.8, still). The details here probably don't matter too # much; I've never heard of an app that cares about these messages, # and metacity actually gets the format wrong in several ways (no # MANAGER or owner_window atoms). But might as well get it as right # as possible. # To announce our existence, we need: # -- the timestamp we arrived at # -- the manager selection atom # -- the window that registered the selection # Of course, because Gtk is doing so much magic for us, we have to do # some weird tricks to get at these. # Ask ourselves when we acquired the selection: ts_data = self.clipboard.wait_for_contents("TIMESTAMP").data #data is a timestamp, X11 datatype is Time which is CARD32, #(which is 64 bits on 64-bit systems!) Lsize = calcsize("@L") if len(ts_data)==Lsize: ts_num = unpack("@L", ts_data[:Lsize])[0] else: ts_num = 0 #CurrentTime log.warn("invalid data for 'TIMESTAMP': %s", ([hex(ord(x)) for x in ts_data])) # Calculate the X atom for this selection: selection_xatom = get_xatom(self.atom) # Ask X what window we used: self._xwindow = X11Window.XGetSelectionOwner(self.atom) root = self.clipboard.get_display().get_default_screen().get_root_window() X11Window.sendClientMessage(root.xid, root.xid, False, StructureNotifyMask, "MANAGER", ts_num, selection_xatom, self._xwindow, 0, 0) if old_owner != XNone and when is self.FORCE: # Block in a recursive mainloop until the previous owner has # cleared out. def getwin(): window = get_pywindow(self.clipboard, old_owner) window.set_events(window.get_events() | gtk.gdk.STRUCTURE_MASK) return window try: window = trap.call_synced(getwin) log("got window") except XError: log("Previous owner is already gone, not blocking") else: log("Waiting for previous owner to exit...") add_event_receiver(window, self) gtk.main() log("...they did.") window = get_pywindow(self.clipboard, self._xwindow) window.set_title("Xpra-ManagerSelection")
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) self._add_watch()
def _add_watch(self): owner = self.xsettings_owner() if owner is not None: add_event_receiver(owner, self)
def __init__(self, replace_other_wm, display=None): gobject.GObject.__init__(self) if display is None: display = gtk.gdk.display_manager_get().get_default_display() self._display = display self._alt_display = gtk.gdk.Display(self._display.get_name()) self._root = self._display.get_default_screen().get_root_window() self._ewmh_window = None self._windows = {} # EWMH says we have to know the order of our windows oldest to # youngest... self._windows_in_order = [] # Become the Official Window Manager of this year's display: self._wm_selection = xpra.x11.gtk_x11.selection.ManagerSelection(self._display, "WM_S0") self._cm_wm_selection = xpra.x11.gtk_x11.selection.ManagerSelection(self._display, "_NET_WM_CM_S0") self._wm_selection.connect("selection-lost", self._lost_wm_selection) self._cm_wm_selection.connect("selection-lost", self._lost_wm_selection) # May throw AlreadyOwned: if replace_other_wm: mode = self._wm_selection.FORCE else: mode = self._wm_selection.IF_UNOWNED self._wm_selection.acquire(mode) self._cm_wm_selection.acquire(mode) # Set up the necessary EWMH properties on the root window. self._setup_ewmh_window() # Start with just one desktop: self.do_desktop_list_changed([u"Main"]) self.set_current_desktop(0) # Start with the full display as workarea: root_w, root_h = gtk.gdk.get_default_root_window().get_size() self.root_set("_NET_SUPPORTED", ["atom"], self._NET_SUPPORTED) self.set_workarea(0, 0, root_w, root_h) self.set_desktop_geometry(root_w, root_h) self.root_set("_NET_DESKTOP_VIEWPORT", ["u32"], [0, 0]) # Load up our full-screen widget self._world_window = WorldWindow() self._world_window.set_screen(self._display.get_default_screen()) self.notify("toplevel") self._world_window.show_all() # Okay, ready to select for SubstructureRedirect and then load in all # the existing clients. add_event_receiver(self._root, self) X11Window.substructureRedirect(self._root.xid) for w in get_children(self._root): # 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. if (w.get_window_type() == gtk.gdk.WINDOW_FOREIGN and not X11Window.is_override_redirect(w.xid) and X11Window.is_mapped(w.xid)): log("Wm managing pre-existing child") self._manage_client(w) # Also watch for focus change events on the root window X11Window.selectFocusChange(self._root.xid) X11Keyboard.selectBellNotification(True)
def __init__(self, props): gobject.GObject.__init__(self) self._props = props self._root = gtk.gdk.get_default_root_window() add_event_receiver(self._root, self)
def acquire(self, when): old_owner = self._owner() if when is self.IF_UNOWNED and old_owner != XNone: raise AlreadyOwned #we can only set strings with GTK3, # we should try to be compliant with ICCCM version 2.0 (see section 4.3) # and use this format instead: # outdata.set("INTEGER", 32, pack("@ii", 2, 0)) thestring = "VERSION" self.clipboard.set_text(thestring, len(thestring)) # Having acquired the selection, we have to announce our existence # (ICCCM 2.8, still). The details here probably don't matter too # much; I've never heard of an app that cares about these messages, # and metacity actually gets the format wrong in several ways (no # MANAGER or owner_window atoms). But might as well get it as right # as possible. # To announce our existence, we need: # -- the timestamp we arrived at # -- the manager selection atom # -- the window that registered the selection # Of course, because Gtk is doing so much magic for us, we have to do # some weird tricks to get at these. # Ask ourselves when we acquired the selection: timestamp_atom = Gdk.Atom.intern("TIMESTAMP", False) contents = self.clipboard.wait_for_contents(timestamp_atom) ts_data = contents.get_data() log("ManagerSelection.acquire(%s) %s.wait_for_contents(%s)=%s", when, self.clipboard, timestamp_atom, ts_data) #data is a timestamp, X11 datatype is Time which is CARD32, #(which is 64 bits on 64-bit systems!) Lsize = calcsize("@L") if len(ts_data)==Lsize: ts_num = unpack("@L", ts_data[:Lsize])[0] else: ts_num = 0 #CurrentTime log.warn("invalid data for 'TIMESTAMP': %s", ([hex(ord(x)) for x in ts_data])) log("selection timestamp(%s)=%s", ts_data, ts_num) # Calculate the X atom for this selection: selection_xatom = get_xatom(self.atom) # Ask X what window we used: self._xwindow = X11WindowBindings().XGetSelectionOwner(self.atom) root = self.clipboard.get_display().get_default_screen().get_root_window() xid = root.get_xid() X11WindowBindings().sendClientMessage(xid, xid, False, StructureNotifyMask, "MANAGER", ts_num, selection_xatom, self._xwindow) if old_owner != XNone and when is self.FORCE: # Block in a recursive mainloop until the previous owner has # cleared out. try: with xsync: window = get_pywindow(old_owner) window.set_events(window.get_events() | Gdk.EventMask.STRUCTURE_MASK) log("got window") except XError: log("Previous owner is already gone? not blocking", exc_info=True) else: log("Waiting for previous owner to exit...") add_event_receiver(window, self) self.exit_timer = GLib.timeout_add(SELECTION_EXIT_TIMEOUT*1000, self.exit_timeout) Gtk.main() if self.exit_timer: GLib.source_remove(self.exit_timer) self.exit_timer = None log("...they did.") window = get_pywindow(self._xwindow) window.set_title("Xpra-ManagerSelection-%s" % self.atom) self.clipboard.connect("owner-change", self._owner_change)
def __init__(self, replace_other_wm, display=None): gobject.GObject.__init__(self) if display is None: display = gtk.gdk.display_manager_get().get_default_display() self._display = display self._alt_display = gtk.gdk.Display(self._display.get_name()) self._root = self._display.get_default_screen().get_root_window() self._ewmh_window = None self._windows = {} # EWMH says we have to know the order of our windows oldest to # youngest... self._windows_in_order = [] # Become the Official Window Manager of this year's display: self._wm_selection = xpra.x11.gtk_x11.selection.ManagerSelection( self._display, "WM_S0") self._cm_wm_selection = xpra.x11.gtk_x11.selection.ManagerSelection( self._display, "_NET_WM_CM_S0") self._wm_selection.connect("selection-lost", self._lost_wm_selection) self._cm_wm_selection.connect("selection-lost", self._lost_wm_selection) # May throw AlreadyOwned: if replace_other_wm: mode = self._wm_selection.FORCE else: mode = self._wm_selection.IF_UNOWNED self._wm_selection.acquire(mode) self._cm_wm_selection.acquire(mode) # Set up the necessary EWMH properties on the root window. self._setup_ewmh_window() # Start with just one desktop: self.do_desktop_list_changed([u"Main"]) self.set_current_desktop(0) # Start with the full display as workarea: root_w, root_h = gtk.gdk.get_default_root_window().get_size() self.root_set("_NET_SUPPORTED", ["atom"], self._NET_SUPPORTED) self.set_workarea(0, 0, root_w, root_h) self.root_set("_NET_DESKTOP_VIEWPORT", ["u32"], [0, 0]) # Load up our full-screen widget self._world_window = WorldWindow() self._world_window.set_screen(self._display.get_default_screen()) self.notify("toplevel") self._world_window.show_all() # Okay, ready to select for SubstructureRedirect and then load in all # the existing clients. add_event_receiver(self._root, self) X11Window.substructureRedirect(get_xwindow(self._root)) for w in get_children(self._root): # 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. if (w.get_window_type() == gtk.gdk.WINDOW_FOREIGN and not X11Window.is_override_redirect(get_xwindow(w)) and X11Window.is_mapped(get_xwindow(w))): log("Wm managing pre-existing child") self._manage_client(w) # Also watch for focus change events on the root window X11Window.selectFocusChange(get_xwindow(self._root)) X11Keyboard.selectBellNotification(True)