From 70f72dcd622312bb81355154f0bfd0d09768440d Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 31 Jan 2018 13:55:17 +0000 Subject: [PATCH] #1312: * notify the user that clipboard synchronization has been disabled * reset clipboard state after client exits so we can re-enable synchronization with new clients * clear uuids from the clipboards after we are done checking git-svn-id: https://xpra.org/svn/Xpra/trunk@18230 3bb7dfac-3a0b-4e04-842a-767bc560f471 --- src/xpra/client/gtk_base/gtk_client_base.py | 14 ++++++++++ src/xpra/clipboard/clipboard_base.py | 30 ++++++++++++++++++--- src/xpra/server/server_base.py | 4 ++- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/xpra/client/gtk_base/gtk_client_base.py b/src/xpra/client/gtk_base/gtk_client_base.py index b4bd140fc6..1b32d1b0c3 100644 --- a/src/xpra/client/gtk_base/gtk_client_base.py +++ b/src/xpra/client/gtk_base/gtk_client_base.py @@ -1268,6 +1268,20 @@ def clipboard_toggled(*_args): self.remote_clipboard_requests = 0 self.clipboard_notify(0) self.connect("clipboard-toggled", clipboard_toggled) + def loop_disabled_notify(): + if self.clipboard_helper.disabled_by_loop and self.notifier: + icon = None + try: + from xpra.notifications.common import parse_image_path + icon = parse_image_path(get_icon_filename("clipboard")) + except ImportError: + pass + summary = "Clipboard Synchronization Error" + body = "A synchronization loop has been detected,\n" + \ + "to prevent further issues clipboard synchronization has been disabled." + self.notifier.show_notify("", self.tray, 0, "Xpra", 0, "", summary, body, [], {}, 10*10000, icon) + return False + self.timeout_add(5*1000, loop_disabled_notify) self.after_handshake(register_clipboard_toggled) return helperClass(clipboard_send, clipboard_progress, **kwargs) diff --git a/src/xpra/clipboard/clipboard_base.py b/src/xpra/clipboard/clipboard_base.py index 8a674a497f..1de1fcef5c 100644 --- a/src/xpra/clipboard/clipboard_base.py +++ b/src/xpra/clipboard/clipboard_base.py @@ -22,7 +22,7 @@ from xpra.gtk_common.nested_main import NestedMainLoop from xpra.net.compression import Compressible from xpra.os_util import WIN32, POSIX, monotonic_time, strtobytes, bytestostr, hexstr, get_hex_uuid -from xpra.util import csv, envint, envbool, repr_ellipsized, nonl, typedict +from xpra.util import csv, envint, envbool, repr_ellipsized, typedict from xpra.platform.features import CLIPBOARD_GREEDY @@ -124,6 +124,7 @@ def __init__(self, send_packet_cb, progress_cb=None, **kwargs): remote_loop_uuids = d.dictget("remote-loop-uuids", {}) self.verify_remote_loop_uuids(remote_loop_uuids) self.remote_clipboards = d.strlistget("clipboards.remote", CLIPBOARDS) + self.disabled_by_loop = [] self.init_proxies_uuid() def __repr__(self): @@ -154,6 +155,16 @@ def nosend(*args): self._clipboard_proxies = {} + def client_reset(self): + #if the client disconnects, + #we can re-enable the clipboards it had problems with: + l = self.disabled_by_loop + self.disabled_by_loop = [] + for x in l: + proxy = self._clipboard_proxies.get(x) + proxy.set_enabled(True) + + def get_loop_uuids(self): uuids = {} for proxy in self._clipboard_proxies.values(): @@ -163,6 +174,8 @@ def get_loop_uuids(self): def verify_remote_loop_uuids(self, uuids): log("verify_remote_loop_uuids(%s)", uuids) + if not uuids: + return for proxy in self._clipboard_proxies.values(): proxy._clipboard.request_text(self._verify_remote_loop_uuids, (proxy, uuids)) @@ -171,7 +184,10 @@ def _verify_remote_loop_uuids(self, clipboard, value, user_data): proxy, uuids = user_data if value: for selection, rvalue in uuids.items(): + if rvalue==proxy._loop_uuid: + clipboard.set_text("") if rvalue and value==rvalue: + clipboard.set_text("") if selection==proxy._selection: log.warn("Warning: loop detected for %s clipboard", selection) else: @@ -180,6 +196,8 @@ def _verify_remote_loop_uuids(self, clipboard, value, user_data): if LOOP_DISABLE: log.warn(" synchronization has been disabled") proxy._enabled = False + if selection not in self.disabled_by_loop: + self.disabled_by_loop.append(selection) def set_direction(self, can_send, can_receive): self.can_send = can_send @@ -259,7 +277,10 @@ def _process_clipboard_token(self, packet): l("ignoring token for clipboard proxy name '%s' (no proxy)", name) return if not proxy.is_enabled(): - log.warn("ignoring token for clipboard proxy name '%s' (disabled)", name) + l = log + if name not in self.disabled_by_loop: + l = log.warn + l("ignoring token for clipboard proxy name '%s' (disabled)", name) return log("process clipboard token selection=%s, local clipboard name=%s, proxy=%s", selection, name, proxy) targets = None @@ -439,7 +460,10 @@ def no_contents(): no_contents() return if not proxy.is_enabled(): - log.warn("Warning: ignoring clipboard request for '%s' (disabled)", name) + l = log + if selection not in self.disabled_by_loop: + l = log.warn + l("Warning: ignoring clipboard request for '%s' (disabled)", name) no_contents() return if TEST_DROP_CLIPBOARD_REQUESTS>0 and (request_id % TEST_DROP_CLIPBOARD_REQUESTS)==0: diff --git a/src/xpra/server/server_base.py b/src/xpra/server/server_base.py index b4183f7d54..f2a1657b20 100644 --- a/src/xpra/server/server_base.py +++ b/src/xpra/server/server_base.py @@ -1244,8 +1244,10 @@ def _disconnect_proto_info(self, proto): def _process_connection_lost(self, proto, packet): ServerCore._process_connection_lost(self, proto, packet) - if self._clipboard_client and self._clipboard_client.protocol==proto: + ch = self._clipboard_helper + if ch and self._clipboard_client and self._clipboard_client.protocol==proto: self._clipboard_client = None + ch.client_reset() self.cleanup_protocol(proto)