Coverage for /home/antoine/projects/xpra-git/dist/python3/lib64/python/xpra/clipboard/clipboard_timeout_helper.py : 34%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# This file is part of Xpra.
2# Copyright (C) 2019-2020 Antoine Martin <antoine@xpra.org>
3# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
4# later version. See the file COPYING for details.
6from gi.repository import GLib
8from xpra.clipboard.clipboard_core import ClipboardProtocolHelperCore
9from xpra.util import repr_ellipsized, ellipsizer, envint, engs
10from xpra.log import Logger
11from xpra.platform.features import CLIPBOARD_GREEDY
13log = Logger("clipboard")
15CONVERT_TIMEOUT = envint("XPRA_CLIPBOARD_CONVERT_TIMEOUT", 100)
16REMOTE_TIMEOUT = envint("XPRA_CLIPBOARD_REMOTE_TIMEOUT", 1500)
17assert 0<CONVERT_TIMEOUT<5000
18assert 0<REMOTE_TIMEOUT<5000
21class ClipboardTimeoutHelper(ClipboardProtocolHelperCore):
23 #a clipboard superclass that handles timeouts
24 def __init__(self, send_packet_cb, progress_cb=None, **kwargs):
25 super().__init__(send_packet_cb, progress_cb, **kwargs)
26 self._clipboard_outstanding_requests = {}
28 def cleanup(self):
29 #reply to outstanding requests with "no data":
30 for request_id in tuple(self._clipboard_outstanding_requests.keys()):
31 self._clipboard_got_contents(request_id)
32 self._clipboard_outstanding_requests = {}
33 ClipboardProtocolHelperCore.cleanup(self)
35 def make_proxy(self, selection):
36 raise NotImplementedError()
38 def _get_proxy(self, selection):
39 proxy = self._clipboard_proxies.get(selection)
40 if not proxy:
41 log.warn("Warning: no clipboard proxy for '%s'", selection)
42 return None
43 return proxy
45 def set_want_targets_client(self, want_targets):
46 super().set_want_targets_client(want_targets)
47 #pass it on to the ClipboardProxy instances:
48 for proxy in self._clipboard_proxies.values():
49 proxy.set_want_targets(want_targets)
52 ############################################################################
53 # network methods for communicating with the remote clipboard:
54 ############################################################################
55 def _send_clipboard_token_handler(self, proxy, packet_data=()):
56 if log.is_debug_enabled():
57 log("_send_clipboard_token_handler(%s, %s)", proxy, repr_ellipsized(packet_data))
58 remote = self.local_to_remote(proxy._selection)
59 packet = ["clipboard-token", remote]
60 if packet_data:
61 #append 'TARGETS' unchanged:
62 packet.append(packet_data[0])
63 #if present, the next element is the target data,
64 #which we have to convert to wire format:
65 if len(packet_data)>=2:
66 target, dtype, dformat, data = packet_data[1]
67 wire_encoding, wire_data = self._munge_raw_selection_to_wire(target, dtype, dformat, data)
68 if wire_encoding:
69 wire_data = self._may_compress(dtype, dformat, wire_data)
70 if wire_data:
71 packet += [target, dtype, dformat, wire_encoding, wire_data]
72 claim = proxy._can_send
73 packet += [claim, CLIPBOARD_GREEDY]
74 log("send_clipboard_token_handler %s to %s", proxy._selection, remote)
75 self.send(*packet)
77 def _send_clipboard_request_handler(self, proxy, selection, target):
78 log("send_clipboard_request_handler%s", (proxy, selection, target))
79 request_id = self._clipboard_request_counter
80 self._clipboard_request_counter += 1
81 remote = self.local_to_remote(selection)
82 log("send_clipboard_request %s to %s, id=%s", selection, remote, request_id)
83 timer = GLib.timeout_add(REMOTE_TIMEOUT, self.timeout_request, request_id, selection, target)
84 self._clipboard_outstanding_requests[request_id] = (timer, selection, target)
85 self.progress()
86 self.send("clipboard-request", request_id, remote, target)
88 def timeout_request(self, request_id, selection, target):
89 try:
90 selection, target = self._clipboard_outstanding_requests.pop(request_id)[1:]
91 except KeyError:
92 log.warn("Warning: clipboard request id %i not found", request_id)
93 log.warn(" selection=%s, target=%s", selection, target)
94 return
95 finally:
96 self.progress()
97 log.warn("Warning: remote clipboard request timed out")
98 log.warn(" request id %i, selection=%s, target=%s", request_id, selection, target)
99 proxy = self._get_proxy(selection)
100 if proxy:
101 proxy.got_contents(target)
103 def _clipboard_got_contents(self, request_id, dtype=None, dformat=None, data=None):
104 try:
105 timer, selection, target = self._clipboard_outstanding_requests.pop(request_id)
106 except KeyError:
107 log.warn("Warning: request id %i not found", request_id)
108 log.warn(" already timed out or duplicate reply")
109 return
110 finally:
111 self.progress()
112 GLib.source_remove(timer)
113 proxy = self._get_proxy(selection)
114 log("clipboard got contents%s: proxy=%s for selection=%s",
115 (request_id, dtype, dformat, ellipsizer(data)), proxy, selection)
116 if proxy:
117 proxy.got_contents(target, dtype, dformat, data)
119 def client_reset(self):
120 super().client_reset()
121 #timeout all pending requests
122 cor = self._clipboard_outstanding_requests
123 if cor:
124 log.info("cancelling %i clipboard request%s", len(cor), engs(cor))
125 self._clipboard_outstanding_requests = {}
126 for request_id in cor:
127 self._clipboard_got_contents(request_id)