Skip to content

Commit

Permalink
#812 refactor more of the generic clipboard code into mixin
Browse files Browse the repository at this point in the history
git-svn-id: https://xpra.org/svn/Xpra/trunk@23179 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Jul 17, 2019
1 parent 19a7224 commit 5bfe539
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 114 deletions.
113 changes: 7 additions & 106 deletions src/xpra/client/gtk_base/gtk_client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
from xpra.platform.gui import (
get_window_frame_sizes, get_window_frame_size,
system_bell, get_wm_name, get_fixed_cursor_size,
get_clipboard_native_class,
)
from xpra.log import Logger

Expand Down Expand Up @@ -95,13 +94,8 @@ def __init__(self):
self.border = None
self.data_send_requests = {}
#clipboard bits:
self.local_clipboard_requests = 0
self.remote_clipboard_requests = 0
self.clipboard_notification_timer = None
self.last_clipboard_notification = 0
#only used with the translated clipboard class:
self.local_clipboard = ""
self.remote_clipboard = ""
#opengl bits:
self.client_supports_opengl = False
self.opengl_enabled = False
Expand All @@ -126,8 +120,6 @@ def __init__(self):
def init(self, opts):
GObjectXpraClient.init(self, opts)
UIXpraClient.init(self, opts)
self.remote_clipboard = opts.remote_clipboard
self.local_clipboard = opts.local_clipboard


def setup_frame_request_windows(self):
Expand Down Expand Up @@ -1203,104 +1195,10 @@ def destroy_window(self, wid, window):
group_leader.destroy()


def get_clipboard_helper_classes(self):
ct = self.client_clipboard_type
if ct and ct.lower() in FALSE_OPTIONS:
return []
from xpra.scripts.main import CLIPBOARD_CLASS
#first add the platform specific one, (may be None):
clipboard_options = [
CLIPBOARD_CLASS,
get_clipboard_native_class(),
]
clipboardlog("get_clipboard_helper_classes() unfiltered list=%s", clipboard_options)
if ct and ct.lower()!="auto" and ct.lower() not in TRUE_OPTIONS:
#try to match the string specified:
filtered = [x for x in clipboard_options if x and x.lower().find(self.client_clipboard_type)>=0]
if not filtered:
clipboardlog.warn("Warning: no clipboard types matching '%s'", self.client_clipboard_type)
clipboardlog.warn(" clipboard synchronization is disabled")
return []
clipboardlog(" found %i clipboard types matching '%s'", len(filtered), self.client_clipboard_type)
clipboard_options = filtered
#now try to load them:
clipboardlog("get_clipboard_helper_classes() options=%s", clipboard_options)
loadable = []
for co in clipboard_options:
if not co:
continue
try:
parts = co.split(".")
mod = ".".join(parts[:-1])
module = __import__(mod, {}, {}, [parts[-1]])
helperclass = getattr(module, parts[-1])
loadable.append(helperclass)
except ImportError:
clipboardlog("cannot load %s", co, exc_info=True)
continue
clipboardlog("get_clipboard_helper_classes()=%s", loadable)
return loadable

def process_clipboard_packet(self, packet):
clipboardlog("process_clipboard_packet(%s) level=%s", packet, gtk.main_level())
#check for clipboard loops:
ch = self.clipboard_helper
self.idle_add(ch.process_clipboard_packet, packet)


def setup_clipboard_helper(self, helperClass):
clipboardlog("setup_clipboard_helper(%s)", helperClass)
#first add the platform specific one, (may be None):
from xpra.platform.features import CLIPBOARDS
kwargs= {
#all the local clipboards supported:
"clipboards.local" : CLIPBOARDS,
#all the remote clipboards supported:
"clipboards.remote" : self.server_clipboards,
"can-send" : self.client_clipboard_direction in ("to-server", "both"),
"can-receive" : self.client_clipboard_direction in ("to-client", "both"),
"remote-loop-uuids" : self.server_clipboard_loop_uuids,
}
#only allow translation overrides if we have a way of telling the server about them:
if self.server_clipboard_enable_selections:
kwargs.update({
#the local clipboard we want to sync to (with the translated clipboard only):
"clipboard.local" : self.local_clipboard,
#the remote clipboard we want to we sync to (with the translated clipboard only):
"clipboard.remote" : self.remote_clipboard
})
clipboardlog("setup_clipboard_helper() kwargs=%s", kwargs)
def clipboard_send(*parts):
clipboardlog("clipboard_send: %s", parts[0])
if not self.clipboard_enabled:
clipboardlog("clipboard is disabled, not sending clipboard packet")
return
#handle clipboard compression if needed:
from xpra.net.compression import Compressible
packet = list(parts)
for v in packet:
if isinstance(v, Compressible):
register_clipboard_compress_cb(v)
self.send_now(*packet)
def register_clipboard_compress_cb(compressible):
#register the compressor which will fire in protocol.encode:
def compress_clipboard():
clipboardlog("compress_clipboard() compressing %s, server compressors=%s",
compressible, self.server_compressors)
from xpra.net import compression
if "brotli" in self.server_compressors and compression.use_brotli:
return compression.compressed_wrapper(compressible.datatype, compressible.data,
level=9, brotli=True, can_inline=False)
return self.compressed_wrapper(compressible.datatype, compressible.data)
compressible.compress = compress_clipboard
def clipboard_progress(local_requests, remote_requests):
clipboardlog("clipboard_progress(%s, %s)", local_requests, remote_requests)
if local_requests is not None:
self.local_clipboard_requests = local_requests
if remote_requests is not None:
self.remote_clipboard_requests = remote_requests
n = self.local_clipboard_requests+self.remote_clipboard_requests
self.clipboard_notify(n)
from xpra.client.mixins.clipboard import ClipboardClient
ch = ClipboardClient.setup_clipboard_helper(self, helperClass)
#check for loops after handshake:
def register_clipboard_toggled(*_args):
def clipboard_toggled(*_args):
#reset tray icon:
Expand All @@ -1324,7 +1222,10 @@ def loop_disabled_notify():
return False
self.timeout_add(5*1000, loop_disabled_notify)
self.after_handshake(register_clipboard_toggled)
return helperClass(clipboard_send, clipboard_progress, **kwargs)
if self.server_clipboard:
#from now on, we will send a message to the server whenever the clipboard flag changes:
self.connect("clipboard-toggled", self.clipboard_toggled)
return ch

def cancel_clipboard_notification_timer(self):
cnt = self.clipboard_notification_timer
Expand Down
112 changes: 104 additions & 8 deletions src/xpra/client/mixins/clipboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

from xpra.client.mixins.stub_client_mixin import StubClientMixin
from xpra.platform.features import CLIPBOARD_WANT_TARGETS, CLIPBOARD_GREEDY, CLIPBOARDS
from xpra.scripts.config import FALSE_OPTIONS
from xpra.platform.gui import get_clipboard_native_class
from xpra.platform.paths import get_icon_filename
from xpra.scripts.config import FALSE_OPTIONS, TRUE_OPTIONS
from xpra.util import flatten_dict
from xpra.os_util import bytestostr
from xpra.log import Logger
Expand Down Expand Up @@ -34,11 +36,18 @@ def __init__(self):
self.server_clipboard_contents_slice_fix = False
self.server_clipboards = []
self.clipboard_helper = None
self.local_clipboard_requests = 0
self.remote_clipboard_requests = 0
#only used with the translated clipboard class:
self.local_clipboard = ""
self.remote_clipboard = ""

def init(self, opts, _extra_args=()):
self.client_clipboard_type = opts.clipboard
self.client_clipboard_direction = opts.clipboard_direction
self.client_supports_clipboard = (opts.clipboard or "").lower() not in FALSE_OPTIONS
self.remote_clipboard = opts.remote_clipboard
self.local_clipboard = opts.local_clipboard


def cleanup(self):
Expand Down Expand Up @@ -131,9 +140,6 @@ def process_ui_capabilities(self):
ch.send_all_tokens()
#ui may want to know this is now set:
self.emit("clipboard-toggled")
if self.server_clipboard:
#from now on, we will send a message to the server whenever the clipboard flag changes:
self.connect("clipboard-toggled", self.clipboard_toggled)


def init_authenticated_packet_handlers(self):
Expand All @@ -146,7 +152,42 @@ def init_authenticated_packet_handlers(self):
self.add_packet_handler("clipboard-%s" % x, self._process_clipboard_packet)

def get_clipboard_helper_classes(self):
return ()
ct = self.client_clipboard_type
if ct and ct.lower() in FALSE_OPTIONS:
return []
from xpra.scripts.main import CLIPBOARD_CLASS
#first add the platform specific one, (may be None):
clipboard_options = [
CLIPBOARD_CLASS,
get_clipboard_native_class(),
]
log("get_clipboard_helper_classes() unfiltered list=%s", clipboard_options)
if ct and ct.lower()!="auto" and ct.lower() not in TRUE_OPTIONS:
#try to match the string specified:
filtered = [x for x in clipboard_options if x and x.lower().find(self.client_clipboard_type)>=0]
if not filtered:
log.warn("Warning: no clipboard types matching '%s'", self.client_clipboard_type)
log.warn(" clipboard synchronization is disabled")
return []
log(" found %i clipboard types matching '%s'", len(filtered), self.client_clipboard_type)
clipboard_options = filtered
#now try to load them:
log("get_clipboard_helper_classes() options=%s", clipboard_options)
loadable = []
for co in clipboard_options:
if not co:
continue
try:
parts = co.split(".")
mod = ".".join(parts[:-1])
module = __import__(mod, {}, {}, [parts[-1]])
helperclass = getattr(module, parts[-1])
loadable.append(helperclass)
except ImportError:
log("cannot load %s", co, exc_info=True)
continue
log("get_clipboard_helper_classes()=%s", loadable)
return loadable

def make_clipboard_helper(self):
"""
Expand All @@ -166,9 +207,6 @@ def make_clipboard_helper(self):
log.error("Error: cannot instantiate %s", helperclass, exc_info=True)
return None

def setup_clipboard_helper(self, helperClass):
raise NotImplementedError()


def _process_clipboard_packet(self, packet):
ch = self.clipboard_helper
Expand Down Expand Up @@ -208,3 +246,61 @@ def send_clipboard_loop_uuids(self):
log("send_clipboard_loop_uuid() uuids=%s", uuids)
if self.server_clipboard_loop_uuids:
self.send_now("clipboard-loop-uuids", uuids)


def setup_clipboard_helper(self, helperClass):
log("setup_clipboard_helper(%s)", helperClass)
#first add the platform specific one, (may be None):
kwargs= {
#all the local clipboards supported:
"clipboards.local" : CLIPBOARDS,
#all the remote clipboards supported:
"clipboards.remote" : self.server_clipboards,
"can-send" : self.client_clipboard_direction in ("to-server", "both"),
"can-receive" : self.client_clipboard_direction in ("to-client", "both"),
"remote-loop-uuids" : self.server_clipboard_loop_uuids,
}
#only allow translation overrides if we have a way of telling the server about them:
if self.server_clipboard_enable_selections:
kwargs.update({
#the local clipboard we want to sync to (with the translated clipboard only):
"clipboard.local" : self.local_clipboard,
#the remote clipboard we want to we sync to (with the translated clipboard only):
"clipboard.remote" : self.remote_clipboard
})
log("setup_clipboard_helper() kwargs=%s", kwargs)
def clipboard_send(*parts):
log("clipboard_send: %s", parts[0])
if not self.clipboard_enabled:
log("clipboard is disabled, not sending clipboard packet")
return
#handle clipboard compression if needed:
from xpra.net.compression import Compressible
packet = list(parts)
for v in packet:
if isinstance(v, Compressible):
register_clipboard_compress_cb(v)
self.send_now(*packet)
def register_clipboard_compress_cb(compressible):
#register the compressor which will fire in protocol.encode:
def compress_clipboard():
log("compress_clipboard() compressing %s, server compressors=%s",
compressible, self.server_compressors)
from xpra.net import compression
if "brotli" in self.server_compressors and compression.use_brotli:
return compression.compressed_wrapper(compressible.datatype, compressible.data,
level=9, brotli=True, can_inline=False)
return self.compressed_wrapper(compressible.datatype, compressible.data)
compressible.compress = compress_clipboard
def clipboard_progress(local_requests, remote_requests):
log("clipboard_progress(%s, %s)", local_requests, remote_requests)
if local_requests is not None:
self.local_clipboard_requests = local_requests
if remote_requests is not None:
self.remote_clipboard_requests = remote_requests
n = self.local_clipboard_requests+self.remote_clipboard_requests
self.clipboard_notify(n)
return helperClass(clipboard_send, clipboard_progress, **kwargs)

def clipboard_notify(self, n):
log("clipboard_notify(%i)", n)

0 comments on commit 5bfe539

Please sign in to comment.