Hello community,

here is the log from the commit of package xpra for openSUSE:Factory checked in 
at 2020-08-10 14:58:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/xpra (Old)
 and      /work/SRC/openSUSE:Factory/.xpra.new.3399 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "xpra"

Mon Aug 10 14:58:03 2020 rev:23 rq:824983 version:4.0.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/xpra/xpra.changes        2020-07-18 
21:00:40.099461876 +0200
+++ /work/SRC/openSUSE:Factory/.xpra.new.3399/xpra.changes      2020-08-10 
14:58:26.880014740 +0200
@@ -1,0 +2,47 @@
+Sat Aug  8 08:24:00 UTC 2020 - [email protected]
+
+- Update to version 4.0.3
+  * fix server crash caused by use after free in scrolling code
+  * fix encryption option overzealously enforced on all socket
+    types
+  * fix network layer compression errors that can cause
+    connections to drop
+  * fix printing errors with some shell character encodings
+  * fix NVENC h264 stream compatibility with HTML5 client
+  * fix windows not getting focused when clicking on title bar
+    (HTML5)
+  * fix suspend / resume errors with tray windows
+  * fix garbled terminal when ssh messages and 'top' client
+    conflict
+  * fix OpenGL force-enable option not honoured
+  * fix tray geometry errors
+  * fix socket setup error handler
+  * fix minimum video scaling not being honoured via heuristics
+  * fix error in main thread verifier (fortunately, never fired)
+  * fix archlinux build root stripping
+  * fix detection of named-pipe creation errors
+  * fix clipboard data sometimes going missing when ownership
+    changes
+  * fix memory contents of the swscale pixel format object
+  * fix csc_swscale converter getting recycled every time
+  * fix division by zero errors during window cleanup
+  * fix rfb connections missing all screen updates
+  * fix toolbox examples when running under wayland
+  * fix notification widget wrongly stealing input focus
+  * fix support for building with CUDA 11.0
+  * fix unshrinkable session-info window
+  * fix window resizing errors when non-GUI clients are also
+    connected
+  * avoid ever using b-frames for text content
+  * avoid opengl warning with wayland
+  * add extra environment variables to try to disable any server
+    side scaling
+  * also update mdns records when the session name changes
+  * workaround for older versions of python-cryptography
+  * use 'text' mode for 'geany' (fixes lossy screen updates)
+  * ensure all toolbox windows set a correct and readable window
+    title
+  * make it possible to specify the path used for saving video
+    streams / frames
+
+-------------------------------------------------------------------

Old:
----
  xpra-4.0.2.tar.xz

New:
----
  xpra-4.0.3.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ xpra.spec ++++++
--- /var/tmp/diff_new_pack.7jOJFO/_old  2020-08-10 14:58:28.752015728 +0200
+++ /var/tmp/diff_new_pack.7jOJFO/_new  2020-08-10 14:58:28.756015731 +0200
@@ -19,7 +19,7 @@
 
 %global __requires_exclude 
^typelib\\(GtkosxApplication\\)|typelib\\(GdkGLExt\\)|typelib\\(GtkGLExt\\).*$
 Name:           xpra
-Version:        4.0.2
+Version:        4.0.3
 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
@@ -144,6 +144,8 @@
     --root %{buildroot} \
     --prefix %{_prefix} \
     --with-service \
+    --with-Xdummy \
+    --with-Xdummy_wrapper \
     --verbose
 
 #Install nvenc.keys file

++++++ xpra-4.0.2.tar.xz -> xpra-4.0.3.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/NEWS new/xpra-4.0.3/NEWS
--- old/xpra-4.0.2/NEWS 2020-06-05 11:40:08.000000000 +0200
+++ new/xpra-4.0.3/NEWS 2020-08-08 08:50:20.000000000 +0200
@@ -1,3 +1,52 @@
+v4.0.3 (2020-08-07)
+======================
+       -- fix server crash caused by use after free in scrolling code
+       -- fix encryption option overzealously enforced on all socket types
+       -- fix network layer compression errors that can cause connections to 
drop
+       -- fix printing errors with some shell character encodings
+       -- fix NVENC h264 stream compatibility with HTML5 client
+       -- fix windows not getting focused when clicking on title bar (HTML5)
+       -- fix suspend / resume errors with tray windows
+       -- fix garbled terminal when ssh messages and 'top' client conflict
+       -- fix OpenGL force-enable option not honoured
+       -- fix tray geometry errors
+       -- fix missing tray with Ubuntu Gnome
+       -- fix socket setup error handler
+       -- fix minimum video scaling not being honoured via heuristics
+       -- fix error in main thread verifier (fortunately, never fired)
+       -- fix archlinux build root stripping
+       -- fix detection of named-pipe creation errors
+       -- fix MS Windows shadow server errors with 'bind=auto'
+       -- fix MS Windows Keymap_info.exe tool
+       -- fix MS Windows servers slow to handle connections with mDNS enabled
+       -- fix MacOS clipboard unnecessarily sending data
+       -- fix clipboard data sometimes going missing when ownership changes
+       -- fix memory contents of the swscale pixel format object
+       -- fix csc_swscale converter getting recycled every time
+       -- fix division by zero errors during window cleanup
+       -- fix rfb connections missing all screen updates
+       -- fix RPM spec file for CentOS 8
+       -- fix toolbox examples when running under wayland
+       -- fix 'xpra toolbox' subcommand on MacOS
+       -- fix MacOS errors with some subcommands (ie: 'list')
+       -- fix MacOS outdated system version requirements in hidden sub 
application
+       -- fix sshfp support on MacOS (was missing dns python module)
+       -- fix notification widget wrongly stealing input focus
+       -- fix support for building with CUDA 11.0
+       -- fix unshrinkable session-info window
+       -- fix window resizing errors when non-GUI clients are also connected
+       -- avoid ever using b-frames for text content
+       -- silence unhelpful gtk warnings on MacOS
+       -- avoid opengl warning with wayland
+       -- add extra environment variables to try to disable any server side 
scaling
+       -- also update mdns records when the session name changes
+       -- workaround for older versions of python-cryptography
+       -- use 'text' mode for 'geany' (fixes lossy screen updates)
+       -- ensure all toolbox windows set a correct and readable window title
+       -- remove workaround for unsupported versions of Ubuntu
+       -- make it possible to specify the path used for saving video streams / 
frames
+
+
 v4.0.2 (2020-06-04)
 ======================
        -- fix encryption not honoured with TCP sockets upgraded to WebSocket
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/content-type/50_class.conf 
new/xpra-4.0.3/content-type/50_class.conf
--- old/xpra-4.0.2/content-type/50_class.conf   2020-06-05 11:40:08.000000000 
+0200
+++ new/xpra-4.0.3/content-type/50_class.conf   2020-06-10 04:38:16.000000000 
+0200
@@ -30,6 +30,7 @@
 class-instance:evolution=text
 class-instance:Firefox=browser
 class-instance:file-roller=text
+class-instance:geany=text
 class-instance:gcm-picker=picture
 class-instance:gcm-import=text
 class-instance:gcm-viewer=text
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/cups/xpraforwarder 
new/xpra-4.0.3/cups/xpraforwarder
--- old/xpra-4.0.2/cups/xpraforwarder   2020-06-05 11:40:08.000000000 +0200
+++ new/xpra-4.0.3/cups/xpraforwarder   2020-06-10 04:38:16.000000000 +0200
@@ -38,7 +38,7 @@
 from urllib.parse import urlparse, parse_qs
 
 
-__version__ = "4.0.2"
+__version__ = "4.0.3"
 
 
 #Writes a syslog entry (msg) at the default facility:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/html5/index.html 
new/xpra-4.0.3/html5/index.html
--- old/xpra-4.0.2/html5/index.html     2020-06-05 11:40:10.000000000 +0200
+++ new/xpra-4.0.3/html5/index.html     2020-06-10 04:38:16.000000000 +0200
@@ -129,7 +129,7 @@
 
                <div id="about">
                        <h2>Xpra HTML5 Client</h2>
-                       <h3>Version 4.0.2</h3>
+                       <h3>Version 4.0.3</h3>
                        <span>
                                Copyright (c) 2013-2020 Antoine Martin 
&lt;[email protected]&gt;
                                <br />
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/html5/js/Utilities.js 
new/xpra-4.0.3/html5/js/Utilities.js
--- old/xpra-4.0.2/html5/js/Utilities.js        2020-06-05 11:40:10.000000000 
+0200
+++ new/xpra-4.0.3/html5/js/Utilities.js        2020-06-10 04:38:16.000000000 
+0200
@@ -10,7 +10,7 @@
 'use strict';
 
 const Utilities = {
-       VERSION : "4.0.2",
+       VERSION : "4.0.3",
        REVISION : "0",
        LOCAL_MODIFICATIONS : "0",
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/html5/js/Window.js 
new/xpra-4.0.3/html5/js/Window.js
--- old/xpra-4.0.2/html5/js/Window.js   2020-06-05 11:40:10.000000000 +0200
+++ new/xpra-4.0.3/html5/js/Window.js   2020-07-09 18:46:42.000000000 +0200
@@ -204,7 +204,7 @@
                //});
                // assign some interesting callbacks
                jQuery(this.d_header).click(function() {
-                       me.set_focus_cb(me);
+                       me.client._window_set_focus(me);
                });
        }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/setup.py new/xpra-4.0.3/setup.py
--- old/xpra-4.0.2/setup.py     2020-06-05 11:40:10.000000000 +0200
+++ new/xpra-4.0.3/setup.py     2020-07-09 18:46:42.000000000 +0200
@@ -739,7 +739,10 @@
             while i>=0 and len(dirs)>i+1:
                 if dirs[i+1] == "xpra":
                     dirs = dirs[i+2:]
-                i = dirs.index("pkg")
+                try:
+                    i = dirs.index("pkg")
+                except ValueError:
+                    break
         elif pkgdir and install_dir.startswith(pkgdir):
             #arch build dir:
             dirs = install_dir.lstrip(pkgdir).split(os.path.sep)
@@ -2004,7 +2007,7 @@
             return None
         vpos = out.rfind(", V")
         if vpos>0:
-            version = out[vpos+3:].strip("\n")
+            version = out[vpos+3:].split("\n")[0]
             version_str = " version %s" % version
         else:
             version = "0"
@@ -2064,10 +2067,13 @@
             #cmd += ["--input-drive-prefix", "/"]
             #cmd += ["--dependency-drive-prefix", "/"]
             cmd += ["-I%s" % os.path.abspath("win32")]
-        comp_code_options = [(30, 30), (35, 35)]
+        comp_code_options = []
+        if version<(11,):
+            comp_code_options.append((30, 30))
+        comp_code_options.append((35, 35))
         #see: 
http://docs.nvidia.com/cuda/maxwell-compatibility-guide/#building-maxwell-compatible-apps-using-cuda-6-0
         if version!=(0,) and version<(7, 5):
-            print("CUDA version %s is very unlikely to work")
+            print("CUDA version %s is very unlikely to work" % (version,))
             print("try upgrading to version 7.5 or later")
         if version>=(7, 5):
             comp_code_options.append((50, 50))
@@ -2081,6 +2087,8 @@
             comp_code_options.append((70, 70))
         if version>=(10, 0):
             comp_code_options.append((75, 75))
+        if version>=(11, 0):
+            comp_code_options.append((80, 80))
         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.2/svn-info new/xpra-4.0.3/svn-info
--- old/xpra-4.0.2/svn-info     2020-06-05 11:40:38.000000000 +0200
+++ new/xpra-4.0.3/svn-info     2020-08-08 08:50:24.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: 26625
+Revision: 27083
 Node Kind: directory
 Schedule: normal
 Last Changed Author: antoine
-Last Changed Rev: 26625
-Last Changed Date: 2020-06-05 04:14:36 +0100 (Fri, 05 Jun 2020)
+Last Changed Rev: 27082
+Last Changed Date: 2020-08-07 17:40:37 +0100 (Fri, 07 Aug 2020)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/svn-version new/xpra-4.0.3/svn-version
--- old/xpra-4.0.2/svn-version  2020-06-05 11:40:38.000000000 +0200
+++ new/xpra-4.0.3/svn-version  2020-08-08 08:50:24.000000000 +0200
@@ -1 +1 @@
-26625
+27083
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/win32/xpra.iss 
new/xpra-4.0.3/win32/xpra.iss
--- old/xpra-4.0.2/win32/xpra.iss       2020-06-05 11:40:10.000000000 +0200
+++ new/xpra-4.0.3/win32/xpra.iss       2020-06-10 04:38:16.000000000 +0200
@@ -1,9 +1,9 @@
 [Setup]
 AppName=Xpra
 AppId=Xpra_is1
-AppVersion=4.0.2
-AppVerName=Xpra 4.0.2
-UninstallDisplayName=Xpra 4.0.2
+AppVersion=4.0.3
+AppVerName=Xpra 4.0.3
+UninstallDisplayName=Xpra 4.0.3
 AppPublisher=xpra.org
 AppPublisherURL=http:;xpra.org/
 DefaultDirName={pf}\Xpra
@@ -16,7 +16,7 @@
 Compression=lzma2/max
 SolidCompression=yes
 AllowUNCPath=false
-VersionInfoVersion=4.0.2
+VersionInfoVersion=4.0.3
 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.2/xpra/__init__.py 
new/xpra-4.0.3/xpra/__init__.py
--- old/xpra-4.0.2/xpra/__init__.py     2020-06-05 11:40:41.000000000 +0200
+++ new/xpra-4.0.3/xpra/__init__.py     2020-08-08 08:50:26.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.2"
+__version__ = "4.0.3"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/client/client_tray.py 
new/xpra-4.0.3/xpra/client/client_tray.py
--- old/xpra-4.0.2/xpra/client/client_tray.py   2020-05-10 19:00:53.000000000 
+0200
+++ new/xpra-4.0.3/xpra/client/client_tray.py   2020-06-10 04:38:17.000000000 
+0200
@@ -93,7 +93,7 @@
         log("%s.reconfigure(%s) geometry=%s", self, force_send_configure, 
geometry)
         if geometry is None:
             if self._geometry or not tw:
-                geometry = self._geometry
+                geometry = self.get_geometry()
             else:
                 #make one up as best we can - maybe we have the size at least?
                 size = tw.get_size()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/client/client_widget_base.py 
new/xpra-4.0.3/xpra/client/client_widget_base.py
--- old/xpra-4.0.2/xpra/client/client_widget_base.py    2020-05-10 
19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/client_widget_base.py    2020-07-09 
18:46:42.000000000 +0200
@@ -55,6 +55,13 @@
         backing.init(ww, wh, bw, bh)
         return backing
 
+    def freeze(self):
+        pass
+
+    def unfreeze(self):
+        pass
+
+
     def workspace_changed(self):            # pragma: no cover
         pass
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/client/gl/gl_check.py 
new/xpra-4.0.3/xpra/client/gl/gl_check.py
--- old/xpra-4.0.2/xpra/client/gl/gl_check.py   2020-05-10 19:00:53.000000000 
+0200
+++ new/xpra-4.0.3/xpra/client/gl/gl_check.py   2020-06-10 04:38:17.000000000 
+0200
@@ -12,7 +12,6 @@
 from xpra.os_util import POSIX, OSX, bytestostr
 from xpra.log import Logger, CaptureHandler
 from xpra.client.gl.gl_drivers import WHITELIST, GREYLIST, VERSION_REQ, 
BLACKLIST, OpenGLFatalError
-from xpra.sound.gstreamer_util import force_enabled
 
 log = Logger("opengl")
 
@@ -130,7 +129,7 @@
         from OpenGL.GL import GL_VERSION, GL_EXTENSIONS
         from OpenGL.GL import glGetString, glGetIntegerv
         gl_version_str = glGetString(GL_VERSION)
-        if gl_version_str is None and not force_enabled:
+        if gl_version_str is None and not force_enable:
             raise_fatal_error("OpenGL version is missing - cannot continue")
             return props
         #b'4.6.0 NVIDIA 440.59' -> ['4', '6', '0 NVIDIA...']
@@ -147,7 +146,7 @@
             props["opengl"] = gl_major, gl_minor
             MIN_VERSION = (1,1)
             if (gl_major, gl_minor) < MIN_VERSION:
-                if not force_enabled:
+                if not force_enable:
                     raise_fatal_error("OpenGL output requires version %s or 
greater, not %s.%s" %
                                   (".".join([str(x) for x in MIN_VERSION]), 
gl_major, gl_minor))
                     return props
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-4.0.2/xpra/client/gl/gtk3/nativegl_client_window.py 
new/xpra-4.0.3/xpra/client/gl/gtk3/nativegl_client_window.py
--- old/xpra-4.0.2/xpra/client/gl/gtk3/nativegl_client_window.py        
2020-05-10 19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gl/gtk3/nativegl_client_window.py        
2020-06-30 17:12:41.000000000 +0200
@@ -9,7 +9,12 @@
 from xpra.client.gl.gtk3.gl_drawing_area import GLDrawingArea, GLContext
 
 def check_support(force_enable=False):
-    return GLContext().check_support(force_enable)  #pylint: 
disable=not-callable
+    import warnings
+    with warnings.catch_warnings():
+        warnings.filterwarnings("ignore", message=".*g_object_get_qdata:")
+        warnings.filterwarnings("ignore", message=".*g_object_set_qdata_full:")
+        warnings.filterwarnings("ignore", message=".*g_object_unref:")
+        return GLContext().check_support(force_enable)  #pylint: 
disable=not-callable
 
 
 class GLClientWindow(GLClientWindowBase):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/client/gobject_client_base.py 
new/xpra-4.0.3/xpra/client/gobject_client_base.py
--- old/xpra-4.0.2/xpra/client/gobject_client_base.py   2020-05-10 
19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gobject_client_base.py   2020-06-30 
17:12:41.000000000 +0200
@@ -443,7 +443,8 @@
             #replace with filename proposed
             self.filename = command[2]
             #read file from stdin
-            self.file_data = sys.stdin.read()
+            with open(sys.stdin.fileno(), mode='rb', closefd=False) as 
stdin_binary:
+                self.file_data = stdin_binary.read()
             log("read %i bytes from stdin", len(self.file_data))
         else:
             import os.path
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/client/gtk_base/example/clicks.py 
new/xpra-4.0.3/xpra/client/gtk_base/example/clicks.py
--- old/xpra-4.0.2/xpra/client/gtk_base/example/clicks.py       2020-05-10 
19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gtk_base/example/clicks.py       2020-06-10 
04:38:17.000000000 +0200
@@ -19,6 +19,7 @@
        def     __init__(self):
                self.window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
                self.window.connect("destroy", Gtk.main_quit)
+               self.window.set_title("Test Button Events")
                self.window.set_default_size(320, 200)
                self.window.set_border_width(20)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/client/gtk_base/example/colors.py 
new/xpra-4.0.3/xpra/client/gtk_base/example/colors.py
--- old/xpra-4.0.2/xpra/client/gtk_base/example/colors.py       2020-05-10 
19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gtk_base/example/colors.py       2020-06-30 
17:12:41.000000000 +0200
@@ -25,7 +25,10 @@
         self.counter = 0
         self.increase = True
         self.last_event = None
-        self.connect("draw", self.area_draw)
+        self.set_title("Animated Colors")
+        drawing_area = Gtk.DrawingArea()
+        drawing_area.connect("draw", self.area_draw)
+        self.add(drawing_area)
         self.connect("destroy", Gtk.main_quit)
         self.connect("key_press_event", self.on_press)
         self.connect("button_press_event", self.on_press)
@@ -56,7 +59,8 @@
         cr.set_font_size(32)
         #Clear everything:
         cr.set_operator(cairo.OPERATOR_CLEAR)
-        w, h = widget.get_size()
+        alloc = widget.get_allocated_size()[0]
+        w, h = alloc.width, alloc.height
         cr.rectangle(0, 0, w, h)
         cr.fill()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-4.0.2/xpra/client/gtk_base/example/colors_gradient.py 
new/xpra-4.0.3/xpra/client/gtk_base/example/colors_gradient.py
--- old/xpra-4.0.2/xpra/client/gtk_base/example/colors_gradient.py      
2020-05-10 19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gtk_base/example/colors_gradient.py      
2020-06-30 17:12:41.000000000 +0200
@@ -19,13 +19,15 @@
 
     def __init__(self):
         super().__init__()
-        self.set_title("Color Gradient")
+        self.set_title("Color Bit Depth")
         self.set_position(Gtk.WindowPosition.CENTER)
         self.set_default_size(1024, 768)
         self.set_app_paintable(True)
         self.set_events(Gdk.EventMask.KEY_PRESS_MASK)
         self.bpc = 16
-        self.connect("draw", self.area_draw)
+        drawing_area = Gtk.DrawingArea()
+        drawing_area.connect("draw", self.area_draw)
+        self.add(drawing_area)
         self.connect("configure_event", self.configure_event)
         #self.connect('resize', changed)
         self.connect("destroy", Gtk.main_quit)
@@ -54,7 +56,8 @@
     def area_draw(self, widget, cr):
         cr.save()
         cr.set_operator(cairo.OPERATOR_CLEAR)
-        w, h = widget.get_size()
+        alloc = widget.get_allocated_size()[0]
+        w, h = alloc.width, alloc.height
         cr.rectangle(0, 0, w, h)
         cr.fill()
         cr.restore()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-4.0.2/xpra/client/gtk_base/example/colors_plain.py 
new/xpra-4.0.3/xpra/client/gtk_base/example/colors_plain.py
--- old/xpra-4.0.2/xpra/client/gtk_base/example/colors_plain.py 2020-05-10 
19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gtk_base/example/colors_plain.py 2020-06-30 
17:12:41.000000000 +0200
@@ -22,7 +22,10 @@
         self.set_default_size(320, 320)
         self.set_app_paintable(True)
         self.set_events(Gdk.EventMask.KEY_PRESS_MASK)
-        self.connect("draw", self.area_draw)
+        self.set_title("Colors")
+        drawing_area = Gtk.DrawingArea()
+        drawing_area.connect("draw", self.area_draw)
+        self.add(drawing_area)
         self.connect("destroy", Gtk.main_quit)
 
     def show_with_focus(self):
@@ -38,7 +41,8 @@
         cr.set_font_size(32)
         #Clear everything:
         cr.set_operator(cairo.OPERATOR_CLEAR)
-        w, h = widget.get_size()
+        alloc = widget.get_allocated_size()[0]
+        w, h = alloc.width, alloc.height
         cr.rectangle(0, 0, w, h)
         cr.fill()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/client/gtk_base/example/cursors.py 
new/xpra-4.0.3/xpra/client/gtk_base/example/cursors.py
--- old/xpra-4.0.2/xpra/client/gtk_base/example/cursors.py      2020-05-10 
19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gtk_base/example/cursors.py      2020-06-10 
04:38:17.000000000 +0200
@@ -19,6 +19,7 @@
 def main():
        with program_context("cursors", "Cursors"):
                window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
+               window.set_title("Cursors")
                window.set_size_request(width, height)
                window.connect("delete_event", Gtk.main_quit)
        
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-4.0.2/xpra/client/gtk_base/example/fontrendering.py 
new/xpra-4.0.3/xpra/client/gtk_base/example/fontrendering.py
--- old/xpra-4.0.2/xpra/client/gtk_base/example/fontrendering.py        
2020-05-10 19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gtk_base/example/fontrendering.py        
2020-06-30 17:12:41.000000000 +0200
@@ -34,7 +34,10 @@
         self.set_position(Gtk.WindowPosition.CENTER)
         self.set_default_size(800, 600)
         self.set_app_paintable(True)
-        self.connect("draw", self.area_draw)
+        self.set_title("Font Rendering")
+        drawing_area = Gtk.DrawingArea()
+        drawing_area.connect("draw", self.area_draw)
+        self.add(drawing_area)
         self.connect("destroy", Gtk.main_quit)
 
     def show_with_focus(self):
@@ -66,7 +69,8 @@
                 self.paint_pattern(cr, x, y+2,   antialias, label, WHITE, 
BLACK)
                 cr.restore()
 
-        w, h = widget.get_size()
+        alloc = widget.get_allocated_size()[0]
+        w, h = alloc.width, alloc.height
         bw = w//4
         bh = h//4
         #copy ANTIALIAS_NONE to right hand side,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/client/gtk_base/example/grabs.py 
new/xpra-4.0.3/xpra/client/gtk_base/example/grabs.py
--- old/xpra-4.0.2/xpra/client/gtk_base/example/grabs.py        2020-05-10 
19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gtk_base/example/grabs.py        2020-06-10 
04:38:17.000000000 +0200
@@ -16,6 +16,7 @@
 def make_grab_window():
        window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
        window.set_size_request(600, 200)
+       window.set_title("Grabs")
        window.connect("delete_event", Gtk.main_quit)
        window.add_events(Gdk.EventMask.ALL_EVENTS_MASK)
        vbox = Gtk.VBox(homogeneous=False, spacing=0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-4.0.2/xpra/client/gtk_base/example/initiate_moveresize.py 
new/xpra-4.0.3/xpra/client/gtk_base/example/initiate_moveresize.py
--- old/xpra-4.0.2/xpra/client/gtk_base/example/initiate_moveresize.py  
2020-05-10 19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gtk_base/example/initiate_moveresize.py  
2020-06-10 04:38:17.000000000 +0200
@@ -23,6 +23,7 @@
 height = 200
 def make_window():
        window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
+       window.set_title("Window Move Resize")
        window.set_size_request(width, height)
        window.connect("delete_event", Gtk.main_quit)
        window.realize()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-4.0.2/xpra/client/gtk_base/example/text_entry.py 
new/xpra-4.0.3/xpra/client/gtk_base/example/text_entry.py
--- old/xpra-4.0.2/xpra/client/gtk_base/example/text_entry.py   2020-05-10 
19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gtk_base/example/text_entry.py   2020-06-10 
04:38:17.000000000 +0200
@@ -16,6 +16,7 @@
 
 def make_window():
     window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
+    window.set_title("Text Entry")
     window.connect("destroy", Gtk.main_quit)
     window.set_default_size(320, 200)
     window.set_border_width(20)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-4.0.2/xpra/client/gtk_base/example/transparent_colors.py 
new/xpra-4.0.3/xpra/client/gtk_base/example/transparent_colors.py
--- old/xpra-4.0.2/xpra/client/gtk_base/example/transparent_colors.py   
2020-05-10 19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gtk_base/example/transparent_colors.py   
2020-06-30 17:12:41.000000000 +0200
@@ -18,6 +18,7 @@
 
     def __init__(self):
         super().__init__()
+        self.set_title("Transparent Colors")
         self.set_position(Gtk.WindowPosition.CENTER)
         self.set_default_size(320, 320)
         screen = self.get_screen()
@@ -28,7 +29,9 @@
             print("transparency not available!")
         self.set_app_paintable(True)
         self.set_events(Gdk.EventMask.KEY_PRESS_MASK)
-        self.connect("draw", self.area_draw)
+        drawing_area = Gtk.DrawingArea()
+        drawing_area.connect("draw", self.area_draw)
+        self.add(drawing_area)
         self.connect("destroy", Gtk.main_quit)
 
     def show_with_focus(self):
@@ -45,7 +48,8 @@
         #Clear everything:
         cr.save()
         cr.set_operator(cairo.OPERATOR_CLEAR)
-        w, h = widget.get_size()
+        alloc = widget.get_allocated_size()[0]
+        w, h = alloc.width, alloc.height
         cr.rectangle(0, 0, w, h)
         cr.fill()
         cr.restore()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-4.0.2/xpra/client/gtk_base/example/transparent_window.py 
new/xpra-4.0.3/xpra/client/gtk_base/example/transparent_window.py
--- old/xpra-4.0.2/xpra/client/gtk_base/example/transparent_window.py   
2020-05-10 19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gtk_base/example/transparent_window.py   
2020-06-30 17:12:41.000000000 +0200
@@ -18,6 +18,7 @@
 
     def __init__(self):
         super().__init__()
+        self.set_title("Window Transparency")
         self.set_position(Gtk.WindowPosition.CENTER)
         self.set_default_size(320, 320)
         screen = self.get_screen()
@@ -28,7 +29,9 @@
             print("transparency not available!")
         self.set_app_paintable(True)
         self.set_events(Gdk.EventMask.KEY_PRESS_MASK)
-        self.connect("draw", self.area_draw)
+        drawing_area = Gtk.DrawingArea()
+        drawing_area.connect("draw", self.area_draw)
+        self.add(drawing_area)
         self.connect("destroy", Gtk.main_quit)
 
     def show_with_focus(self):
@@ -48,7 +51,8 @@
         cr.paint()
 
         # Draw a circle
-        (width, height) = widget.get_size()
+        alloc = widget.get_allocated_size()[0]
+        width, height = alloc.width, alloc.height
         cr.set_source_rgba(1.0, 0.2, 0.2, 0.6)
         # Python <2.4 doesn't have conditional expressions
         if width < height:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-4.0.2/xpra/client/gtk_base/example/window_focus.py 
new/xpra-4.0.3/xpra/client/gtk_base/example/window_focus.py
--- old/xpra-4.0.2/xpra/client/gtk_base/example/window_focus.py 2020-05-10 
19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gtk_base/example/window_focus.py 2020-06-10 
04:38:17.000000000 +0200
@@ -21,6 +21,7 @@
 
 def make_window():
        window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
+       window.set_title("Window Focus")
        window.set_size_request(640, 200)
        window.connect("delete_event", Gtk.main_quit)
        vbox = Gtk.VBox()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-4.0.2/xpra/client/gtk_base/example/window_opacity.py 
new/xpra-4.0.3/xpra/client/gtk_base/example/window_opacity.py
--- old/xpra-4.0.2/xpra/client/gtk_base/example/window_opacity.py       
2020-05-10 19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gtk_base/example/window_opacity.py       
2020-06-10 04:38:17.000000000 +0200
@@ -16,7 +16,7 @@
 def make_window():
     win = Gtk.Window()
 
-    win.set_title('Alpha Demo')
+    win.set_title('Opacity Test')
     win.connect('delete-event', Gtk.main_quit)
 
     btn = Gtk.Button(label="Change Opacity")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-4.0.2/xpra/client/gtk_base/example/window_states.py 
new/xpra-4.0.3/xpra/client/gtk_base/example/window_states.py
--- old/xpra-4.0.2/xpra/client/gtk_base/example/window_states.py        
2020-05-10 19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gtk_base/example/window_states.py        
2020-06-10 04:38:17.000000000 +0200
@@ -15,6 +15,7 @@
 
 def make_window():
        window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
+       window.set_title("Window States")
        window.set_size_request(320, 500)
        window.connect("delete_event", Gtk.main_quit)
        vbox = Gtk.VBox(False, 0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-4.0.2/xpra/client/gtk_base/example/window_transient.py 
new/xpra-4.0.3/xpra/client/gtk_base/example/window_transient.py
--- old/xpra-4.0.2/xpra/client/gtk_base/example/window_transient.py     
2020-05-10 19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gtk_base/example/window_transient.py     
2020-06-10 04:38:17.000000000 +0200
@@ -14,6 +14,7 @@
 
 def make_window():
        window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
+       window.set_title("Window Transient Test")
        window.set_size_request(400, 300)
        window.connect("delete_event", Gtk.main_quit)
        vbox = Gtk.VBox(homogeneous=False, spacing=0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/client/gtk_base/session_info.py 
new/xpra-4.0.3/xpra/client/gtk_base/session_info.py
--- old/xpra-4.0.2/xpra/client/gtk_base/session_info.py 2020-05-10 
19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gtk_base/session_info.py 2020-07-09 
18:46:42.000000000 +0200
@@ -1110,7 +1110,9 @@
         W = 360
         H = 160*3//ngraphs
         w = min(maxw, max(W, rect.width-20))
-        h = min(maxh//ngraphs, max(H, (h-bh-20)//ngraphs, 
(rect.height-bh-20)//ngraphs))
+        #need some padding to be able to shrink the window again:
+        pad = 50
+        h = min(maxh-pad//ngraphs, max(H, (h-bh-pad)//ngraphs, 
(rect.height-bh-pad)//ngraphs))
         #bandwidth graph:
         labels, datasets = [], []
         if self.net_in_bitcount and self.net_out_bitcount:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/client/gtk_base/toolbox.py 
new/xpra-4.0.3/xpra/client/gtk_base/toolbox.py
--- old/xpra-4.0.2/xpra/client/gtk_base/toolbox.py      2020-05-10 
19:00:53.000000000 +0200
+++ new/xpra-4.0.3/xpra/client/gtk_base/toolbox.py      2020-08-07 
11:17:40.000000000 +0200
@@ -21,7 +21,7 @@
     label,
     )
 from xpra.platform.paths import get_icon_dir, get_python_execfile_command
-from xpra.os_util import OSX, WIN32, is_X11
+from xpra.os_util import WIN32, is_X11
 from xpra.log import Logger
 
 log = Logger("client", "util")
@@ -189,11 +189,7 @@
         gui = ToolboxGUI()
         register_os_signals(gui.app_signal, "Xpra Toolbox")
         ready()
-        if OSX:
-            from xpra.platform.darwin.gui import wait_for_open_handlers
-            wait_for_open_handlers(gui.show, gui.open_file, gui.open_url)
-        else:
-            gui.show()
+        gui.show()
         Gtk.main()
         log("do_main() gui.exit_code=%i", gui.exit_code)
         return gui.exit_code
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/client/top_client.py 
new/xpra-4.0.3/xpra/client/top_client.py
--- old/xpra-4.0.2/xpra/client/top_client.py    2020-06-05 11:40:10.000000000 
+0200
+++ new/xpra-4.0.3/xpra/client/top_client.py    2020-08-07 11:17:40.000000000 
+0200
@@ -62,6 +62,8 @@
     return stdscr
 
 def curses_clean(stdscr):
+    if not stdscr:
+        return
     stdscr.keypad(False)
     curses.nocbreak()
     curses.echo()
@@ -90,7 +92,7 @@
 class TopClient:
 
     def __init__(self, opts):
-        self.stdscr = curses_init()
+        self.stdscr = None
         self.socket_dirs = opts.socket_dirs
         self.socket_dir = opts.socket_dir
         self.position = 0
@@ -100,6 +102,7 @@
         self.dotxpra = DotXpra(self.socket_dir, self.socket_dirs)
 
     def run(self):
+        self.stdscr = curses_init()
         for signum in (signal.SIGINT, signal.SIGTERM):
             signal.signal(signum, self.signal_handler)
         self.update_loop()
@@ -278,8 +281,14 @@
         self.server_last_info = typedict()
         self.server_last_info_time = 0
         self.info_timer = 0
+        self.stdscr = None
+        self.update_screen()
+
+    def server_connection_established(self, caps):
+        r = super().server_connection_established(caps)
         self.stdscr = curses_init()
         self.update_screen()
+        return r
 
     def run(self):
         register_os_signals(self.signal_handler, "Top Client")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/clipboard/clipboard_core.py 
new/xpra-4.0.3/xpra/clipboard/clipboard_core.py
--- old/xpra-4.0.2/xpra/clipboard/clipboard_core.py     2020-05-10 
19:00:54.000000000 +0200
+++ new/xpra-4.0.3/xpra/clipboard/clipboard_core.py     2020-06-30 
17:12:41.000000000 +0200
@@ -620,7 +620,7 @@
             self._have_token, self._greedy_client, self._block_owner_change)
         if not self._enabled or self._block_owner_change:
             return
-        if self._have_token or (self._greedy_client and self._can_send):
+        if self._have_token or ((self._greedy_client or self._want_targets) 
and self._can_send):
             if self._have_token or DELAY_SEND_TOKEN<0:
                 #token ownership will change or told not to wait
                 GLib.idle_add(self.emit_token)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-4.0.2/xpra/codecs/csc_swscale/colorspace_converter.pyx 
new/xpra-4.0.3/xpra/codecs/csc_swscale/colorspace_converter.pyx
--- old/xpra-4.0.2/xpra/codecs/csc_swscale/colorspace_converter.pyx     
2020-05-10 19:00:54.000000000 +0200
+++ new/xpra-4.0.3/xpra/codecs/csc_swscale/colorspace_converter.pyx     
2020-06-30 17:12:41.000000000 +0200
@@ -1,6 +1,6 @@
 # This file is part of Xpra.
 # Copyright (C) 2013 Arthur Huillet
-# Copyright (C) 2012-2018 Antoine Martin <[email protected]>
+# Copyright (C) 2012-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.
 
@@ -70,11 +70,11 @@
 
 cdef class CSCPixelFormat:
     cdef AVPixelFormat av_enum
-    cdef char* av_enum_name
+    cdef object av_enum_name
     cdef float width_mult[4]
     cdef float height_mult[4]
-    cdef char *pix_fmt
-    def __init__(self, AVPixelFormat av_enum, char *av_enum_name, width_mult, 
height_mult, char *pix_fmt):
+    cdef object pix_fmt
+    def __init__(self, AVPixelFormat av_enum, av_enum_name, width_mult, 
height_mult, pix_fmt):
         self.av_enum = av_enum
         self.av_enum_name = av_enum_name
         for i in range(4):
@@ -86,7 +86,7 @@
         self.pix_fmt = pix_fmt
 
     def __repr__(self):
-        return "CSCPixelFormat(%s)" % av_enum_name
+        return "CSCPixelFormat(%s)" % self.av_enum_name
 
 #we could use a class to represent these options:
 COLORSPACES = []
@@ -107,7 +107,7 @@
      ]
 FORMATS = {}
 for av_enum_name, av_enum, width_mult, height_mult, pix_fmt in FORMAT_OPTIONS:
-    FORMATS[pix_fmt] = CSCPixelFormat(av_enum, av_enum_name.encode("latin1"), 
width_mult, height_mult, pix_fmt.encode("latin1"))
+    FORMATS[pix_fmt] = CSCPixelFormat(av_enum, av_enum_name, width_mult, 
height_mult, pix_fmt)
     if pix_fmt not in COLORSPACES:
         COLORSPACES.append(pix_fmt)
 log("swscale pixel formats: %s", FORMATS)
@@ -251,17 +251,7 @@
                     setup_cost=20, min_w=8, min_h=2, can_scale=True,
                     max_w=MAX_WIDTH, max_h=MAX_HEIGHT)
 
-
-MIN_SWSCALE_VERSION = (2, 1, 1)
-if (LIBSWSCALE_VERSION_MAJOR, LIBSWSCALE_VERSION_MINOR, 
LIBSWSCALE_VERSION_MICRO)<MIN_SWSCALE_VERSION and is_Ubuntu():
-    log.warn("buggy Ubuntu swscale version detected: %s", get_version())
-    if envbool("XPRA_FORCE_SWSCALE", False):
-        log.warn("XPRA_FORCE_SWSCALE enabled at your own risk!")
-    else:
-        log.warn("cowardly refusing to use it to avoid problems, set the 
environment variable:")
-        log.warn("XPRA_FORCE_SWSCALE=1")
-        log.warn("to use it anyway, at your own risk")
-        COLORSPACES = []
+assert (LIBSWSCALE_VERSION_MAJOR, LIBSWSCALE_VERSION_MINOR, 
LIBSWSCALE_VERSION_MICRO)>(2, 1, 1)
 
 
 cdef class ColorspaceConverter:
@@ -406,7 +396,7 @@
             self.out_size[i] = 0
 
     def is_closed(self):
-        return self.context!=NULL
+        return self.context==NULL
 
 
     def convert_image(self, image):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/codecs/enc_x264/encoder.pyx 
new/xpra-4.0.3/xpra/codecs/enc_x264/encoder.pyx
--- old/xpra-4.0.2/xpra/codecs/enc_x264/encoder.pyx     2020-05-10 
19:00:54.000000000 +0200
+++ new/xpra-4.0.3/xpra/codecs/enc_x264/encoder.pyx     2020-08-07 
11:17:40.000000000 +0200
@@ -539,8 +539,8 @@
             return TUNE
         if self.content_type=="video":
             return b"film"
-        elif self.content_type=="text":
-            return b"grain"
+        #elif self.content_type=="text":
+        #    return b"grain"
         #return "animation"
         return b"zerolatency"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/codecs/nvenc/encoder.pyx 
new/xpra-4.0.3/xpra/codecs/nvenc/encoder.pyx
--- old/xpra-4.0.2/xpra/codecs/nvenc/encoder.pyx        2020-05-10 
19:00:54.000000000 +0200
+++ new/xpra-4.0.3/xpra/codecs/nvenc/encoder.pyx        2020-08-07 
11:17:40.000000000 +0200
@@ -1217,6 +1217,12 @@
         },
     }
 
+PROFILE_STR = {}
+for codec_guid, profiles in CODEC_PROFILES_GUIDS.items():
+    for profile_guid, profile_name in profiles.items():
+        PROFILE_STR[profile_guid] = profile_name
+
+
 #this one is not defined anywhere but in the OBS source
 #(I think they have access to information we do not have):
 #GUID NV_ENC_PRESET_STREAMING = 
c_parseguid("7ADD423D-D035-4F6F-AEA5-50885658643C")
@@ -1479,6 +1485,7 @@
     cdef NV_ENC_BUFFER_FORMAT bufferFmt
     cdef object codec_name
     cdef object preset_name
+    cdef object profile_name
     cdef object pixel_format
     cdef uint8_t lossless
     #statistics, etc:
@@ -1567,6 +1574,7 @@
 
         #the pixel format we feed into the encoder
         self.pixel_format = self.get_target_pixel_format(self.quality)
+        self.profile_name = self._get_profile(options)
         self.lossless = self.get_target_lossless(self.pixel_format, 
self.quality)
         log("using %s %s compression at %s%% quality with pixel format %s",
             ["lossy","lossless"][self.lossless], encoding, self.quality, 
self.pixel_format)
@@ -1578,6 +1586,21 @@
             self.init_device(options)
 
 
+    cdef _get_profile(self, options):
+        #convert the pixel format into a "colourspace" string:
+        csc_mode = "YUV420P"
+        if self.pixel_format in ("BGRX", "BGRA", "YUV444P"):
+            csc_mode = "YUV444P"
+        elif self.pixel_format=="r210":
+            csc_mode = "YUV444P10"
+
+        #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)
+        return profile
+
+
     def threaded_init_device(self, options):
         global device_lock
         with device_lock:
@@ -1821,6 +1844,16 @@
         preset = self.get_preset(self.codec)
         self.preset_name = CODEC_PRESETS_GUIDS.get(guidstr(preset), 
guidstr(preset))
         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]
+        profile_guidstr = profiles.get(self.profile_name)
+        cdef GUID profile
+        if profile_guidstr:
+            profile = c_parseguid(profile_guidstr)
+        else:
+            profile = NV_ENC_CODEC_PROFILE_AUTOSELECT_GUID
+        log("using profile=%s", PROFILE_STR.get(guidstr(profile)))
 
         input_format = BUFFER_FORMAT[self.bufferFmt]
         input_formats = self.query_input_formats(codec)
@@ -1855,6 +1888,7 @@
             #config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_VBR     
#FIXME: check NV_ENC_CAPS_SUPPORTED_RATECONTROL_MODES caps
             #config.rcParams.enableMinQP = 1
             #config.rcParams.enableMaxQP = 1
+            config.profileGUID = profile
             config.gopLength = NVENC_INFINITE_GOPLENGTH
             config.frameIntervalP = 1
             #0=max quality, 63 lowest quality
@@ -2002,6 +2036,8 @@
                 "ratio_pct" : int(100 * self.bytes_out // b)})
         if self.preset_name:
             info["preset"] = self.preset_name
+        if self.profile_name:
+            info["profile"] = self.profile_name
         cdef double t = self.time
         info["total_time_ms"] = int(self.time*1000.0)
         if self.frames>0 and t>0:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/gtk_common/error.py 
new/xpra-4.0.3/xpra/gtk_common/error.py
--- old/xpra-4.0.2/xpra/gtk_common/error.py     2020-05-10 19:00:54.000000000 
+0200
+++ new/xpra-4.0.3/xpra/gtk_common/error.py     2020-06-30 17:12:41.000000000 
+0200
@@ -51,7 +51,8 @@
 else:
     def verify_main_thread():
         if not is_main_thread():
-            log.error("Error: invalid access from thread %s", ct)
+            import threading
+            log.error("Error: invalid access from thread %s", 
threading.current_thread())
             traceback.print_stack()
     verify_main_thread()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/gtk_common/gtk_notifier.py 
new/xpra-4.0.3/xpra/gtk_common/gtk_notifier.py
--- old/xpra-4.0.2/xpra/gtk_common/gtk_notifier.py      2020-05-10 
19:00:54.000000000 +0200
+++ new/xpra-4.0.3/xpra/gtk_common/gtk_notifier.py      2020-07-09 
18:46:42.000000000 +0200
@@ -167,6 +167,8 @@
         self.nid = nid
         Gtk.Window.__init__(self)
 
+        self.set_accept_focus(False)
+        self.set_focus_on_map(False)
         self.set_size_request(stack.size_x, -1)
         self.set_decorated(False)
         self.set_deletable(False)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/gtk_common/keymap.py 
new/xpra-4.0.3/xpra/gtk_common/keymap.py
--- old/xpra-4.0.2/xpra/gtk_common/keymap.py    2020-05-10 19:00:54.000000000 
+0200
+++ new/xpra-4.0.3/xpra/gtk_common/keymap.py    2020-07-09 18:46:42.000000000 
+0200
@@ -1,11 +1,10 @@
 #!/usr/bin/env python
 # This file is part of Xpra.
 # Copyright (C) 2008 Nathaniel Smith <[email protected]>
-# Copyright (C) 2011-2019 Antoine Martin <[email protected]>
+# Copyright (C) 2011-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.
 
-from gi.repository import Gdk
 
 from xpra.log import Logger
 
@@ -23,6 +22,7 @@
         by adding the keyval_name.
         We can also ignore some keys
     """
+    from gi.repository import Gdk
     display = Gdk.Display.get_default()
     if not display:
         return ()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/net/file_transfer.py 
new/xpra-4.0.3/xpra/net/file_transfer.py
--- old/xpra-4.0.2/xpra/net/file_transfer.py    2020-05-10 19:00:54.000000000 
+0200
+++ new/xpra-4.0.3/xpra/net/file_transfer.py    2020-06-30 17:12:41.000000000 
+0200
@@ -781,7 +781,7 @@
         #convert str to utf8 bytes:
         try:
             base = basefilename.encode("utf8")
-        except UnicodeEncodeError:
+        except (AttributeError, UnicodeEncodeError):
             base = strtobytes(basefilename)
         self.send("send-file", base, mimetype, printit, openit, filesize, 
cdata, options, send_id)
         return True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/net/protocol.py 
new/xpra-4.0.3/xpra/net/protocol.py
--- old/xpra-4.0.2/xpra/net/protocol.py 2020-06-05 11:40:11.000000000 +0200
+++ new/xpra-4.0.3/xpra/net/protocol.py 2020-08-07 11:17:40.000000000 +0200
@@ -576,7 +576,7 @@
                     packet[i] = item.data
                     min_comp_size += l
                     size_check += l
-            elif ti in (str, bytes) and level>0 and l>LARGE_PACKET_SIZE:
+            elif ti==bytes and level>0 and l>LARGE_PACKET_SIZE:
                 log.warn("Warning: found a large uncompressed item")
                 log.warn(" in packet '%s' at position %i: %s bytes", 
packet[0], i, len(item))
                 #add new binary packet with large item:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/net/pycryptography_backend.py 
new/xpra-4.0.3/xpra/net/pycryptography_backend.py
--- old/xpra-4.0.2/xpra/net/pycryptography_backend.py   2020-05-10 
19:00:54.000000000 +0200
+++ new/xpra-4.0.3/xpra/net/pycryptography_backend.py   2020-06-10 
04:38:17.000000000 +0200
@@ -1,10 +1,10 @@
 # This file is part of Xpra.
-# Copyright (C) 2011-2015 Antoine Martin <[email protected]>
+# Copyright (C) 2011-2020 Antoine Martin <[email protected]>
 # Copyright (C) 2008, 2009, 2010 Nathaniel Smith <[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.
 
-from xpra.os_util import strtobytes
+from xpra.os_util import strtobytes, memoryview_to_bytes
 from xpra.log import Logger
 
 log = Logger("network", "crypto")
@@ -88,7 +88,25 @@
 
 def get_decryptor(key, iv):
     decryptor = _get_cipher(key, iv).decryptor()
-    decryptor.decrypt = decryptor.update
+    def i(s):
+        try:
+            return int(s)
+        except ValueError:
+            return 0
+    import cryptography
+    version = cryptography.__version__
+    supports_memoryviews = tuple(i(s) for s in version.split("."))>=(2, 5)
+    log("get_decryptor(..) python-cryptography supports_memoryviews(%s)=%s",
+        version, supports_memoryviews)
+    if supports_memoryviews:
+        decryptor.decrypt = decryptor.update
+    else:
+        del key, iv
+        #with older versions of python-cryptography,
+        #we have to copy the memoryview to a bytearray:
+        def decrypt(v):
+            return decryptor.update(memoryview_to_bytes(v))
+        decryptor.decrypt = decrypt
     return decryptor
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/net/socket_util.py 
new/xpra-4.0.3/xpra/net/socket_util.py
--- old/xpra-4.0.2/xpra/net/socket_util.py      2020-05-10 19:00:54.000000000 
+0200
+++ new/xpra-4.0.3/xpra/net/socket_util.py      2020-08-08 08:50:20.000000000 
+0200
@@ -599,8 +599,8 @@
                     except Exception as e:
                         handle_socket_error(sockpath, sperms, e)
                         del e
-    except:
-        for sock, cleanup_socket in defs:
+    except Exception:
+        for sock, cleanup_socket in defs.items():
             try:
                 cleanup_socket()
             except Exception as e:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/os_util.py 
new/xpra-4.0.3/xpra/os_util.py
--- old/xpra-4.0.2/xpra/os_util.py      2020-05-10 19:00:54.000000000 +0200
+++ new/xpra-4.0.3/xpra/os_util.py      2020-08-08 08:50:20.000000000 +0200
@@ -334,7 +334,8 @@
     return _linux_distribution
 
 def is_unity() -> bool:
-    return os.environ.get("XDG_CURRENT_DESKTOP", "").lower().find("unity")>=0
+    d = os.environ.get("XDG_CURRENT_DESKTOP", "").lower()
+    return d.find("unity")>=0 or d.find("ubuntu")>=0
 
 def is_gnome() -> bool:
     if os.environ.get("XDG_SESSION_DESKTOP", "").split("-", 1)[0] in ("i3", 
"ubuntu", ):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/platform/darwin/osx_clipboard.py 
new/xpra-4.0.3/xpra/platform/darwin/osx_clipboard.py
--- old/xpra-4.0.2/xpra/platform/darwin/osx_clipboard.py        2020-05-10 
19:00:55.000000000 +0200
+++ new/xpra-4.0.3/xpra/platform/darwin/osx_clipboard.py        2020-06-30 
17:12:41.000000000 +0200
@@ -101,13 +101,15 @@
         self.pasteboard.clearContents()
 
     def do_emit_token(self):
-        targets = filter_targets(self.pasteboard.types())
-        log("do_emit_token() targets=%s", targets)
-        packet_data = [targets, ]
-        if self._greedy_client:
-            text = self.get_clipboard_text()
-            if text:
-                packet_data += ["STRING", "bytes", 8, text]
+        packet_data = []
+        if self._want_targets:
+            targets = filter_targets(self.pasteboard.types())
+            log("do_emit_token() targets=%s", targets)
+            packet_data.append(targets)
+            if self._greedy_client:
+                text = self.get_clipboard_text()
+                if text:
+                    packet_data += ["STRING", "bytes", 8, text]
         self.send_clipboard_token_handler(self, packet_data)
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/platform/win32/dotxpra.py 
new/xpra-4.0.3/xpra/platform/win32/dotxpra.py
--- old/xpra-4.0.2/xpra/platform/win32/dotxpra.py       2020-05-10 
19:00:55.000000000 +0200
+++ new/xpra-4.0.3/xpra/platform/win32/dotxpra.py       2020-08-07 
11:17:40.000000000 +0200
@@ -25,6 +25,11 @@
         #socket-dir is not used by the win32 shadow server
         pass
 
+
+    def norm_socket_paths(self, local_display_name):
+        return [self.socket_path(local_display_name)]
+
+
     def socket_path(self, local_display_name):
         return PIPE_PATH+PIPE_PREFIX+local_display_name.replace(":", "")
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-4.0.2/xpra/platform/win32/namedpipes/listener.py 
new/xpra-4.0.3/xpra/platform/win32/namedpipes/listener.py
--- old/xpra-4.0.2/xpra/platform/win32/namedpipes/listener.py   2020-05-10 
19:00:55.000000000 +0200
+++ new/xpra-4.0.3/xpra/platform/win32/namedpipes/listener.py   2020-08-07 
11:17:40.000000000 +0200
@@ -7,7 +7,7 @@
 #@PydevCodeAnalysisIgnore
 
 from ctypes.wintypes import HANDLE, DWORD
-from ctypes import byref, sizeof, create_string_buffer, cast, c_void_p, 
pointer, POINTER
+from ctypes import byref, sizeof, create_string_buffer, cast, c_void_p, 
c_long, pointer, POINTER
 from threading import Thread
 
 from xpra.log import Logger
@@ -127,7 +127,7 @@
                     log.error(" %s", e)
                     return
                 log("CreatePipeHandle()=%#x", pipe_handle)
-                if pipe_handle==INVALID_HANDLE_VALUE:
+                if c_long(pipe_handle).value==INVALID_HANDLE_VALUE:
                     log.error("Error: invalid handle for named pipe '%s'", 
self.pipe_name)
                     return
             event = CreateEventA(None, True, False, None)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/platform/xposix/features.py 
new/xpra-4.0.3/xpra/platform/xposix/features.py
--- old/xpra-4.0.2/xpra/platform/xposix/features.py     2020-05-10 
19:00:55.000000000 +0200
+++ new/xpra-4.0.3/xpra/platform/xposix/features.py     2020-06-30 
17:12:41.000000000 +0200
@@ -24,6 +24,9 @@
              "GDK_BACKEND=x11",
              "#force Qt applications to use X11 so we can intercept them:",
              "QT_QPA_PLATFORM=xcb",
+             "#disable Qt scaling:"
+             "QT_AUTO_SCREEN_SET_FACTOR=0",
+             "QT_SCALE_FACTOR=1",
              "#overlay scrollbars complicate things:"
              "GTK_OVERLAY_SCROLLING=0",
              "#some versions of GTK3 honour this option, sadly not all:",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/platform/xposix/gui.py 
new/xpra-4.0.3/xpra/platform/xposix/gui.py
--- old/xpra-4.0.2/xpra/platform/xposix/gui.py  2020-05-10 19:00:55.000000000 
+0200
+++ new/xpra-4.0.3/xpra/platform/xposix/gui.py  2020-08-08 08:50:20.000000000 
+0200
@@ -10,7 +10,7 @@
 
 from xpra.os_util import bytestostr, hexstr
 from xpra.util import iround, envbool, envint, csv, ellipsizer
-from xpra.os_util import is_unity, is_gnome, is_kde, is_Fedora, is_X11, 
is_Wayland
+from xpra.os_util import is_unity, is_gnome, is_kde, is_Ubuntu, is_Fedora, 
is_X11, is_Wayland
 from xpra.log import Logger
 
 log = Logger("posix")
@@ -54,7 +54,7 @@
 GTK_MENUS = envbool("XPRA_GTK_MENUS", False)
 RANDR_DPI = envbool("XPRA_RANDR_DPI", True)
 XSETTINGS_DPI = envbool("XPRA_XSETTINGS_DPI", True)
-USE_NATIVE_TRAY = envbool("XPRA_USE_NATIVE_TRAY", is_unity() or (is_gnome() 
and not is_Fedora()) or is_kde())
+USE_NATIVE_TRAY = envbool("XPRA_USE_NATIVE_TRAY", is_unity() or (is_Ubuntu() 
and is_gnome()) or (is_gnome() and not is_Fedora()) or is_kde())
 XINPUT_WHEEL_DIV = envint("XPRA_XINPUT_WHEEL_DIV", 15)
 DBUS_SCREENSAVER = envbool("XPRA_DBUS_SCREENSAVER", False)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/scripts/main.py 
new/xpra-4.0.3/xpra/scripts/main.py
--- old/xpra-4.0.2/xpra/scripts/main.py 2020-05-17 18:12:15.000000000 +0200
+++ new/xpra-4.0.3/xpra/scripts/main.py 2020-08-07 11:17:40.000000000 +0200
@@ -98,6 +98,7 @@
 
     #turn off gdk scaling to make sure we get the actual window geometry:
     os.environ["GDK_SCALE"]="1"
+    os.environ["GDK_DPI_SCALE"] = "1"
     #client side decorations break window geometry,
     #disable this "feature" unless explicitly enabled:
     if os.environ.get("GTK_CSD") is None:
@@ -1800,7 +1801,10 @@
     if POSIX and os.environ.get("GDK_BACKEND") is None and not OSX:
         os.environ["GDK_BACKEND"] = "x11"
     if opts.opengl=="probe":
-        opts.opengl = run_opengl_probe()
+        if os.environ.get("XDG_SESSION_TYPE")=="wayland":
+            opts.opengl = "no"
+        else:
+            opts.opengl = run_opengl_probe()
     from xpra.platform.gui import init as gui_init
     gui_init()
 
@@ -2019,6 +2023,10 @@
 
 
 def no_gtk():
+    if OSX:
+        #we can't verify on macos because importing GtkosxApplication
+        #will import Gtk, and we need GtkosxApplication early to find the paths
+        return
     Gtk = sys.modules.get("gi.repository.Gtk")
     if Gtk is None:
         #all good, not loaded
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/server/mixins/fileprint_server.py 
new/xpra-4.0.3/xpra/server/mixins/fileprint_server.py
--- old/xpra-4.0.2/xpra/server/mixins/fileprint_server.py       2020-05-10 
19:00:55.000000000 +0200
+++ new/xpra-4.0.3/xpra/server/mixins/fileprint_server.py       2020-06-30 
17:12:41.000000000 +0200
@@ -141,16 +141,22 @@
             printlog.error("Error: invalid print packet, only %i arguments", 
len(packet))
             printlog.error(" %s", [repr_ellipsized(x) for x in packet])
             return
-        filename, file_data = packet[1:3]
+        def s(b):
+            try:
+                return b.decode("utf-8")
+            except Exception:
+                return bytestostr(b)
+        filename = s(packet[1])
+        file_data = packet[2]
         mimetype, source_uuid, title, printer, no_copies, print_options = "", 
"*", "unnamed document", "", 1, ""
         if len(packet)>=4:
-            mimetype = packet[3]
+            mimetype = bytestostr(packet[3])
         if len(packet)>=5:
             source_uuid = bytestostr(packet[4])
         if len(packet)>=6:
-            title = packet[5]
+            title = s(packet[5])
         if len(packet)>=7:
-            printer = packet[6]
+            printer = bytestostr(packet[6])
         if len(packet)>=8:
             no_copies = int(packet[7])
         if len(packet)>=9:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-4.0.2/xpra/server/mixins/server_base_controlcommands.py 
new/xpra-4.0.3/xpra/server/mixins/server_base_controlcommands.py
--- old/xpra-4.0.2/xpra/server/mixins/server_base_controlcommands.py    
2020-05-10 19:00:55.000000000 +0200
+++ new/xpra-4.0.3/xpra/server/mixins/server_base_controlcommands.py    
2020-06-30 17:12:41.000000000 +0200
@@ -371,6 +371,7 @@
         log.info("changed session name: %s", self.session_name)
         #self.all_send_client_command("name", name)    not supported by any 
clients, don't bother!
         self.setting_changed("session_name", name)
+        self.mdns_update()
         return "session name set to %s" % name
 
     def _control_windowsources_from_args(self, *args):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/server/mixins/window_server.py 
new/xpra-4.0.3/xpra/server/mixins/window_server.py
--- old/xpra-4.0.2/xpra/server/mixins/window_server.py  2020-05-10 
19:00:55.000000000 +0200
+++ new/xpra-4.0.3/xpra/server/mixins/window_server.py  2020-06-30 
17:12:41.000000000 +0200
@@ -16,6 +16,9 @@
 geomlog = Logger("geometry")
 eventslog = Logger("events")
 
+def noop(*_args):
+    pass
+
 
 """
 Mixin for servers that forward windows.
@@ -254,8 +257,8 @@
     def refresh_window_area(self, window, x, y, width, height, options=None):
         wid = self._window_to_id[window]
         for ss in tuple(self._server_sources.values()):
-            if isinstance(ss, WindowsMixin):
-                ss.damage(wid, window, x, y, width, height, options)
+            damage = getattr(ss, "damage", noop)
+            damage(wid, window, x, y, width, height, options)
 
     def _process_buffer_refresh(self, proto, packet):
         """ can be used for requesting a refresh, or tuning batch config, or 
both """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/server/server_base.py 
new/xpra-4.0.3/xpra/server/server_base.py
--- old/xpra-4.0.2/xpra/server/server_base.py   2020-05-10 19:00:56.000000000 
+0200
+++ new/xpra-4.0.3/xpra/server/server_base.py   2020-07-09 18:46:42.000000000 
+0200
@@ -11,6 +11,7 @@
 
 from xpra.server.server_core import ServerCore, get_thread_info
 from xpra.server.mixins.server_base_controlcommands import 
ServerBaseControlCommands
+from xpra.server.background_worker import add_work_item
 from xpra.net.common import may_log_packet
 from xpra.os_util import monotonic_time, bytestostr, strtobytes, WIN32
 from xpra.util import (
@@ -391,7 +392,7 @@
             ss.close()
             raise
         self._server_sources[proto] = ss
-        self.mdns_update()
+        add_work_item(self.mdns_update)
         #process ui half in ui thread:
         send_ui = ui_client and not is_request
         self.idle_add(self._process_hello_ui, ss, c, auth_caps, send_ui, 
share_count)
@@ -882,7 +883,7 @@
         source = self._server_sources.pop(protocol, None)
         if source:
             self.cleanup_source(source)
-            self.mdns_update()
+            add_work_item(self.mdns_update)
         for c in SERVER_BASES:
             c.cleanup_protocol(self, protocol)
         return source
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/server/window/window_source.py 
new/xpra-4.0.3/xpra/server/window/window_source.py
--- old/xpra-4.0.2/xpra/server/window/window_source.py  2020-05-10 
19:00:56.000000000 +0200
+++ new/xpra-4.0.3/xpra/server/window/window_source.py  2020-07-09 
18:46:42.000000000 +0200
@@ -1068,7 +1068,7 @@
                               self.global_statistics, self.statistics, 
self.bandwidth_limit)
         #update the normalized value:
         ww, wh = self.window_dimensions
-        self.batch_config.delay_per_megapixel = 
int(self.batch_config.delay*1000000//(ww*wh))
+        self.batch_config.delay_per_megapixel = 
int(self.batch_config.delay*1000000//max(1, (ww*wh)))
         self.statistics.last_recalculate = now
         self.update_av_sync_frame_delay()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/server/window/window_video_source.py 
new/xpra-4.0.3/xpra/server/window/window_video_source.py
--- old/xpra-4.0.2/xpra/server/window/window_video_source.py    2020-05-10 
19:00:56.000000000 +0200
+++ new/xpra-4.0.3/xpra/server/window/window_video_source.py    2020-08-07 
11:17:40.000000000 +0200
@@ -87,6 +87,7 @@
 SCROLL_MIN_PERCENT = max(1, min(100, envint("XPRA_SCROLL_MIN_PERCENT", 50)))
 MIN_SCROLL_IMAGE_SIZE = envint("XPRA_MIN_SCROLL_IMAGE_SIZE", 384)
 
+SAVE_VIDEO_PATH = os.environ.get("XPRA_SAVE_VIDEO_PATH", "")
 SAVE_VIDEO_STREAMS = envbool("XPRA_SAVE_VIDEO_STREAMS", False)
 SAVE_VIDEO_FRAMES = os.environ.get("XPRA_SAVE_VIDEO_FRAMES")
 if SAVE_VIDEO_FRAMES not in ("png", "jpeg", None):
@@ -1430,6 +1431,8 @@
                     #high speed means more scaling:
                     target = target * 60**2 // (q+20)**2
                     sscaling = {}
+                    mrs = get_min_required_scaling()
+                    min_ratio = mrs[0]/mrs[1]
                     for num, denom in SCALING_OPTIONS:
                         #scaled pixels per second value:
                         spps = pps*(num**2)/(denom**2)
@@ -1441,6 +1444,9 @@
                             #try to stick to the same value longer:
                             #give it a score boost (lowest score wins):
                             score = int(score/1.5)
+                        if num/denom>min_ratio:
+                            #higher than minimum, should not be used unless we 
have no choice:
+                            score = int(score*100)
                         sscaling[score] = (num, denom)
                     scalinglog("calculate_scaling%s wid=%i, pps=%s, target=%s, 
scores=%s",
                                (width, height, max_w, max_h), self.wid, pps, 
target, sscaling)
@@ -1746,13 +1752,16 @@
                 #don't scroll very low quality content, better to refresh it
                 scrolllog("low quality %s update, invalidating all scroll data 
(scaled_size=%s, quality=%s)",
                           coding, client_options.get("scaled_size"), 
client_options.get("quality", 100))
-                self.free_scroll_data()
+                self.do_free_scroll_data()
             else:
                 sd.invalidate(x, y, w, h)
         return packet
 
 
     def free_scroll_data(self):
+        self.call_in_encode_thread(False, self.do_free_scroll_data)
+
+    def do_free_scroll_data(self):
         sd = self.scroll_data
         if sd:
             self.scroll_data = None
@@ -1786,7 +1795,7 @@
         scroll_data = self.scroll_data
         if self.b_frame_flush_timer and scroll_data:
             scrolllog("no scrolling: b_frame_flush_timer=%s", 
self.b_frame_flush_timer)
-            self.free_scroll_data()
+            self.do_free_scroll_data()
             return False
         try:
             start = monotonic_time()
@@ -1829,7 +1838,7 @@
                 scrolllog.error("Error during scrolling detection")
                 scrolllog.error(" with image=%s, options=%s", image, options, 
exc_info=True)
             #make sure we start again from scratch next time:
-            self.free_scroll_data()
+            self.do_free_scroll_data()
             return False
 
     def encode_scrolling(self, scroll_data, image, options, match_pct):
@@ -2049,7 +2058,9 @@
                           }
             t = monotonic_time()
             tstr = time.strftime("%H-%M-%S", time.localtime(t))
-            filename = "./W%i-VDO-%s.%03i.%s" % (self.wid, tstr, 
(t*1000)%1000, SAVE_VIDEO_FRAMES)
+            filename = "W%i-VDO-%s.%03i.%s" % (self.wid, tstr, (t*1000)%1000, 
SAVE_VIDEO_FRAMES)
+            if SAVE_VIDEO_PATH:
+                filename = os.path.join(SAVE_VIDEO_PATH, filename)
             videolog("do_video_encode: saving %4ix%-4i pixels, %7i bytes to 
%s", w, h, (stride*h), filename)
             img.save(filename, SAVE_VIDEO_FRAMES, **kwargs)
 
@@ -2152,6 +2163,8 @@
             self.close_video_stream_file()
             elapsed = monotonic_time()-self.start_time
             stream_filename = "window-%i-%.1f-%s.%s" % (self.wid, elapsed, 
ve.get_type(), ve.get_encoding())
+            if SAVE_VIDEO_PATH:
+                stream_filename = os.path.join(SAVE_VIDEO_PATH, 
stream_filename)
             self.video_stream_file = open(stream_filename, "wb")
             log.info("saving new %s stream for window %i to %s", 
ve.get_encoding(), self.wid, stream_filename)
         if self.video_stream_file:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/src_info.py 
new/xpra-4.0.3/xpra/src_info.py
--- old/xpra-4.0.2/xpra/src_info.py     2020-06-05 11:40:38.000000000 +0200
+++ new/xpra-4.0.3/xpra/src_info.py     2020-08-08 08:50:24.000000000 +0200
@@ -1,2 +1,2 @@
 LOCAL_MODIFICATIONS=0
-REVISION=26625
+REVISION=27083
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-4.0.2/xpra/x11/server.py 
new/xpra-4.0.3/xpra/x11/server.py
--- old/xpra-4.0.2/xpra/x11/server.py   2020-06-05 11:40:13.000000000 +0200
+++ new/xpra-4.0.3/xpra/x11/server.py   2020-08-07 11:17:40.000000000 +0200
@@ -1030,7 +1030,7 @@
                         #try to ensure this won't trigger a resizing loop:
                         counter = max(0, resize_counter-1)
                         for s in self._server_sources.values():
-                            if s!=ss and isinstance(ss, WindowsMixin):
+                            if s!=ss and isinstance(s, WindowsMixin):
                                 s.resize_window(wid, window, aw, ah, 
resize_counter=counter)
                     damage |= owx!=ax or owy!=ay or resized
             if not shown and not skip_geometry:



Reply via email to