Hello community,

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

Package is "xpra"

Mon Mar 16 10:17:40 2020 rev:16 rq:784854 version:3.0.7

Changes:
--------
--- /work/SRC/openSUSE:Factory/xpra/xpra.changes        2020-02-10 
21:54:43.898234379 +0100
+++ /work/SRC/openSUSE:Factory/.xpra.new.3160/xpra.changes      2020-03-16 
10:18:13.447584445 +0100
@@ -1,0 +2,51 @@
+Sat Mar 14 07:50:10 UTC 2020 - [email protected]
+
+- Update to version 3.0.7
+  * fix avcodec2 race condition crash
+  * fix errors when re-initializing windows (ie: toggling OpenGL
+    on or off)
+  * fix deiconification error when there are system trays
+    forwarded
+  * fix missing alpha channel when some windows are first shown
+  * fix systemd-run errors: verify it does work before trying to
+    use it
+  * fix server crashes on SIGINT: shutdown cleanly
+  * fix proxy server client connection setup error hanlder
+  * fix file authentication handler using a default password
+    filename
+  * fix directshow errors on local mingw installations
+  * fix opengl properties missing from server hello packet
+  * fix HTML5 sound-control errors when speaker forwarding is
+    disabled
+  * fix HTML5 "Terminate" options wrongly enabled in "Connect"
+    mode
+  * fix clipboard sharing with the MacOS shadow server
+  * fix MS Windows clipboard access denied errors
+  * fix X11 clipboard error handling: continue processing
+  * fix unit tests failures (clipboard, etc)
+  * fix bug report clipboard copy and screnshots
+  * fix clipboard timeouts when a client disconnects
+  * fix mdns cleanup done twice on server exit, causing errors
+  * fix malformed XSettings due to invalid color data format
+  * fix HMAC hashes exposed, keep only valid options
+  * fix 'showconfig' output for boolean values set to 'auto'
+  * fix parsing of client display information in legacy format
+  * fix validation of size-hints
+  * fix cursor saving debug code with GTK3
+  * fix keyboard layout group not getting reset on client exit
+  * fix some empty keyboard layout group strings parsed as
+    non-empty
+  * fix keyboard-sync mode not being honoured by servers
+  * fix keyboard raw mode
+  * fix missing 'perispomeni' key mapping with Python 2 servers
+  * add missing debug logging to keyboard mapping
+  * more reliable lookup of keycodes when translating (non-X11
+    clients)
+  * skip bundling some external test modules with binary
+    installers
+  * avoid spurious background worker warnings on exit
+  * make unavoidable comtypes error less scary
+  * add 'libreoffice' to the text mode whitelist
+  * packaging workarounds for setuptools breakage
+
+-------------------------------------------------------------------

Old:
----
  xpra-3.0.6.tar.xz

New:
----
  xpra-3.0.7.tar.xz

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

Other differences:
------------------
++++++ xpra.spec ++++++
--- /var/tmp/diff_new_pack.OzzrMA/_old  2020-03-16 10:18:14.039584686 +0100
+++ /var/tmp/diff_new_pack.OzzrMA/_new  2020-03-16 10:18:14.039584686 +0100
@@ -19,7 +19,7 @@
 
 %global __requires_exclude 
^typelib\\(GtkosxApplication\\)|typelib\\(GdkGLExt\\)|typelib\\(GtkGLExt\\).*$
 Name:           xpra
-Version:        3.0.6
+Version:        3.0.7
 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
@@ -40,6 +40,7 @@
 BuildRequires:  python3-Cython >= 0.20.0
 BuildRequires:  python3-devel
 BuildRequires:  python3-gobject-devel
+BuildRequires:  python3-setuptools
 BuildRequires:  update-desktop-files
 BuildRequires:  pkgconfig(gtk+-3.0)
 BuildRequires:  pkgconfig(libavcodec) >= 58

++++++ xpra-3.0.6.tar.xz -> xpra-3.0.7.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/NEWS new/xpra-3.0.7/NEWS
--- old/xpra-3.0.6/NEWS 2020-02-07 12:19:08.000000000 +0100
+++ new/xpra-3.0.7/NEWS 2020-03-13 17:51:18.000000000 +0100
@@ -1,3 +1,52 @@
+v3.0.7 (2020-03-02)
+======================
+       -- fix avcodec2 race condition crash
+       -- fix errors when re-initializing windows (ie: toggling OpenGL on or 
off)
+       -- fix deiconification error when there are system trays forwarded
+       -- fix missing alpha channel when some windows are first shown
+       -- fix systemd-run errors: verify it does work before trying to use it
+       -- fix debug builds compilation error on MS Windows
+       -- fix server crashes on SIGINT: shutdown cleanly
+       -- fix proxy server client connection setup error hanlder
+       -- fix file authentication handler using a default password filename
+       -- fix directshow errors on local mingw installations
+       -- fix opengl properties missing from server hello packet
+       -- fix HTML5 sound-control errors when speaker forwarding is disabled
+       -- fix HTML5 "Terminate" options wrongly enabled in "Connect" mode
+       -- fix clipboard sharing with the MacOS shadow server
+       -- fix MS Windows clipboard access denied errors
+       -- fix X11 clipboard error handling: continue processing
+       -- fix unit tests failures (clipboard, etc)
+       -- fix bug report clipboard copy and screnshots
+       -- fix clipboard timeouts when a client disconnects
+       -- fix mdns cleanup done twice on server exit, causing errors
+       -- fix malformed XSettings due to invalid color data format
+       -- fix FreeBSD builds
+       -- fix MS Windows packaging missing a codec DLL, Plink DLL
+       -- fix HMAC hashes exposed, keep only valid options
+       -- fix 'showconfig' output for boolean values set to 'auto'
+       -- fix parsing of client display information in legacy format
+       -- fix validation of size-hints
+       -- fix cursor saving debug code with GTK3
+       -- fix keyboard layout group not getting reset on client exit
+       -- fix some empty keyboard layout group strings parsed as non-empty
+       -- fix keyboard-sync mode not being honoured by servers
+       -- fix keyboard raw mode
+       -- fix missing 'perispomeni' key mapping with Python 2 servers
+       -- add missing debug logging to keyboard mapping
+       -- more reliable lookup of keycodes when translating (non-X11 clients)
+       -- add missing dependency for printer forwarding on Debian
+       -- packaging for Ubuntu Focal Fossa
+       -- skip bundling some external test modules with binary installers
+       -- more correct code for locating the 'Downloads' folder on MS Windows
+       -- avoid spurious background worker warnings on exit
+       -- make unavoidable comtypes error less scary
+       -- add 'libreoffice' to the text mode whitelist
+       -- library updates: Python 3.8.2, etc
+       -- packaging workarounds for setuptools breakage
+
+
+
 v3.0.6 (2020-02-05)
 ======================
        -- fix UDP with Python3
@@ -21,13 +70,17 @@
        -- fix MS Windows packaging workarounds for TK
        -- fix for crashes on X11 displays lacking RandR support
        -- fix handling of non 24/32-bit png window icons
+       -- fix 'User' not honoured in ssh_config
+       -- fix X11 server initiate move-resize
        -- man page connection string fixes
        -- disable cpuinfo module - known to cause problems on various platforms
        -- ignore error and continue when loading version information from 
invalid builds
+       -- prettier format for new connection information
        -- remove executable file permissions on files uploaded to the server
        -- blacklist 'Intel(R) UHD Graphics 620'
        -- use correct location for appdata.xml
        -- use Debian location for systemd service config file
+       -- Debian packaging: prefer python3 installations
        -- ensure emacs, gvim and xxdiff always use 'text' mode
        -- re-enable pulseaudio memfd (was wrongly disabled in v3.0.0)
        -- remove remnants of GTK2 dependencies from non-GTK2 components
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/content-type/50_class.conf 
new/xpra-3.0.7/content-type/50_class.conf
--- old/xpra-3.0.6/content-type/50_class.conf   2020-01-25 11:03:50.000000000 
+0100
+++ new/xpra-3.0.7/content-type/50_class.conf   2020-03-08 03:21:09.000000000 
+0100
@@ -12,6 +12,7 @@
 class-instance:emacs=text
 class-instance:gvim=text
 
+class-instance:libreoffice=text
 class-instance:vlc=video
 
 class-instance:VirtualBox Machine=picture
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/cups/xpraforwarder 
new/xpra-3.0.7/cups/xpraforwarder
--- old/xpra-3.0.6/cups/xpraforwarder   2020-01-20 20:48:07.000000000 +0100
+++ new/xpra-3.0.7/cups/xpraforwarder   2020-02-18 06:58:41.000000000 +0100
@@ -42,7 +42,7 @@
     from urllib.parse import urlparse, parse_qs
 
 
-__version__ = "3.0.6"
+__version__ = "3.0.7"
 
 
 #Writes a syslog entry (msg) at the default facility:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/html5/connect.html 
new/xpra-3.0.7/html5/connect.html
--- old/xpra-3.0.6/html5/connect.html   2019-11-18 16:50:49.000000000 +0100
+++ new/xpra-3.0.7/html5/connect.html   2020-03-13 17:51:18.000000000 +0100
@@ -417,7 +417,6 @@
                var action = $(this).val();
                set_exit_actions(action=="connect");
        });
-       set_exit_actions(action=="connect" || action=="")
        $('input:radio[value="'+action+'"]').click();
 
        var encoding = getparam("encoding") || "auto";
@@ -544,6 +543,9 @@
        floating_menu_checkbox.change(set_menu_attributes_visibility);
        set_menu_attributes_visibility();
 
+       //this may override default values (ie: terminate flags are off for 
connect mode):
+       set_exit_actions(action=="connect" || action=="")
+
        $("#expandopts").click(function() {
                $("#hiddenopts").slideToggle();
        });
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/html5/index.html 
new/xpra-3.0.7/html5/index.html
--- old/xpra-3.0.6/html5/index.html     2020-02-07 12:19:08.000000000 +0100
+++ new/xpra-3.0.7/html5/index.html     2020-03-13 17:51:18.000000000 +0100
@@ -986,18 +986,23 @@
                                        $("#sound_button").attr("data-icon", 
data_icon);
                                        $("#sound_button").attr("title", 
tooltip);
                                };
-                               $("#sound_button").click(function() {
-                                       clog("speaker icon clicked");
-                                       if (client.audio_state=="playing" || 
client.audio_state=="waiting") {
-                                               
client.on_audio_state_change("stopped", "user action");
-                                               client.close_audio();
-                                       }
-                                       else {
-                                               
client.on_audio_state_change("waiting", "user action");
-                                               client._audio_start_stream();
-                                               client._sound_start_receiving();
-                                       }
-                               })
+                               if (client.audio_enabled) {
+                                       $("#sound_button").click(function() {
+                                               clog("speaker icon clicked, 
audio_enabled=", client.audio_enabled);
+                                               if 
(client.audio_state=="playing" || client.audio_state=="waiting") {
+                                                       
client.on_audio_state_change("stopped", "user action");
+                                                       client.close_audio();
+                                               }
+                                               else {
+                                                       
client.on_audio_state_change("waiting", "user action");
+                                                       
client._audio_start_stream();
+                                                       
client._sound_start_receiving();
+                                               }
+                                       })
+                               }
+                               else {
+                                       $("#sound_button").hide();
+                               }
                                document.addEventListener("visibilitychange", 
function (e) {
                                        window_ids = 
Object.keys(client.id_to_window).map(Number);
                                        clog("visibilitychange hidden=", 
document.hidden, "connected=", client.connected);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/html5/js/Utilities.js 
new/xpra-3.0.7/html5/js/Utilities.js
--- old/xpra-3.0.6/html5/js/Utilities.js        2020-01-20 20:48:07.000000000 
+0100
+++ new/xpra-3.0.7/html5/js/Utilities.js        2020-02-18 06:58:41.000000000 
+0100
@@ -10,7 +10,7 @@
 'use strict';
 
 var Utilities = {
-       VERSION : "3.0.6",
+       VERSION : "3.0.7",
 
        exc : function() {
                console.error.apply(console, arguments);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/setup.py new/xpra-3.0.7/setup.py
--- old/xpra-3.0.6/setup.py     2020-02-07 12:19:08.000000000 +0100
+++ new/xpra-3.0.7/setup.py     2020-03-13 17:51:18.000000000 +0100
@@ -165,7 +165,7 @@
 minify_ENABLED = html5_ENABLED
 pam_ENABLED = DEFAULT and (server_ENABLED or proxy_ENABLED) and POSIX and not 
OSX and (os.path.exists("/usr/include/pam/pam_misc.h") or 
os.path.exists("/usr/include/security/pam_misc.h"))
 
-xdg_open_ENABLED        = LINUX and DEFAULT
+xdg_open_ENABLED        = (LINUX or FREEBSD) and DEFAULT
 netdev_ENABLED          = LINUX and DEFAULT
 vsock_ENABLED           = LINUX and 
os.path.exists("/usr/include/linux/vm_sockets.h")
 bencode_ENABLED         = DEFAULT
@@ -373,7 +373,9 @@
                     "curses", "pdb",
                     "tty",
                     "setuptools", "doctest"
-                    "_pytest", "pluggy", "more_itertools", "apipkg", "py", 
"funcsigs",
+                    "nose", "pytest", "_pytest", "pluggy", "more_itertools", 
"apipkg", "py", "funcsigs",
+                    "Cython", "cython", "pyximport",
+                    "pydoc_data",
                     ]
 if not PYTHON3:
     external_excludes.append("cpuinfo")
@@ -704,7 +706,7 @@
     if debug_ENABLED:
         add_to_keywords(kw, 'extra_compile_args', '-g')
         add_to_keywords(kw, 'extra_compile_args', '-ggdb')
-        if get_gcc_version()>=[4, 8]:
+        if get_gcc_version()>=[4, 8] and not WIN32:
             add_to_keywords(kw, 'extra_compile_args', '-fsanitize=address')
             add_to_keywords(kw, 'extra_link_args', '-fsanitize=address')
     if rpath and kw.get("libraries"):
@@ -1219,6 +1221,10 @@
             #svg pixbuf loader:
             add_DLLs("rsvg", "croco")
 
+        if dec_avcodec2_ENABLED:
+            #why isn't this one picked up automatically?
+            add_DLLs("x265")
+
         if sound_ENABLED:
             add_dir("share", ["gst-plugins-bad", "gst-plugins-base", 
"gstreamer-1.0"])
             add_gi("Gst-1.0", "GstAllocators-1.0", "GstAudio-1.0", 
"GstBase-1.0",
@@ -1481,14 +1487,14 @@
 
#*******************************************************************************
 else:
     #OSX and *nix:
+    if is_Fedora() or is_CentOS() or is_RedHat() or FREEBSD:
+        libexec = "libexec"
+    else:
+        libexec = "lib"
     if LINUX:
         if scripts_ENABLED:
             scripts += ["scripts/xpra_udev_product_version", 
"scripts/xpra_signal_listener"]
         libexec_scripts = []
-        if is_Fedora() or is_CentOS() or is_RedHat():
-            libexec = "libexec"
-        else:
-            libexec = "lib"
         if xdg_open_ENABLED:
             libexec_scripts += ["scripts/xdg-open", "scripts/gnome-open", 
"scripts/gvfs-open"]
         if server_ENABLED:
@@ -1497,7 +1503,7 @@
             add_data_files("%s/xpra/" % libexec, libexec_scripts)
     if data_ENABLED:
         man_path = "share/man"
-        if OPENBSD:
+        if OPENBSD or FREEBSD:
             man_path = "man"
         add_data_files("%s/man1" % man_path,  ["man/xpra.1", 
"man/xpra_launcher.1"])
         add_data_files("share/applications",  glob.glob("xdg/*.desktop"))
@@ -1551,7 +1557,10 @@
 
             if printing_ENABLED and POSIX:
                 #install "/usr/lib/cups/backend" with 0700 permissions:
-                copytodir("cups/xpraforwarder", "lib/cups/backend", 
chmod=0o700)
+                lib_cups = "lib/cups"
+                if FREEBSD:
+                    lib_cups = "libexec/cups"
+                copytodir("cups/xpraforwarder", "%s/backend" % lib_cups, 
chmod=0o700)
 
             if x11_ENABLED:
                 #install xpra_Xdummy if we need it:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/svn-info new/xpra-3.0.7/svn-info
--- old/xpra-3.0.6/svn-info     2020-02-07 12:24:52.000000000 +0100
+++ new/xpra-3.0.7/svn-info     2020-03-13 18:03:50.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: 25177
+Revision: 25629
 Node Kind: directory
 Schedule: normal
 Last Changed Author: antoine
-Last Changed Rev: 25156
-Last Changed Date: 2020-02-05 12:06:46 +0000 (Wed, 05 Feb 2020)
+Last Changed Rev: 25627
+Last Changed Date: 2020-03-12 15:57:01 +0000 (Thu, 12 Mar 2020)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/svn-version new/xpra-3.0.7/svn-version
--- old/xpra-3.0.6/svn-version  2020-02-07 12:24:52.000000000 +0100
+++ new/xpra-3.0.7/svn-version  2020-03-13 18:03:50.000000000 +0100
@@ -1 +1 @@
-25177
+25629
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-3.0.6/unittests/unit/client/mixins/webcam_test.py 
new/xpra-3.0.7/unittests/unit/client/mixins/webcam_test.py
--- old/xpra-3.0.6/unittests/unit/client/mixins/webcam_test.py  2019-09-24 
15:53:57.000000000 +0200
+++ new/xpra-3.0.7/unittests/unit/client/mixins/webcam_test.py  2020-02-26 
16:43:23.000000000 +0100
@@ -22,14 +22,16 @@
                        "virtual-video-devices" : 1,
                        })
                x = self.mixin
-               if x.webcam_forwarding>0:
-                       self.glib.timeout_add(2500, x.stop_sending_webcam)
-                       self.glib.timeout_add(5000, self.stop)
-                       self.main_loop.run()
-                       assert len(self.packets)>2
-                       self.verify_packet(0, ("webcam-start", 0, ))
-                       self.verify_packet(1, ("webcam-frame", 0, ))
-                       self.verify_packet(-1, ("webcam-stop", 0, ))
+               if not x.webcam_device:
+                       print("no webcam device found, test skipped")
+                       return
+               self.glib.timeout_add(2500, x.stop_sending_webcam)
+               self.glib.timeout_add(5000, self.stop)
+               self.main_loop.run()
+               assert len(self.packets)>2
+               self.verify_packet(0, ("webcam-start", 0, ))
+               self.verify_packet(1, ("webcam-frame", 0, ))
+               self.verify_packet(-1, ("webcam-stop", 0, ))
 
 def main():
        unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-3.0.6/unittests/unit/client/x11_clipboard_test_util.py 
new/xpra-3.0.7/unittests/unit/client/x11_clipboard_test_util.py
--- old/xpra-3.0.6/unittests/unit/client/x11_clipboard_test_util.py     
2019-09-24 15:53:57.000000000 +0200
+++ new/xpra-3.0.7/unittests/unit/client/x11_clipboard_test_util.py     
2020-03-13 17:51:18.000000000 +0100
@@ -58,6 +58,14 @@
                assert pollwait(client, 2) is None, "client has exited with 
return code %s" % client.poll()
                client_display = xvfb.display
 
+               #wait for client to own the clipboard:
+               cmd = self.get_xpra_cmd()+["info", server_display]
+               for _ in range(10):
+                       out = self.get_command_output(cmd)
+                       if out.find(b"clipboard.client=")>0:
+                               break
+                       time.sleep(1)
+
                if SANITY_CHECKS:
                        log("sanity checks")
                        #xclip sanity check: retrieve from the same display:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/unittests/unit/net/protocol_test.py 
new/xpra-3.0.7/unittests/unit/net/protocol_test.py
--- old/xpra-3.0.6/unittests/unit/net/protocol_test.py  2019-09-24 
15:53:57.000000000 +0200
+++ new/xpra-3.0.7/unittests/unit/net/protocol_test.py  2020-02-18 
06:58:42.000000000 +0100
@@ -152,7 +152,7 @@
         p.enable_compressor("lz4")
         #catch network packets before we write them:
         data = []
-        def raw_write(items, *_args):
+        def raw_write(_packet_type, items, *_args):
             for item in items:
                 data.append(item)
         p.raw_write = raw_write
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/unittests/unit/run.py 
new/xpra-3.0.7/unittests/unit/run.py
--- old/xpra-3.0.6/unittests/unit/run.py        2019-09-24 15:53:57.000000000 
+0200
+++ new/xpra-3.0.7/unittests/unit/run.py        2020-02-26 16:43:23.000000000 
+0100
@@ -39,8 +39,8 @@
         cmd = ["python%s" % sys.version_info[0], p]
         try:
             proc = subprocess.Popen(cmd)
-        except OSError:
-            write("failed to execute %s" % p)
+        except OSError as e:
+            write("failed to execute %s: %s" % (p, e))
             return 1
         v = proc.wait()
         if v!=0:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-3.0.6/unittests/unit/server/server_sockets_test.py 
new/xpra-3.0.7/unittests/unit/server/server_sockets_test.py
--- old/xpra-3.0.6/unittests/unit/server/server_sockets_test.py 2019-09-24 
15:53:58.000000000 +0200
+++ new/xpra-3.0.7/unittests/unit/server/server_sockets_test.py 2020-02-18 
06:58:42.000000000 +0100
@@ -11,7 +11,7 @@
 
 from xpra.util import repr_ellipsized
 from xpra.os_util import load_binary_file, pollwait, OSX, POSIX
-from xpra.exit_codes import EXIT_OK, EXIT_CONNECTION_LOST, EXIT_SSL_FAILURE, 
EXIT_STR
+from xpra.exit_codes import EXIT_OK, EXIT_CONNECTION_LOST, 
EXIT_CONNECTION_FAILED, EXIT_SSL_FAILURE, EXIT_STR, 
EXIT_SSL_CERTIFICATE_VERIFY_FAILURE
 from xpra.net.net_util import get_free_tcp_port
 from unit.server_test_util import ServerTestUtil, log
 
@@ -27,7 +27,7 @@
 
        def start_server(self, *args):
                server_proc = self.run_xpra(["start", "--no-daemon"]+list(args))
-               if pollwait(server_proc, 5) is not None:
+               if pollwait(server_proc, 10) is not None:
                        r = server_proc.poll()
                        raise Exception("server failed to start with args=%s, 
returned %s" % (args, estr(r)))
                return server_proc
@@ -61,6 +61,7 @@
                server.terminate()
                if r!=exit_code:
                        raise Exception("expected info client to return %s but 
got %s" % (estr(exit_code), estr(r)))
+               pollwait(server, 10)
 
        def test_default_socket(self):
                self._test_connect([], "allow", [], b"hello", ":", EXIT_OK)
@@ -68,6 +69,7 @@
        def test_tcp_socket(self):
                port = get_free_tcp_port()
                self._test_connect(["--bind-tcp=0.0.0.0:%i" % port], "allow", 
[], b"hello", "tcp://127.0.0.1:%i/" % port, EXIT_OK)
+               port = get_free_tcp_port()
                self._test_connect(["--bind-tcp=0.0.0.0:%i" % port], "allow", 
[], b"hello", "ws://127.0.0.1:%i/" % port, EXIT_OK)
 
        def test_ws_socket(self):
@@ -145,10 +147,10 @@
                        test_connect("wss://127.0.0.1:%i/" % ws_port, EXIT_OK, 
noverify)
 
                        #self signed cert should fail without noverify:
-                       test_connect("ssl://127.0.0.1:%i/" % ssl_port, 
EXIT_SSL_FAILURE)
-                       test_connect("ssl://127.0.0.1:%i/" % tcp_port, 
EXIT_SSL_FAILURE)
-                       test_connect("wss://127.0.0.1:%i/" % ws_port, 
EXIT_SSL_FAILURE)
-                       test_connect("wss://127.0.0.1:%i/" % wss_port, 
EXIT_SSL_FAILURE)
+                       test_connect("ssl://127.0.0.1:%i/" % ssl_port, 
EXIT_SSL_CERTIFICATE_VERIFY_FAILURE)
+                       test_connect("ssl://127.0.0.1:%i/" % tcp_port, 
EXIT_SSL_CERTIFICATE_VERIFY_FAILURE)
+                       test_connect("wss://127.0.0.1:%i/" % ws_port, 
EXIT_SSL_CERTIFICATE_VERIFY_FAILURE)
+                       test_connect("wss://127.0.0.1:%i/" % wss_port, 
EXIT_SSL_CERTIFICATE_VERIFY_FAILURE)
 
                finally:
                        shutil.rmtree(tmpdir)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/win32/MINGW_BUILD.sh 
new/xpra-3.0.7/win32/MINGW_BUILD.sh
--- old/xpra-3.0.6/win32/MINGW_BUILD.sh 2019-12-10 12:20:42.000000000 +0100
+++ new/xpra-3.0.7/win32/MINGW_BUILD.sh 2020-03-13 17:51:18.000000000 +0100
@@ -348,6 +348,9 @@
                fi
        fi
        cp -fn "${TORTOISESVN}/bin/TortoisePlink.exe" "${DIST}/Plink.exe"
+       for dll in vcruntime140.dll msvcp140.dll vcruntime140_1.dll; do
+               cp "/c/Windows/System32/$dll" "${DIST}/"
+       done
        #are we meant to include those DLLs?
        #rsync -rplogt "${TORTOISESVN}/bin/"*dll "${DIST}/"
 fi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/win32/xpra.iss 
new/xpra-3.0.7/win32/xpra.iss
--- old/xpra-3.0.6/win32/xpra.iss       2020-01-20 20:48:07.000000000 +0100
+++ new/xpra-3.0.7/win32/xpra.iss       2020-02-18 06:58:42.000000000 +0100
@@ -1,9 +1,9 @@
 [Setup]
 AppName=Xpra
 AppId=Xpra_is1
-AppVersion=3.0.6
-AppVerName=Xpra 3.0.6
-UninstallDisplayName=Xpra 3.0.6
+AppVersion=3.0.7
+AppVerName=Xpra 3.0.7
+UninstallDisplayName=Xpra 3.0.7
 AppPublisher=xpra.org
 AppPublisherURL=http:;xpra.org/
 DefaultDirName={pf}\Xpra
@@ -16,7 +16,7 @@
 Compression=lzma2/max
 SolidCompression=yes
 AllowUNCPath=false
-VersionInfoVersion=3.0.6
+VersionInfoVersion=3.0.7
 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.6/xpra/__init__.py 
new/xpra-3.0.7/xpra/__init__.py
--- old/xpra-3.0.6/xpra/__init__.py     2020-02-07 12:24:56.000000000 +0100
+++ new/xpra-3.0.7/xpra/__init__.py     2020-03-13 18:03:50.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.6"
+__version__ = "3.0.7"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/client/auth/file_handler.py 
new/xpra-3.0.7/xpra/client/auth/file_handler.py
--- old/xpra-3.0.6/xpra/client/auth/file_handler.py     2019-09-24 
15:53:58.000000000 +0200
+++ new/xpra-3.0.7/xpra/client/auth/file_handler.py     2020-02-18 
06:58:42.000000000 +0100
@@ -17,7 +17,6 @@
             if client.password_file:
                 self.password_file = client.password_file[0]
                 client.password_file = client.password_file[1:]
-            self.password_file = "password.txt"
 
     def __repr__(self):
         return "file"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/client/gtk_base/bug_report.py 
new/xpra-3.0.7/xpra/client/gtk_base/bug_report.py
--- old/xpra-3.0.6/xpra/client/gtk_base/bug_report.py   2019-12-08 
12:59:03.000000000 +0100
+++ new/xpra-3.0.7/xpra/client/gtk_base/bug_report.py   2020-03-08 
03:21:09.000000000 +0100
@@ -16,7 +16,7 @@
     JUSTIFY_LEFT, WIN_POS_CENTER, FILE_CHOOSER_ACTION_SAVE,
     )
 from xpra.util import nonl, envint, repr_ellipsized
-from xpra.os_util import strtobytes
+from xpra.os_util import strtobytes, hexstr, PYTHON3
 from xpra.log import Logger
 
 log = Logger("util")
@@ -212,9 +212,7 @@
             hbox.pack_start(btn)
             return btn
 
-        if not is_gtk3():
-            #clipboard does not work in gtk3..
-            btn("Copy to clipboard", "Copy all data to clipboard", 
self.copy_clicked, "clipboard.png")
+        btn("Copy to clipboard", "Copy all data to clipboard", 
self.copy_clicked, "clipboard.png")
         btn("Save", "Save Bug Report", self.save_clicked, "download.png")
         btn("Cancel", "", self.close, "quit.png")
 
@@ -235,12 +233,14 @@
 
     def hide(self):
         log("hide()")
-        self.window.hide()
+        if self.window:
+            self.window.hide()
 
     def close(self, *args):
         log("close%s", args)
-        self.hide()
-        self.window = None
+        if self.window:
+            self.hide()
+            self.window = None
         return True
 
     def destroy(self, *args):
@@ -269,8 +269,8 @@
         return None
 
 
-    def get_text_data(self):
-        log("get_text_data() collecting bug report data")
+    def get_data(self):
+        log("get_data() collecting bug report data")
         data = []
         tb = self.description.get_buffer()
         buf = tb.get_text(*tb.get_bounds(), include_hidden_chars=False)
@@ -304,15 +304,19 @@
             elif isinstance(value, (list, tuple)):
                 s = os.linesep.join(str(x) for x in value)
             else:
-                s = str(value)
+                s = value
             log("%s (%s) %s: %s", title, tooltip, dtype, repr_ellipsized(s))
             data.append((title, tooltip, dtype, s))
             time.sleep(STEP_DELAY)
         return data
 
     def copy_clicked(self, *_args):
-        data = self.get_text_data()
-        text = os.linesep.join("%s: %s%s%s%s" % (title, tooltip, os.linesep, 
v, os.linesep)
+        data = self.get_data()
+        def cdata(v):
+            if isinstance(v, bytes):
+                return hexstr(v)
+            return str(v)
+        text = os.linesep.join("%s: %s%s%s%s" % (title, tooltip, os.linesep, 
cdata(v), os.linesep)
                                for (title,tooltip,dtype,v) in data if 
dtype=="txt")
         clipboard = gtk.clipboard_get(gdk.SELECTION_CLIPBOARD)
         clipboard.set_text(text)
@@ -329,7 +333,7 @@
         if not filename.lower().endswith(".zip"):
             filename = filename+".zip"
         basenoext = os.path.splitext(os.path.basename(filename))[0]
-        data = self.get_text_data()
+        data = self.get_data()
         import zipfile
         zf = zipfile.ZipFile(filename, mode='w', 
compression=zipfile.ZIP_DEFLATED)
         try:
@@ -340,6 +344,23 @@
                 #very poorly documented:
                 info.external_attr = 0o644 << 16
                 info.comment = strtobytes(tooltip)
-                zf.writestr(info, s)
+                if PYTHON3 and isinstance(s, bytes):
+                    try:
+                        try:
+                            import tempfile
+                            temp = tempfile.NamedTemporaryFile(prefix="xpra.", 
suffix=".screenshot", delete=False)
+                            with temp:
+                                temp.write(s)
+                                temp.flush()
+                        except OSError as e:
+                            log.error("Error: cannot create mmap file:")
+                            log.error(" %s", e)
+                        else:
+                            zf.write(temp.name, cfile, zipfile.ZIP_STORED, 0)
+                    finally:
+                        if temp:
+                            os.unlink(temp.name)
+                else:
+                    zf.writestr(info, str(s))
         finally:
             zf.close()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/client/gtk_base/gtk_client_base.py 
new/xpra-3.0.7/xpra/client/gtk_base/gtk_client_base.py
--- old/xpra-3.0.6/xpra/client/gtk_base/gtk_client_base.py      2020-01-08 
12:52:06.000000000 +0100
+++ new/xpra-3.0.7/xpra/client/gtk_base/gtk_client_base.py      2020-03-08 
03:21:09.000000000 +0100
@@ -664,7 +664,7 @@
     def make_hello(self):
         capabilities = UIXpraClient.make_hello(self)
         capabilities["named_cursors"] = len(cursor_types)>0
-        capabilities["transparency"] = self.has_transparency()
+        capabilities["encoding.transparency"] = self.has_transparency()
         capabilities.update(flatten_dict(get_gtk_version_info()))
         if EXPORT_ICON_DATA:
             #tell the server which icons GTK can use
@@ -866,7 +866,10 @@
             else:
                 cursor_pixbuf = pixbuf
         if SAVE_CURSORS:
-            cursor_pixbuf.save("cursor-%#x.png" % serial, "png")
+            if PYTHON3:
+                cursor_pixbuf.savev("cursor-%#x.png" % serial, "png", [], [])
+            else:
+                cursor_pixbuf.save("cursor-%#x.png" % serial, "png")
         #clamp to pixbuf size:
         w = cursor_pixbuf.get_width()
         h = cursor_pixbuf.get_height()
@@ -1113,7 +1116,7 @@
         self.opengl_enabled = not self.opengl_enabled
         opengllog("opengl_toggled: %s", self.opengl_enabled)
         #now replace all the windows with new ones:
-        for wid, window in self._id_to_window.items():
+        for wid, window in tuple(self._id_to_window.items()):
             self.reinit_window(wid, window)
         opengllog("replaced all the windows with opengl=%s: %s", 
self.opengl_enabled, self._id_to_window)
         self.reinit_window_icons()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/client/mixins/window_manager.py 
new/xpra-3.0.7/xpra/client/mixins/window_manager.py
--- old/xpra-3.0.6/xpra/client/mixins/window_manager.py 2020-02-07 
12:19:09.000000000 +0100
+++ new/xpra-3.0.7/xpra/client/mixins/window_manager.py 2020-03-08 
03:21:09.000000000 +0100
@@ -879,7 +879,9 @@
     def deiconify_windows(self):
         log("deiconify_windows()")
         for window in self._id_to_window.values():
-            window.deiconify()
+            deiconify = getattr(window, "deiconify", None)
+            if deiconify:
+                deiconify()
 
 
     def resize_windows(self, new_size_fn):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/clipboard/clipboard_core.py 
new/xpra-3.0.7/xpra/clipboard/clipboard_core.py
--- old/xpra-3.0.6/xpra/clipboard/clipboard_core.py     2019-09-24 
15:53:59.000000000 +0200
+++ new/xpra-3.0.7/xpra/clipboard/clipboard_core.py     2020-03-08 
03:21:09.000000000 +0100
@@ -539,6 +539,7 @@
         #clients that need a new token for every owner-change: (ie: win32 and 
osx)
         #(forces the client to request new contents - prevents stale clipboard 
data)
         self._greedy_client = False
+        self._want_targets = False
         #semaphore to block the sending of the token when we change the owner 
ourselves:
         self._block_owner_change = False
         self._last_emit_token = 0
@@ -564,6 +565,10 @@
         self._can_send = can_send
         self._can_receive = can_receive
 
+    def set_want_targets(self, want_targets):
+        self._want_targets = want_targets
+
+
     def get_info(self):
         info = {
                 "have_token"            : self._have_token,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/xpra-3.0.6/xpra/clipboard/clipboard_timeout_helper.py 
new/xpra-3.0.7/xpra/clipboard/clipboard_timeout_helper.py
--- old/xpra-3.0.6/xpra/clipboard/clipboard_timeout_helper.py   2019-09-24 
15:53:59.000000000 +0200
+++ new/xpra-3.0.7/xpra/clipboard/clipboard_timeout_helper.py   2020-03-13 
17:51:18.000000000 +0100
@@ -5,7 +5,7 @@
 
 from xpra.gtk_common.gobject_compat import import_glib
 from xpra.clipboard.clipboard_core import ClipboardProtocolHelperCore
-from xpra.util import repr_ellipsized, envint
+from xpra.util import repr_ellipsized, envint, engs
 from xpra.log import Logger
 from xpra.platform.features import CLIPBOARD_GREEDY
 
@@ -113,3 +113,13 @@
             (request_id, dtype, dformat, repr_ellipsized(str(data))), proxy, 
selection)
         if proxy:
             proxy.got_contents(target, dtype, dformat, data)
+
+    def client_reset(self):
+        super().client_reset()
+        #timeout all pending requests
+        cor = self._clipboard_outstanding_requests
+        if cor:
+            log.info("cancelling %i clipboard request%s", len(cor), engs(cor))
+            self._clipboard_outstanding_requests = {}
+            for request_id in cor:
+                self._clipboard_got_contents(request_id)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/codecs/dec_avcodec2/decoder.pyx 
new/xpra-3.0.7/xpra/codecs/dec_avcodec2/decoder.pyx
--- old/xpra-3.0.6/xpra/codecs/dec_avcodec2/decoder.pyx 2019-09-24 
15:53:59.000000000 +0200
+++ new/xpra-3.0.7/xpra/codecs/dec_avcodec2/decoder.pyx 2020-03-08 
03:21:09.000000000 +0100
@@ -254,7 +254,8 @@
         log("%s.free() context=%#x, frame=%#x", self, <uintptr_t> self.avctx, 
<uintptr_t> self.frame)
         if self.avctx!=NULL and self.frame!=NULL:
             av_frame_unref(self.frame)
-            self.frame = NULL
+            av_frame_free(&self.frame)
+            self.frame = NULL   #should be redundant
             self.avctx = NULL
 
 
@@ -375,13 +376,6 @@
             log.error("could not open codec: %s", av_error_str(r))
             self.clean_decoder()
             return  False
-        #up to 3 AVFrame objects used:
-        self.av_frame = av_frame_alloc()
-        log("av_frame_alloc()=%#x", <uintptr_t> self.av_frame)
-        if self.av_frame==NULL:
-            log.error("could not allocate an AVFrame for decoding")
-            self.clean_decoder()
-            return  False
         self.frames = 0
         #to keep track of images not freed yet:
         #(we want a weakref.WeakSet() but this is python2.7+ only..)
@@ -397,7 +391,6 @@
         self.actual_pix_fmt = 0
         self.colorspace = ""
         self.weakref_images = []
-        self.av_frame = NULL                        #should be redundant
         self.frames = 0
         self.width = 0
         self.height = 0
@@ -418,12 +411,6 @@
             for img in images:
                 if not img.freed:
                     img.clone_pixel_data()
-
-        if self.av_frame!=NULL:
-            log("clean_decoder() freeing AVFrame: %#x", <uintptr_t> 
self.av_frame)
-            av_frame_free(&self.av_frame)
-            #redundant: self.frame = NULL
-
         log("clean_decoder() freeing AVCodecContext: %#x", <uintptr_t> 
self.codec_ctx)
         if self.codec_ctx!=NULL:
             r = avcodec_close(self.codec_ctx)
@@ -511,6 +498,13 @@
         assert self.codec_ctx!=NULL, "no codec context! (not initialized or 
already closed)"
         assert self.codec!=NULL
 
+        av_frame = av_frame_alloc()
+        log("av_frame_alloc()=%#x", <uintptr_t> av_frame)
+        if av_frame==NULL:
+            log.error("could not allocate an AVFrame for decoding")
+            self.clean_decoder()
+            return None
+
         #copy the whole input buffer into a padded C buffer:
         assert object_as_buffer(input, <const void**> &buf, &buf_len)==0
         padded_buf = <unsigned char *> memalign(buf_len+128)
@@ -524,7 +518,7 @@
         outsize = 0
 
         #ensure we can detect if the frame buffer got allocated:
-        clear_frame(self.av_frame)
+        clear_frame(av_frame)
         #now safe to run without gil:
         with nogil:
             av_init_packet(&avpkt)
@@ -537,7 +531,7 @@
             self.log_av_error(buf_len, ret, options)
             return None
         with nogil:
-            ret = avcodec_receive_frame(self.codec_ctx, self.av_frame)
+            ret = avcodec_receive_frame(self.codec_ctx, av_frame)
         free(padded_buf)
         if ret==-errno.EAGAIN:
             d = options.intget("delayed", 0)
@@ -547,19 +541,21 @@
             self.log_error(buf_len, "no picture", options)
             return None
         if ret!=0:
-            av_frame_unref(self.av_frame)
+            av_frame_unref(av_frame)
+            av_frame_free(&av_frame)
             log("%s.decompress_image(%s:%s, %s) avcodec_decode_video2 failure: 
%s", self, type(input), buf_len, options, av_error_str(ret))
             self.log_av_error(buf_len, ret, options)
             return None
 
         log("avcodec_decode_video2 returned %i", ret)
-        if self.actual_pix_fmt!=self.av_frame.format:
-            if self.av_frame.format==-1:
+        if self.actual_pix_fmt!=av_frame.format:
+            if av_frame.format==-1:
                 self.log_error(buf_len, "unknown format returned")
                 return None
-            self.actual_pix_fmt = self.av_frame.format
+            self.actual_pix_fmt = av_frame.format
             if self.actual_pix_fmt not in ENUM_TO_FORMAT:
-                av_frame_unref(self.av_frame)
+                av_frame_unref(av_frame)
+                av_frame_free(&av_frame)
                 log.error("unknown output pixel format: %s, expected %s (%s)", 
self.actual_pix_fmt, self.pix_fmt, self.colorspace)
                 return None
             log("avcodec actual output pixel format is %s (%s), expected %s 
(%s)", self.actual_pix_fmt, self.get_actual_colorspace(), self.pix_fmt, 
self.colorspace)
@@ -575,32 +571,34 @@
                 elif dy==2:
                     height = (self.codec_ctx.height+1)>>1
                 else:
-                    av_frame_unref(self.av_frame)
+                    av_frame_unref(av_frame)
+                    av_frame_free(&av_frame)
                     raise Exception("invalid height divisor %s" % dy)
-                stride = self.av_frame.linesize[i]
+                stride = av_frame.linesize[i]
                 size = height * stride
                 outsize += size
 
-                out.append(memory_as_pybuffer(<void *>self.av_frame.data[i], 
size, True))
+                out.append(memory_as_pybuffer(<void *>av_frame.data[i], size, 
True))
                 strides.append(stride)
                 log("decompress_image() read back yuv plane %s: %s bytes", i, 
size)
         else:
             #RGB mode: "out" is a single buffer
-            strides = 
self.av_frame.linesize[0]+self.av_frame.linesize[1]+self.av_frame.linesize[2]
+            strides = 
av_frame.linesize[0]+av_frame.linesize[1]+av_frame.linesize[2]
             outsize = self.codec_ctx.height * strides
-            out = memory_as_pybuffer(<void *>self.av_frame.data[0], outsize, 
True)
+            out = memory_as_pybuffer(<void *>av_frame.data[0], outsize, True)
             nplanes = 0
             log("decompress_image() read back rgb buffer: %s bytes", outsize)
 
         if outsize==0:
-            av_frame_unref(self.av_frame)
+            av_frame_unref(av_frame)
+            av_frame_free(&av_frame)
             raise Exception("output size is zero!")
         if self.codec_ctx.width<self.width or 
self.codec_ctx.height<self.height:
             raise Exception("%s context dimension %ix%i is smaller than the 
codec's expected size of %ix%i for frame %i" % (self.encoding, 
self.codec_ctx.width, self.codec_ctx.height, self.width, self.height, 
self.frames+1))
 
         bpp = BYTES_PER_PIXEL.get(self.actual_pix_fmt, 0)
         framewrapper = AVFrameWrapper()
-        framewrapper.set_context(self.codec_ctx, self.av_frame)
+        framewrapper.set_context(self.codec_ctx, av_frame)
         img = AVImageWrapper(0, 0, self.width, self.height, out, cs, 24, 
strides, bpp, nplanes, thread_safe=False)
         img.av_frame = framewrapper
         self.frames += 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/keyboard/layouts.py 
new/xpra-3.0.7/xpra/keyboard/layouts.py
--- old/xpra-3.0.6/xpra/keyboard/layouts.py     2020-01-25 11:03:51.000000000 
+0100
+++ new/xpra-3.0.7/xpra/keyboard/layouts.py     2020-03-08 03:21:09.000000000 
+0100
@@ -396,7 +396,7 @@
         m = opt_re.match(line)
         if m:
             v = m.group(2).strip()
-            if v!=",":
+            if v.strip(","):
                 settings[m.group(1)] = v
     return settings
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/net/bytestreams.py 
new/xpra-3.0.7/xpra/net/bytestreams.py
--- old/xpra-3.0.6/xpra/net/bytestreams.py      2019-10-20 14:13:42.000000000 
+0200
+++ new/xpra-3.0.7/xpra/net/bytestreams.py      2020-02-10 16:32:04.000000000 
+0100
@@ -600,7 +600,7 @@
     try:
         peername = sock.getpeername()
     except socket.error:
-        peername = str(address)
+        peername = address
     try:
         sockname = sock.getsockname()
     except AttributeError:
@@ -611,7 +611,7 @@
     if peername:
         frominfo = pretty_socket(peername)
         log.info("New %s connection received", socktype)
-        log.info(" from '%s'", frominfo)
+        log.info(" from '%s'", pretty_socket(frominfo))
         if socket_info:
             log.info(" on '%s'", pretty_socket(socket_info))
     elif socktype=="unix-domain":
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/net/digest.py 
new/xpra-3.0.7/xpra/net/digest.py
--- old/xpra-3.0.6/xpra/net/digest.py   2019-09-24 15:54:00.000000000 +0200
+++ new/xpra-3.0.7/xpra/net/digest.py   2020-02-26 16:43:23.000000000 +0100
@@ -30,7 +30,7 @@
     #python versions older than 2.7.9 may not have this attribute:
     #(in which case, your options will be more limited)
     if algorithms_available:
-        digests += ["hmac+%s" % x for x in 
tuple(reversed(sorted(algorithms_available)))]
+        digests += ["hmac+%s" % x for x in 
tuple(reversed(sorted(algorithms_available))) if not x.startswith("shake_") and 
getattr(hashlib, x, None) is not None]
     try:
         from xpra.net import d3des
         assert d3des
@@ -87,7 +87,7 @@
         return memoryview_to_bytes(v)
     digestmod = get_digest_module(digest)
     if not digestmod:
-        log("invalid digest module '%s': %s", digest)
+        log("invalid digest module '%s'", digest)
         return None
         #warn_server_and_exit(EXIT_UNSUPPORTED, "server requested digest '%s' 
but it is not supported" % digest, "invalid digest")
     v = hmac.HMAC(strtobytes(password), strtobytes(salt), 
digestmod=digestmod).hexdigest()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/net/ssh.py 
new/xpra-3.0.7/xpra/net/ssh.py
--- old/xpra-3.0.6/xpra/net/ssh.py      2019-11-05 18:31:07.000000000 +0100
+++ new/xpra-3.0.7/xpra/net/ssh.py      2020-02-10 16:32:04.000000000 +0100
@@ -258,7 +258,7 @@
             host_config = ssh_config.lookup(host)
             if host_config:
                 host = host_config.get("hostname", host)
-                username = host_config.get("username", username)
+                username = host_config.get("user", username)
                 port = host_config.get("port", port)
                 try:
                     port = int(port)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/platform/win32/clipboard.py 
new/xpra-3.0.7/xpra/platform/win32/clipboard.py
--- old/xpra-3.0.6/xpra/platform/win32/clipboard.py     2019-10-28 
16:04:05.000000000 +0100
+++ new/xpra-3.0.7/xpra/platform/win32/clipboard.py     2020-03-08 
03:21:09.000000000 +0100
@@ -9,11 +9,11 @@
     WinError, FormatError,
     )
 from xpra.platform.win32.common import (
-    WNDCLASSEX, GetLastError, ERROR_ACCESS_DENIED, WNDPROC, LPCWSTR, LPWSTR,
+    WNDCLASSEX, GetLastError, WNDPROC, LPCWSTR, LPWSTR,
     DefWindowProcW,
     GetModuleHandleA, RegisterClassExW, UnregisterClassA,
     CreateWindowExW, DestroyWindow,
-    OpenClipboard, EmptyClipboard, CloseClipboard, GetClipboardData,
+    OpenClipboard, EmptyClipboard, CloseClipboard, GetClipboardData, 
GetClipboardOwner,
     GlobalLock, GlobalUnlock, GlobalAlloc, GlobalFree,
     WideCharToMultiByte, MultiByteToWideChar,
     AddClipboardFormatListener, RemoveClipboardFormatListener,
@@ -147,28 +147,22 @@
         self.send_clipboard_token_handler = send_clipboard_token_handler
         ClipboardProxyCore.__init__(self, selection)
 
-    def set_want_targets(self, want_targets):
-        self._want_targets = want_targets
-
     def with_clipboard_lock(self, success_callback, failure_callback, 
retries=5, delay=5):
         r = OpenClipboard(self.window)
-        log("OpenClipboard(%#x)=%s", self.window, r)
         if r:
+            log("OpenClipboard(%#x)=%s", self.window, r)
             try:
                 success_callback()
                 return
             finally:
                 CloseClipboard()
-        if GetLastError()!=ERROR_ACCESS_DENIED:
-            failure_callback("OpenClipboard: access denied")
-            return
-        log("clipboard lock: access denied")
+        log("OpenClipboard(%#x)=%s, owner=%#x", self.window, 
WinError(GetLastError()), GetClipboardOwner())
         if retries<=0:
             failure_callback("OpenClipboard: too many failed attemps, giving 
up")
             return
         #try again later:
         glib.timeout_add(delay, self.with_clipboard_lock,
-                         success_callback, failure_callback, retries-1, delay)
+                         success_callback, failure_callback, retries-1, 
delay+5)
 
     def clear(self):
         def clear_error(error_text=""):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/platform/win32/namedpipes/common.py 
new/xpra-3.0.7/xpra/platform/win32/namedpipes/common.py
--- old/xpra-3.0.6/xpra/platform/win32/namedpipes/common.py     2019-09-24 
15:54:00.000000000 +0200
+++ new/xpra-3.0.7/xpra/platform/win32/namedpipes/common.py     2020-02-10 
16:32:04.000000000 +0100
@@ -76,7 +76,7 @@
 CreateNamedPipeA.argtypes = [LPCSTR, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, 
LPSECURITY_ATTRIBUTES]
 CreateNamedPipeA.restype = HANDLE
 ConnectNamedPipe = kernel32.ConnectNamedPipe
-ConnectNamedPipe.argtypes = [HANDLE, OVERLAPPED]
+ConnectNamedPipe.argtypes = [HANDLE, LPOVERLAPPED]
 ConnectNamedPipe.restype = BOOL
 DisconnectNamedPipe = kernel32.DisconnectNamedPipe
 DisconnectNamedPipe.argtypes = [HANDLE]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/platform/win32/netdev_query.py 
new/xpra-3.0.7/xpra/platform/win32/netdev_query.py
--- old/xpra-3.0.6/xpra/platform/win32/netdev_query.py  2019-09-24 
15:54:00.000000000 +0200
+++ new/xpra-3.0.7/xpra/platform/win32/netdev_query.py  2020-03-13 
17:51:19.000000000 +0100
@@ -47,8 +47,8 @@
             log("get_interface_info(%s)", iface, exc_info=True)
             from xpra.util import first_time
             if first_time("win32-network-query"):
-                log.error("Error: failed to query network interface:")
-                log.error(" %s", e)
+                log.info("cannot query network interface:")
+                log.info(" %s", e)
         return {}
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/platform/win32/paths.py 
new/xpra-3.0.7/xpra/platform/win32/paths.py
--- old/xpra-3.0.6/xpra/platform/win32/paths.py 2019-09-24 15:54:00.000000000 
+0200
+++ new/xpra-3.0.7/xpra/platform/win32/paths.py 2020-03-08 03:21:09.000000000 
+0100
@@ -134,22 +134,15 @@
 
 
 def do_get_download_dir():
-    #TODO: use "FOLDERID_Downloads":
-    # FOLDERID_Downloads = "{374DE290-123F-4565-9164-39C4925E467B}"
-    # maybe like here:
-    # https://gist.github.com/mkropat/7550097
-    #from win32com.shell import shell, shellcon
-    #shell.SHGetFolderPath(0, shellcon.CSIDL_MYDOCUMENTS, None, 0)
     try:
         try:
             import _winreg as winreg
         except ImportError:
             import winreg   #@UnresolvedImport @Reimport
-        #use the internet explorer registry key:
-        #HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer
-        key_path = 'Software\\Microsoft\\Internet Explorer'
-        key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_path, 0, 
winreg.KEY_READ)    #@UndefinedVariable
-        DOWNLOAD_PATH = winreg.QueryValueEx(key, 'Download Directory')[0]      
         #@UndefinedVariable
+        sub_key = r'SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell 
Folders'
+        downloads_guid = '{374DE290-123F-4565-9164-39C4925E467B}'
+        with winreg.OpenKey(winreg.HKEY_CURRENT_USER, sub_key) as key:
+            DOWNLOAD_PATH = winreg.QueryValueEx(key, downloads_guid)[0]
     except:
         #fallback to what the documentation says is the default:
         DOWNLOAD_PATH = os.path.join(os.environ.get("USERPROFILE", "~"), "My 
Documents", "Downloads")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/platform/win32/win32_webcam.py 
new/xpra-3.0.7/xpra/platform/win32/win32_webcam.py
--- old/xpra-3.0.6/xpra/platform/win32/win32_webcam.py  2019-09-24 
15:54:00.000000000 +0200
+++ new/xpra-3.0.7/xpra/platform/win32/win32_webcam.py  2020-02-26 
16:43:23.000000000 +0100
@@ -32,9 +32,16 @@
 
 
 #try to load directshow tlb from various directories,
-#depending on how xpra was packaged, or even run from the source directory:
-dirs = [app_dir, os.path.join(app_dir, "win32"), os.path.join(app_dir, 
"share", "xpra")]
+#depending on how xpra was packaged, installed locally,
+#or even run from the source directory:
+dirs = [
+    app_dir,
+    os.path.join(app_dir, "win32"),
+    os.path.join(app_dir, "share", "xpra"),
+    os.path.join(os.environ.get("MINGW_PREFIX", ""), "share", "xpra"),
+    ]
 filenames = [os.environ.get("XPRA_DIRECTSHOW_TLB")] + [os.path.join(d, 
"DirectShow.tlb") for d in dirs]
+directshow_tlb = None
 for filename in filenames:
     if filename and os.path.exists(filename):
         directshow_tlb = filename
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/scripts/main.py 
new/xpra-3.0.7/xpra/scripts/main.py
--- old/xpra-3.0.6/xpra/scripts/main.py 2019-12-29 17:24:22.000000000 +0100
+++ new/xpra-3.0.7/xpra/scripts/main.py 2020-03-13 17:51:19.000000000 +0100
@@ -21,7 +21,7 @@
 from xpra.util import csv, envbool, envint, unsetenv, repr_ellipsized, nonl, 
pver, DEFAULT_PORT, DEFAULT_PORTS
 from xpra.exit_codes import EXIT_SSL_FAILURE, EXIT_STR, EXIT_UNSUPPORTED
 from xpra.os_util import (
-    get_util_logger, getuid, getgid,
+    get_util_logger, getuid, getgid, pollwait,
     monotonic_time, setsid, bytestostr, use_tty,
     WIN32, OSX, POSIX, PYTHON2, PYTHON3, SIGNAMES, is_Ubuntu, getUbuntuVersion,
     )
@@ -299,7 +299,18 @@
                 systemd_run = False
             else:
                 from xpra.os_util import is_systemd_pid1
-                systemd_run = is_systemd_pid1()
+                if is_systemd_pid1():
+                    cmd = ["systemd-run", "--quiet", "--user", "--scope", 
"--", "true"]
+                    proc = Popen(cmd, stdin=None, stdout=None, stderr=None, 
shell=False)
+                    r = pollwait(proc, timeout=1)
+                    if r is None:
+                        try:
+                            proc.terminate()
+                        except:
+                            pass
+                    systemd_run = r==0
+                else:
+                    systemd_run = False
         if systemd_run:
             #check if we have wrapped it already (or if disabled via env var)
             if SYSTEMD_RUN:
@@ -2639,9 +2650,10 @@
             from xpra.platform.pycups_printing import get_printer_definition
             for mimetype in ("pdf", "postscript"):
                 pdef = get_printer_definition(mimetype)
-                #ie: d.pdf_printer = 
"/usr/share/ppd/cupsfilters/Generic-PDF_Printer-PDF.ppd"
-                setattr(d, "%s_printer" % mimetype, pdef)
-        except:
+                if pdef:
+                    #ie: d.pdf_printer = 
"/usr/share/ppd/cupsfilters/Generic-PDF_Printer-PDF.ppd"
+                    setattr(d, "%s_printer" % mimetype, pdef)
+        except Exception:
             pass
     VIRTUAL = ["mode"]       #no such option! (it's a virtual one for the 
launch by config files)
     #hide irrelevant options:
@@ -2664,7 +2676,7 @@
             HIDDEN += ["lpadmin", "daemon", "use-display", "mmap-group", 
"mdns"]
         if not OSX:
             HIDDEN += ["dock-icon", "swap-keys"]
-    for opt in sorted(OPTION_TYPES.keys()):
+    for opt, otype in sorted(OPTION_TYPES.items()):
         if opt in VIRTUAL:
             continue
         i = log.info
@@ -2679,19 +2691,21 @@
         dv = getattr(d, k)
         cv = getattr(options, k, dv)
         if cv!=dv:
-            w("%-20s  (used)   = %-32s  %s", opt, vstr(cv), type(cv))
-            w("%-20s (default) = %-32s  %s", opt, vstr(dv), type(dv))
+            w("%-20s  (used)   = %-32s  %s", opt, vstr(otype, cv), type(cv))
+            w("%-20s (default) = %-32s  %s", opt, vstr(otype, dv), type(dv))
         else:
-            i("%-20s           = %s", opt, vstr(cv))
+            i("%-20s           = %s", opt, vstr(otype, cv))
 
-def vstr(v):
+def vstr(otype, v):
     #just used to quote all string values
     if v is None:
+        if otype==bool:
+            return "auto"
         return ""
     if isinstance(v, str):
         return "'%s'" % nonl(v)
     if isinstance(v, (tuple, list)):
-        return csv(vstr(x) for x in v)
+        return csv(vstr(otype, x) for x in v)
     return str(v)
 
 def run_showsetting(options, args):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/server/background_worker.py 
new/xpra-3.0.7/xpra/server/background_worker.py
--- old/xpra-3.0.6/xpra/server/background_worker.py     2019-09-24 
15:54:01.000000000 +0200
+++ new/xpra-3.0.7/xpra/server/background_worker.py     2020-03-13 
17:51:19.000000000 +0100
@@ -32,16 +32,17 @@
     def stop(self, force=False):
         if self.exit:
             return
+        items = tuple(x for x in tuple(self.items.queue) if x is not None)
+        log("Worker_Thread.stop(%s) %i items still in work queue: %s", force, 
len(items), items)
         if force:
-            if self.items.qsize()>0:
-                log.warn("Worker stop: %s items in the queue will not be 
run!", self.items.qsize())
+            if items:
+                log.warn("Worker stop: %s items in the queue will not be 
run!", len(items))
                 self.items.put(None)
                 self.items = Queue()
             self.exit = True
         else:
-            if self.items.qsize()>0:
-                log.info("waiting for %s items in work queue to complete", 
self.items.qsize())
-        debug("Worker_Thread.stop(%s) %s items in work queue", force, 
self.items)
+            if items:
+                log.info("waiting for %s items in work queue to complete", 
len(items))
         self.items.put(None)
 
     def add(self, item):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/server/mixins/clipboard_server.py 
new/xpra-3.0.7/xpra/server/mixins/clipboard_server.py
--- old/xpra-3.0.6/xpra/server/mixins/clipboard_server.py       2019-09-24 
15:54:01.000000000 +0200
+++ new/xpra-3.0.7/xpra/server/mixins/clipboard_server.py       2020-03-13 
17:51:19.000000000 +0100
@@ -56,7 +56,11 @@
     def get_info(self, _proto):
         if self._clipboard_helper is None:
             return {}
-        return {"clipboard" : self._clipboard_helper.get_info()}
+        ci = self._clipboard_helper.get_info()
+        cc = self._clipboard_client
+        if cc:
+            ci["client"] = cc.uuid
+        return {"clipboard" : ci}
 
 
     def get_server_features(self, server_source=None):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/server/mixins/input_server.py 
new/xpra-3.0.7/xpra/server/mixins/input_server.py
--- old/xpra-3.0.6/xpra/server/mixins/input_server.py   2020-01-25 
11:03:51.000000000 +0100
+++ new/xpra-3.0.7/xpra/server/mixins/input_server.py   2020-03-08 
03:21:09.000000000 +0100
@@ -154,7 +154,7 @@
         if ss is None:
             return
         keyname = bytestostr(keyname)
-        modifiers = tuple(bytestostr(x) for x in modifiers)
+        modifiers = list(bytestostr(x) for x in modifiers)
         self.set_ui_driver(ss)
         if group>=0:
             self.set_keyboard_layout_group(group)
@@ -235,7 +235,7 @@
             delay_ms = min(1500, max(250, delay_ms))
             keylog("scheduling key repeat timer with delay %s for %s / %s", 
delay_ms, keyname, keycode)
             now = monotonic_time()
-            self.key_repeat_timer = self.timeout_add(0, 
self._key_repeat_timeout, now, delay_ms, wid, keyname, keyval, keycode, 
modifiers, is_mod)
+            self.key_repeat_timer = self.timeout_add(delay_ms, 
self._key_repeat_timeout, now, delay_ms, wid, keyname, keyval, keycode, 
modifiers, is_mod)
 
     def _key_repeat_timeout(self, when, delay_ms, wid, keyname, keyval, 
keycode, modifiers, is_mod):
         self.key_repeat_timer = None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/server/proxy/proxy_server.py 
new/xpra-3.0.7/xpra/server/proxy/proxy_server.py
--- old/xpra-3.0.6/xpra/server/proxy/proxy_server.py    2019-09-24 
15:54:01.000000000 +0200
+++ new/xpra-3.0.7/xpra/server/proxy/proxy_server.py    2020-03-13 
17:51:19.000000000 +0100
@@ -432,6 +432,7 @@
         def start_proxy_process():
             log("start_proxy_process()")
             message_queue = MQueue()
+            client_conn = None
             try:
                 #no other packets should be arriving until the proxy instance 
responds to the initial hello packet
                 def unexpected_packet(packet):
@@ -474,7 +475,8 @@
             finally:
                 #now we can close our handle on the connection:
                 log("handover complete: closing connection from proxy server")
-                client_conn.close()
+                if client_conn:
+                    client_conn.close()
                 server_conn.close()
                 log("sending socket-handover-complete")
                 message_queue.put("socket-handover-complete")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/server/server_core.py 
new/xpra-3.0.7/xpra/server/server_core.py
--- old/xpra-3.0.6/xpra/server/server_core.py   2019-11-26 16:58:06.000000000 
+0100
+++ new/xpra-3.0.7/xpra/server/server_core.py   2020-03-13 17:51:19.000000000 
+0100
@@ -438,7 +438,7 @@
             p.quit()
         netlog("cleanup will disconnect: %s", self._potential_protocols)
         self.cancel_touch_timer()
-        if self.mdns:
+        if self.mdns_publishers:
             add_work_item(self.mdns_cleanup)
         if self._upgrading:
             reason = SERVER_UPGRADE
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/server/source/encodings_mixin.py 
new/xpra-3.0.7/xpra/server/source/encodings_mixin.py
--- old/xpra-3.0.6/xpra/server/source/encodings_mixin.py        2019-09-24 
15:54:01.000000000 +0200
+++ new/xpra-3.0.7/xpra/server/source/encodings_mixin.py        2020-03-08 
03:21:09.000000000 +0100
@@ -277,7 +277,9 @@
         if send_ui and not self.core_encodings:
             raise ClientException("client failed to specify any supported 
encodings")
         self.window_icon_encodings = c.strlistget("encodings.window-icon", 
["premult_argb32"])
-        self.rgb_formats = c.strlistget("encodings.rgb_formats", ["RGB"])
+        #try both spellings for older versions:
+        for x in ("encodings", "encoding",):
+            self.rgb_formats = c.strlistget(x+".rgb_formats", self.rgb_formats)
         #skip all other encoding related settings if we don't send pixels:
         if not send_ui:
             log("windows/pixels forwarding is disabled for this client")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/src_info.py 
new/xpra-3.0.7/xpra/src_info.py
--- old/xpra-3.0.6/xpra/src_info.py     2020-02-07 12:24:52.000000000 +0100
+++ new/xpra-3.0.7/xpra/src_info.py     2020-03-13 18:03:50.000000000 +0100
@@ -1,2 +1,2 @@
 LOCAL_MODIFICATIONS=0
-REVISION=25177
+REVISION=25629
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/x11/fakeXinerama.py 
new/xpra-3.0.7/xpra/x11/fakeXinerama.py
--- old/xpra-3.0.6/xpra/x11/fakeXinerama.py     2019-12-26 21:19:44.000000000 
+0100
+++ new/xpra-3.0.7/xpra/x11/fakeXinerama.py     2020-03-08 03:21:09.000000000 
+0100
@@ -67,10 +67,10 @@
         return delfile("cannot save fake xinerama settings: no display found")
     if len(ss)>1:
         return delfile("cannot save fake xinerama settings: more than one 
display found")
-    if len(ss)==2 and isinstance(ss[0], int) and isinstance(ss[1], int):
+    display_info = ss[0]
+    if len(display_info)==2 and isinstance(display_info[0], int) and 
isinstance(display_info[1], int):
         #just WxH, not enough display information
         return delfile("cannot save fake xinerama settings: missing display 
data from client %s" % source)
-    display_info = ss[0]
     if len(display_info)<10:
         return delfile("cannot save fake xinerama settings: incomplete display 
data from client %s" % source)
     #display_name, width, height, width_mm, height_mm, \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/x11/gtk_x11/clipboard.py 
new/xpra-3.0.7/xpra/x11/gtk_x11/clipboard.py
--- old/xpra-3.0.6/xpra/x11/gtk_x11/clipboard.py        2019-11-18 
16:50:50.000000000 +0100
+++ new/xpra-3.0.7/xpra/x11/gtk_x11/clipboard.py        2020-03-08 
03:21:09.000000000 +0100
@@ -20,6 +20,7 @@
     init_x11_filter,
     cleanup_x11_filter,
     )
+from xpra.gtk_common.error import XError
 from xpra.clipboard.clipboard_core import (
     ClipboardProtocolHelperCore, ClipboardProxyCore, TEXT_TARGETS,
     must_discard, must_discard_extra, _filter_targets,
@@ -260,10 +261,6 @@
         ClipboardProxyCore.init_uuid(self)
         self.claim()
 
-    def set_want_targets(self, want_targets):
-        self._want_targets = want_targets
-
-
     def got_token(self, targets, target_data=None, claim=True, 
synchronous_client=False):
         # the remote end now owns the clipboard
         self.cancel_emit_token()
@@ -432,15 +429,22 @@
         log("set_selection_response(%s, %s, %s, %s, %s, %r, %i)",
             requestor, target, prop, dtype, dformat, 
repr_ellipsized(bytestostr(data)), time)
         #answer the selection request:
-        with xsync:
-            xid = get_xwindow(requestor)
-            if data is not None:
-                X11Window.XChangeProperty(xid, prop, dtype, dformat, data)
-            else:
-                #maybe even delete the property?
-                #X11Window.XDeleteProperty(xid, prop)
-                prop = None
-            X11Window.sendSelectionNotify(xid, self._selection, target, prop, 
time)
+        try:
+            with xsync:
+                xid = get_xwindow(requestor)
+                if data is not None:
+                    X11Window.XChangeProperty(xid, prop, dtype, dformat, data)
+                else:
+                    #maybe even delete the property?
+                    #X11Window.XDeleteProperty(xid, prop)
+                    prop = None
+                X11Window.sendSelectionNotify(xid, self._selection, target, 
prop, time)
+        except XError as e:
+            log("failed to set selection", exc_info=True)
+            log.warn("Warning: failed to set selection for target '%s'", 
target)
+            log.warn(" on requestor %s", self.get_wininfo(xid))
+            log.warn(" property '%s'", prop)
+            log.warn(" %s", e)
 
     def got_contents(self, target, dtype=None, dformat=None, data=None):
         #if this is the special target 'TARGETS', cache the result:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/x11/models/size_hints_util.py 
new/xpra-3.0.7/xpra/x11/models/size_hints_util.py
--- old/xpra-3.0.6/xpra/x11/models/size_hints_util.py   2019-09-24 
15:54:02.000000000 +0200
+++ new/xpra-3.0.7/xpra/x11/models/size_hints_util.py   2020-03-08 
03:21:09.000000000 +0100
@@ -45,21 +45,13 @@
         if v is not None:
             try:
                 w,h = v
+                int(w)
+                int(h)
             except (ValueError, TypeError):
                 w,h = None,None
             if (w is None or h is None) or w>=MAX_WINDOW_SIZE or 
h>=MAX_WINDOW_SIZE:
                 log("clearing invalid size hint value for %s: %s", attr, v)
                 del size_hints[attr]
-    for attr in ("minimum-aspect-ratio", "maximum-aspect-ratio"):
-        v = size_hints.get(attr)
-        if v is not None:
-            try:
-                w,h = v
-            except (ValueError, TypeError):
-                w,h = None,None
-            if (not w or not h) or w>=MAX_WINDOW_SIZE or h>=MAX_WINDOW_SIZE:
-                log.warn("Warning: clearing invalid size hint value for %s: 
%s", attr, v)
-                del size_hints[attr]
     #if max-size is smaller than min-size (bogus), clamp it..
     mins = size_hints.get("minimum-size")
     maxs = size_hints.get("maximum-size")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/x11/server.py 
new/xpra-3.0.7/xpra/x11/server.py
--- old/xpra-3.0.6/xpra/x11/server.py   2020-01-25 11:03:51.000000000 +0100
+++ new/xpra-3.0.7/xpra/x11/server.py   2020-02-10 16:32:04.000000000 +0100
@@ -829,7 +829,8 @@
         #x_root, y_root, direction, button, source_indication = event.data
         wid = self._window_to_id[window]
         #find clients that handle windows:
-        wsources = [ss for ss in self._server_sources.values() is 
isinstance(ss, WindowsMixin)]
+        from xpra.server.source.windows_mixin import WindowsMixin
+        wsources = [ss for ss in self._server_sources.values() if 
isinstance(ss, WindowsMixin)]
         if not wsources:
             return
         #prefer the "UI driver" if we find it:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/x11/server_keyboard_config.py 
new/xpra-3.0.7/xpra/x11/server_keyboard_config.py
--- old/xpra-3.0.6/xpra/x11/server_keyboard_config.py   2020-01-25 
11:03:51.000000000 +0100
+++ new/xpra-3.0.7/xpra/x11/server_keyboard_config.py   2020-03-13 
17:51:19.000000000 +0100
@@ -20,6 +20,7 @@
     get_modifiers_from_meanings, get_modifiers_from_keycodes,
     clear_modifiers, set_modifiers, map_missing_modifiers,
     clean_keyboard_state,
+    DEBUG_KEYSYMS,
     )
 from xpra.x11.bindings.keyboard_bindings import X11KeyboardBindings 
#@UnresolvedImport
 from xpra.log import Logger
@@ -29,6 +30,7 @@
 X11Keyboard = X11KeyboardBindings()
 
 MAP_MISSING_MODIFIERS = envbool("XPRA_MAP_MISSING_MODIFIERS", True)
+SIMULATE_MODIFIERS = envbool("XPRA_SIMULATE_MODIFIERS", True)
 
 ALL_X11_MODIFIERS = {
                     "shift"     : 0,
@@ -69,6 +71,7 @@
         self.modifier_client_keycodes = {}
         self.compute_modifier_map()
         self.modifiers_filter = []
+        self.keycode_mappings = {}
 
     def __repr__(self):
         return "KeyboardConfig(%s / %s / %s)" % (self.xkbmap_layout, 
self.xkbmap_variant, self.xkbmap_options)
@@ -320,6 +323,7 @@
             self.compute_modifiers()
             self.compute_modifier_keynames()
             self.compute_client_modifier_keycodes()
+            self.update_keycode_mappings()
             return
 
         with xlog:
@@ -367,6 +371,7 @@
             self.compute_client_modifier_keycodes()
             log("keyname_for_mod=%s", self.keynames_for_mod)
             clean_keyboard_state()
+            self.update_keycode_mappings()
 
     def add_gtk_keynames(self):
         #add the keynames we find via gtk
@@ -375,6 +380,19 @@
         for _, keyname, keycode, _, _ in get_gtk_keymap():
             if keyname not in self.keycode_translation:
                 self.keycode_translation[keyname] = keycode
+                if keyname in DEBUG_KEYSYMS:
+                    log.info("add_gtk_keynames: %s=%s", keyname, keycode)
+        #some keys may still be missing with GTK2:
+        for keyname, equiv in {
+            "dead_perispomeni"  : "dead_tilde",
+            }.items():
+            if keyname not in self.keycode_translation:
+                keycode = self.keycode_translation.get(equiv)
+                if keycode:
+                    self.keycode_translation[keyname] = keycode
+                    if keyname in DEBUG_KEYSYMS:
+                        log.info("add_gtk_keynames: %s=%s", keyname, keycode)
+
 
     def set_default_keymap(self):
         """ assign a default keymap based on the current X11 server keymap
@@ -388,9 +406,21 @@
             #keycodes:
             keycode_to_keynames = X11Keyboard.get_keycode_mappings()
             self.keycode_translation = {}
+            #prefer keycodes that don't use the lowest level+mode:
+            default_for_keyname = {}
             for keycode, keynames in keycode_to_keynames.items():
-                for keyname in keynames:
-                    self.keycode_translation[keyname] = keycode
+                for i, keyname in enumerate(keynames):
+                    self.keycode_translation[(keyname, i)] = keycode
+                    if keyname in DEBUG_KEYSYMS:
+                        log.info("set_default_keymap: %s=%s", (keyname, i), 
keycode)
+                    kd = default_for_keyname.get(keyname)
+                    if kd is None or kd[1]>i:
+                        default_for_keyname[keyname] = (keycode, i)
+            for keyname, kd in default_for_keyname.items():
+                keycode = kd[0]
+                self.keycode_translation[keyname] = keycode
+                if keyname in DEBUG_KEYSYMS:
+                    log.info("set_default_keymap: %s=%s", keyname, keycode)
             self.add_gtk_keynames()
             log("set_default_keymap: keycode_translation=%s", 
self.keycode_translation)
             #modifiers:
@@ -409,6 +439,10 @@
             log("set_default_keymap: keynames_for_mod=%s", 
self.keynames_for_mod)
             log("set_default_keymap: keycodes_for_modifier_keynames=%s", 
self.keycodes_for_modifier_keynames)
             log("set_default_keymap: modifier_map=%s", self.modifier_map)
+            self.update_keycode_mappings()
+
+    def update_keycode_mappings(self):
+        self.keycode_mappings = X11Keyboard.get_keycode_mappings()
 
 
     def do_get_keycode(self, client_keycode, keyname, pressed, modifiers, 
group):
@@ -417,11 +451,15 @@
             return -1
         if keyname=="0xffffff":
             return -1
+        if self.xkbmap_raw:
+            return client_keycode
         keycode = None
         if self.xkbmap_query:
             keycode = self.keycode_translation.get((client_keycode, keyname)) 
or client_keycode
             log("get_keycode(%s, %s, %s)=%s (native keymap)", client_keycode, 
keyname, modifiers, keycode)
         else:
+            if SIMULATE_MODIFIERS:
+                return self.do_get_keycode_new(client_keycode, keyname, 
pressed, modifiers, group)
             #non-native: try harder to find matching keysym
             #first, try to honour shift state:
             shift = ("shift" in modifiers) ^ ("lock" in modifiers)
@@ -452,6 +490,85 @@
                 log("get_keycode(%s, %s)=%i (keyname translation)", 
client_keycode, keyname, keycode)
         return keycode
 
+    def do_get_keycode_new(self, client_keycode, keyname, pressed, modifiers, 
group):
+        #non-native: try harder to find matching keysym
+        def kmlog(msg, *args):
+            if keyname in DEBUG_KEYSYMS:
+                l = log.info
+            else:
+                l = log
+            l(msg, *args)
+        def klog(msg, *args):
+            kmlog("do_get_keycode%s"+msg, (client_keycode, keyname, pressed, 
modifiers, group), *args)
+        #first, try to honour shift state:
+        shift = ("shift" in modifiers) ^ ("lock" in modifiers)
+        mode = 0
+        for mod in modifiers:
+            names = self.keynames_for_mod.get(mod, [])
+            for name in names:
+                if name in ("ISO_Level3_Shift", "Mode_switch"):
+                    mode = 1
+                    break
+        level = int(shift) + int(mode)*2
+        levels = []
+        #first, match with group if set:
+        if group:
+            levels.append(level+4)
+        #then try exact match without group:
+        levels.append(level)
+        #try default group:
+        for i in range(2):
+            level = int(shift) + i*2
+            if level not in levels:
+                levels.append(level)
+        #catch all:
+        for level in range(8):
+            if level not in levels:
+                levels.append(level)
+        kmlog("will try levels: %s", levels)
+        for level in levels:
+            keycode = self.keycode_translation.get((keyname, level))
+            if keycode:
+                klog("=%i (level=%i, shift=%s, mode=%i)", keycode, level, 
shift, mode)
+                if self.xkbmap_raw:
+                    break
+                keysyms = self.keycode_mappings.get(keycode)
+                level0 = levels[0]
+                if len(keysyms)>level0 and keysyms[level0]=="":
+                    #if the keysym we would match for this keycode is 
'NoSymbol',
+                    #then we can probably ignore it ('NoSymbol' shows up as "")
+                    kmlog("not toggling any modifiers state for keysyms=%s", 
keysyms)
+                    break
+                def toggle_modifier(mod):
+                    keynames = self.keynames_for_mod.get(mod)
+                    if keyname in keynames:
+                        kmlog("not toggling '%s' since '%s' should deal with 
it", mod, keyname)
+                        #the keycode we're returning is for this modifier,
+                        #assume that this will end up doing what is needed
+                        return
+                    if mod in modifiers:
+                        kmlog("removing '%s' from modifiers", mod)
+                        modifiers.remove(mod)
+                    else:
+                        kmlog("adding '%s' to modifiers", mod)
+                        modifiers.append(mod)
+                if (level & 1) ^ shift:
+                    #shift state does not match
+                    toggle_modifier("shift")
+                if (level & 2) ^ mode:
+                    #try to set / unset mode:
+                    for mod, keynames in self.keynames_for_mod.items():
+                        if "ISO_Level3_Shift" in keynames or "Mode_switch" in 
keynames:
+                            #found mode switch modified
+                            toggle_modifier(mod)
+                            break
+                break
+            #this should not find anything new?:
+            if keycode is None:
+                keycode = self.keycode_translation.get(keyname, -1)
+                klog("=%i (keyname translation)", keycode)
+        return keycode
+
 
     def get_current_mask(self):
         current_mask = get_default_root_window().get_pointer()[-1]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/x11/vfb_util.py 
new/xpra-3.0.7/xpra/x11/vfb_util.py
--- old/xpra-3.0.6/xpra/x11/vfb_util.py 2019-09-24 15:54:02.000000000 +0200
+++ new/xpra-3.0.7/xpra/x11/vfb_util.py 2020-02-18 06:58:42.000000000 +0100
@@ -242,7 +242,7 @@
                 xvfb_cmd += ["-displayfd", str(w_pipe)]
                 xvfb_cmd[0] = "%s-for-Xpra-%s" % (xvfb_executable, 
display_name)
                 def preexec():
-                    setsid()
+                    os.setpgrp()
                     if getuid()==0 and uid:
                         setuidgid(uid, gid)
                     close_fds([0, 1, 2, r_pipe, w_pipe])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/x11/x11_server_core.py 
new/xpra-3.0.7/xpra/x11/x11_server_core.py
--- old/xpra-3.0.6/xpra/x11/x11_server_core.py  2020-02-07 12:19:10.000000000 
+0100
+++ new/xpra-3.0.7/xpra/x11/x11_server_core.py  2020-03-08 03:21:10.000000000 
+0100
@@ -369,6 +369,8 @@
                     capabilities["screen-sizes"] = sizes
             if self.default_cursor_image and source.wants_default_cursor:
                 capabilities["cursor.default"] = self.default_cursor_image
+            if self.opengl_props:
+                capabilities["opengl"] = self.opengl_props
         return capabilities
 
     def do_get_info(self, proto, server_sources):
@@ -500,8 +502,7 @@
             self.keys_pressed = {}
         #this will take care of any remaining ones we are not aware of:
         #(there should not be any - but we want to be certain)
-        with xswallow:
-            X11Keyboard.unpress_all_keys()
+        clean_keyboard_state()
 
 
     def get_cursor_sizes(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/x11/xkbhelper.py 
new/xpra-3.0.7/xpra/x11/xkbhelper.py
--- old/xpra-3.0.6/xpra/x11/xkbhelper.py        2019-09-24 15:54:02.000000000 
+0200
+++ new/xpra-3.0.7/xpra/x11/xkbhelper.py        2020-03-08 03:21:10.000000000 
+0100
@@ -50,6 +50,8 @@
     with xlog:
         X11Keyboard.ungrab_all_keys()
     with xlog:
+        X11Keyboard.set_layout_group(0)
+    with xlog:
         X11Keyboard.unpress_all_keys()
 
 
################################################################################
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xpra-3.0.6/xpra/x11/xsettings_prop.py 
new/xpra-3.0.7/xpra/x11/xsettings_prop.py
--- old/xpra-3.0.6/xpra/x11/xsettings_prop.py   2019-10-20 14:13:42.000000000 
+0200
+++ new/xpra-3.0.7/xpra/x11/xsettings_prop.py   2020-03-13 17:51:19.000000000 
+0100
@@ -142,7 +142,7 @@
                 x += b'\0'*pad_len
             elif setting_type==XSettingsTypeColor:
                 red, blue, green, alpha = value
-                x = struct.pack(b"=HHHH", red, blue, green, alpha)
+                x += struct.pack(b"=HHHH", red, blue, green, alpha)
             else:
                 log.error("Error: invalid type %i for xsetting property '%s'", 
setting_type, prop_name)
                 continue



Reply via email to