-
-
Notifications
You must be signed in to change notification settings - Fork 180
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#1761 move clipboard code to a mixin
git-svn-id: https://xpra.org/svn/Xpra/trunk@18541 3bb7dfac-3a0b-4e04-842a-767bc560f471
- Loading branch information
Showing
2 changed files
with
191 additions
and
150 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
# -*- coding: utf-8 -*- | ||
# This file is part of Xpra. | ||
# Copyright (C) 2010-2018 Antoine Martin <antoine@devloop.org.uk> | ||
# Copyright (C) 2008 Nathaniel Smith <njs@pobox.com> | ||
# Xpra is released under the terms of the GNU GPL v2, or, at your option, any | ||
# later version. See the file COPYING for details. | ||
|
||
import os.path | ||
|
||
from xpra.log import Logger | ||
log = Logger("clipboard") | ||
|
||
from xpra.platform.features import CLIPBOARDS | ||
from xpra.util import csv | ||
from xpra.scripts.config import FALSE_OPTIONS | ||
|
||
|
||
""" | ||
Mixin for servers that handle clipboard synchronization. | ||
""" | ||
class ClipboardServer(object): | ||
|
||
def __init__(self): | ||
self.clipboard = False | ||
self.clipboard_direction = "both" | ||
self.clipboard_filter_file = None | ||
|
||
def init(self, opts): | ||
self.clipboard = not ((opts.clipboard or "").lower() in FALSE_OPTIONS) | ||
self.clipboard_direction = opts.clipboard_direction | ||
self.clipboard_filter_file = opts.clipboard_filter_file | ||
|
||
def setup(self, _opts): | ||
self.init_clipboard() | ||
|
||
def cleanup(self): | ||
pass | ||
|
||
|
||
def get_caps(self): | ||
return { | ||
} | ||
|
||
def get_server_features(self, server_source=None): | ||
clipboard = self._clipboard_helper is not None and self._clipboard_client == server_source | ||
log("clipboard_helper=%s, clipboard_client=%s, source=%s, clipboard=%s", self._clipboard_helper, self._clipboard_client, server_source, clipboard) | ||
if not clipboard: | ||
return {} | ||
f = { | ||
"clipboards" : self._clipboards, | ||
"clipboard-direction" : self.clipboard_direction, | ||
"clipboard" : { | ||
"" : True, | ||
"enable-selections" : True, | ||
}, | ||
} | ||
if self._clipboard_helper: | ||
f["clipboard.loop-uuids"] = self._clipboard_helper.get_loop_uuids() | ||
return f | ||
|
||
def init_clipboard(self): | ||
log("init_clipboard() enabled=%s, filter file=%s", self.clipboard, self.clipboard_filter_file) | ||
### Clipboard handling: | ||
self._clipboard_helper = None | ||
self._clipboard_client = None | ||
self._clipboards = [] | ||
if not self.clipboard: | ||
return | ||
clipboard_filter_res = [] | ||
if self.clipboard_filter_file: | ||
if not os.path.exists(self.clipboard_filter_file): | ||
log.error("invalid clipboard filter file: '%s' does not exist - clipboard disabled!", self.clipboard_filter_file) | ||
return | ||
try: | ||
with open(self.clipboard_filter_file, "r" ) as f: | ||
for line in f: | ||
clipboard_filter_res.append(line.strip()) | ||
log("loaded %s regular expressions from clipboard filter file %s", len(clipboard_filter_res), self.clipboard_filter_file) | ||
except: | ||
log.error("error reading clipboard filter file %s - clipboard disabled!", self.clipboard_filter_file, exc_info=True) | ||
return | ||
try: | ||
from xpra.clipboard.gdk_clipboard import GDKClipboardProtocolHelper | ||
kwargs = { | ||
"filters" : clipboard_filter_res, | ||
"can-send" : self.clipboard_direction in ("to-client", "both"), | ||
"can-receive" : self.clipboard_direction in ("to-server", "both"), | ||
} | ||
self._clipboard_helper = GDKClipboardProtocolHelper(self.send_clipboard_packet, self.clipboard_progress, **kwargs) | ||
self._clipboards = CLIPBOARDS | ||
except Exception: | ||
#log("gdk clipboard helper failure", exc_info=True) | ||
log.error("Error: failed to setup clipboard helper", exc_info=True) | ||
|
||
def parse_hello_ui_clipboard(self, ss, c): | ||
#take the clipboard if no-one else has it yet: | ||
if not ss.clipboard_enabled: | ||
log("client does not support clipboard") | ||
return | ||
if not self._clipboard_helper: | ||
log("server does not support clipboard") | ||
return | ||
cc = self._clipboard_client | ||
if cc and not cc.is_closed(): | ||
log("another client already owns the clipboard") | ||
return | ||
self._clipboard_client = ss | ||
self._clipboard_helper.init_proxies_uuid() | ||
#deal with buggy win32 clipboards: | ||
if "clipboard.greedy" not in c: | ||
#old clients without the flag: take a guess based on platform: | ||
client_platform = c.strget("platform", "") | ||
greedy = client_platform.startswith("win") or client_platform.startswith("darwin") | ||
else: | ||
greedy = c.boolget("clipboard.greedy") | ||
self._clipboard_helper.set_greedy_client(greedy) | ||
want_targets = c.boolget("clipboard.want_targets") | ||
self._clipboard_helper.set_want_targets_client(want_targets) | ||
#the selections the client supports (default to all): | ||
client_selections = c.strlistget("clipboard.selections", CLIPBOARDS) | ||
log("client %s is the clipboard peer", ss) | ||
log(" greedy=%s", greedy) | ||
log(" want targets=%s", want_targets) | ||
log(" server has selections: %s", csv(self._clipboards)) | ||
log(" client initial selections: %s", csv(client_selections)) | ||
self._clipboard_helper.enable_selections(client_selections) | ||
|
||
def _process_clipboard_packet(self, proto, packet): | ||
if self.readonly: | ||
return | ||
ss = self._server_sources.get(proto) | ||
if not ss: | ||
#protocol has been dropped! | ||
return | ||
assert self._clipboard_client==ss, \ | ||
"the clipboard packet '%s' does not come from the clipboard owner!" % packet[0] | ||
if not ss.clipboard_enabled: | ||
#this can happen when we disable clipboard in the middle of transfers | ||
#(especially when there is a clipboard loop) | ||
log.warn("received a clipboard packet from a source which does not have clipboard enabled!") | ||
return | ||
assert self._clipboard_helper, "received a clipboard packet but we do not support clipboard sharing" | ||
self.idle_add(self._clipboard_helper.process_clipboard_packet, packet) | ||
|
||
def _process_clipboard_enabled_status(self, proto, packet): | ||
if self.readonly: | ||
return | ||
clipboard_enabled = packet[1] | ||
ss = self._server_sources.get(proto) | ||
self.set_clipboard_enabled_status(ss, clipboard_enabled) | ||
|
||
def set_clipboard_enabled_status(self, ss, clipboard_enabled): | ||
ch = self._clipboard_helper | ||
if not ch: | ||
log.warn("Warning: client try to toggle clipboard-enabled status,") | ||
log.warn(" but we do not support clipboard at all! Ignoring it.") | ||
return | ||
cc = self._clipboard_client | ||
if cc!=ss or ss is None: | ||
log.warn("Warning: received a request to change the clipboard status,") | ||
log.warn(" but it does not come from the clipboard owner! Ignoring it.") | ||
cc.clipboard_enabled = clipboard_enabled | ||
if not clipboard_enabled: | ||
ch.enable_selections([]) | ||
log("toggled clipboard to %s for %s", clipboard_enabled, ss.protocol) | ||
|
||
def clipboard_progress(self, local_requests, _remote_requests): | ||
assert self._clipboard_helper is not None | ||
if self._clipboard_client: | ||
self._clipboard_client.send_clipboard_progress(local_requests) | ||
|
||
def send_clipboard_packet(self, *parts): | ||
assert self._clipboard_helper is not None | ||
if self._clipboard_client: | ||
self._clipboard_client.send_clipboard(parts) | ||
|
||
def get_clipboard_info(self): | ||
if self._clipboard_helper is None: | ||
return {} | ||
return self._clipboard_helper.get_info() | ||
|
||
|
||
def init_packet_handlers(self): | ||
self._authenticated_packet_handlers.update({ | ||
"set-clipboard-enabled": self._process_clipboard_enabled_status, | ||
}) | ||
for x in ("token", "request", "contents", "contents-none", "pending-requests", "enable-selections", "loop-uuids"): | ||
self._authenticated_ui_packet_handlers["clipboard-%s" % x] = self._process_clipboard_packet |
Oops, something went wrong.