Hello community,

here is the log from the commit of package xpra for openSUSE:Factory checked in 
at 2019-12-11 12:13:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/xpra (Old)
 and      /work/SRC/openSUSE:Factory/.xpra.new.4691 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "xpra"

Wed Dec 11 12:13:44 2019 rev:11 rq:755729 version:3.0.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/xpra/xpra.changes        2019-11-21 
12:59:19.910515592 +0100
+++ /work/SRC/openSUSE:Factory/.xpra.new.4691/xpra.changes      2019-12-11 
12:14:05.712528912 +0100
@@ -1,0 +2,39 @@
+Wed Dec 11 07:13:25 UTC 2019 - Luigi Baldoni <aloi...@gmx.com>
+
+- Update to version 3.0.3
+  * fix clipboard synchronization with HTML5 client
+  * fix window repaints with GTK3
+  * fix GDK scaling causing window painting issues (force off)
+  * fix slow repaint with OpenGL and combined updates (ie:
+    scrolling)
+  * fix missing video screen updates with 32-bit browsers:
+    disable video
+  * fix for X11 applications requesting invalid clipboard targets
+  * fix "xpra top" errors when the terminal window is too small
+  * fix blank xpra dialog windows when closed then shown again
+    (ie: server commands)
+  * fix compilation on non-i386 32-bit platforms
+  * fix platform query errors causing command failures
+  * fix Python2 builds: ignore GTK2 deprecation warnings
+  * fix X11 property synchronization with Python2 builds
+  * fix XSetClassHint call with Python 3
+  * fix window move + resize shortcut
+  * fix ssh proxy options not preserved when loading session
+    files
+  * fix error and missing refresh after changing quality or
+    speed settings
+  * fix NVENC error when pynvml is not installed
+  * fix NVENC temporary failure retry code path
+  * fix DPI value from the command line with desktop-scaling
+  * fix typo in man page
+  * fix errors with some odd Python3 builds
+    (subprocess.getoutput)
+  * fix cursor packets missing encoding attribute
+  * fix notification error handling the speaker forwarding error
+    message
+  * fix incorrect and unhelpful message on connection error
+  * make it possible to disable colourspace synchronization
+  * show mdns status in xpra info
+  * support CUDA 10.2
+
+-------------------------------------------------------------------

Old:
----
  xpra-3.0.2.tar.xz

New:
----
  xpra-3.0.3.tar.xz

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

Other differences:
------------------
++++++ xpra.spec ++++++
--- /var/tmp/diff_new_pack.d4TjNW/_old  2019-12-11 12:14:07.624528374 +0100
+++ /var/tmp/diff_new_pack.d4TjNW/_new  2019-12-11 12:14:07.628528373 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package xpra
 #
-# Copyright (c) 2019 SUSE LLC.
+# Copyright (c) 2019 SUSE LLC
 # Copyright (c) 2012-2013 Pascal Bleser <pascal.ble...@opensuse.org>
 #
 # All modifications and additions to the file contributed by third parties
@@ -19,7 +19,7 @@
 
 %global __requires_exclude 
^typelib\\(GtkosxApplication\\)|typelib\\(GdkGLExt\\)|typelib\\(GtkGLExt\\).*$
 Name:           xpra
-Version:        3.0.2
+Version:        3.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

++++++ xpra-3.0.2.tar.xz -> xpra-3.0.3.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/NEWS new/xpra-3.0.3/NEWS
--- old/xpra-3.0.2/NEWS 2019-11-05 18:31:07.000000000 +0100
+++ new/xpra-3.0.3/NEWS 2019-12-10 12:20:42.000000000 +0100
@@ -1,3 +1,46 @@
+v3.0.3 (2019-12-10)
+======================
+       -- fix clipboard synchronization with HTML5 client
+       -- fix window repaints with GTK3
+       -- fix GDK scaling causing window painting issues (force off)
+       -- fix slow repaint with OpenGL and combined updates (ie: scrolling)
+       -- fix missing video screen updates with 32-bit browsers: disable video
+       -- fix for X11 applications requesting invalid clipboard targets
+       -- fix "xpra top" errors when the terminal window is too small
+       -- fix blank xpra dialog windows when closed then shown again (ie: 
server commands)
+       -- fix compilation on non-i386 32-bit platforms
+       -- fix platform query errors causing command failures
+       -- fix Python2 builds: ignore GTK2 deprecation warnings
+       -- fix X11 property synchronization with Python2 builds
+       -- fix XSetClassHint call with Python 3
+       -- fix window move + resize shortcut
+       -- fix ssh proxy options not preserved when loading session files
+       -- fix focus of dialogs with MacOS clients (ie: SSH dialogs)
+       -- fix error and missing refresh after changing quality or speed 
settings
+       -- fix NVENC error when pynvml is not installed
+       -- fix NVENC temporary failure retry code path
+       -- fix SSH start for shadow and start-desktop subcommands from MacOS
+       -- fix fullscreen / maximized windows on MacOS
+       -- fix bogus screen dimensions with GTK3 on MacOS
+       -- fix client launcher helper script on MacOS
+       -- fix window resizing with OpenGL on MacOS
+       -- fix DPI value from the command line with desktop-scaling
+       -- fix typo in man page
+       -- fix errors with some odd Python3 builds (subprocess.getoutput)
+       -- fix cursor packets missing encoding attribute
+       -- fix dangling symlink in html5 client Fedora RPM package
+       -- fix notification error handling the speaker forwarding error message
+       -- fix incorrect and unhelpful message on connection error
+       -- fix openssl crypto DLL errors during MS Windows installation
+       -- prevent conflict with Fedora downstream packaging of xpra
+       -- make it possible to disable colourspace synchronization
+       -- show mdns status in xpra info
+       -- MacOS library updates (many, including Python 3.8.0)
+       -- support CUDA 10.2
+       -- disable CSD on MS Windows (GTK3 CSD bug workaround)
+       -- re-enable OpenGL on MS Windows (was GTK3 bug)
+
+
 v3.0.2 (2019-11-05)
 ======================
        -- fix clipboard synchronization issue with MS Windows clients properly
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/cups/xpraforwarder 
new/xpra-3.0.3/cups/xpraforwarder
--- old/xpra-3.0.2/cups/xpraforwarder   2019-10-30 04:23:47.000000000 +0100
+++ new/xpra-3.0.3/cups/xpraforwarder   2019-11-18 16:50:49.000000000 +0100
@@ -42,7 +42,7 @@
     from urllib.parse import urlparse, parse_qs
 
 
-__version__ = "3.0.2"
+__version__ = "3.0.3"
 
 
 #Writes a syslog entry (msg) at the default facility:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/etc/xpra/conf.d/40_client.conf.in 
new/xpra-3.0.3/etc/xpra/conf.d/40_client.conf.in
--- old/xpra-3.0.2/etc/xpra/conf.d/40_client.conf.in    2019-11-05 
18:31:07.000000000 +0100
+++ new/xpra-3.0.3/etc/xpra/conf.d/40_client.conf.in    2019-11-08 
16:44:54.000000000 +0100
@@ -6,7 +6,7 @@
 #opengl = no
 #opengl = gtk, native
 #opengl = auto
-opengl = %(opengl)s
+opengl = probe
 
 # How we handle server authentication requests:
 #challenge-handlers=none
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/html5/connect.html 
new/xpra-3.0.3/html5/connect.html
--- old/xpra-3.0.2/html5/connect.html   2019-09-24 15:53:53.000000000 +0200
+++ new/xpra-3.0.3/html5/connect.html   2019-11-18 16:50:49.000000000 +0100
@@ -511,7 +511,10 @@
                        "sharing", "steal", "reconnect", "swap_keys",
                        "video", "mediasource_video", "floating_menu", 
"autohide", "clock",
                        "debug_main", "debug_keyboard", "debug_geometry", 
"debug_mouse", "debug_clipboard", "debug_draw", "debug_audio", "debug_network"];
-       var default_on = ["steal", "clipboard", "printing", "file_transfer", 
"reconnect", "floating_menu", "clock", "exit_with_children", 
"exit_with_client", "video"];
+       var default_on = ["steal", "clipboard", "printing", "file_transfer", 
"reconnect", "floating_menu", "clock", "exit_with_children", 
"exit_with_client"];
+       if (Utilities.is_64bit()) {
+               default_on.push("video");
+       }
        if (Utilities.isMacOS()) {
                default_on.push("swap_keys");
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/html5/index.html 
new/xpra-3.0.3/html5/index.html
--- old/xpra-3.0.2/html5/index.html     2019-09-24 15:53:54.000000000 +0200
+++ new/xpra-3.0.3/html5/index.html     2019-11-18 16:50:49.000000000 +0100
@@ -212,12 +212,6 @@
                        var float_menu_padding = 20;
                        var float_menu_width = (float_menu_item_size*4) + 
float_menu_padding;
 
-                       // disable right click menu:
-                       window.oncontextmenu = function(e) {
-                               //showCustomMenu();
-                               return false;
-                       }
-
                        var cdebug = function () {
                                Utilities.clog.apply(Utilities, arguments);
                        }
@@ -430,7 +424,7 @@
                                var exit_with_children = 
getboolparam("exit_with_children", false);
                                var exit_with_client = 
getboolparam("exit_with_client", false);
                                var sharing = getboolparam("sharing", false);
-                               var video = getboolparam("video", true);
+                               var video = getboolparam("video", 
Utilities.is_64bit());
                                var mediasource_video = 
getboolparam("mediasource_video", false);
                                var remote_logging = 
getboolparam("remote_logging", true);
                                var insecure = getboolparam("insecure", false);
@@ -932,6 +926,7 @@
 
                        var client = null;
                        $(document).ready(function() {
+                               clog("document is ready, browser is", 
navigator.platform, "64-bit:", Utilities.is_64bit());
                                var touchaction = getparam("touchaction") || 
"scroll";
                                touchaction_scroll = touchaction == "scroll";
                                set_touchaction();
@@ -1024,6 +1019,12 @@
                                                
$('#fullscreen_button').attr('data-icon', 'fullscreen');
                                        }
                                });
+                               // disable right click menu:
+                               window.oncontextmenu = function(e) {
+                                       client._poll_clipboard(e);
+                                       //showCustomMenu();
+                                       return false;
+                               }
                        });
                </script>
        </body>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/html5/js/Client.js 
new/xpra-3.0.3/html5/js/Client.js
--- old/xpra-3.0.2/html5/js/Client.js   2019-11-05 18:31:07.000000000 +0100
+++ new/xpra-3.0.3/html5/js/Client.js   2019-11-18 16:50:49.000000000 +0100
@@ -775,6 +775,8 @@
                }
        }
 
+       this._poll_clipboard(event);
+
        if (this.topwindow != null) {
                //send via a timer so we get a chance to capture the clipboard 
value,
                //before we send control-V to the server:
@@ -1409,8 +1411,8 @@
 
 XpraClient.prototype._poll_clipboard = function(e) {
        //see if the clipboard contents have changed:
-       this.debug("clipboard", "poll clipboard, navigator.clipboard=", 
navigator.clipboard);
        if (navigator.clipboard && navigator.clipboard.readText) {
+               this.debug("clipboard", "polling using", 
navigator.clipboard.readText);
                var client = this;
                //warning: this can take a while,
                //so we may send the click before the clipboard contents...
@@ -1433,6 +1435,7 @@
                if (!clipboardData) {
                        clipboardData = window.clipboardData;
                        if (!clipboardData) {
+                               this.debug("clipboard", "polling: no data 
available")
                                return;
                        }
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/html5/js/Utilities.js 
new/xpra-3.0.3/html5/js/Utilities.js
--- old/xpra-3.0.2/html5/js/Utilities.js        2019-10-30 04:23:47.000000000 
+0100
+++ new/xpra-3.0.3/html5/js/Utilities.js        2019-11-18 16:50:49.000000000 
+0100
@@ -10,7 +10,7 @@
 'use strict';
 
 var Utilities = {
-       VERSION : "3.0.2",
+       VERSION : "3.0.3",
 
        exc : function() {
                console.error.apply(console, arguments);
@@ -259,6 +259,26 @@
                return navigator.userAgent.includes("MSIE") || 
navigator.userAgent.includes("Trident/");
        },
 
+       is_64bit : function() {
+               var _to_check = [] ;
+               if (window.navigator.cpuClass)
+                       _to_check.push((window.navigator.cpuClass + 
"").toLowerCase());
+               if (window.navigator.platform)
+                       _to_check.push((window.navigator.platform + 
"").toLowerCase());
+               if (navigator.userAgent)
+                       _to_check.push((navigator.userAgent + 
"").toLowerCase());
+               var _64bits_signatures = ["x86_64", "x86-64", "Win64", "x64;", 
"amd64", "AMD64", "WOW64", "x64_64", "ia64", "sparc64", "ppc64", "IRIX64"];
+               var _i, _c;
+               for (_c=0; _c<_to_check.length; _c++) {
+                       for (_i=0 ; _i<_64bits_signatures.length; _i++) {
+                               if 
(_to_check[_c].indexOf(_64bits_signatures[_i].toLowerCase())!=-1) {
+                                       return true;
+                               }
+                       }
+               }
+               return false;
+       },
+
        getSimpleUserAgentString : function() {
                if (Utilities.isFirefox()) {
                        return "Firefox";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/man/xpra.1 new/xpra-3.0.3/man/xpra.1
--- old/xpra-3.0.2/man/xpra.1   2019-09-24 15:53:55.000000000 +0200
+++ new/xpra-3.0.3/man/xpra.1   2019-11-26 16:58:06.000000000 +0100
@@ -779,7 +779,7 @@
 \fB--ws-auth\fP=\fIMODULE\fP
 Just like the \fBauth\fP switch, except this one only applies
 to ws sockets: sockets defined using the \fBbind-ws\fP switch,
-or TCP sockets upgraded to websockets. (if the \fBhtmlfP option is enabled).
+or TCP sockets upgraded to websockets. (if the \fBhtml\fP option is enabled).
 .TP
 \fB--wss-auth\fP=\fIMODULE\fP
 Just like the \fBauth\fP switch, except this one only applies
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/scripts/xpra_launcher 
new/xpra-3.0.3/scripts/xpra_launcher
--- old/xpra-3.0.2/scripts/xpra_launcher        2019-09-24 15:53:55.000000000 
+0200
+++ new/xpra-3.0.3/scripts/xpra_launcher        2019-12-08 12:59:02.000000000 
+0100
@@ -18,6 +18,7 @@
         os.execvpe(py_exe, argv, env)
     sys.exit(1)
 
+os.environ["GTK_CSD"] = "0"
 from xpra.platform import program_context
 with program_context("Xpra-Launcher", "Xpra Connection Launcher"):
     from xpra.client.gtk_base.client_launcher import do_main
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/setup.py new/xpra-3.0.3/setup.py
--- old/xpra-3.0.2/setup.py     2019-11-05 18:31:07.000000000 +0100
+++ new/xpra-3.0.3/setup.py     2019-11-26 16:58:06.000000000 +0100
@@ -859,7 +859,6 @@
             'printing'              : bstr(printing_ENABLED),
             'dbus_control'          : bstr(dbus_ENABLED),
             'mmap'                  : bstr(True),
-            'opengl'                : "no" if WIN32 else "probe",
             }
     def convert_templates(subdirs):
         dirname = os.path.join(*(["etc", "xpra"] + subdirs))
@@ -1737,7 +1736,8 @@
 if modules_ENABLED:
     add_packages("xpra.buffers")
     buffers_pkgconfig = pkgconfig(optimize=3)
-    if BITS==32:
+    import platform
+    if platform.machine()=="i386":
         #this may well be sub-optimal:
         add_to_keywords(buffers_pkgconfig, "extra_compile_args", 
"-mfpmath=387")
     if cython_ENABLED:
@@ -2056,6 +2056,7 @@
         nvcc_exe = "nvcc.exe"
         CUDA_DIR = os.environ.get("CUDA_DIR", "C:\\Program Files\\NVIDIA GPU 
Computing Toolkit\\CUDA")
         path_options = [os.path.join(CUDA_DIR, x, "bin") for x in (
+            "v10.2",
             "v10.1",
             "v10.0",
             "v9.2",
@@ -2072,7 +2073,7 @@
                 break
     else:
         nvcc_exe = "nvcc"
-        for v in ("", "-10.1", "-10.0", "-9.2", "-9.1", "-9.0", "-8.0", 
"-7.5"):
+        for v in ("", "10.2", "-10.1", "-10.0", "-9.2", "-9.1", "-9.0", 
"-8.0", "-7.5"):
             path_options += ["/usr/local/cuda%s/bin" % v, "/opt/cuda%s/bin" % 
v]
     options = [os.path.join(x, nvcc_exe) for x in path_options]
     def which(cmd):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/setup_html5.py 
new/xpra-3.0.3/setup_html5.py
--- old/xpra-3.0.2/setup_html5.py       2019-09-24 15:53:55.000000000 +0200
+++ new/xpra-3.0.3/setup_html5.py       2019-12-08 12:59:02.000000000 +0100
@@ -61,10 +61,12 @@
     symlinks = {
         "jquery.js"     : [
             "/usr/share/javascript/jquery/jquery.js",
+            "/usr/share/javascript/jquery/latest/jquery.js",
             "/usr/share/javascript/jquery/3/jquery.js",
             ],
         "jquery-ui.js"     : [
             "/usr/share/javascript/jquery-ui/jquery-ui.js",
+            "/usr/share/javascript/jquery-ui/latest/jquery-ui.js",
             "/usr/share/javascript/jquery-ui/3/jquery-ui.js",
             ],
         }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/svn-info new/xpra-3.0.3/svn-info
--- old/xpra-3.0.2/svn-info     2019-11-05 18:31:10.000000000 +0100
+++ new/xpra-3.0.3/svn-info     2019-12-10 18:47:53.000000000 +0100
@@ -4,10 +4,10 @@
 Relative URL: ^/tags/v3.0.x/src
 Repository Root: file:///var/svn/repos/Xpra
 Repository UUID: 3bb7dfac-3a0b-4e04-842a-767bc560f471
-Revision: 24387
+Revision: 24692
 Node Kind: directory
 Schedule: normal
 Last Changed Author: antoine
-Last Changed Rev: 24387
-Last Changed Date: 2019-11-05 12:01:27 +0000 (Tue, 05 Nov 2019)
+Last Changed Rev: 24688
+Last Changed Date: 2019-12-10 08:58:31 +0000 (Tue, 10 Dec 2019)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/svn-version new/xpra-3.0.3/svn-version
--- old/xpra-3.0.2/svn-version  2019-11-05 18:31:10.000000000 +0100
+++ new/xpra-3.0.3/svn-version  2019-12-10 18:47:54.000000000 +0100
@@ -1 +1 @@
-24387
+24692
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/win32/BUILD_CUDA_KERNEL.BAT 
new/xpra-3.0.3/win32/BUILD_CUDA_KERNEL.BAT
--- old/xpra-3.0.2/win32/BUILD_CUDA_KERNEL.BAT  2019-09-24 15:53:58.000000000 
+0200
+++ new/xpra-3.0.3/win32/BUILD_CUDA_KERNEL.BAT  2019-11-26 16:58:06.000000000 
+0100
@@ -5,7 +5,7 @@
 SET CUDA_SRC=xpra\codecs\cuda_common\%KERNEL%.cu
 SET CUDA_BIN=xpra\codecs\cuda_common\%KERNEL%.fatbin
 
-SET NVCC_DIR=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin\
+SET NVCC_DIR=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.2\bin\
 SET NVCC=%NVCC_DIR%\nvcc.exe
 CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" 
x86_amd64
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/win32/MINGW_BUILD.sh 
new/xpra-3.0.3/win32/MINGW_BUILD.sh
--- old/xpra-3.0.2/win32/MINGW_BUILD.sh 2019-10-06 04:56:55.000000000 +0200
+++ new/xpra-3.0.3/win32/MINGW_BUILD.sh 2019-12-10 12:20:42.000000000 +0100
@@ -366,6 +366,11 @@
        cp -fn "${MINGW_PREFIX}/bin/openssl.exe" "${DIST}/"
        #use the old filename so we don't have to change the xpra.iss and the 
setup.py build system:
        cp -fn "${MINGW_PREFIX}/ssl/openssl.cnf" "${DIST}/openssl.cfg"
+       if [ "${PYTHON_MAJOR_VERSION}" == "3" ]; then
+               #we need those libraries at the top level:
+               mv "${DIST}"/lib/libssl-*dll "${DIST}/"
+               mv "${DIST}"/lib/libcrypto-*dll "${DIST}/"
+       fi
 fi
 
 if [ "${DO_VERPATCH}" == "1" ]; then
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/win32/xpra.iss 
new/xpra-3.0.3/win32/xpra.iss
--- old/xpra-3.0.2/win32/xpra.iss       2019-10-30 04:23:47.000000000 +0100
+++ new/xpra-3.0.3/win32/xpra.iss       2019-11-18 16:50:49.000000000 +0100
@@ -1,9 +1,9 @@
 [Setup]
 AppName=Xpra
 AppId=Xpra_is1
-AppVersion=3.0.2
-AppVerName=Xpra 3.0.2
-UninstallDisplayName=Xpra 3.0.2
+AppVersion=3.0.3
+AppVerName=Xpra 3.0.3
+UninstallDisplayName=Xpra 3.0.3
 AppPublisher=xpra.org
 AppPublisherURL=http:;xpra.org/
 DefaultDirName={pf}\Xpra
@@ -16,7 +16,7 @@
 Compression=lzma2/max
 SolidCompression=yes
 AllowUNCPath=false
-VersionInfoVersion=3.0.2
+VersionInfoVersion=3.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-3.0.2/xpra/__init__.py 
new/xpra-3.0.3/xpra/__init__.py
--- old/xpra-3.0.2/xpra/__init__.py     2019-11-05 18:31:19.000000000 +0100
+++ new/xpra-3.0.3/xpra/__init__.py     2019-12-10 18:47:54.000000000 +0100
@@ -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__ = "3.0.2"
+__version__ = "3.0.3"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/client/client_base.py 
new/xpra-3.0.3/xpra/client/client_base.py
--- old/xpra-3.0.2/xpra/client/client_base.py   2019-09-24 15:53:58.000000000 
+0200
+++ new/xpra-3.0.3/xpra/client/client_base.py   2019-12-08 13:07:35.000000000 
+0100
@@ -590,11 +590,11 @@
         if p and p.input_raw_packetcount==0:
             props = p.get_info()
             c = props.get("compression", "unknown")
-            e = props.get("encoder", "unknown")
+            e = props.get("encoder", "rencode")
             netlog.error("Error: failed to receive anything, not an xpra 
server?")
             netlog.error("  could also be the wrong protocol, username, 
password or port")
             netlog.error("  or the session was not found")
-            if c!="unknown" or e!="unknown":
+            if c!="unknown" or e!="rencode":
                 netlog.error("  or maybe this server does not support '%s' 
compression or '%s' packet encoding?", c, e)
         if self.exit_code is None:
             self.warn_and_quit(EXIT_CONNECTION_LOST, "Connection lost")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/client/client_window_base.py 
new/xpra-3.0.3/xpra/client/client_window_base.py
--- old/xpra-3.0.2/xpra/client/client_window_base.py    2019-10-06 
04:56:55.000000000 +0200
+++ new/xpra-3.0.3/xpra/client/client_window_base.py    2019-11-26 
16:58:06.000000000 +0100
@@ -25,7 +25,6 @@
 alphalog = Logger("alpha")
 
 
-REPAINT_ALL = os.environ.get("XPRA_REPAINT_ALL", "")
 SIMULATE_MOUSE_DOWN = envbool("XPRA_SIMULATE_MOUSE_DOWN", True)
 PROPERTIES_DEBUG = [x.strip() for x in 
os.environ.get("XPRA_WINDOW_PROPERTIES_DEBUG", "").split(",")]
 AWT_DIALOG_WORKAROUND = envbool("XPRA_AWT_DIALOG_WORKAROUND", WIN32)
@@ -76,6 +75,7 @@
         self.button_state = {}
         self.pixel_depth = pixel_depth      #0 for default
         self.window_offset = None           #actual vs reported coordinates
+        self.pending_refresh = []
 
         self.init_window(metadata)
         self.setup_window(bw, bh)
@@ -649,27 +649,34 @@
             from xpra.client.window_backing_base import fire_paint_callbacks
             fire_paint_callbacks(callbacks, -1, "no backing")
             return
-        def after_draw_refresh(success, message=""):
-            plog("after_draw_refresh(%s, %s) %sx%s at %sx%s encoding=%s, 
options=%s",
-                 success, message, width, height, x, y, coding, options)
-            if success<=0:
-                return
-            backing = self._backing
-            if backing and (backing.draw_needs_refresh or REPAINT_ALL):
-                if REPAINT_ALL=="1" or self._client.xscale!=1 or 
self._client.yscale!=1 or is_Wayland():
-                    rw, rh = self.get_size()
-                    rx, ry = 0, 0
-                else:
-                    rx, ry, rw, rh = self._client.srect(x, y, width, height)
-                #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)
         #only register this callback if we actually need it:
         if backing.draw_needs_refresh:
-            callbacks.append(after_draw_refresh)
+            if not backing.repaint_all:
+                self.pending_refresh.append((x, y, width, height))
+            if options.intget("flush", 0)==0:
+                callbacks.append(self.after_draw_refresh)
         backing.draw_region(x, y, width, height, coding, img_data, rowstride, 
options, callbacks)
 
+    def after_draw_refresh(self, success, message=""):
+        plog("after_draw_refresh(%s, %s) pending_refresh=%s",
+             success, message, self.pending_refresh)
+        backing = self._backing
+        if not backing:
+            return
+        if backing.repaint_all or self._client.xscale!=1 or 
self._client.yscale!=1 or is_Wayland():
+            #easy: just repaint the whole window:
+            rw, rh = self.get_size()
+            self.idle_add(self.queue_draw_area, 0, 0, rw, rh)
+            return
+        pr = self.pending_refresh
+        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]
+            self.idle_add(self.queue_draw_area, rx, ry, rw, rh)
+
     def eos(self):
         """ Note: this runs from the draw thread (not UI thread) """
         backing = self._backing
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/client/gl/gl_window_backing_base.py 
new/xpra-3.0.3/xpra/client/gl/gl_window_backing_base.py
--- old/xpra-3.0.2/xpra/client/gl/gl_window_backing_base.py     2019-11-05 
18:31:07.000000000 +0100
+++ new/xpra-3.0.3/xpra/client/gl/gl_window_backing_base.py     2019-12-08 
12:59:02.000000000 +0100
@@ -76,10 +76,10 @@
 JPEG_YUV = envbool("XPRA_JPEG_YUV", True)
 WEBP_YUV = envbool("XPRA_WEBP_YUV", True)
 FORCE_CLONE = envbool("XPRA_OPENGL_FORCE_CLONE", False)
-DRAW_REFRESH = envbool("XPRA_OPENGL_DRAW_REFRESH", PYTHON3)
+DRAW_REFRESH = envbool("XPRA_OPENGL_DRAW_REFRESH", True)
 FBO_RESIZE = envbool("XPRA_OPENGL_FBO_RESIZE", True)
 FBO_RESIZE_DELAY = envint("XPRA_OPENGL_FBO_RESIZE_DELAY", 50)
-CONTEXT_REINIT = envbool("XPRA_OPENGL_CONTEXT_REINIT", OSX)
+CONTEXT_REINIT = envbool("XPRA_OPENGL_CONTEXT_REINIT", False)
 
 CURSOR_IDLE_TIMEOUT = envint("XPRA_CURSOR_IDLE_TIMEOUT", 6)
 TEXTURE_CURSOR = envbool("XPRA_OPENGL_TEXTURE_CURSOR", True)
@@ -255,6 +255,10 @@
         self.bit_depth = self.get_bit_depth(pixel_depth)
         self.init_formats()
         self.draw_needs_refresh = DRAW_REFRESH
+        #the correct check would be this:
+        #self.repaint_all = self.is_double_buffered() or bw!=ww or bh!=wh
+        #but we're meant to be using double-buffered everywhere, so don't 
bother:
+        self.repaint_all = True
         self._backing.show()
 
     def init_gl_config(self, window_alpha):
@@ -347,6 +351,7 @@
         #and then doing the gl_init() call but without initializing the 
offscreen fbo.
         sx, sy, dx, dy, w, h = self.gravity_copy_coords(oldw, oldh, bw, bh)
         with context:
+            context.update_geometry()
             #invert Y coordinates for OpenGL:
             sy = (oldh-h)-sy
             dy = (bh-h)-dy
@@ -630,7 +635,8 @@
             glBindTexture(target, 0)
             glDisable(target)
             fire_paint_callbacks(callbacks, True)
-            self.present_fbo(0, 0, bw, bh, flush)
+            if not self.draw_needs_refresh:
+                self.present_fbo(0, 0, bw, bh, flush)
 
     def copy_fbo(self, w, h, sx=0, sy=0, dx=0, dy=0):
         #copy from offscreen to tmp:
@@ -1068,7 +1074,8 @@
                 glDisable(target)
                 self.paint_box(options.strget("encoding"), 
options.intget("delta", -1)>=0, x, y, width, height)
                 # Present update to screen
-                self.present_fbo(x, y, width, height, options.intget("flush", 
0))
+                if not self.draw_needs_refresh:
+                    self.present_fbo(x, y, width, height, 
options.intget("flush", 0))
                 # present_fbo has reset state already
             fire_paint_callbacks(callbacks)
             return
@@ -1122,7 +1129,8 @@
                 self.paint_box(encoding, False, x, y, width, height)
                 fire_paint_callbacks(callbacks, True)
                 # Present it on screen
-                self.present_fbo(x, y, width, height, flush)
+                if not self.draw_needs_refresh:
+                    self.present_fbo(x, y, width, height, flush)
             img.free()
             return
         except GLError as e:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/client/gtk_base/bug_report.py 
new/xpra-3.0.3/xpra/client/gtk_base/bug_report.py
--- old/xpra-3.0.2/xpra/client/gtk_base/bug_report.py   2019-09-24 
15:53:58.000000000 +0200
+++ new/xpra-3.0.3/xpra/client/gtk_base/bug_report.py   2019-12-08 
12:59:03.000000000 +0100
@@ -40,7 +40,7 @@
     def setup_window(self):
         self.window = gtk.Window()
         window_defaults(self.window)
-        self.window.connect("destroy", self.close)
+        self.window.connect("delete-event", self.close)
         self.window.set_default_size(400, 300)
         self.window.set_title("Xpra Bug Report")
 
@@ -241,6 +241,7 @@
         log("close%s", args)
         self.hide()
         self.window = None
+        return True
 
     def destroy(self, *args):
         log("destroy%s", args)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/client/gtk_base/client_launcher.py 
new/xpra-3.0.3/xpra/client/gtk_base/client_launcher.py
--- old/xpra-3.0.2/xpra/client/gtk_base/client_launcher.py      2019-10-07 
15:47:58.000000000 +0200
+++ new/xpra-3.0.3/xpra/client/gtk_base/client_launcher.py      2019-12-08 
12:59:03.000000000 +0100
@@ -191,7 +191,7 @@
     def do_create_window(self):
         self.window = gtk.Window()
         window_defaults(self.window)
-        self.window.connect("destroy", self.destroy)
+        self.window.connect("delete-event", self.destroy)
         self.window.set_default_size(400, 260)
         self.window.set_title("Xpra Launcher")
 
@@ -648,10 +648,16 @@
                 # sshpass cannot do different username/passwords for proxy and 
destination
                 if not sshpass:
                     self.check_boxes_hbox.show()
+                    p = self.password_entry.get_text()
+                    pp = self.proxy_password_entry.get_text()
+                    u = self.username_entry.get_text()
+                    pu = self.proxy_username_entry.get_text()
                 else:
                     self.check_boxes_hbox.hide()
-                    self.password_scb.set_active(True)
-                    self.username_scb.set_active(True)
+                    p = pp = None
+                    u = pu = None
+                self.password_scb.set_active(p==pp)
+                self.username_scb.set_active(u==pu)
         else:
             self.password_hbox.hide()
             if sshtossh:
@@ -1040,9 +1046,6 @@
                 #then select it in the combo:
                 if index>=0:
                     self.encoding_combo.set_history(index)
-        self.username_entry.set_text(self.config.username)
-        self.password_entry.set_text(self.config.password)
-        self.host_entry.set_text(self.config.host)
         def get_port(vstr, default_port=""):
             try:
                 iport = int(vstr)
@@ -1060,11 +1063,20 @@
         #proxy bits:
         self.proxy_host_entry.set_text(self.config.proxy_host)
         self.proxy_port_entry.set_text(get_port(self.config.proxy_port))
-        self.proxy_username_entry.set_text(self.config.proxy_username)
-        self.proxy_password_entry.set_text(self.config.proxy_password)
+        username = self.config.username
+        proxy_username = self.config.proxy_username
+        self.username_scb.set_active(username==proxy_username)
+        self.proxy_username_entry.set_text(proxy_username)
+        password = self.config.password
+        proxy_password = self.config.proxy_password
+        self.password_scb.set_active(password==proxy_password)
+        self.proxy_password_entry.set_text(proxy_password)
         if self.is_putty:
             self.proxy_key_entry.set_text(self.config.proxy_key)
         self.sharing.set_active(bool(self.config.sharing))
+        self.username_entry.set_text(username)
+        self.password_entry.set_text(password)
+        self.host_entry.set_text(self.config.host)
 
     def close_window(self, *_args):
         w = self.window
@@ -1078,6 +1090,7 @@
         self.clean_client()
         self.close_window()
         gtk_main_quit_really()
+        return False
 
     def update_options_from_URL(self, url):
         from xpra.scripts.parsing import parse_URL
@@ -1217,7 +1230,7 @@
             app.reset_errors()
         if not app.config.autoconnect or app.config.debug:
             if OSX and not has_file:
-                from xpra.platform.darwin.gui import wait_for_open_handlers, 
show_with_focus_workaround
+                from xpra.platform.darwin.gui import wait_for_open_handlers, 
force_focus
                 def open_file(filename):
                     log("open_file(%s)", filename)
                     app.update_options_from_file(filename)
@@ -1229,7 +1242,8 @@
                         app.__osx_open_signal = True
                         glib.idle_add(app.do_connect)
                     else:
-                        show_with_focus_workaround(app.show)
+                        force_focus()
+                        app.show()
                 def open_URL(url):
                     log("open_URL(%s)", url)
                     app.__osx_open_signal = True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/client/gtk_base/confirm_dialog.py 
new/xpra-3.0.3/xpra/client/gtk_base/confirm_dialog.py
--- old/xpra-3.0.2/xpra/client/gtk_base/confirm_dialog.py       2019-09-24 
15:53:58.000000000 +0200
+++ new/xpra-3.0.3/xpra/client/gtk_base/confirm_dialog.py       2019-12-10 
12:20:42.000000000 +0100
@@ -17,6 +17,7 @@
     window_defaults, color_parse, is_gtk3,
     WIN_POS_CENTER, WINDOW_POPUP, STATE_NORMAL,
     )
+from xpra.platform.gui import force_focus
 from xpra.platform.paths import get_icon_dir
 from xpra.os_util import get_util_logger
 
@@ -36,7 +37,7 @@
             self.window = gtk.Window(WINDOW_POPUP)
         window_defaults(self.window)
         self.window.set_position(WIN_POS_CENTER)
-        self.window.connect("destroy", self.quit)
+        self.window.connect("delete-event", self.quit)
         self.window.set_default_size(400, 150)
         self.window.set_title(title)
         #self.window.set_modal(True)
@@ -124,6 +125,7 @@
         log("quit%s", args)
         self.destroy()
         gtk.main_quit()
+        return True
 
 
     def get_icon(self, icon_name):
@@ -164,6 +166,7 @@
     app = ConfirmDialogWindow(title, prompt, info, icon, buttons)
     register_os_signals(app.quit)
     gui_ready()
+    force_focus()
     app.show()
     return app.run()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-3.0.2/xpra/client/gtk_base/gtk_client_window_base.py 
new/xpra-3.0.3/xpra/client/gtk_base/gtk_client_window_base.py
--- old/xpra-3.0.2/xpra/client/gtk_base/gtk_client_window_base.py       
2019-10-01 07:09:12.000000000 +0200
+++ new/xpra-3.0.3/xpra/client/gtk_base/gtk_client_window_base.py       
2019-12-08 12:59:03.000000000 +0100
@@ -12,7 +12,7 @@
 except ImportError:
     from urllib.parse import unquote    #python3 @Reimport @UnresolvedImport
 
-from xpra.os_util import bytestostr, is_X11, monotonic_time, WIN32, OSX, 
POSIX, PYTHON3
+from xpra.os_util import bytestostr, strtobytes, is_X11, monotonic_time, 
WIN32, OSX, POSIX, PYTHON3, PYTHON2
 from xpra.util import (
     AdHocStruct, typedict, envint, envbool, nonl, csv, first_time,
     WORKSPACE_UNSET, WORKSPACE_ALL, WORKSPACE_NAMES, 
MOVERESIZE_DIRECTION_STRING, SOURCE_INDICATION_STRING,
@@ -937,6 +937,8 @@
         dtype = bytestostr(dtype)
         if dtype=="latin1":
             value = bytestostr(value)
+            if PYTHON2:
+               value = unicode(value)
         prop_set(gdk_window, prop_name, dtype, value)
 
     def set_class_instance(self, wmclass_name, wmclass_class):
@@ -948,7 +950,7 @@
         elif HAS_X11_BINDINGS:
             xid = get_xwindow(self.get_window())
             with xlog:
-                X11Window.setClassHint(xid, wmclass_class, wmclass_name)
+                X11Window.setClassHint(xid, strtobytes(wmclass_class), 
strtobytes(wmclass_name))
                 log("XSetClassHint(%s, %s) done", wmclass_class, wmclass_name)
 
     def set_shape(self, shape):
@@ -1915,8 +1917,8 @@
             y += self.window_offset[1]
             #TODO: check this doesn't move it off-screen!
         self._resize_counter = resize_counter
-        window = self.get_window()
-        if window.get_position()==(x, y):
+        wx, wy = self.get_drawing_area_geometry()[:2]
+        if (wx, wy)==(x, y):
             #same location, just resize:
             if self._size==(w, h):
                 geomlog("window unchanged")
@@ -1930,6 +1932,7 @@
             geomlog("window was not realized yet")
             self.realize()
         #adjust for window frame:
+        window = self.get_window()
         ox, oy = window.get_origin()[-2:]
         rx, ry = window.get_root_origin()
         ax = x - (ox - rx)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/client/gtk_base/open_requests.py 
new/xpra-3.0.3/xpra/client/gtk_base/open_requests.py
--- old/xpra-3.0.2/xpra/client/gtk_base/open_requests.py        2019-09-24 
15:53:59.000000000 +0200
+++ new/xpra-3.0.3/xpra/client/gtk_base/open_requests.py        2019-12-08 
12:59:03.000000000 +0100
@@ -46,7 +46,7 @@
         self.expire_labels = {}
         self.window = gtk.Window()
         window_defaults(self.window)
-        self.window.connect("destroy", self.close)
+        self.window.connect("delete-event", self.close)
         self.window.set_default_size(400, 150)
         self.window.set_title("Transfers")
 
@@ -199,6 +199,7 @@
     def close(self, *args):
         log("close%s", args)
         self.hide()
+        return True
 
     def destroy(self, *args):
         log("destroy%s", args)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/client/gtk_base/pass_dialog.py 
new/xpra-3.0.3/xpra/client/gtk_base/pass_dialog.py
--- old/xpra-3.0.2/xpra/client/gtk_base/pass_dialog.py  2019-09-24 
15:53:59.000000000 +0200
+++ new/xpra-3.0.3/xpra/client/gtk_base/pass_dialog.py  2019-12-10 
12:20:42.000000000 +0100
@@ -12,6 +12,7 @@
     import_gtk, import_pango, import_glib,
     register_os_signals,
     )
+from xpra.platform.gui import force_focus
 from xpra.os_util import get_util_logger
 from xpra.gtk_common.gtk_util import (
     gtk_main, add_close_accel, pixbuf_new_from_file, window_defaults,
@@ -35,7 +36,7 @@
             self.window = gtk.Window(WINDOW_TOPLEVEL)
         window_defaults(self.window)
         self.window.set_position(WIN_POS_CENTER)
-        self.window.connect("destroy", self.quit)
+        self.window.connect("delete-event", self.quit)
         self.window.set_default_size(400, 150)
         self.window.set_title(title)
         self.window.set_modal(True)
@@ -99,8 +100,11 @@
     def show(self):
         log("show()")
         self.window.show_all()
-        glib.idle_add(self.window.present)
-        glib.idle_add(self.password_input.grab_focus)
+        def show():
+            force_focus()
+            self.present()
+            self.password_input.grab_focus()
+        glib.idle_add(show)
 
     def destroy(self, *args):
         log("destroy%s", args)
@@ -118,6 +122,7 @@
         log("quit%s", args)
         self.destroy()
         gtk.main_quit()
+        return True
 
     def activate(self, *args):
         log("activate%s", args)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/client/gtk_base/server_commands.py 
new/xpra-3.0.3/xpra/client/gtk_base/server_commands.py
--- old/xpra-3.0.2/xpra/client/gtk_base/server_commands.py      2019-09-24 
15:53:59.000000000 +0200
+++ new/xpra-3.0.3/xpra/client/gtk_base/server_commands.py      2019-12-08 
12:59:03.000000000 +0100
@@ -46,7 +46,7 @@
         self.table = None
         self.window = gtk.Window()
         window_defaults(self.window)
-        self.window.connect("destroy", self.close)
+        self.window.connect("delete-event", self.close)
         self.window.set_default_size(400, 150)
         self.window.set_title("Server Commands")
 
@@ -191,6 +191,7 @@
     def close(self, *args):
         log("close%s", args)
         self.hide()
+        return True
 
     def destroy(self, *args):
         log("destroy%s", args)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/client/gtk_base/sessions_gui.py 
new/xpra-3.0.3/xpra/client/gtk_base/sessions_gui.py
--- old/xpra-3.0.2/xpra/client/gtk_base/sessions_gui.py 2019-09-24 
15:53:59.000000000 +0200
+++ new/xpra-3.0.3/xpra/client/gtk_base/sessions_gui.py 2019-12-08 
12:59:03.000000000 +0100
@@ -12,6 +12,7 @@
 
 from xpra.platform.paths import get_icon_dir, get_xpra_command, 
get_nodock_command
 from xpra.platform.dotxpra import DotXpra
+from xpra.platform.gui import force_focus
 from xpra.child_reaper import getChildReaper
 from xpra.exit_codes import EXIT_STR
 from xpra.gtk_common.gtk_util import (
@@ -103,6 +104,13 @@
         self.vbox.show()
         self.show()
 
+    def show(self):
+        self.show_all()
+        def show():
+            force_focus()
+            self.present()
+        glib.idle_add(show)
+
     def quit(self, *args):
         log("quit%s", args)
         self.do_quit()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/client/gtk_base/start_new_command.py 
new/xpra-3.0.3/xpra/client/gtk_base/start_new_command.py
--- old/xpra-3.0.2/xpra/client/gtk_base/start_new_command.py    2019-09-24 
15:53:59.000000000 +0200
+++ new/xpra-3.0.3/xpra/client/gtk_base/start_new_command.py    2019-12-08 
12:59:03.000000000 +0100
@@ -44,7 +44,7 @@
         self.xdg_menu = typedict(xdg_menu or {})
         self.window = gtk.Window()
         window_defaults(self.window)
-        self.window.connect("destroy", self.close)
+        self.window.connect("delete-event", self.close)
         self.window.set_default_size(400, 150)
         self.window.set_title("Start New Command")
 
@@ -56,6 +56,7 @@
         vbox = gtk.VBox(False, 0)
         vbox.set_spacing(0)
 
+        self.entry = None
         if xdg_menu:
             # or use menus if we have xdg data:
             hbox = gtk.HBox(False, 20)
@@ -135,7 +136,7 @@
         category = self.category_combo.get_active_text()
         entries = typedict(self.xdg_menu.dictget(category.encode("utf-8"), 
{})).dictget("Entries", {})
         log("command_changed(%s) category=%s, entries=%s", args, category, 
entries)
-        if entries:
+        if entries and self.entry:
             command_name = self.command_combo.get_active_text()
             command_props = 
typedict(entries).dictget(command_name.encode("utf-8"), {})
             log("command properties=%s", command_props)
@@ -155,6 +156,7 @@
     def close(self, *args):
         log("close%s", args)
         self.hide()
+        return True
 
     def destroy(self, *args):
         log("destroy%s", args)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/client/gtk_base/update_status.py 
new/xpra-3.0.3/xpra/client/gtk_base/update_status.py
--- old/xpra-3.0.2/xpra/client/gtk_base/update_status.py        2019-09-24 
15:53:59.000000000 +0200
+++ new/xpra-3.0.3/xpra/client/gtk_base/update_status.py        2019-12-08 
12:59:03.000000000 +0100
@@ -8,7 +8,7 @@
 import os.path
 import sys
 
-from xpra.platform.gui import init as gui_init
+from xpra.platform.gui import init as gui_init, force_focus
 from xpra.gtk_common.gtk_util import (
     gtk_main, add_close_accel, scaled_image, pixbuf_new_from_file,
     window_defaults, WIN_POS_CENTER,
@@ -38,7 +38,7 @@
     def __init__(self):
         self.window = gtk.Window()
         window_defaults(self.window)
-        self.window.connect("destroy", self.close)
+        self.window.connect("delete-event", self.close)
         self.window.set_default_size(400, 200)
         self.window.set_title("Xpra Version Check")
 
@@ -112,8 +112,11 @@
 
     def show(self):
         log("show()")
-        self.window.show()
-        self.window.present()
+        def show():
+            force_focus()
+            self.window.show()
+            self.window.present()
+        glib.idle_add(show)
 
     def hide(self):
         log("hide()")
@@ -122,6 +125,7 @@
     def close(self, *args):
         log("close%s", args)
         self.hide()
+        return True
 
     def destroy(self, *args):
         log("destroy%s", args)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/client/mixins/audio.py 
new/xpra-3.0.3/xpra/client/mixins/audio.py
--- old/xpra-3.0.2/xpra/client/mixins/audio.py  2019-09-24 15:53:59.000000000 
+0200
+++ new/xpra-3.0.3/xpra/client/mixins/audio.py  2019-12-08 12:59:03.000000000 
+0100
@@ -429,9 +429,10 @@
         if sound_sink!=self.sound_sink:
             log("sound_sink_error(%s, %s) not the current sink, ignoring it", 
sound_sink, error)
             return
-        self.may_notify_audio("Speaker forwarding error", error)
+        estr = bytestostr(error).replace("gst-resource-error-quark: ", "")
+        self.may_notify_audio("Speaker forwarding error", estr)
         log.warn("Error: stopping speaker:")
-        log.warn(" %s", bytestostr(error).replace("gst-resource-error-quark: 
", ""))
+        log.warn(" %s", estr)
         self.stop_receiving_sound()
     def sound_process_stopped(self, sound_sink, *args):
         if self.exit_code is not None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/client/mixins/display.py 
new/xpra-3.0.3/xpra/client/mixins/display.py
--- old/xpra-3.0.2/xpra/client/mixins/display.py        2019-09-24 
15:53:59.000000000 +0200
+++ new/xpra-3.0.3/xpra/client/mixins/display.py        2019-12-08 
12:59:03.000000000 +0100
@@ -14,7 +14,7 @@
 from xpra.scripts.config import FALSE_OPTIONS
 from xpra.os_util import monotonic_time
 from xpra.util import (
-    iround, envint, envfloat, log_screen_sizes, engs, flatten_dict,
+    iround, envint, envfloat, envbool, log_screen_sizes, engs, flatten_dict,
     XPRA_SCALING_NOTIFICATION_ID,
     )
 from xpra.client.mixins.stub_client_mixin import StubClientMixin
@@ -31,6 +31,7 @@
 MAX_SCALING = envfloat("XPRA_MAX_SCALING", "8")
 SCALING_OPTIONS = [float(x) for x in 
os.environ.get("XPRA_TRAY_SCALING_OPTIONS", 
"0.25,0.5,0.666,1,1.25,1.5,2.0,3.0,4.0,5.0").split(",") if 
float(x)>=MIN_SCALING and float(x)<=MAX_SCALING]
 SCALING_EMBARGO_TIME = int(os.environ.get("XPRA_SCALING_EMBARGO_TIME", 
"1000"))/1000.0
+SYNC_ICC = envbool("XPRA_SYNC_ICC", True)
 
 
 def r4cmp(v, rounding=1000.0):    #ignore small differences in floats for 
scale values
@@ -142,7 +143,7 @@
         dpi = 0
         if self.dpi>0:
             #scale it:
-            dpi = self.cx(self.cy(self.dpi))
+            dpi = self.cx(self.cy(self.dpi*2))
         else:
             #not supplied, use platform detection code:
             #platforms may also provide per-axis dpi (later win32 versions do)
@@ -170,14 +171,18 @@
             }
 
     def get_screen_caps(self):
-        return {
+        caps = {
             "antialias"    : get_antialias_info(),
-            "icc"          : self.get_icc_info(),
-            "display-icc"  : self.get_display_icc_info(),
             "cursor" : {
                 "size"  : int(2*get_cursor_size()/(self.xscale+self.yscale)),
                 },
             }
+        if SYNC_ICC:
+            caps.update({
+            "icc"          : self.get_icc_info(),
+            "display-icc"  : self.get_display_icc_info(),
+            })
+        return caps
 
     #this is the format we should be moving towards
     #with proper namespace:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/client/mixins/window_manager.py 
new/xpra-3.0.3/xpra/client/mixins/window_manager.py
--- old/xpra-3.0.2/xpra/client/mixins/window_manager.py 2019-10-28 
16:04:05.000000000 +0100
+++ new/xpra-3.0.3/xpra/client/mixins/window_manager.py 2019-11-21 
08:29:31.000000000 +0100
@@ -1308,10 +1308,14 @@
         if self._suspended_at>0:
             elapsed = max(0, time()-self._suspended_at)
             self._suspended_at = 0
+        self.send_refresh_all()
+        if elapsed<1:
+            #not really suspended
+            #happens on macos when switching workspace!
+            return
         delta = datetime.timedelta(seconds=int(elapsed))
         log.info("system resumed, was suspended for %s", 
str(delta).lstrip("0:"))
         #this will reset the refresh rate too:
-        self.send_refresh_all()
         if self.opengl_enabled:
             #with opengl, the buffers sometimes contain garbage after resuming,
             #this should create new backing buffers:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/client/top_client.py 
new/xpra-3.0.3/xpra/client/top_client.py
--- old/xpra-3.0.2/xpra/client/top_client.py    2019-10-20 14:13:42.000000000 
+0200
+++ new/xpra-3.0.3/xpra/client/top_client.py    2019-11-18 16:50:49.000000000 
+0100
@@ -7,7 +7,7 @@
 from datetime import datetime, timedelta
 
 from xpra import __version__
-from xpra.util import typedict, std, envint, csv
+from xpra.util import typedict, std, envint, csv, engs
 from xpra.os_util import platform_name, bytestostr
 from xpra.client.gobject_client_base import MonitorXpraClient
 from xpra.log import Logger
@@ -51,10 +51,16 @@
         curses.endwin()
 
     def update_screen(self):
+        self.stdscr.clear()
+        try:
+            self.do_update_screen()
+        finally:
+            self.stdscr.refresh()
+
+    def do_update_screen(self):
         #c = self.stdscr.getch()
         #if c==curses.KEY_RESIZE:
-        self.stdscr.clear()
-        _, width = self.stdscr.getmaxyx()
+        height, width = self.stdscr.getmaxyx()
         #log.info("update_screen() %ix%i", height, width)
         title = "Xpra top %s" % __version__
         try:
@@ -68,6 +74,8 @@
         sli = self.server_last_info
         try:
             self.stdscr.addstr(0, x, title, curses.A_BOLD)
+            if height<=1:
+                return
             server_info = self.dictget("server")
             build = self.dictget("build")
             v = build.strget("version")
@@ -91,6 +99,8 @@
                     std(proxy_version or "unknown")
                     )
             self.stdscr.addstr(1, 0, server_str)
+            if height<=2:
+                return
             #load and uptime:
             now = datetime.now()
             uptime = ""
@@ -107,17 +117,28 @@
                 load_average = ", load average: %1.2f, %1.2f, %1.2f" % 
float_load
             self.stdscr.addstr(2, 0, "xpra top - %s%s, %2i users%s" % (
                                now.strftime("%H:%M:%S"), uptime, nclients, 
load_average))
+            if height<=3:
+                return
             thread_info = self.dictget("threads")
             self.stdscr.addstr(3, 0, "%i threads" % 
thread_info.intget("count"))
+            if height<=4:
+                return
             #cursor:
             cursor_info = self.dictget("cursor")
             cx, cy = cursor_info.intlistget("position", (0, 0))
             self.stdscr.addstr(4, 0, "cursor at %ix%i" % (cx, cy))
+            if height<=5:
+                return
 
             hpos = 6
             for client_no in range(nclients):
                 ci = self.get_client_info(client_no)
                 l = len(ci)
+                if hpos+2+l>height:
+                    if hpos<height:
+                        more = nclients-client_no
+                        self.stdscr.addstr(hpos, 0, "%i client%s not shown" % 
(more, engs(more)), curses.A_BOLD)
+                    break
                 self.box(self.stdscr, 1, hpos, width-2, 2+l)
                 for i, info in enumerate(ci):
                     info_text, color = info
@@ -125,13 +146,21 @@
                     self.stdscr.addstr(hpos+i+1, 2, info_text, cpair)
                 hpos += 2+l
 
-            hpos += 1
             windows = self.dictget("windows")
-            self.stdscr.addstr(hpos, 0, "%i windows" % len(windows))
-            hpos += 1
-            for win in windows.values():
+            if hpos<height-3:
+                hpos += 1
+                self.stdscr.addstr(hpos, 0, "%i windows" % len(windows))
+                hpos += 1
+            wins = tuple(windows.values())
+            nwindows = len(wins)
+            for win_no, win in enumerate(wins):
                 wi = self.get_window_info(typedict(win))
                 l = len(wi)
+                if hpos+2+l>height:
+                    if hpos<height:
+                        more = nwindows-win_no
+                        self.stdscr.addstr(hpos, 0, "terminal window is too 
small: %i window%s not shown" % (more, engs(more)), curses.A_BOLD)
+                    break
                 self.box(self.stdscr, 1, hpos, width-2, 2+l)
                 for i, info in enumerate(wi):
                     info_text, color = info
@@ -142,9 +171,6 @@
             import traceback
             self.stdscr.addstr(0, 0, str(e))
             self.stdscr.addstr(0, 1, traceback.format_exc())
-            self.stdscr.refresh()
-        else:
-            self.stdscr.refresh()
 
     def dictget(self, *parts):
         d = self.server_last_info
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/client/window_backing_base.py 
new/xpra-3.0.3/xpra/client/window_backing_base.py
--- old/xpra-3.0.2/xpra/client/window_backing_base.py   2019-09-24 
15:53:59.000000000 +0200
+++ new/xpra-3.0.3/xpra/client/window_backing_base.py   2019-11-26 
16:58:06.000000000 +0100
@@ -52,6 +52,7 @@
 PAINT_BOX = envint("XPRA_PAINT_BOX", 0) or envint("XPRA_OPENGL_PAINT_BOX", 0)
 WEBP_PILLOW = envbool("XPRA_WEBP_PILLOW", False)
 SCROLL_ENCODING = envbool("XPRA_SCROLL_ENCODING", True)
+REPAINT_ALL = envbool("XPRA_REPAINT_ALL", False)
 
 
 #ie:
@@ -128,6 +129,7 @@
         self.jpeg_decoder = get_codec("dec_jpeg")
         self.webp_decoder = get_codec("dec_webp")
         self.draw_needs_refresh = True
+        self.repaint_all = REPAINT_ALL
         self.mmap = None
         self.mmap_enabled = False
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/codecs/nv_util.py 
new/xpra-3.0.3/xpra/codecs/nv_util.py
--- old/xpra-3.0.2/xpra/codecs/nv_util.py       2019-09-24 15:53:59.000000000 
+0200
+++ new/xpra-3.0.3/xpra/codecs/nv_util.py       2019-11-30 13:36:58.000000000 
+0100
@@ -34,15 +34,16 @@
         from pynvml import nvmlInit, nvmlShutdown, nvmlSystemGetDriverVersion
         try:
             if wrap_nvml_init(nvmlInit):
-                v = nvmlSystemGetDriverVersion()
+                try:
+                    v = nvmlSystemGetDriverVersion()
+                finally:
+                    nvmlShutdown()
                 log("nvmlSystemGetDriverVersion=%s", bytestostr(v))
                 return v.split(b".")
         except Exception as e:
             log("get_nvml_driver_version() pynvml error", exc_info=True)
             log.warn("Warning: failed to query the NVidia kernel module 
version using NVML:")
             log.warn(" %s", e)
-        finally:
-            nvmlShutdown()
     except ImportError as e:
         log("cannot use nvml to query the kernel module version:")
         log(" %s", e)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/codecs/nvenc/encoder.pyx 
new/xpra-3.0.3/xpra/codecs/nvenc/encoder.pyx
--- old/xpra-3.0.2/xpra/codecs/nvenc/encoder.pyx        2019-09-24 
15:53:59.000000000 +0200
+++ new/xpra-3.0.3/xpra/codecs/nvenc/encoder.pyx        2019-11-18 
16:50:49.000000000 +0100
@@ -2236,13 +2236,14 @@
             finally:
                 self.cuda_context.pop()
         except driver.LogicError as e:
+            log("compress_image%s", (image, quality, speed, options, retry), 
exc_info=True)
             if retry>0:
                 raise
             log.warn("Warning: PyCUDA %s", e)
             del e
             self.clean()
             self.init_cuda()
-            return self.convert_image(image, options, retry+1)
+            return self.compress_image(image, options, retry+1)
 
     cdef do_compress_image(self, image, options={}):
         cdef unsigned int stride, w, h
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/gtk_common/gtk_util.py 
new/xpra-3.0.3/xpra/gtk_common/gtk_util.py
--- old/xpra-3.0.2/xpra/gtk_common/gtk_util.py  2019-10-20 14:13:42.000000000 
+0200
+++ new/xpra-3.0.3/xpra/gtk_common/gtk_util.py  2019-11-30 13:36:58.000000000 
+0100
@@ -7,7 +7,7 @@
 import os.path
 import array
 
-from xpra.util import iround, first_time
+from xpra.util import iround, first_time, envint
 from xpra.os_util import (
     strtobytes, bytestostr,
     WIN32, OSX, PYTHON2, POSIX,
@@ -928,6 +928,12 @@
     display = display_get_default()
     if not display:
         return ()
+    MIN_DPI = envint("XPRA_MIN_DPI", 10)
+    MAX_DPI = envint("XPRA_MIN_DPI", 500)
+    def dpi(size_pixels, size_mm):
+        if size_mm==0:
+            return 0
+        return int(size_pixels * 254 / size_mm / 10)
     n_screens = display.get_n_screens()
     get_n_monitors = getattr(display, "get_n_monitors", None)
     if get_n_monitors:
@@ -965,8 +971,27 @@
         if workarea:
             work_x, work_y, work_width, work_height = swork(*workarea)  
#pylint: disable=not-an-iterable
         screenlog(" workarea=%s", workarea)
+        wmm = screen.get_width_mm()
+        hmm = screen.get_height_mm()
+        xdpi = dpi(sw, wmm)
+        ydpi = dpi(sh, hmm)
+        if xdpi<MIN_DPI or xdpi>MAX_DPI or ydpi<MIN_DPI or ydpi>MAX_DPI:
+            warn = first_time("invalid-screen-size-%ix%i" % (wmm, hmm))
+            if warn:
+                log.warn("Warning: invalid screen size %ix%imm", wmm, hmm)
+            if n_monitors>0:
+                wmm = sum(display.get_monitor(i).get_width_mm() for i in 
range(n_monitors))
+                hmm = sum(display.get_monitor(i).get_height_mm() for i in 
range(n_monitors))
+                xdpi = dpi(sw, wmm)
+                ydpi = dpi(sh, hmm)
+            if xdpi<MIN_DPI or xdpi>MAX_DPI or ydpi<MIN_DPI or ydpi>MAX_DPI:
+                #still invalid, generate one from DPI=96
+                wmm = iround(sw*254/10/96.0)
+                hmm = iround(sh*254/10/96.0)
+            if warn:
+                log.warn(" using %ix%i mm", wmm, hmm)
         item = (screen.make_display_name(), xs(sw), ys(sh),
-                    screen.get_width_mm(), screen.get_height_mm(),
+                    wmm, hmm,
                     monitors,
                     work_x, work_y, work_width, work_height)
         screenlog(" screen: %s", item)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/gtk_common/gui.py 
new/xpra-3.0.3/xpra/gtk_common/gui.py
--- old/xpra-3.0.2/xpra/gtk_common/gui.py       2019-10-20 14:13:42.000000000 
+0200
+++ new/xpra-3.0.3/xpra/gtk_common/gui.py       2019-12-08 12:59:03.000000000 
+0100
@@ -242,7 +242,7 @@
         icon = get_pixbuf("xpra")
         if icon:
             self.set_icon(icon)
-        self.connect("destroy", self.close)
+        self.connect("delete-event", self.close)
         add_close_accel(self, self.close)
 
         vbox = gtk.VBox(False, 0)
@@ -448,6 +448,7 @@
     def close(self, *args):
         log("close%s", args)
         self.hide()
+        return True
 
 
     def run_command(self, *_args):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/platform/darwin/gl_context.py 
new/xpra-3.0.3/xpra/platform/darwin/gl_context.py
--- old/xpra-3.0.2/xpra/platform/darwin/gl_context.py   2019-10-20 
14:13:42.000000000 +0200
+++ new/xpra-3.0.3/xpra/platform/darwin/gl_context.py   2019-12-08 
12:59:03.000000000 +0100
@@ -48,6 +48,12 @@
         assert self.gl_context
         self.gl_context.flushBuffer()
 
+    def update_geometry(self):
+        glc = self.gl_context
+        log.warn("update() gl_context=%s", glc)
+        if glc:
+            glc.update()
+
     def __del__(self):
         self.destroy()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/platform/darwin/gui.py 
new/xpra-3.0.3/xpra/platform/darwin/gui.py
--- old/xpra-3.0.2/xpra/platform/darwin/gui.py  2019-09-24 15:54:00.000000000 
+0200
+++ new/xpra-3.0.3/xpra/platform/darwin/gui.py  2019-11-18 16:50:50.000000000 
+0100
@@ -521,6 +521,13 @@
     buf.close()
     return w, h, "png", image.get_rowstride(), data
 
+def force_focus(duration=2000):
+    enable_focus_workaround()
+    from xpra.gtk_common.gobject_compat import import_glib
+    glib = import_glib()
+    glib.timeout_add(duration, disable_focus_workaround)
+
+
 def show_with_focus_workaround(show_cb):
     from xpra.gtk_common.gobject_compat import import_glib
     glib = import_glib()
@@ -568,7 +575,8 @@
         global __osx_open_signal
         log("may_show() osx open signal=%s", __osx_open_signal)
         if not __osx_open_signal:
-            show_with_focus_workaround(show_cb)
+            force_focus()
+            show_cb()
     glib.timeout_add(delay, may_show)
 
 def register_file_handler(handler):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/platform/gui.py 
new/xpra-3.0.3/xpra/platform/gui.py
--- old/xpra-3.0.2/xpra/platform/gui.py 2019-10-22 14:15:47.000000000 +0200
+++ new/xpra-3.0.3/xpra/platform/gui.py 2019-11-18 16:50:50.000000000 +0100
@@ -37,6 +37,11 @@
     pass
 
 
+def force_focus(duration=2000):
+    #only implemented on macos
+    pass
+
+
 def use_stdin():
     stdin = sys.stdin
     return stdin and stdin.isatty()
@@ -277,6 +282,7 @@
 platform_import(globals(), "gui", False,
                 "do_ready",
                 "do_init",
+                "force_focus",
                 "gl_check",
                 "use_stdin",
                 "get_wm_name",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/platform/win32/gl_context.py 
new/xpra-3.0.3/xpra/platform/win32/gl_context.py
--- old/xpra-3.0.2/xpra/platform/win32/gl_context.py    2019-10-30 
04:23:47.000000000 +0100
+++ new/xpra-3.0.3/xpra/platform/win32/gl_context.py    2019-12-08 
12:59:03.000000000 +0100
@@ -60,6 +60,9 @@
         self.paint_hdc = None
         self.ps = None
 
+    def update_geometry(self):
+        pass
+
     def swap_buffers(self):
         assert self.paint_hdc
         log("swap_buffers: calling SwapBuffers(%#x)", self.paint_hdc)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/platform/xposix/gl_context.py 
new/xpra-3.0.3/xpra/platform/xposix/gl_context.py
--- old/xpra-3.0.2/xpra/platform/xposix/gl_context.py   2019-09-24 
15:54:00.000000000 +0200
+++ new/xpra-3.0.3/xpra/platform/xposix/gl_context.py   2019-12-08 
12:59:03.000000000 +0100
@@ -79,6 +79,9 @@
             log("glXMakeCurrent: NULL for xid=%#x", self.xid)
             GLX.glXMakeCurrent(self.xdisplay, 0, null_context)
 
+    def update_geometry(self):
+        pass
+
     def swap_buffers(self):
         assert self.valid
         GLX.glXSwapBuffers(self.xdisplay, self.xid)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/platform/xposix/keyboard.py 
new/xpra-3.0.3/xpra/platform/xposix/keyboard.py
--- old/xpra-3.0.2/xpra/platform/xposix/keyboard.py     2019-10-20 
14:13:42.000000000 +0200
+++ new/xpra-3.0.3/xpra/platform/xposix/keyboard.py     2019-12-08 
12:59:03.000000000 +0100
@@ -9,7 +9,7 @@
 from xpra.keyboard.mask import MODIFIER_MAP
 from xpra.keyboard.layouts import xkbmap_query_tostring
 from xpra.log import Logger
-from xpra.os_util import is_X11, is_Wayland
+from xpra.os_util import is_X11, is_Wayland, bytestostr
 
 log = Logger("keyboard", "posix")
 
@@ -85,7 +85,7 @@
         if not out:
             return {}
         locale = {}
-        for line in out.splitlines():
+        for line in bytestostr(out).splitlines():
             parts = line.lstrip(" ").split(": ")
             if len(parts)==2:
                 locale[parts[0]]=parts[1]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/scripts/config.py 
new/xpra-3.0.3/xpra/scripts/config.py
--- old/xpra-3.0.2/xpra/scripts/config.py       2019-11-05 18:31:07.000000000 
+0100
+++ new/xpra-3.0.3/xpra/scripts/config.py       2019-11-08 16:44:54.000000000 
+0100
@@ -1007,7 +1007,7 @@
                     "av-sync"           : True,
                     "exit-ssh"          : True,
                     "dbus-control"      : not WIN32 and not OSX,
-                    "opengl"            : "no" if (WIN32 and not PYTHON2) else 
"probe",
+                    "opengl"            : "probe",
                     "mdns"              : not WIN32,
                     "swap-keys"         : OSX,  #only used on osx
                     "desktop-fullscreen": False,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/scripts/main.py 
new/xpra-3.0.3/xpra/scripts/main.py
--- old/xpra-3.0.2/xpra/scripts/main.py 2019-11-05 18:31:07.000000000 +0100
+++ new/xpra-3.0.3/xpra/scripts/main.py 2019-11-26 16:58:06.000000000 +0100
@@ -83,8 +83,12 @@
     if "XPRA_ALT_PYTHON_RETRY" in os.environ:
         del os.environ["XPRA_ALT_PYTHON_RETRY"]
 
-    #some environment variables cause us problems if set:
-    unsetenv("GDK_SCALE")
+    #turn off gdk scaling to make sure we get the actual window geometry:
+    os.environ["GDK_SCALE"]="1"
+    #client side decorations break window geometry,
+    #disable this "feature" unless explicitly enabled:
+    if PYTHON3 and os.environ.get("GTK_CSD") is None:
+        os.environ["GTK_CSD"] = "0"
 
     if envbool("XPRA_NOMD5", False):
         import hashlib
@@ -1577,7 +1581,7 @@
         app.hello_extra = {"connect" : False}
         app.start_new_session = sns
     else:
-        if PYTHON3 and POSIX and os.environ.get("GDK_BACKEND") is None:
+        if PYTHON3 and 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()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/scripts/server.py 
new/xpra-3.0.3/xpra/scripts/server.py
--- old/xpra-3.0.2/xpra/scripts/server.py       2019-10-28 16:04:05.000000000 
+0100
+++ new/xpra-3.0.3/xpra/scripts/server.py       2019-11-18 16:50:50.000000000 
+0100
@@ -599,7 +599,8 @@
     if POSIX:
         if xrd:
             os.environ["XDG_RUNTIME_DIR"] = xrd
-        os.environ["XDG_SESSION_TYPE"] = "x11"
+        if not OSX:
+            os.environ["XDG_SESSION_TYPE"] = "x11"
         if not starting_desktop:
             os.environ["XDG_CURRENT_DESKTOP"] = opts.wm_name
         configure_imsettings_env(opts.input_method)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/server/mixins/window_server.py 
new/xpra-3.0.3/xpra/server/mixins/window_server.py
--- old/xpra-3.0.2/xpra/server/mixins/window_server.py  2019-09-24 
15:54:01.000000000 +0200
+++ new/xpra-3.0.3/xpra/server/mixins/window_server.py  2019-11-18 
16:50:50.000000000 +0100
@@ -303,7 +303,7 @@
             ss.refresh(wid, window, opts)
 
     def _idle_refresh_all_windows(self, proto):
-        self.idle_add(self._refresh_windows, proto, self._id_to_window)
+        self.idle_add(self._refresh_windows, proto, self._id_to_window, {})
 
 
     def get_window_position(self, _window):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/server/server_core.py 
new/xpra-3.0.3/xpra/server/server_core.py
--- old/xpra-3.0.2/xpra/server/server_core.py   2019-09-30 22:31:59.000000000 
+0200
+++ new/xpra-3.0.3/xpra/server/server_core.py   2019-11-26 16:58:06.000000000 
+0100
@@ -2039,7 +2039,8 @@
                        ""                   : self._html,
                        "dir"                : self._www_dir or "",
                        "http-headers-dir"   : self._http_headers_dir or "",
-                       }
+                       },
+                   "mdns"           : self.mdns,
                    })
         up("network", ni)
         up("threads",   self.get_thread_info(proto))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/server/source/clientdisplay_mixin.py 
new/xpra-3.0.3/xpra/server/source/clientdisplay_mixin.py
--- old/xpra-3.0.2/xpra/server/source/clientdisplay_mixin.py    2019-09-24 
15:54:01.000000000 +0200
+++ new/xpra-3.0.3/xpra/server/source/clientdisplay_mixin.py    2019-11-30 
13:36:58.000000000 +0100
@@ -5,7 +5,7 @@
 # later version. See the file COPYING for details.
 
 from xpra.os_util import strtobytes
-from xpra.util import get_screen_info
+from xpra.util import get_screen_info, envint, first_time, iround
 from xpra.server.source.stub_source_mixin import StubSourceMixin
 from xpra.log import Logger
 
@@ -67,8 +67,43 @@
 
 
     def set_screen_sizes(self, screen_sizes):
+        log("set_screen_sizes(%s)", screen_sizes)
         self.screen_sizes = screen_sizes or []
-        log("client screen sizes: %s", screen_sizes)
+        #validate dpi / screen size in mm
+        #(ticket 2480: GTK3 on macos can return bogus values)
+        MIN_DPI = envint("XPRA_MIN_DPI", 10)
+        MAX_DPI = envint("XPRA_MIN_DPI", 500)
+        def dpi(size_pixels, size_mm):
+            if size_mm==0:
+                return 0
+            return int(size_pixels * 254 / size_mm / 10)
+        for i,screen in enumerate(screen_sizes):
+            if len(screen)<10:
+                continue
+            sw, sh, wmm, hmm, monitors = screen[1:6]
+            xdpi = dpi(sw, wmm)
+            ydpi = dpi(sh, hmm)
+            if xdpi<MIN_DPI or xdpi>MAX_DPI or ydpi<MIN_DPI or ydpi>MAX_DPI:
+                warn = first_time("invalid-screen-size-%ix%i" % (wmm, hmm))
+                if warn:
+                    log.warn("Warning: sanitizing invalid screen size %ix%i 
mm", wmm, hmm)
+                if monitors:
+                    #[plug_name, xs(geom.x), ys(geom.y), xs(geom.width), 
ys(geom.height), wmm, hmm]
+                    wmm = sum(monitor[5] for monitor in monitors)
+                    hmm = sum(monitor[6] for monitor in monitors)
+                    xdpi = dpi(sw, wmm)
+                    ydpi = dpi(sh, hmm)
+                if xdpi<MIN_DPI or xdpi>MAX_DPI or ydpi<MIN_DPI or 
ydpi>MAX_DPI:
+                    #still invalid, generate one from DPI=96
+                    wmm = iround(sw*254/10/96.0)
+                    hmm = iround(sh*254/10/96.0)
+                if warn:
+                    log.warn(" using %ix%i mm", wmm, hmm)
+                screen = list(screen)
+                screen[3] = wmm
+                screen[4] = hmm
+                screen_sizes[i] = tuple(screen)
+        log("client validated screen sizes: %s", screen_sizes)
 
     def set_desktops(self, desktops, desktop_names):
         self.desktops = desktops or 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/server/source/windows_mixin.py 
new/xpra-3.0.3/xpra/server/source/windows_mixin.py
--- old/xpra-3.0.2/xpra/server/source/windows_mixin.py  2019-09-24 
15:54:01.000000000 +0200
+++ new/xpra-3.0.3/xpra/server/source/windows_mixin.py  2019-12-08 
12:59:03.000000000 +0100
@@ -256,7 +256,7 @@
         self.last_cursor_sent = cursor_data[:9]
         w, h, _xhot, _yhot, serial, pixels, name = cursor_data[2:9]
         #compress pixels if needed:
-        encoding = None
+        encoding = "raw"
         if pixels is not None:
             #convert bytearray to string:
             cpixels = strtobytes(pixels)
@@ -283,9 +283,7 @@
             cursor_data[7] = cpixels
         cursorlog("do_send_cursor(..) %sx%s %s cursor name='%s', serial=%#x 
with delay=%s (cursor_encodings=%s)",
                   w, h, (encoding or "empty"), bytestostr(name), serial, 
delay, self.cursor_encodings)
-        args = list(cursor_data[:9]) + [cursor_sizes[0]] + 
list(cursor_sizes[1])
-        if self.cursor_encodings and encoding:
-            args = [encoding] + args
+        args = [encoding] + list(cursor_data[:9]) + [cursor_sizes[0]] + 
list(cursor_sizes[1])
         self.send_more("cursor", *args)
 
     def send_empty_cursor(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/src_info.py 
new/xpra-3.0.3/xpra/src_info.py
--- old/xpra-3.0.2/xpra/src_info.py     2019-11-05 18:31:10.000000000 +0100
+++ new/xpra-3.0.3/xpra/src_info.py     2019-12-10 18:47:53.000000000 +0100
@@ -1,2 +1,2 @@
 LOCAL_MODIFICATIONS=0
-REVISION=24387
+REVISION=24692
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/version_util.py 
new/xpra-3.0.3/xpra/version_util.py
--- old/xpra-3.0.2/xpra/version_util.py 2019-09-24 15:54:01.000000000 +0200
+++ new/xpra-3.0.3/xpra/version_util.py 2019-11-08 16:44:54.000000000 +0100
@@ -152,7 +152,11 @@
     ld = get_linux_distribution()
     if ld:
         info["linux_distribution"] = ld
-    release = platform_release(pp.release())
+    try:
+        release = platform_release(pp.release())
+    except OSError:
+        log("do_get_platform_info()", exc_info=True)
+        release = "unknown"
     info.update({
             ""          : sys.platform,
             "name"      : platform_name(sys.platform, 
info.get("linux_distribution") or release),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/x11/gtk_x11/clipboard.py 
new/xpra-3.0.3/xpra/x11/gtk_x11/clipboard.py
--- old/xpra-3.0.2/xpra/x11/gtk_x11/clipboard.py        2019-10-28 
16:04:05.000000000 +0100
+++ new/xpra-3.0.3/xpra/x11/gtk_x11/clipboard.py        2019-11-18 
16:50:50.000000000 +0100
@@ -48,6 +48,23 @@
 sizeof_long = struct.calcsize(b'@L')
 
 BLACKLISTED_CLIPBOARD_CLIENTS = 
os.environ.get("XPRA_BLACKLISTED_CLIPBOARD_CLIENTS", "clipit").split(",")
+def parse_translated_targets(v):
+    trans = {}
+    #we can't use ";" or "/" as separators
+    #because those are used in mime-types
+    #and we use "," and ":" ourselves..
+    for entry in v.split("#"):
+        parts = entry.split(":", 1)
+        if len(parts)!=2:
+            log.warn("Warning: invalid clipboard translated target:")
+            log.warn(" '%s'", entry)
+            continue
+        src_target = parts[0]
+        dst_targets = parts[1].split(",")
+        trans[src_target] = dst_targets
+    return trans
+TRANSLATED_TARGETS = 
parse_translated_targets(os.environ.get("XPRA_CLIPBOARD_TRANSLATED_TARGETS",
+                                                             
"text/plain;charset=utf-8:UTF8_STRING,text/plain"))
 
 
 def xatoms_to_strings(data):
@@ -385,11 +402,17 @@
 
         if self.targets and target not in self.targets:
             log.info("client is requesting an unknown target: '%s'", target)
-            log.info(" valid targets: %s", csv(self.targets))
-            if must_discard_extra(target):
-                log.info(" dropping the request")
-                nodata()
-                return
+            translated_targets = TRANSLATED_TARGETS.get(target, ())
+            can_translate = tuple(x for x in translated_targets if x in 
self.targets)
+            if can_translate:
+                target = can_translate[0]
+                log.info(" using '%s' instead", target)
+            else:
+                log.info(" valid targets: %s", csv(self.targets))
+                if must_discard_extra(target):
+                    log.info(" dropping the request")
+                    nodata()
+                    return
 
         target_data = self.target_data.get(target)
         if target_data and not self._have_token:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.2/xpra/x11/x11_server_base.py 
new/xpra-3.0.3/xpra/x11/x11_server_base.py
--- old/xpra-3.0.2/xpra/x11/x11_server_base.py  2019-10-20 14:13:42.000000000 
+0200
+++ new/xpra-3.0.3/xpra/x11/x11_server_base.py  2019-11-30 13:36:58.000000000 
+0100
@@ -23,6 +23,7 @@
 X11Keyboard = X11KeyboardBindings()
 
 SCALED_FONT_ANTIALIAS = envbool("XPRA_SCALED_FONT_ANTIALIAS", False)
+SYNC_ICC = envbool("XPRA_SYNC_ICC", True)
 
 
 def _get_antialias_hintstyle(antialias):
@@ -189,6 +190,8 @@
 
 
     def set_icc_profile(self):
+        if not SYNC_ICC:
+            return
         ui_clients = [s for s in self._server_sources.values() if s.ui_client]
         if len(ui_clients)!=1:
             screenlog("%i UI clients, resetting ICC profile to default", 
len(ui_clients))



Reply via email to