Skip to content

Commit

Permalink
in order to be able to toggle the active selection on the client side…
Browse files Browse the repository at this point in the history
…, we need to be able to tell the server which selections it should be monitoring

git-svn-id: https://xpra.org/svn/Xpra/trunk@10380 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Aug 20, 2015
1 parent 85284f9 commit cbf4a5d
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 21 deletions.
19 changes: 13 additions & 6 deletions src/xpra/client/gtk_base/gtk_tray_menu_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from xpra.platform.gui import get_icon_size
from xpra.log import Logger
log = Logger("tray")
clipboardlog = Logger("tray", "clipboard")


HIDE_DISABLED_MENU_ENTRIES = sys.platform.startswith("darwin")
Expand Down Expand Up @@ -434,16 +435,17 @@ def set_notifications_menuitem(*args):
return self.notifications_menuitem

def make_clipboard_togglemenuitem(self):
clipboardlog("make_clipboard_togglemenuitem()")
def menu_clipboard_toggled(*args):
new_state = self.clipboard_menuitem.get_active()
log("clipboard_toggled(%s) clipboard_enabled=%s, new_state=%s", args, self.client.clipboard_enabled, new_state)
clipboardlog("clipboard_toggled(%s) clipboard_enabled=%s, new_state=%s", args, self.client.clipboard_enabled, new_state)
if self.client.clipboard_enabled!=new_state:
self.client.clipboard_enabled = new_state
self.client.emit("clipboard-toggled")
self.clipboard_menuitem = self.checkitem("Clipboard", menu_clipboard_toggled)
self.clipboard_menuitem.set_sensitive(False)
def set_clipboard_menuitem(*args):
log("set_clipboard_menuitem%s enabled=%s", args, self.client.clipboard_enabled)
clipboardlog("set_clipboard_menuitem%s enabled=%s", args, self.client.clipboard_enabled)
self.clipboard_menuitem.set_active(self.client.clipboard_enabled)
c = self.client
can_clipboard = c.server_supports_clipboard and c.client_supports_clipboard
Expand All @@ -461,6 +463,7 @@ def clipboard_toggled(*args):
return self.clipboard_menuitem

def make_translatedclipboard_optionsmenuitem(self):
clipboardlog("make_translatedclipboard_optionsmenuitem()")
clipboard_menu = self.menuitem("Clipboard", "clipboard.png", "Choose which remote clipboard to connect to", None)
clipboard_menu.set_sensitive(False)
def set_clipboard_menu(*args):
Expand All @@ -469,7 +472,7 @@ def set_clipboard_menu(*args):
self.popup_menu_workaround(clipboard_submenu)
c = self.client
can_clipboard = c.server_supports_clipboard and c.client_supports_clipboard and c.server_supports_clipboard
log("set_clipboard_menu(%s) can_clipboard=%s, server=%s, client=%s", args, can_clipboard, c.server_supports_clipboard, c.client_supports_clipboard)
clipboardlog("set_clipboard_menu(%s) can_clipboard=%s, server=%s, client=%s", args, can_clipboard, c.server_supports_clipboard, c.client_supports_clipboard)
clipboard_menu.set_sensitive(can_clipboard)
LABEL_TO_NAME = {"Disabled" : None,
"Clipboard" : "CLIPBOARD",
Expand All @@ -484,7 +487,7 @@ def remote_clipboard_changed(item):
label = item.get_label()
remote_clipboard = LABEL_TO_NAME.get(label)
old_state = self.client.clipboard_enabled
log("remote_clipboard_changed(%s) remote_clipboard=%s, old_state=%s", item, remote_clipboard, old_state)
clipboardlog("remote_clipboard_changed(%s) remote_clipboard=%s, old_state=%s", item, remote_clipboard, old_state)
send_tokens = False
if remote_clipboard is not None:
#clipboard is not disabled
Expand All @@ -493,11 +496,15 @@ def remote_clipboard_changed(item):
self.client.clipboard_helper.remote_clipboard = remote_clipboard
send_tokens = True
new_state = True
selections = [remote_clipboard]
else:
self.client.clipboard_helper = None
send_tokens = False
new_state = False
log("remote_clipboard_changed(%s) label=%s, remote_clipboard=%s, old_state=%s, new_state=%s",
selections = []
#tell the server what to look for:
self.client.send_clipboard_selections(selections)
clipboardlog("remote_clipboard_changed(%s) label=%s, remote_clipboard=%s, old_state=%s, new_state=%s",
item, label, remote_clipboard, old_state, new_state)
if new_state!=old_state:
self.client.clipboard_enabled = new_state
Expand All @@ -523,7 +530,7 @@ def make_clipboardmenuitem(self):
if CLIPBOARD_NATIVE_CLASS[0].find("translated_clipboard")>0:
return self.make_translatedclipboard_optionsmenuitem()
except:
log.error("make_clipboardmenuitem()", exc_info=True)
clipboardlog.error("make_clipboardmenuitem()", exc_info=True)
return self.make_clipboard_togglemenuitem()


Expand Down
11 changes: 10 additions & 1 deletion src/xpra/client/ui_client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
screenlog = Logger("client", "screen")
mouselog = Logger("mouse")
avsynclog = Logger("av-sync")
clipboardlog = Logger("clipboard")


from xpra import __version__ as XPRA_VERSION
Expand Down Expand Up @@ -1328,6 +1329,7 @@ def parse_server_capabilities(self):
self.server_supports_bell = c.boolget("bell") #added in 0.5, default to True!
self.bell_enabled = self.server_supports_bell and self.client_supports_bell
self.server_supports_clipboard = c.boolget("clipboard")
self.server_supports_clipboard_enable_selections = c.boolget("clipboard.enable-selections")
self.server_clipboards = c.strlistget("clipboards", ALL_CLIPBOARDS)
self.server_compressors = c.strlistget("compressors", ["zlib"])
self.clipboard_enabled = self.client_supports_clipboard and self.server_supports_clipboard
Expand Down Expand Up @@ -1864,13 +1866,19 @@ def send_deflate_level(self):
def _process_clipboard_enabled_status(self, packet):
clipboard_enabled, reason = packet[1:3]
if self.clipboard_enabled!=clipboard_enabled:
log.info("clipboard toggled to %s by the server, reason: %s", ["off", "on"][int(clipboard_enabled)], reason)
clipboardlog.info("clipboard toggled to %s by the server, reason: %s", ["off", "on"][int(clipboard_enabled)], reason)
self.clipboard_enabled = bool(clipboard_enabled)
self.emit("clipboard-toggled")

def send_clipboard_enabled_status(self, *args):
clipboardlog("send_clipboard_enabled_status%s clipboard_enabled=%s", args, self.clipboard_enabled)
self.send("set-clipboard-enabled", self.clipboard_enabled)

def send_clipboard_selections(self, selections):
clipboardlog("send_clipboard_selections(%s) server_supports_clipboard_enable_selections=%s", selections, self.server_supports_clipboard_enable_selections)
if self.server_supports_clipboard_enable_selections:
self.send("clipboard-enable-selections", selections)

def send_keyboard_sync_enabled_status(self, *args):
self.send("set-keyboard-sync-enabled", self.keyboard_sync)

Expand Down Expand Up @@ -2236,6 +2244,7 @@ def delhandler(k):
self._packet_handlers[k] = v

def process_clipboard_packet(self, packet):
clipboardlog("process_clipboard_packet: %s", packet[0])
self.idle_add(self.clipboard_helper.process_clipboard_packet, packet)

def process_packet(self, proto, packet):
Expand Down
13 changes: 10 additions & 3 deletions src/xpra/clipboard/clipboard_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ def nosend(*args):
self._clipboard_proxies = {}

def enable_selections(self, selections):
#when clients connect, they can tell us which
#clipboards they want enabled
#(ie: OSX and win32 only use "CLIPBOARD", and not "PRIMARY" or "SECONDARY")
#when clients first connect or later through the "clipboard-enable-selections" packet,
#clients can tell us which clipboard selections they want enabled
#(ie: OSX and win32 only use "CLIPBOARD" by default, and not "PRIMARY" or "SECONDARY")
for selection, proxy in self._clipboard_proxies.items():
proxy.set_enabled(selection in selections)

Expand All @@ -121,6 +121,7 @@ def init_packet_handlers(self):
"clipboard-contents": self._process_clipboard_contents,
"clipboard-contents-none": self._process_clipboard_contents_none,
"clipboard-pending-requests": self._process_clipboard_pending_requests,
"clipboard-enable-selections": self._process_clipboard_enable_selections,
}

def make_proxy(self, clipboard):
Expand Down Expand Up @@ -386,6 +387,12 @@ def _process_clipboard_pending_requests(self, packet):
if self.progress_cb:
self.progress_cb(None, pending)

def _process_clipboard_enable_selections(self, packet):
selections = packet[1]
log("enabling selections: %s", selections)
self.enable_selections(selections)


def process_clipboard_packet(self, packet):
packet_type = packet[0]
log("process clipboard packet type=%s", packet_type)
Expand Down
11 changes: 7 additions & 4 deletions src/xpra/clipboard/translated_clipboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@
if DEFAULT_LOCAL_SELECTION not in CLIPBOARDS:
log.warn("invalid default local selection: %s, using %s instead", DEFAULT_LOCAL_SELECTION, CLIPBOARDS[0])
DEFAULT_LOCAL_SELECTION = CLIPBOARDS[0]
DEFAULT_REMOTE_SELECTION = os.environ.get("XPRA_TRANSLATEDCLIPBOARD_REMOTE_SELECTION", "CLIPBOARD")
if DEFAULT_REMOTE_SELECTION not in ("PRIMARY", "SECONDARY", "CLIPBOARD"):
log.warn("invalid default remote selection: %s, using %s instead", DEFAULT_REMOTE_SELECTION, "CLIPBOARD")
DEFAULT_REMOTE_SELECTION = "CLIPBOARD"
#we have to validate the remote selection against the list of *LOCAL* selections,
#because the hello packet tells the server which selections to enable,
#and if we use one that is not enabled... nothing happens!
DEFAULT_REMOTE_SELECTION = os.environ.get("XPRA_TRANSLATEDCLIPBOARD_REMOTE_SELECTION", CLIPBOARDS[0])
if DEFAULT_REMOTE_SELECTION not in CLIPBOARDS:
log.warn("invalid default remote selection: %s, using %s instead", DEFAULT_REMOTE_SELECTION, CLIPBOARDS[0])
DEFAULT_REMOTE_SELECTION = CLIPBOARDS[0]


class TranslatedClipboardProtocolHelper(GDKClipboardProtocolHelper):
Expand Down
18 changes: 11 additions & 7 deletions src/xpra/server/server_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
printlog = Logger("printing")
netlog = Logger("network")
windowlog = Logger("window")
clipboardlog = Logger("clipboard")

from xpra.keyboard.mask import DEFAULT_MODIFIER_MEANINGS
from xpra.server.server_core import ServerCore, get_thread_info
Expand Down Expand Up @@ -417,7 +418,7 @@ def init_sound_options(self, sound_source_plugin, speaker, speaker_codec, microp
log.warn(" %s", e)

def init_clipboard(self):
log("init_clipboard() enabled=%s, filter file=%s", self.supports_clipboard, self.clipboard_filter_file)
clipboardlog("init_clipboard() enabled=%s, filter file=%s", self.supports_clipboard, self.clipboard_filter_file)
### Clipboard handling:
self._clipboard_helper = None
self._clipboard_client = None
Expand All @@ -428,22 +429,22 @@ def init_clipboard(self):
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)
clipboardlog.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)
clipboardlog("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)
clipboardlog.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
self._clipboard_helper = GDKClipboardProtocolHelper(self.send_clipboard_packet, self.clipboard_progress, CLIPBOARDS, clipboard_filter_res)
self._clipboards = CLIPBOARDS
except Exception as e:
log.error("failed to setup clipboard helper: %s" % e)
clipboardlog.error("failed to setup clipboard helper: %s" % e)

def init_keyboard(self):
keylog("init_keyboard()")
Expand Down Expand Up @@ -929,7 +930,7 @@ def parse_hello_ui_clipboard(self, ss, c):
#the selections the client supports (default to all):
from xpra.platform.features import CLIPBOARDS
client_selections = c.strlistget("clipboard.selections", CLIPBOARDS)
log("process_hello server has clipboards: %s, client supports: %s", self._clipboards, client_selections)
clipboardlog("process_hello server has clipboards: %s, client supports: %s", self._clipboards, client_selections)
self._clipboard_helper.enable_selections(client_selections)

def parse_hello_ui_keyboard(self, ss, c):
Expand Down Expand Up @@ -994,6 +995,7 @@ def get_server_features(self):
"sound_sequence", "notify-startup-complete", "suspend-resume",
"encoding.generic", "encoding.strict_control",
"sound.server_driven",
"clipboard.enable-selections",
"av-sync",
"command_request",
"event_request", "server-events",
Expand Down Expand Up @@ -1052,7 +1054,9 @@ def send_hello(self, server_source, root_w, root_h, key_repeat, server_cipher):
"key_repeat" : key_repeat,
"key_repeat_modifiers" : True})
if server_source.wants_features:
capabilities["clipboard"] = self._clipboard_helper is not None and self._clipboard_client == server_source
clipboard = self._clipboard_helper is not None and self._clipboard_client == server_source
capabilities["clipboard"] = clipboard
clipboardlog("clipboard_helper=%s, clipboard_client=%s, source=%s, clipboard=%s", self._clipboard_helper, self._clipboard_client, server_source, clipboard)
capabilities["remote-logging"] = self.remote_logging
if self._reverse_aliases and server_source.wants_aliases:
capabilities["aliases"] = self._reverse_aliases
Expand Down

0 comments on commit cbf4a5d

Please sign in to comment.