xpra icon
Bug tracker and wiki

Ticket #988: paint-root-overlay-v2.patch

File paint-root-overlay-v2.patch, 7.2 KB (added by Antoine Martin, 5 years ago)

much better implementation: with timer, command line option, etc..

  • xpra/x11/server.py

     
    1313import time
    1414
    1515from xpra.util import AdHocStruct, updict
     16from xpra.os_util import memoryview_to_bytes
    1617from xpra.gtk_common.gobject_util import one_arg_signal
    1718from xpra.gtk_common.gtk_util import get_default_root_window, get_xwindow
    1819from xpra.x11.xsettings import XSettingsManager, XSettingsHelper
     
    3334X11Window = X11WindowBindings()
    3435from xpra.x11.bindings.keyboard_bindings import X11KeyboardBindings #@UnresolvedImport
    3536X11Keyboard = X11KeyboardBindings()
    36 from xpra.gtk_common.error import trap, xsync
     37from xpra.gtk_common.error import trap, xsync, xswallow
    3738
    3839from xpra.log import Logger
    3940log = Logger("server")
     
    173174        }
    174175
    175176    def __init__(self, clobber):
     177        self.root_overlay = None
     178        self.repaint_root_overlay_due = False
    176179        gobject.GObject.__init__(self)
    177180        X11ServerBase.__init__(self, clobber)
    178181
     
    179182    def init(self, opts):
    180183        self.xsettings_enabled = opts.xsettings
    181184        self.wm_name = opts.wm_name
     185        self.sync_vfb = int(opts.sync_vfb)
    182186        X11ServerBase.init(self, opts)
    183187
    184188    def x11_init(self):
     
    197201                            gtk.gdk.PROP_MODE_REPLACE,
    198202                            xpra.__version__)
    199203        add_event_receiver(root, self)
     204        if self.sync_vfb>0:
     205            with xswallow:
     206                self.root_overlay = X11Window.XCompositeGetOverlayWindow(root.xid)
    200207
    201208        ### Create the WM object
    202209        self._wm = Wm(self.clobber, self.wm_name)
     
    326333        if self._tray:
    327334            self._tray.cleanup()
    328335            self._tray = None
     336        if self.root_overlay:
     337            with xswallow:
     338                X11Window.XCompositeReleaseOverlayWindow(self.root_overlay)
     339            self.root_overlay = None
    329340        X11ServerBase.do_cleanup(self)
    330341        remove_catchall_receiver("xpra-motion-event", self)
    331342        cleanup_x11_filter()
     
    675686        del self._id_to_window[wid]
    676687        for ss in self._server_sources.values():
    677688            ss.remove_window(wid, window)
     689        self.repaint_root_overlay()
    678690
    679691    def _contents_changed(self, window, event):
    680692        if window.is_OR() or window.is_tray() or self._desktop_manager.visible(window):
     
    780792        if iconified and not window.get_property("iconic"):
    781793            window.set_property("iconic", True)
    782794        self._desktop_manager.hide_window(window)
     795        self.repaint_root_overlay()
    783796
    784797    def _process_configure_window(self, proto, packet):
    785798        wid, x, y, w, h = packet[1:6]
     
    818831                damage |= oww!=w or owh!=h
    819832        if len(packet)>=7:
    820833            self._set_client_properties(proto, wid, window, packet[6])
     834        self.repaint_root_overlay()
    821835        if damage:
    822836            self._damage(window, 0, 0, w, h)
    823837
     
    857871            window.request_close()
    858872        else:
    859873            windowlog("cannot close window %s: it is already gone!", wid)
     874        self.repaint_root_overlay()
    860875
    861876
     877    def _damage(self, window, x, y, width, height, options=None):
     878        image = None
     879        if self.root_overlay:
     880            #get the image early, so damage has a chance to re-use it when not batching
     881            image = window.get_image(x, y, width, height)
     882        X11ServerBase._damage(self, window, x, y, width, height, options)
     883        if image:
     884            self.update_root_overlay(window, x, y, image)
     885
     886    def update_root_overlay(self, window, x, y, image):
     887        img_data = memoryview_to_bytes(image.get_pixels())
     888        rowstride = image.get_rowstride()
     889        overlaywin = gtk.gdk.window_foreign_new(self.root_overlay)
     890        gc = overlaywin.new_gc()
     891        if window.is_OR():
     892            wx, wy = window.get_property("geometry")[:2]
     893        else:
     894            wx, wy = self._desktop_manager.window_geometry(window)[:2]
     895        width = image.get_width()
     896        height = image.get_height()
     897        overlaywin.draw_rgb_32_image(gc, wx+x, wy+y, width, height, gtk.gdk.RGB_DITHER_NONE, img_data, rowstride)
     898
     899    def repaint_root_overlay(self):
     900        log.warn("repaint_root_overlay() root_overlay=%s, due=%s, sync-vfb=%sms", self.root_overlay, self.repaint_root_overlay_due, self.sync_vfb)
     901        if not self.root_overlay or self.repaint_root_overlay_due:
     902            return
     903        self.repaint_root_overlay_due = True
     904        self.timeout_add(self.sync_vfb, self.do_repaint_root_overlay)
     905
     906    def do_repaint_root_overlay(self):
     907        self.repaint_root_overlay_due = False
     908        width, height = self.get_root_window_size()
     909        overlaywin = gtk.gdk.window_foreign_new(self.root_overlay)
     910        cr = overlaywin.cairo_create()
     911        cr.set_source_rgb(1, 1, 1)
     912        cr.rectangle(0, 0, width, height)
     913        cr.fill()
     914        cr.paint()
     915        #now paint all the windows on top:
     916        windows = self._wm.get_property("windows")
     917        log.warn("do_repaint_root_overlay() windows=%s", windows)
     918        for window in windows:
     919            image = window.get_image(0, 0, width, height)
     920            log.warn("do_repaint_root_overlay() painting window %s with %s", window, image)
     921            if image:
     922                self.update_root_overlay(window, 0, 0, image)
     923        return False
     924           
     925
    862926    def make_screenshot_packet(self):
    863927        try:
    864928            return self.do_make_screenshot_packet()
  • xpra/scripts/config.py

     
    321321                    "file-size-limit"   : int,
    322322                    "idle-timeout"      : int,
    323323                    "server-idle-timeout" : int,
     324                    "sync-vfb"          : int,
    324325                    #float options:
    325326                    "auto-refresh-delay": float,
    326327                    #boolean options:
     
    448449                    "file-size-limit"   : 10,
    449450                    "idle-timeout"      : 0,
    450451                    "server-idle-timeout" : 0,
     452                    "sync-vfb"          : 0,
    451453                    "auto-refresh-delay": 0.15,
    452454                    "daemon"            : CAN_DAEMONIZE,
    453455                    "use-display"       : False,
  • xpra/scripts/main.py

     
    597597    group.add_option("--dpi", action="store",
    598598                      dest="dpi", default=defaults.dpi,
    599599                      help="The 'dots per inch' value that client applications should try to honour, from 10 to 1000 or 0 for automatic setting. Default: %s." % print_number(defaults.dpi))
     600    group.add_option("--sync-vfb", action="store",
     601                      dest="sync_vfb", default=defaults.sync_vfb,
     602                      help="How often to synchronize the virtual framebuffer used for X11 seamless servers (0 to disable). Default: %s." % defaults.sync_vfb)
    600603    from xpra.platform.paths import get_socket_dirs
    601604    group.add_option("--socket-dirs", action="append",
    602605                      dest="socket_dirs", default=[],