Hello community, here is the log from the commit of package xpra for openSUSE:Factory checked in at 2020-09-28 14:29:01 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/xpra (Old) and /work/SRC/openSUSE:Factory/.xpra.new.4249 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "xpra" Mon Sep 28 14:29:01 2020 rev:26 rq:838116 version:4.0.4 Changes: -------- --- /work/SRC/openSUSE:Factory/xpra/xpra.changes 2020-09-07 21:37:09.465430841 +0200 +++ /work/SRC/openSUSE:Factory/.xpra.new.4249/xpra.changes 2020-09-28 14:29:14.206156584 +0200 @@ -1,0 +2,42 @@ +Sun Sep 27 18:50:56 UTC 2020 - [email protected] + +- Update to version 4.0.4 + * fix memory leak with 'scroll' encoding + * fix NVENC encoder (profile errors) + * fix unmanaged X11 message call which could cause GTK to + crash when it fails + * fix missing auto-refresh leaving a blurry image + * fix incomplete repaints when window contents have padding + * fix missing pixels on the edge of video areas in 'auto' + encoding mode + * fix connection errors with notifications disabled on the + server + * fix 'sync-xvfb' option: setup error, non-standard bit depth + support + * fix shadow server dbus SetRefreshDelay causing all further + "xpra info" requests to fail + * fix incomplete data in initial packets from shadow servers + * fix error in dbus debug logging + * fix client invalid list of encodings + * fix workspace spurious warnings on 64-bit X11 systems + * fix named-pipe server clash + * fix syntax error in HTML5 client maximize toggle + * fix keysym mapping with Xkb and some specific configurations + * fix right click on systray using the gtk StatusIcon + implementation + * fix small file transfers not showing as completed + * fix file-transfer UI for download vs download-and-open not + being honoured + * fix file-transfer identifiers getting lost + * fix websocket compatibility with some client / middleware + * fix missing windows due to an error in the named window icon + handling + * fix hard to trigger mmap memory leak + * add support for sm86 architecture with CUDA 11.1 + * allow 'pager' source indication value to activate window + server-side + * workaround corruption on some windows when maximized + * workaround more pyxdg bugs + * make OpenGL probe timeout configurable + +------------------------------------------------------------------- Old: ---- xpra-4.0.3.tar.xz New: ---- xpra-4.0.4.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ xpra.spec ++++++ --- /var/tmp/diff_new_pack.FADjmK/_old 2020-09-28 14:29:15.414157632 +0200 +++ /var/tmp/diff_new_pack.FADjmK/_new 2020-09-28 14:29:15.414157632 +0200 @@ -19,7 +19,7 @@ %global __requires_exclude ^typelib\\(GtkosxApplication\\)|typelib\\(GdkGLExt\\)|typelib\\(GtkGLExt\\).*$ Name: xpra -Version: 4.0.3 +Version: 4.0.4 Release: 0 Summary: Remote display server for applications and desktops License: GPL-2.0-or-later AND BSD-3-Clause AND LGPL-3.0-or-later AND MIT ++++++ xpra-4.0.3.tar.xz -> xpra-4.0.4.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/NEWS new/xpra-4.0.4/NEWS --- old/xpra-4.0.3/NEWS 2020-08-08 08:50:20.000000000 +0200 +++ new/xpra-4.0.4/NEWS 2020-09-27 20:11:39.000000000 +0200 @@ -1,3 +1,43 @@ +v4.0.4 (2020-09-26) +====================== + -- fix memory leak with 'scroll' encoding + -- fix NVENC encoder (profile errors) + -- fix unmanaged X11 message call which could cause GTK to crash when it fails + -- fix missing auto-refresh leaving a blurry image + -- fix incomplete repaints when window contents have padding + -- fix missing pixels on the edge of video areas in 'auto' encoding mode + -- fix connection errors with notifications disabled on the server + -- fix 'sync-xvfb' option: setup error, non-standard bit depth support + -- fix shadow server dbus SetRefreshDelay causing all further "xpra info" requests to fail + -- fix incomplete data in initial packets from shadow servers + -- fix error in dbus debug logging + -- fix client invalid list of encodings + -- fix missing system tray on Ubuntu 18.04 + -- fix workspace spurious warnings on 64-bit X11 systems + -- fix event handler with 64-bit MS Windows builds + -- fix named-pipe server clash + -- fix error handing in MS Windows printer query API + -- fix missing 'openssl' dependency in DEB packages + -- fix syntax error in HTML5 client maximize toggle + -- fix keysym mapping with Xkb and some specific configurations + -- fix right click on systray using the gtk StatusIcon implementation + -- fix small file transfers not showing as completed + -- fix file-transfer UI for download vs download-and-open not being honoured + -- fix file-transfer identifiers getting lost + -- fix int overflow errors on some 64-bit mswindows installations + -- fix websocket compatibility with some client / middleware + -- fix missing windows due to an error in the named window icon handling + -- fix hard to trigger mmap memory leak + -- add support for sm86 architecture with CUDA 11.1 + -- allow 'pager' source indication value to activate window server-side + -- switch to Xvfb on Debian and Ubuntu + -- workaround corruption on some windows when maximized + -- workaround more pyxdg bugs + -- make OpenGL probe timeout configurable + -- add missing DEB dependency + -- MacOS and MS Windows: fix security issue in brotli decompression + + v4.0.3 (2020-08-07) ====================== -- fix server crash caused by use after free in scrolling code diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/cups/xpraforwarder new/xpra-4.0.4/cups/xpraforwarder --- old/xpra-4.0.3/cups/xpraforwarder 2020-06-10 04:38:16.000000000 +0200 +++ new/xpra-4.0.4/cups/xpraforwarder 2020-09-27 20:11:39.000000000 +0200 @@ -38,7 +38,7 @@ from urllib.parse import urlparse, parse_qs -__version__ = "4.0.3" +__version__ = "4.0.4" #Writes a syslog entry (msg) at the default facility: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/html5/index.html new/xpra-4.0.4/html5/index.html --- old/xpra-4.0.3/html5/index.html 2020-06-10 04:38:16.000000000 +0200 +++ new/xpra-4.0.4/html5/index.html 2020-09-27 20:11:39.000000000 +0200 @@ -129,7 +129,7 @@ <div id="about"> <h2>Xpra HTML5 Client</h2> - <h3>Version 4.0.3</h3> + <h3>Version 4.0.4</h3> <span> Copyright (c) 2013-2020 Antoine Martin <[email protected]> <br /> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/html5/js/Utilities.js new/xpra-4.0.4/html5/js/Utilities.js --- old/xpra-4.0.3/html5/js/Utilities.js 2020-06-10 04:38:16.000000000 +0200 +++ new/xpra-4.0.4/html5/js/Utilities.js 2020-09-27 20:11:39.000000000 +0200 @@ -10,7 +10,7 @@ 'use strict'; const Utilities = { - VERSION : "4.0.3", + VERSION : "4.0.4", REVISION : "0", LOCAL_MODIFICATIONS : "0", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/html5/js/Window.js new/xpra-4.0.4/html5/js/Window.js --- old/xpra-4.0.3/html5/js/Window.js 2020-07-09 18:46:42.000000000 +0200 +++ new/xpra-4.0.4/html5/js/Window.js 2020-09-27 20:11:39.000000000 +0200 @@ -692,7 +692,7 @@ */ XpraWindow.prototype.toggle_minimized = function() { if (!this.minimized) { - this.client.send(["unmap-window", this.wid, True]); + this.client.send(["unmap-window", this.wid, true]); } else { const geom = this.get_internal_geometry(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/setup.py new/xpra-4.0.4/setup.py --- old/xpra-4.0.3/setup.py 2020-07-09 18:46:42.000000000 +0200 +++ new/xpra-4.0.4/setup.py 2020-09-27 20:11:39.000000000 +0200 @@ -2089,6 +2089,8 @@ comp_code_options.append((75, 75)) if version>=(11, 0): comp_code_options.append((80, 80)) + if version>=(11, 1): + comp_code_options.append((86, 86)) for arch, code in comp_code_options: cmd.append("-gencode=arch=compute_%s,code=sm_%s" % (arch, code)) print("CUDA compiling %s (%s)" % (kernel.ljust(16), reason)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/svn-info new/xpra-4.0.4/svn-info --- old/xpra-4.0.3/svn-info 2020-08-08 08:50:24.000000000 +0200 +++ new/xpra-4.0.4/svn-info 2020-09-27 20:11:46.000000000 +0200 @@ -4,10 +4,10 @@ Relative URL: ^/tags/v4.0.x/src Repository Root: file:///var/svn/repos/Xpra Repository UUID: 3bb7dfac-3a0b-4e04-842a-767bc560f471 -Revision: 27083 +Revision: 27557 Node Kind: directory Schedule: normal Last Changed Author: antoine -Last Changed Rev: 27082 -Last Changed Date: 2020-08-07 17:40:37 +0100 (Fri, 07 Aug 2020) +Last Changed Rev: 27557 +Last Changed Date: 2020-09-27 18:17:12 +0100 (Sun, 27 Sep 2020) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/svn-version new/xpra-4.0.4/svn-version --- old/xpra-4.0.3/svn-version 2020-08-08 08:50:24.000000000 +0200 +++ new/xpra-4.0.4/svn-version 2020-09-27 20:11:46.000000000 +0200 @@ -1 +1 @@ -27083 +27557 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/win32/xpra.iss new/xpra-4.0.4/win32/xpra.iss --- old/xpra-4.0.3/win32/xpra.iss 2020-06-10 04:38:16.000000000 +0200 +++ new/xpra-4.0.4/win32/xpra.iss 2020-09-27 20:11:39.000000000 +0200 @@ -1,9 +1,9 @@ [Setup] AppName=Xpra AppId=Xpra_is1 -AppVersion=4.0.3 -AppVerName=Xpra 4.0.3 -UninstallDisplayName=Xpra 4.0.3 +AppVersion=4.0.4 +AppVerName=Xpra 4.0.4 +UninstallDisplayName=Xpra 4.0.4 AppPublisher=xpra.org AppPublisherURL=http:;xpra.org/ DefaultDirName={pf}\Xpra @@ -16,7 +16,7 @@ Compression=lzma2/max SolidCompression=yes AllowUNCPath=false -VersionInfoVersion=4.0.3 +VersionInfoVersion=4.0.4 VersionInfoCompany=xpra.org VersionInfoDescription=multi-platform screen and application forwarding system WizardImageFile=win32\xpra-logo.bmp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/__init__.py new/xpra-4.0.4/xpra/__init__.py --- old/xpra-4.0.3/xpra/__init__.py 2020-08-08 08:50:26.000000000 +0200 +++ new/xpra-4.0.4/xpra/__init__.py 2020-09-27 20:11:48.000000000 +0200 @@ -4,4 +4,4 @@ # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. -__version__ = "4.0.3" +__version__ = "4.0.4" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/client/client_window_base.py new/xpra-4.0.4/xpra/client/client_window_base.py --- old/xpra-4.0.3/xpra/client/client_window_base.py 2020-05-10 19:00:53.000000000 +0200 +++ new/xpra-4.0.4/xpra/client/client_window_base.py 2020-09-27 20:11:39.000000000 +0200 @@ -711,9 +711,9 @@ self.pending_refresh = [] for x, y, w, h in pr: rx, ry, rw, rh = self._client.srect(x, y, w, h) - #if self.window_offset: - # rx -= self.window_offset[0] - # ry -= self.window_offset[1] + if self.window_offset: + rx += self.window_offset[0] + ry += self.window_offset[1] self.idle_add(self.queue_draw_area, rx, ry, rw, rh) def eos(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/client/gtk_base/gtk_client_window_base.py new/xpra-4.0.4/xpra/client/gtk_base/gtk_client_window_base.py --- old/xpra-4.0.3/xpra/client/gtk_base/gtk_client_window_base.py 2020-05-10 19:00:53.000000000 +0200 +++ new/xpra-4.0.4/xpra/client/gtk_base/gtk_client_window_base.py 2020-09-27 20:11:39.000000000 +0200 @@ -99,6 +99,8 @@ DRAGNDROP = envbool("XPRA_DRAGNDROP", True) CLAMP_WINDOW_TO_SCREEN = envbool("XPRA_CLAMP_WINDOW_TO_SCREEN", True) FOCUS_RECHECK_DELAY = envint("XPRA_FOCUS_RECHECK_DELAY", 0) +REPAINT_MAXIMIZED = envint("XPRA_REPAINT_MAXIMIZED", 0) +REFRESH_MAXIMIZED = envbool("XPRA_REFRESH_MAXIMIZED", True) WINDOW_OVERFLOW_TOP = envbool("XPRA_WINDOW_OVERFLOW_TOP", False) AWT_RECENTER = envbool("XPRA_AWT_RECENTER", True) @@ -826,6 +828,17 @@ self.process_map_event() statelog("window_state_updated(..) state updates: %s, actual updates: %s, server updates: %s", state_updates, actual_updates, server_updates) + if "maximized" in state_updates: + if REPAINT_MAXIMIZED>0: + def repaint_maximized(): + widget = self.drawing_area + if not self._backing or not widget: + return + ww, wh = self.get_size() + widget.queue_draw_area(0, 0, ww, wh) + self.timeout_add(REPAINT_MAXIMIZED, repaint_maximized) + if REFRESH_MAXIMIZED: + self._client.send_refresh(self._id) self._window_state.update(server_updates) self.emit("state-updated") #if we have state updates, send them back to the server using a configure window packet: @@ -1222,6 +1235,9 @@ #which will look at the window metadata again workspacelog("workspace=%s will be set when the window is mapped", wn(workspace)) return + workspace = workspace + if workspace is not None: + workspace = workspace & 0xffffffff desktop = self.get_desktop_workspace() ndesktops = self.get_workspace_count() current = self.get_window_workspace() @@ -1278,7 +1294,7 @@ if value is not None: workspacelog("do_get_workspace %s=%s on window %i: %#x", prop, wn(value), self._id, target.get_xid()) - return value + return value & 0xffffffff workspacelog("do_get_workspace %s unset on window %i: %#x, returning default value=%s", prop, self._id, target.get_xid(), wn(default_value)) return default_value diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/client/gtk_base/gtk_tray_menu_base.py new/xpra-4.0.4/xpra/client/gtk_base/gtk_tray_menu_base.py --- old/xpra-4.0.3/xpra/client/gtk_base/gtk_tray_menu_base.py 2020-05-10 19:00:53.000000000 +0200 +++ new/xpra-4.0.4/xpra/client/gtk_base/gtk_tray_menu_base.py 2020-09-27 20:11:39.000000000 +0200 @@ -6,7 +6,7 @@ import os import re -from gi.repository import GLib, Gtk +from gi.repository import GLib, Gtk, GdkPixbuf from xpra.util import CLIENT_EXIT, iround, envbool, repr_ellipsized, reverse_dict, typedict from xpra.os_util import bytestostr, OSX, WIN32 @@ -1690,7 +1690,6 @@ if not pixbuf and icondata: #gtk pixbuf loader: try: - from gi.repository import GdkPixbuf loader = GdkPixbuf.PixbufLoader() loader.write(icondata) loader.close() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/client/gtk_base/open_requests.py new/xpra-4.0.4/xpra/client/gtk_base/open_requests.py --- old/xpra-4.0.3/xpra/client/gtk_base/open_requests.py 2020-05-10 19:00:53.000000000 +0200 +++ new/xpra-4.0.4/xpra/client/gtk_base/open_requests.py 2020-09-27 20:11:39.000000000 +0200 @@ -167,28 +167,29 @@ else: self.populate_table() self.window.resize(1, 1) - def ok(*_args): - remove_entry(False) - cb_answer(ACCEPT, False) - def okopen(*_args): + def cancel(*_args): remove_entry(True) + cb_answer(DENY) + def accept(*_args): + remove_entry(False) cb_answer(ACCEPT, True) + def download(*_args): + remove_entry(False) + cb_answer(ACCEPT, False) def remote(*_args): remove_entry(True) cb_answer(OPEN) - def cancel(*_args): - remove_entry(True) - cb_answer(DENY) - hbox.pack_start(self.btn("Cancel", None, cancel, "close.png")) + cancel_btn = self.btn("Cancel", None, cancel, "close.png") + hbox.pack_start(cancel_btn) if bytestostr(dtype)=="url": - hbox.pack_start(self.btn("Open Locally", None, ok, "open.png")) + hbox.pack_start(self.btn("Open Locally", None, accept, "open.png")) hbox.pack_start(self.btn("Open on server", None, remote)) elif printit: - hbox.pack_start(self.btn("Print", None, ok, "printer.png")) + hbox.pack_start(self.btn("Print", None, accept, "printer.png")) else: - hbox.pack_start(self.btn("Download", None, ok, "download.png")) + hbox.pack_start(self.btn("Download", None, download, "download.png")) if openit: - hbox.pack_start(self.btn("Download and Open", None, okopen, "open.png")) + hbox.pack_start(self.btn("Download and Open", None, accept, "open.png")) hbox.pack_start(self.btn("Open on server", None, remote)) return hbox diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/client/gtk_base/statusicon_tray.py new/xpra-4.0.4/xpra/client/gtk_base/statusicon_tray.py --- old/xpra-4.0.3/xpra/client/gtk_base/statusicon_tray.py 2020-05-10 19:00:53.000000000 +0200 +++ new/xpra-4.0.4/xpra/client/gtk_base/statusicon_tray.py 2020-09-27 20:11:39.000000000 +0200 @@ -53,7 +53,7 @@ modifiers_mask = get_default_root_window().get_pointer()[-1] log("activate_menu(%s) modifiers_mask=%s", widget, modifiers_mask) if (modifiers_mask & Gdk.ModifierType.SHIFT_MASK) ^ OSX: - self.handle_click(2) + self.handle_click(3) else: self.handle_click(1) @@ -63,7 +63,7 @@ if (modifiers_mask & Gdk.ModifierType.SHIFT_MASK) ^ OSX: self.handle_click(1) else: - self.handle_click(2) + self.handle_click(3) def handle_click(self, button, event_time=0): log("handle_click(%i, %i)", button, event_time) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/client/mixins/encodings.py new/xpra-4.0.4/xpra/client/mixins/encodings.py --- old/xpra-4.0.3/xpra/client/mixins/encodings.py 2020-05-10 19:00:53.000000000 +0200 +++ new/xpra-4.0.4/xpra/client/mixins/encodings.py 2020-09-27 20:11:39.000000000 +0200 @@ -236,7 +236,7 @@ and the actual encoding used ("rgb24" or "rgb32") depends on the window's bit depth. ("rgb32" if there is an alpha channel, and if the client supports it) """ - cenc = self.get_core_encodings() + cenc = list(self.get_core_encodings()) if ("rgb24" in cenc or "rgb32" in cenc) and "rgb" not in cenc: cenc.append("rgb") return [x for x in PREFERED_ENCODING_ORDER if x in cenc and x not in ("rgb32", "rgb24")] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/client/mixins/window_manager.py new/xpra-4.0.4/xpra/client/mixins/window_manager.py --- old/xpra-4.0.3/xpra/client/mixins/window_manager.py 2020-05-10 19:00:53.000000000 +0200 +++ new/xpra-4.0.4/xpra/client/mixins/window_manager.py 2020-09-27 20:11:39.000000000 +0200 @@ -1422,7 +1422,7 @@ if not window: #window is gone def draw_cleanup(): - if bytestostr(coding)==b"mmap": + if bytestostr(coding)=="mmap": assert self.mmap_enabled from xpra.net.mmap_pipe import int_from_buffer #we need to ack the data to free the space! diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/codecs/argb/argb.pyx new/xpra-4.0.4/xpra/codecs/argb/argb.pyx --- old/xpra-4.0.3/xpra/codecs/argb/argb.pyx 2020-05-10 19:00:54.000000000 +0200 +++ new/xpra-4.0.4/xpra/codecs/argb/argb.pyx 2020-09-27 20:11:39.000000000 +0200 @@ -276,6 +276,33 @@ return bgra_to_rgba(buf) +def bgra_to_rgbx(buf): + assert len(buf) % 4 == 0, "invalid buffer size: %s is not a multiple of 4" % len(buf) + # buf is a Python buffer object + cdef unsigned char * bgra_buf = NULL + cdef Py_ssize_t bgra_buf_len = 0 + assert as_buffer(buf, <const void**> &bgra_buf, &bgra_buf_len)==0, "cannot convert %s to a readable buffer" % type(buf) + return bgradata_to_rgbx(bgra_buf, bgra_buf_len) + +cdef bgradata_to_rgbx(const unsigned char* bgra, const int bgra_len): + if bgra_len <= 0: + return None + assert bgra_len>0 and bgra_len % 4 == 0, "invalid buffer size: %s is not a multiple of 4" % bgra_len + #same number of bytes: + cdef MemBuf output_buf = getbuf(bgra_len) + cdef unsigned char* rgbx = <unsigned char*> output_buf.get_mem() + cdef int i = 0 #@DuplicateSignature + while i < bgra_len: + rgbx[i] = bgra[i+2] #R + rgbx[i+1] = bgra[i+1] #G + rgbx[i+2] = bgra[i] #B + rgbx[i+3] = 0xff #X + i += 4 + return memoryview(output_buf) + + + + def premultiply_argb(buf): # b is a Python buffer object cdef unsigned int * argb = <unsigned int *> 0 #@DuplicateSignature @@ -460,6 +487,11 @@ image.set_pixel_format("RGB") image.set_rowstride(rs*3//4) return True + if "RGBX" in rgb_formats: + log("argb_swap: bgra_to_rgbx for %s on %s", pixel_format, type(pixels)) + image.set_pixels(bgra_to_rgbx(pixels)) + image.set_pixel_format("RGBX") + return True elif pixel_format in ("XRGB", "ARGB"): if supports_transparency and "RGBA" in rgb_formats: log("argb_swap: argb_to_rgba for %s on %s", pixel_format, type(pixels)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/codecs/csc_libyuv/colorspace_converter.pyx new/xpra-4.0.4/xpra/codecs/csc_libyuv/colorspace_converter.pyx --- old/xpra-4.0.3/xpra/codecs/csc_libyuv/colorspace_converter.pyx 2020-05-10 19:00:54.000000000 +0200 +++ new/xpra-4.0.4/xpra/codecs/csc_libyuv/colorspace_converter.pyx 2020-09-27 20:11:39.000000000 +0200 @@ -182,6 +182,7 @@ divs = get_subsampling_divs(self.dst_format) for i in range(3): xdiv, ydiv = divs[i] + #we don't scale, so the size is the src size: self.out_width[i] = src_width // xdiv self.out_height[i] = src_height // ydiv self.out_stride[i] = roundup(self.out_width[i], MEMALIGN_ALIGNMENT) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/codecs/csc_swscale/colorspace_converter.pyx new/xpra-4.0.4/xpra/codecs/csc_swscale/colorspace_converter.pyx --- old/xpra-4.0.3/xpra/codecs/csc_swscale/colorspace_converter.pyx 2020-06-30 17:12:41.000000000 +0200 +++ new/xpra-4.0.4/xpra/codecs/csc_swscale/colorspace_converter.pyx 2020-09-27 20:11:39.000000000 +0200 @@ -10,7 +10,6 @@ import time from xpra.log import Logger -from xpra.codecs.codec_checks import do_testcsc log = Logger("csc", "swscale") from xpra.util import envbool diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/codecs/nvenc/encoder.pyx new/xpra-4.0.4/xpra/codecs/nvenc/encoder.pyx --- old/xpra-4.0.3/xpra/codecs/nvenc/encoder.pyx 2020-08-07 11:17:40.000000000 +0200 +++ new/xpra-4.0.4/xpra/codecs/nvenc/encoder.pyx 2020-09-27 20:11:39.000000000 +0200 @@ -18,7 +18,7 @@ from xpra.os_util import WIN32, OSX, LINUX, strtobytes from xpra.make_thread import start_thread -from xpra.util import AtomicInteger, engs, csv, pver, envint, envbool, first_time +from xpra.util import AtomicInteger, engs, csv, pver, envint, envbool, first_time, typedict from xpra.codecs.cuda_common.cuda_context import ( init_all_devices, get_devices, select_device, get_device_info, get_device_name, get_cuda_info, get_pycuda_info, device_info, reset_state, @@ -1597,7 +1597,7 @@ #use the environment as default if present: profile = os.environ.get("XPRA_NVENC_%s_PROFILE" % csc_mode, "") #now see if the client has requested a different value: - profile = options.strget("h264.%s.profile" % csc_mode, profile) + profile = typedict(options).strget("h264.%s.profile" % csc_mode, profile) return profile @@ -1846,7 +1846,7 @@ log("init_params(%s) using preset=%s", codecstr(codec), presetstr(preset)) profiles = self.query_profiles(codec) if self.profile_name and profiles and self.profile_name not in profiles: - self.profile_name = profiles[0] + self.profile_name = tuple(profiles.keys())[0] profile_guidstr = profiles.get(self.profile_name) cdef GUID profile if profile_guidstr: @@ -2254,6 +2254,7 @@ cdef flushEncoder(self): cdef NV_ENC_PIC_PARAMS picParams cdef NVENCSTATUS r #@DuplicatedSignature + assert not self.closed, "encoder context is closed" assert self.context, "context is not initialized" memset(&picParams, 0, sizeof(NV_ENC_PIC_PARAMS)) picParams.version = NV_ENC_PIC_PARAMS_VER @@ -2265,6 +2266,7 @@ raiseNVENC(r, "flushing encoder buffer") def compress_image(self, image, quality=-1, speed=-1, options={}, retry=0): + assert not self.closed, "encoder context is closed" self.cuda_context.push() try: try: @@ -2288,7 +2290,6 @@ cdef do_compress_image(self, image, options={}): cdef unsigned int stride, w, h assert self.context, "context is not initialized" - assert self.context!=NULL, "context is not initialized" w = image.get_width() h = image.get_height() gpu_buffer = image.get_gpu_buffer() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/net/file_transfer.py new/xpra-4.0.4/xpra/net/file_transfer.py --- old/xpra-4.0.3/xpra/net/file_transfer.py 2020-06-30 17:12:41.000000000 +0200 +++ new/xpra-4.0.4/xpra/net/file_transfer.py 2020-09-27 20:11:39.000000000 +0200 @@ -262,10 +262,11 @@ def _process_send_file_chunk(self, packet): chunk_id, chunk, file_data, has_more = packet[1:5] + chunk_id = bytestostr(chunk_id) filelog("_process_send_file_chunk%s", (chunk_id, chunk, "%i bytes" % len(file_data), has_more)) chunk_state = self.receive_chunks_in_progress.get(chunk_id) if not chunk_state: - filelog.error("Error: cannot find the file transfer id '%s'", nonl(bytestostr(chunk_id))) + filelog.error("Error: cannot find the file transfer id '%s'", nonl(chunk_id)) self.send("ack-file-chunk", chunk_id, False, "file transfer id not found", chunk) return fd = chunk_state[1] @@ -317,9 +318,7 @@ elapsed = monotonic_time()-start_time mimetype = bytestostr(mimetype) filelog("%i bytes received in %i chunks, took %ims", filesize, chunk, elapsed*1000) - t = start_thread(self.do_process_downloaded_file, "process-download", daemon=False, - args=(filename, mimetype, printit, openit, filesize, options)) - filelog("started process-download thread: %s", t) + self.process_downloaded_file(filename, mimetype, printit, openit, filesize, options) def accept_data(self, send_id, dtype, basefilename, printit, openit): #subclasses should check the flags, @@ -343,6 +342,7 @@ def _process_send_file(self, packet): #the remote end is sending us a file + start = monotonic_time() basefilename, mimetype, printit, openit, filesize, file_data, options = packet[1:8] send_id = "" if len(packet)>=9: @@ -384,7 +384,6 @@ return self.file_descriptors.add(fd) if chunk_id: - chunk_id = strtobytes(chunk_id) l = len(self.receive_chunks_in_progress) if l>=MAX_CONCURRENT_FILES: self.send("ack-file-chunk", chunk_id, False, "too many file transfers in progress: %i" % l, 0) @@ -422,7 +421,14 @@ os.write(fd, file_data) finally: os.close(fd) - self.do_process_downloaded_file(filename, mimetype, printit, openit, filesize, options) + self.transfer_progress_update(False, send_id, monotonic_time()-start, filesize, filesize, None) + self.process_downloaded_file(filename, mimetype, printit, openit, filesize, options) + + + def process_downloaded_file(self, filename, mimetype, printit, openit, filesize, options): + t = start_thread(self.do_process_downloaded_file, "process-download", daemon=False, + args=(filename, mimetype, printit, openit, filesize, options)) + filelog("started process-download thread: %s", t) def do_process_downloaded_file(self, filename, mimetype, printit, openit, filesize, options): filelog("do_process_downloaded_file%s", (filename, mimetype, printit, openit, filesize, options)) @@ -803,12 +809,12 @@ #send some more file data filelog("ack-file-chunk: %s", packet[1:]) chunk_id, state, error_message, chunk = packet[1:5] + chunk_id = bytestostr(chunk_id) if not state: filelog.error("Error: remote end is cancelling the file transfer:") filelog.error(" %s", error_message) del self.send_chunks_in_progress[chunk_id] return - chunk_id = bytestostr(chunk_id) chunk_state = self.send_chunks_in_progress.get(chunk_id) if not chunk_state: filelog.error("Error: cannot find the file transfer id '%s'", nonl(chunk_id)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/net/websockets/common.py new/xpra-4.0.4/xpra/net/websockets/common.py --- old/xpra-4.0.3/xpra/net/websockets/common.py 2020-05-10 19:00:54.000000000 +0200 +++ new/xpra-4.0.4/xpra/net/websockets/common.py 2020-09-27 20:11:39.000000000 +0200 @@ -6,6 +6,7 @@ import uuid from hashlib import sha1 from base64 import b64encode +from requests.structures import CaseInsensitiveDict from xpra.os_util import strtobytes, bytestostr, monotonic_time from xpra.log import Logger @@ -49,7 +50,7 @@ now = monotonic_time() response = b"" - while response.find(b"Sec-WebSocket-Protocol")<0 and monotonic_time()-now<MAX_READ_TIME: + while ("Sec-WebSocket-Protocol".lower() not in response.decode("utf-8").lower()) and monotonic_time()-now<MAX_READ_TIME: response += read(READ_CHUNK_SIZE) headers = parse_response_header(response) verify_response_headers(headers, key) @@ -70,6 +71,7 @@ log("verify_response_headers(%s)", headers) if not headers: raise Exception("no http headers found in response") + headers = CaseInsensitiveDict(headers) upgrade = headers.get(b"Upgrade", b"") if upgrade!=b"websocket": raise Exception("invalid http upgrade: '%s'" % upgrade) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/platform/win32/common.py new/xpra-4.0.4/xpra/platform/win32/common.py --- old/xpra-4.0.3/xpra/platform/win32/common.py 2020-05-10 19:00:55.000000000 +0200 +++ new/xpra-4.0.4/xpra/platform/win32/common.py 2020-09-27 20:11:39.000000000 +0200 @@ -17,7 +17,7 @@ from ctypes.wintypes import ( HANDLE, LPSTR, LPCWSTR, UINT, INT, BOOL, WORD, HGDIOBJ, LONG, LPVOID, HBITMAP, LPCSTR, LPWSTR, HWINSTA, - HINSTANCE, HMENU, ULONG, + HINSTANCE, HMENU, ULONG, HHOOK, ) #imported from this module but not used here: assert GetLastError @@ -240,7 +240,7 @@ UnregisterClassW.argtypes = [LPCWSTR, HINSTANCE] CreateWindowExA = user32.CreateWindowExA CreateWindowExA.restype = HWND -#CreateWindowExA.argtypes = [DWORD, ATOM, LPCTSTR, DWORD, c_int, c_int, c_int, c_int, HWND, HMENU, HINSTANCE, LPVOID] +CreateWindowExA.argtypes = [DWORD, ATOM, LPCWSTR, DWORD, c_int, c_int, c_int, c_int, HWND, HMENU, HINSTANCE, LPVOID] CreateWindowExW = user32.CreateWindowExW CreateWindowExW.restype = HWND CreateWindowExW.argtypes = [DWORD, ATOM, LPCWSTR, DWORD, c_int, c_int, c_int, c_int, HWND, HMENU, HINSTANCE, LPVOID] @@ -248,7 +248,11 @@ DestroyWindow.restype = BOOL DestroyWindow.argtypes = [HWND] DefWindowProcA = user32.DefWindowProcA +DefWindowProcA.argtypes = [HWND, UINT, WPARAM, LPARAM] +DefWindowProcA.restype = INT DefWindowProcW = user32.DefWindowProcW +DefWindowProcW.argtypes = [HWND, UINT, WPARAM, LPARAM] +DefWindowProcW.restype = INT MessageBoxA = user32.MessageBoxA MessageBoxA.restype = INT MessageBoxA.argtypes = [HWND, LPCTSTR, LPCTSTR, UINT] @@ -287,6 +291,8 @@ UnhookWindowsHookEx = user32.UnhookWindowsHookEx CallNextHookEx = user32.CallNextHookEx SetWindowsHookExA = user32.SetWindowsHookExA +SetWindowsHookExA.restype = HHOOK +SetWindowsHookExA.argtypes = [INT, HANDLE, HINSTANCE, DWORD] GetMessageA = user32.GetMessageA TranslateMessage = user32.TranslateMessage DispatchMessageA = user32.DispatchMessageA diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/platform/win32/win32_NotifyIcon.py new/xpra-4.0.4/xpra/platform/win32/win32_NotifyIcon.py --- old/xpra-4.0.3/xpra/platform/win32/win32_NotifyIcon.py 2020-05-10 19:00:55.000000000 +0200 +++ new/xpra-4.0.4/xpra/platform/win32/win32_NotifyIcon.py 2020-08-11 14:52:59.000000000 +0200 @@ -256,9 +256,9 @@ self.hwnd = CreateWindowExA(0, NIclassAtom, window_name, style, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, 0, 0, \ 0, 0, NIwc.hInstance, None) - if self.hwnd==0: + log("create_window() hwnd=%#x", self.hwnd or 0) + if not self.hwnd: raise ctypes.WinError(ctypes.get_last_error()) - log("create_window() hwnd=%#x", self.hwnd) UpdateWindow(self.hwnd) #register callbacks: win32NotifyIcon.instances[self.hwnd] = self diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/platform/win32/win32_printing.py new/xpra-4.0.4/xpra/platform/win32/win32_printing.py --- old/xpra-4.0.3/xpra/platform/win32/win32_printing.py 2020-05-10 19:00:55.000000000 +0200 +++ new/xpra-4.0.4/xpra/platform/win32/win32_printing.py 2020-08-11 14:52:59.000000000 +0200 @@ -134,7 +134,7 @@ log("GetPrinter: PRINTER_INFO_1 size=%#x", size.value) self.info1 = msvcrt.malloc(size.value) if not GetPrinterA(self.handle, 1, self.info1, size.value, pointer(size)): - raise Exception("GetPrinterA PRINTER_INFO_1 failed for '%s'", self.printer_name) + raise Exception("GetPrinterA PRINTER_INFO_1 failed for '%s'" % self.printer_name) info = cast(self.info1, POINTER(PRINTER_INFO_1)) log(" flags=%#x" % info[0].Flags) log(" name=%#s" % info[0].pName) @@ -144,7 +144,7 @@ size = DWORD(0) GetPrinterA(self.handle, 2, None, 0, pointer(size)) if size.value==0: - raise Exception("GetPrinterA PRINTER_INFO_2 failed for '%s'", self.printer_name) + raise Exception("GetPrinterA PRINTER_INFO_2 failed for '%s'" % self.printer_name) log("GetPrinter: PRINTER_INFO_2 size=%#x", size.value) self.info2 = msvcrt.malloc(size.value) if GetPrinterA(self.handle, 2, self.info2, size.value, pointer(size)): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/platform/xposix/gui.py new/xpra-4.0.4/xpra/platform/xposix/gui.py --- old/xpra-4.0.3/xpra/platform/xposix/gui.py 2020-08-08 08:50:20.000000000 +0200 +++ new/xpra-4.0.4/xpra/platform/xposix/gui.py 2020-09-27 20:11:39.000000000 +0200 @@ -476,7 +476,9 @@ SubstructureNotifyMask = constants["SubstructureNotifyMask"] SubstructureRedirectMask = constants["SubstructureRedirectMask"] event_mask = SubstructureNotifyMask | SubstructureRedirectMask - X11Window.sendClientMessage(root_xid, xid, False, event_mask, message_type, *values) + from xpra.gtk_common.error import xsync + with xsync: + X11Window.sendClientMessage(root_xid, xid, False, event_mask, message_type, *values) except Exception as e: log.warn("failed to send client message '%s' with values=%s: %s", message_type, values, e) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/platform/xposix/xdg_helper.py new/xpra-4.0.4/xpra/platform/xposix/xdg_helper.py --- old/xpra-4.0.3/xpra/platform/xposix/xdg_helper.py 2020-06-05 11:40:11.000000000 +0200 +++ new/xpra-4.0.4/xpra/platform/xposix/xdg_helper.py 2020-09-27 20:11:39.000000000 +0200 @@ -263,7 +263,7 @@ try: menu = parse() break - except (ParsingError, AttributeError) as e: + except Exception as e: log("do_load_xdg_menu_data()", exc_info=True) error = e menu = None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/scripts/config.py new/xpra-4.0.4/xpra/scripts/config.py --- old/xpra-4.0.3/xpra/scripts/config.py 2020-05-10 19:00:55.000000000 +0200 +++ new/xpra-4.0.4/xpra/scripts/config.py 2020-09-27 20:11:39.000000000 +0200 @@ -11,7 +11,7 @@ from xpra.os_util import ( WIN32, OSX, POSIX, osexpand, getuid, getgid, get_username_for_uid, - is_Debian, is_arm, + is_Debian, is_Ubuntu, is_arm, ) def warn(msg): @@ -133,6 +133,10 @@ if is_arm(): #arm struggles to launch Xdummy, so use Xvfb: return get_Xvfb_command() + if is_Ubuntu() or is_Debian(): + #These distros do weird things and this can cause the real X11 server to crash + #see ticket #2834 + return get_Xvfb_command() xorg_bin = get_xorg_bin() def Xorg_suid_check(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/scripts/main.py new/xpra-4.0.4/xpra/scripts/main.py --- old/xpra-4.0.3/xpra/scripts/main.py 2020-08-07 11:17:40.000000000 +0200 +++ new/xpra-4.0.4/xpra/scripts/main.py 2020-09-27 20:11:39.000000000 +0200 @@ -54,6 +54,7 @@ CLIPBOARD_CLASS = os.environ.get("XPRA_CLIPBOARD_CLASS") WAIT_SERVER_TIMEOUT = envint("WAIT_SERVER_TIMEOUT", 90) CONNECT_TIMEOUT = envint("XPRA_CONNECT_TIMEOUT", 20) +OPENGL_PROBE_TIMEOUT = envint("XPRA_OPENGL_PROBE_TIMEOUT", 5) SYSTEMD_RUN = envbool("XPRA_SYSTEMD_RUN", True) LOG_SYSTEMD_WRAP = envbool("XPRA_LOG_SYSTEMD_WRAP", True) VERIFY_X11_SOCKET_TIMEOUT = envint("XPRA_VERIFY_X11_SOCKET_TIMEOUT", 1) @@ -1776,7 +1777,7 @@ log.warn("Warning: failed to execute OpenGL probe command") log.warn(" %s", e) return "probe-failed:%s" % e - r = pollwait(proc) + r = pollwait(proc, OPENGL_PROBE_TIMEOUT) log("OpenGL probe command returned %s for command=%s", r, cmd) end = monotonic_time() log("probe took %ims", 1000*(end-start)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/server/dbus/dbus_server.py new/xpra-4.0.4/xpra/server/dbus/dbus_server.py --- old/xpra-4.0.3/xpra/server/dbus/dbus_server.py 2020-05-10 19:00:55.000000000 +0200 +++ new/xpra-4.0.4/xpra/server/dbus/dbus_server.py 2020-09-27 20:11:39.000000000 +0200 @@ -251,7 +251,7 @@ @dbus.service.method(INTERFACE, in_signature='is') def SetWindowEncoding(self, wid, encoding): wid, encoding = ni(wid), ns(encoding) - self.log(".SetWindowEncoding(%i, %i)", wid, encoding) + self.log(".SetWindowEncoding(%i, %s)", wid, encoding) self.server.control_command_encoding(encoding, wid) @dbus.service.method(INTERFACE, in_signature='i') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/server/shadow/gtk_shadow_server_base.py new/xpra-4.0.4/xpra/server/shadow/gtk_shadow_server_base.py --- old/xpra-4.0.3/xpra/server/shadow/gtk_shadow_server_base.py 2020-05-10 19:00:56.000000000 +0200 +++ new/xpra-4.0.4/xpra/server/shadow/gtk_shadow_server_base.py 2020-09-27 20:11:39.000000000 +0200 @@ -72,7 +72,8 @@ def make_hello(self, source): - caps = super().make_hello(source) + caps = ShadowServerBase.make_hello(self, source) + caps.update(GTKServerBase.make_hello(self, source)) if source.wants_features: caps["screen_sizes"] = get_screen_sizes() return caps diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/server/shadow/shadow_dbus_server.py new/xpra-4.0.4/xpra/server/shadow/shadow_dbus_server.py --- old/xpra-4.0.3/xpra/server/shadow/shadow_dbus_server.py 2020-05-10 19:00:56.000000000 +0200 +++ new/xpra-4.0.4/xpra/server/shadow/shadow_dbus_server.py 2020-09-27 20:11:39.000000000 +0200 @@ -1,12 +1,12 @@ #!/usr/bin/env python # This file is part of Xpra. -# Copyright (C) 2015-2019 Antoine Martin <[email protected]> +# Copyright (C) 2015-2020 Antoine Martin <[email protected]> # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import dbus.service -from xpra.server.dbus.dbus_server import DBUS_Server, INTERFACE +from xpra.server.dbus.dbus_server import DBUS_Server, INTERFACE, ni from xpra.log import Logger log = Logger("dbus", "server") @@ -15,4 +15,5 @@ @dbus.service.method(INTERFACE, in_signature='i') def SetRefreshDelay(self, milliseconds): - return self.server.set_refresh_delay(milliseconds) + log("SetRefreshDelay(%i)", milliseconds) + return self.server.set_refresh_delay(ni(milliseconds)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/server/source/windows_mixin.py new/xpra-4.0.4/xpra/server/source/windows_mixin.py --- old/xpra-4.0.3/xpra/server/source/windows_mixin.py 2020-05-10 19:00:56.000000000 +0200 +++ new/xpra-4.0.4/xpra/server/source/windows_mixin.py 2020-09-27 20:11:39.000000000 +0200 @@ -138,8 +138,8 @@ self.window_frame_sizes = typedict(c.dictget("window.frame_sizes", {})) self.window_min_size = c.inttupleget("window.min-size", (0, 0)) self.window_max_size = c.inttupleget("window.max-size", (0, 0)) - log("cursors=%s (encodings=%s), bell=%s, notifications=%s", - self.send_cursors, self.cursor_encodings, self.send_bell, self.send_notifications) + log("cursors=%s (encodings=%s)", + self.send_cursors, self.cursor_encodings) log("client uuid %s", self.uuid) #window filters: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/server/window/window_source.py new/xpra-4.0.4/xpra/server/window/window_source.py --- old/xpra-4.0.3/xpra/server/window/window_source.py 2020-07-09 18:46:42.000000000 +0200 +++ new/xpra-4.0.4/xpra/server/window/window_source.py 2020-09-27 20:11:39.000000000 +0200 @@ -1314,9 +1314,16 @@ def do_damage(self, ww, wh, x, y, w, h, options): now = monotonic_time() - if self.refresh_timer and (w*h>=ww*wh//4 or w*h>=512*1024): - #large enough screen update: cancel refresh timer - self.cancel_refresh_timer() + if self.refresh_timer and options.get("quality", self._current_quality)<self.refresh_quality: + rr = tuple(self.refresh_regions) + if rr: + #does this screen update intersect with + #the areas that are due to be refreshed? + overlap = sum(rect.width*rect.height for rect in rr) + if overlap>0: + pct = int(min(100, 100*overlap//(ww*wh)) * (1+self.global_statistics.congestion_value)) + sched_delay = max(self.min_auto_refresh_delay, int(self.base_auto_refresh_delay * pct // 100)) + self.refresh_target_time = max(self.refresh_target_time, now + sched_delay/1000.0) delayed = self._damage_delayed if delayed: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/server/window/window_video_source.py new/xpra-4.0.4/xpra/server/window/window_video_source.py --- old/xpra-4.0.3/xpra/server/window/window_video_source.py 2020-08-07 11:17:40.000000000 +0200 +++ new/xpra-4.0.4/xpra/server/window/window_video_source.py 2020-09-27 20:11:39.000000000 +0200 @@ -578,6 +578,11 @@ damage_options["novideo"] = True super().full_quality_refresh(damage_options) + def timer_full_refresh(self): + self.free_scroll_data() + self.last_scroll_time = 0 + super().timer_full_refresh() + def quality_changed(self, window, *args): super().quality_changed(window, args) @@ -875,7 +880,8 @@ # * we want av-sync # * the video encoder needs a thread safe image # (the xshm backing may change from underneath us if we don't freeze it) - must_freeze = av_delay>0 or ((coding in self.video_encodings or coding=="auto") and not image.is_thread_safe()) + video_mode = coding in self.video_encodings or coding=="auto" + must_freeze = av_delay>0 or (video_mode and not image.is_thread_safe()) log("process_damage_region: av_delay=%s, must_freeze=%s, size=%s, encoding=%s", av_delay, must_freeze, (w, h), coding) if must_freeze: @@ -896,7 +902,7 @@ self.encode_queue.append(item) self.schedule_encode_from_queue(av_delay) #now figure out if we need to send edges separately: - if coding in self.video_encodings and self.edge_encoding and not VIDEO_SKIP_EDGE: + if video_mode and self.edge_encoding and not VIDEO_SKIP_EDGE: dw = w - (w & self.width_mask) dh = h - (h & self.height_mask) if dw>0 and h>0: @@ -1913,6 +1919,7 @@ assert encoding, "no nonvideo encoding found for %ix%i screen update" % (w, sh) encode_fn = self._encoders[encoding] ret = encode_fn(encoding, sub, options) + self.free_image_wrapper(sub) if not ret: #cancelled? return None @@ -1943,6 +1950,7 @@ assert flush==0 self.last_scroll_time = monotonic_time() scrolllog("scroll encoding total time: %ims", (self.last_scroll_time-start)*1000) + self.free_image_wrapper(image) def do_schedule_auto_refresh(self, encoding, data, region, client_options, options): #for scroll encoding, data is a LargeStructure wrapper: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/src_info.py new/xpra-4.0.4/xpra/src_info.py --- old/xpra-4.0.3/xpra/src_info.py 2020-08-08 08:50:24.000000000 +0200 +++ new/xpra-4.0.4/xpra/src_info.py 2020-09-27 20:11:46.000000000 +0200 @@ -1,2 +1,2 @@ LOCAL_MODIFICATIONS=0 -REVISION=27083 +REVISION=27557 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/x11/bindings/ximage.pyx new/xpra-4.0.4/xpra/x11/bindings/ximage.pyx --- old/xpra-4.0.3/xpra/x11/bindings/ximage.pyx 2020-05-10 19:00:56.000000000 +0200 +++ new/xpra-4.0.4/xpra/x11/bindings/ximage.pyx 2020-09-27 20:11:39.000000000 +0200 @@ -459,6 +459,10 @@ if posix_memalign(<void **> &self.pixels, 64, buf_len): raise Exception("posix_memalign failed!") assert self.pixels!=NULL + #from now on, we own the buffer, + #so we're no longer a direct sub-image, + #and we must free the buffer later: + self.sub = False if self.image==NULL: self.thread_safe = 1 #we can now mark this object as thread safe diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/x11/gtk_x11/selection.py new/xpra-4.0.4/xpra/x11/gtk_x11/selection.py --- old/xpra-4.0.3/xpra/x11/gtk_x11/selection.py 2020-05-10 19:00:56.000000000 +0200 +++ new/xpra-4.0.4/xpra/x11/gtk_x11/selection.py 2020-08-11 14:52:59.000000000 +0200 @@ -162,10 +162,10 @@ #log("_owner_change(..) not our selection: %s vs %s", event.selection, self.atom) return if event.owner: - owner = event.owner.get_xid() - if owner==self._xwindow: - log("_owner_change(..) we still own %s", event.selection) - return + owner = event.owner.get_xid() + if owner==self._xwindow: + log("_owner_change(..) we still own %s", event.selection) + return if self._xwindow: self._xwindow = None self.emit("selection-lost") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/x11/models/base.py new/xpra-4.0.4/xpra/x11/models/base.py --- old/xpra-4.0.3/xpra/x11/models/base.py 2020-05-17 18:12:15.000000000 +0200 +++ new/xpra-4.0.4/xpra/x11/models/base.py 2020-09-27 20:11:39.000000000 +0200 @@ -625,7 +625,10 @@ log("_NET_WM_MOVERESIZE: %s", event) self.emit("initiate-moveresize", event) return True - if event.message_type=="_NET_ACTIVE_WINDOW" and event.data[0] in (0, 1): + if event.message_type=="_NET_ACTIVE_WINDOW": + #to filter based on the source indication: + #ACTIVE_WINDOW_SOURCE = tuple(int(x) for x in os.environ.get("XPRA_ACTIVE_WINDOW_SOURCE", "0,1").split(",")) + #if event.data[0] in ACTIVE_WINDOW_SOURCE: log("_NET_ACTIVE_WINDOW: %s", event) self.set_active() self.emit("raised", event) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/x11/server.py new/xpra-4.0.4/xpra/x11/server.py --- old/xpra-4.0.3/xpra/x11/server.py 2020-08-07 11:17:40.000000000 +0200 +++ new/xpra-4.0.4/xpra/x11/server.py 2020-09-27 20:11:39.000000000 +0200 @@ -9,11 +9,11 @@ import os import signal import math -from collections import deque, namedtuple -from gi.repository import GObject, Gtk, Gdk +from collections import deque +from gi.repository import GObject, Gtk, Gdk, GdkX11 from xpra.version_util import XPRA_VERSION -from xpra.util import updict, rindex, envbool, envint, typedict, WORKSPACE_NAMES +from xpra.util import updict, rindex, envbool, envint, typedict, AdHocStruct, WORKSPACE_NAMES from xpra.os_util import memoryview_to_bytes, strtobytes, bytestostr, monotonic_time from xpra.common import CLOBBER_UPGRADE, MAX_WINDOW_SIZE from xpra.server import server_features @@ -244,10 +244,12 @@ with xsync: self.root_overlay = X11Window.XCompositeGetOverlayWindow(xid) if self.root_overlay: - #ugly: API expects a window object with a ".xid" - X11WindowModel = namedtuple("X11WindowModel", "xid") - root_overlay = X11WindowModel(xid=self.root_overlay) - prop_set(root_overlay, "WM_TITLE", "latin1", "RootOverlay") + #ugly: API expects a window object with a ".get_xid()" method + window = AdHocStruct() + def get_xid(): + return self.root_overlay + window.get_xid = root.get_xid + prop_set(window, "WM_TITLE", "latin1", "RootOverlay") X11Window.AllowInputPassthrough(self.root_overlay) except Exception as e: log("XCompositeGetOverlayWindow(%#x)", xid, exc_info=True) @@ -1160,8 +1162,8 @@ # def update_root_overlay(self, window, x, y, image): - overlaywin = Gdk.window_foreign_new(self.root_overlay) - gc = overlaywin.new_gc() + display = Gdk.Display.get_default() + overlaywin = GdkX11.X11Window.foreign_new_for_display(display, self.root_overlay) wx, wy = window.get_property("geometry")[:2] #FIXME: we should paint the root overlay directly # either using XCopyArea or XShmPutImage, @@ -1170,29 +1172,39 @@ height = image.get_height() rowstride = image.get_rowstride() img_data = image.get_pixels() - if image.get_pixel_format().startswith("BGR"): - try: - from xpra.codecs.argb.argb import unpremultiply_argb, bgra_to_rgba #@UnresolvedImport - if image.get_pixel_format()=="BGRA": - img_data = unpremultiply_argb(img_data) - img_data = bgra_to_rgba(img_data) - except: - pass + rgb_format = image.get_pixel_format() + from xpra.codecs.argb.argb import ( #@UnresolvedImport + unpremultiply_argb, bgra_to_rgba, bgra_to_rgbx, r210_to_rgbx, bgr565_to_rgbx #@UnresolvedImport + ) + from cairo import OPERATOR_OVER, OPERATOR_SOURCE #pylint: disable=no-name-in-module + log("update_root_overlay%s rgb_format=%s, img_data=%i (%s)", + (window, x, y, image), rgb_format, len(img_data), type(img_data)) + operator = OPERATOR_SOURCE + if rgb_format=="BGRA": + img_data = unpremultiply_argb(img_data) + img_data = bgra_to_rgba(img_data) + operator = OPERATOR_OVER + elif rgb_format=="BGRX": + img_data = bgra_to_rgbx(img_data) + elif rgb_format=="r210": + #lossy... + img_data = r210_to_rgbx(img_data, width, height, rowstride, width*4) + rowstride = width*4 + elif rgb_format=="BGR565": + img_data = bgr565_to_rgbx(img_data) + rowstride *= 2 + else: + raise Exception("xync-xvfb root overlay paint code does not handle %s pixel format" % image.get_pixel_format()) img_data = memoryview_to_bytes(img_data) - has_alpha = image.get_pixel_format().find("A")>=0 log("update_root_overlay%s painting rectangle %s", (window, x, y, image), (wx+x, wy+y, width, height)) - if has_alpha: - import cairo - pixbuf = get_pixbuf_from_data(img_data, True, width, height, rowstride) - cr = overlaywin.cairo_create() - cr.new_path() - cr.rectangle(wx+x, wy+y, width, height) - cr.clip() - cr.set_source_pixbuf(pixbuf, wx+x, wy+y) - cr.set_operator(cairo.OPERATOR_OVER) - cr.paint() - else: - overlaywin.draw_rgb_32_image(gc, wx+x, wy+y, width, height, Gdk.RGB_DITHER_NONE, img_data, rowstride) + pixbuf = get_pixbuf_from_data(img_data, True, width, height, rowstride) + cr = overlaywin.cairo_create() + cr.new_path() + cr.rectangle(wx+x, wy+y, width, height) + cr.clip() + Gdk.cairo_set_source_pixbuf(cr, pixbuf, wx+x, wy+y) + cr.set_operator(operator) + cr.paint() image.free() def repaint_root_overlay(self): @@ -1213,7 +1225,8 @@ def do_repaint_root_overlay(self): self.repaint_root_overlay_timer = None root_width, root_height = self.get_root_window_size() - overlaywin = Gdk.window_foreign_new(self.root_overlay) + display = Gdk.Display.get_default() + overlaywin = GdkX11.X11Window.foreign_new_for_display(display, self.root_overlay) log("overlaywin: %s", overlaywin.get_geometry()) cr = overlaywin.cairo_create() def fill_grey_rect(shade, x, y, w, h): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xpra-4.0.3/xpra/x11/server_keyboard_config.py new/xpra-4.0.4/xpra/x11/server_keyboard_config.py --- old/xpra-4.0.3/xpra/x11/server_keyboard_config.py 2020-06-05 11:40:13.000000000 +0200 +++ new/xpra-4.0.4/xpra/x11/server_keyboard_config.py 2020-09-27 20:11:39.000000000 +0200 @@ -499,9 +499,11 @@ if self.xkbmap_raw: break level0 = levels[0] - if len(keysyms)>level0 and keysyms[level0]=="": + uq_keysyms = set(keysyms) + if len(uq_keysyms)<=1 or (len(keysyms)>level0 and keysyms[level0]==""): #if the keysym we would match for this keycode is 'NoSymbol', #then we can probably ignore it ('NoSymbol' shows up as "") + #same if there's only one actual keysym for this keycode kmlog("not toggling any modifiers state for keysyms=%s", keysyms) break def toggle_modifier(mod):
