Пример #1
0
 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)
Пример #2
0
 def setup(self):
     xwin = self._window.xid
     if not self._already_composited:
         X11Window.XCompositeRedirectWindow(xwin)
     self._border_width = X11Window.geometry_with_border(xwin)[-1]
     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)
Пример #3
0
 def setup(self):
     self.invalidate_pixmap()
     xid = self.client_window.xid
     geom = X11Window.geometry_with_border(xid)
     if geom is None:
         raise Unmanageable("window %#x disappeared already" % xid)
     self._border_width = geom[-1]
     self.create_damage_handle()
     add_event_receiver(self.client_window, self)
Пример #4
0
 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
Пример #5
0
 def x11_init(self):
     X11ServerBase.x11_init(self)
     assert init_x11_filter() is True
     display = gtk.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)
     X11Keyboard.selectBellNotification(True)
Пример #6
0
 def call_setup(self):
     """
         Call this method to prepare the window:
         * makes sure it still exists
           (by querying its geometry which may raise an XError)
         * setup composite redirection
         * calls setup
         The difficulty comes from X11 errors and synchronization:
         we want to catch errors and undo what we've done.
         The mix of GTK and pure-X11 calls is not helping.
     """
     try:
         with xsync:
             geom = X11Window.geometry_with_border(self.xid)
             if geom is None:
                 raise Unmanageable("window %#x disappeared already" % self.xid)
             self._internal_set_property("geometry", geom[:4])
             self._read_initial_X11_properties()
     except XError as e:
         raise Unmanageable(e)
     add_event_receiver(self.client_window, self)
     # Keith Packard says that composite state is undefined following a
     # reparent, so I'm not sure doing this here in the superclass,
     # before we reparent, actually works... let's wait and see.
     try:
         self._composite = CompositeHelper(self.client_window)
         with xsync:
             self._composite.setup()
             if X11Window.displayHasXShape():
                 X11Window.XShapeSelectInput(self.xid)
     except Exception as e:
         remove_event_receiver(self.client_window, self)
         log("%s %#x does not support compositing: %s", self._MODELTYPE, self.xid, e)
         with xswallow:
             self._composite.destroy()
         self._composite = None
         if isinstance(e, Unmanageable):
             raise
         raise Unmanageable(e)
     #compositing is now enabled,
     #from now on we must call setup_failed to clean things up
     self._managed = True
     try:
         with xsync:
             self.setup()
     except XError as e:
         try:
             with xsync:
                 self.setup_failed(e)
         except Exception as ex:
             log.error("error in cleanup handler: %s", ex)
         raise Unmanageable(e)
     self._setup_done = True
Пример #7
0
    def setup(self):
        super(WindowModel, self).setup()

        x, y, w, h, _ = self.client_window.get_geometry()
        # We enable PROPERTY_CHANGE_MASK so that we can call
        # x11_get_server_time on this window.
        self.corral_window = gtk.gdk.Window(self.parking_window,
                                            x = x, y = y, width =w, height= h,
                                            window_type=gtk.gdk.WINDOW_CHILD,
                                            wclass=gtk.gdk.INPUT_OUTPUT,
                                            event_mask=gtk.gdk.PROPERTY_CHANGE_MASK,
                                            title = "CorralWindow-%#x" % self.xid)
        log("setup() corral_window=%#x", self.corral_window.xid)
        prop_set(self.corral_window, "_NET_WM_NAME", "utf8", u"Xpra-CorralWindow-%#x" % self.xid)
        X11Window.substructureRedirect(self.corral_window.xid)
        add_event_receiver(self.corral_window, self)

        # The child might already be mapped, in case we inherited it from
        # a previous window manager.  If so, we unmap it now, and save the
        # serial number of the request -- this way, when we get an
        # UnmapNotify later, we'll know that it's just from us unmapping
        # the window, not from the client withdrawing the window.
        if X11Window.is_mapped(self.xid):
            log("hiding inherited window")
            self.last_unmap_serial = X11Window.Unmap(self.xid)

        log("setup() adding to save set")
        X11Window.XAddToSaveSet(self.xid)
        self.in_save_set = True

        log("setup() reparenting")
        X11Window.Reparent(self.xid, self.corral_window.xid, 0, 0)
        self.client_reparented = True

        log("setup() geometry")
        w, h = X11Window.geometry_with_border(self.xid)[2:4]
        hints = self.get_property("size-hints")
        log("setup() hints=%s size=%ix%i", hints, w, h)
        nw, nh = calc_constrained_size(w, h, hints)
        if nw>=MAX_WINDOW_SIZE or nh>=MAX_WINDOW_SIZE:
            #we can't handle windows that big!
            raise Unmanageable("window constrained size is too large: %sx%s (from client geometry: %s,%s with size hints=%s)" % (nw, nh, w, h, hints))
        self._updateprop("geometry", (x, y, nw, nh))
        log("setup() resizing windows to %sx%s", nw, nh)
        self.corral_window.resize(nw, nh)
        self.client_window.resize(nw, nh)
        self.client_window.show_unraised()
        #this is here to trigger X11 errors if any are pending
        #or if the window is deleted already:
        self.client_window.get_geometry()
Пример #8
0
 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)
Пример #9
0
 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)
     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")
             X11Window.sendClientMessage(root.xid, root.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
Пример #10
0
    def __init__(self, replace_other_wm, wm_name, display=None):
        gobject.GObject.__init__(self)

        if display is None:
            display = gtk.gdk.display_manager_get().get_default_display()
        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 = gtk.gdk.get_default_root_window().get_size()
        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])

        # Load up our full-screen widget
        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)
        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 window %#x", w.xid)
                self._manage_client(w)

        # Also watch for focus change events on the root window
        X11Window.selectFocusChange(self._root.xid)
        X11Keyboard.selectBellNotification(True)
Пример #11
0
    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)

        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(self.clipboard, old_owner)
                    window.set_events(window.get_events() | gtk.gdk.STRUCTURE_MASK)
                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")
Пример #12
0
 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()
Пример #13
0
 def _add_watch(self):
     owner = self.xsettings_owner()
     if owner is not None:
         add_event_receiver(owner, self)
Пример #14
0
 def _add_watch(self):
     owner = self.xsettings_owner()
     if owner is not None:
         add_event_receiver(owner, self)