Skip to content

Commit

Permalink
move keymap detection code to platform and only apply keymaps when a …
Browse files Browse the repository at this point in the history
…client connects and supplies one (use same old default if they don't)

git-svn-id: https://xpra.org/svn/Xpra/trunk@187 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Sep 23, 2011
1 parent 5c8bce8 commit c65bfe9
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 63 deletions.
28 changes: 2 additions & 26 deletions src/xpra/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,32 +485,8 @@ def parse_shortcuts(self, strs):
return shortcuts

def query_xkbmap(self):
from xpra.platform import X11_KEYMAPS
if not X11_KEYMAPS:
log.info("this platform does not support X11 keymaps, not querying the system with setxkbmap or xmodmap");
self.xkbmap_print, self.xkbmap_query, self.xkbmap_query, self.xmodmap_data = None, None, None, None
return
def get_keyboard_data(command, arg):
# Find the client's current keymap so we can send it to the server:
try:
import subprocess
cmd = [command, arg]
process = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
(out,_) = process.communicate(None)
if process.returncode==0:
return out
log.error("'%s %s' failed with exit code %s\n" % (command, arg, process.returncode))
except Exception, e:
log.error("error running '%s %s': %s\n" % (command, arg, e))
return None
self.xkbmap_print = get_keyboard_data("setxkbmap", "-print")
if self.xkbmap_print is None:
log.error("your keyboard mapping will probably be incorrect unless you are using a 'us' layout");
self.xkbmap_query = get_keyboard_data("setxkbmap", "-query")
if self.xkbmap_query is None and self.xkbmap_print is not None:
log.error("the server will try to guess your keyboard mapping, which works reasonably well in most cases");
log.error("however, upgrading 'setxkbmap' to a version that supports the '-query' parameter is preferred");
self.xmodmap_data = get_keyboard_data("xmodmap", "-pke");
from xpra.platform.gui import get_keymap_spec
self.xkbmap_print, self.xkbmap_query, self.xmodmap_data = get_keymap_spec()

def _keys_changed(self, *args):
self._keymap = gtk.gdk.keymap_get_default()
Expand Down
1 change: 0 additions & 1 deletion src/xpra/darwin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
XPRA_LOCAL_SERVERS_SUPPORTED = False
DEFAULT_SSH_CMD = "ssh"
GOT_PASSWORD_PROMPT_SUGGESTION = "Perhaps you need to set up your ssh agent?\n"
X11_KEYMAPS = False

def add_client_options(parser):
parser.add_option("--dock-icon", action="store",
Expand Down
3 changes: 3 additions & 0 deletions src/xpra/darwin/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ def grok_modifier_map(display_source):
| modifier_map["num"])
return modifier_map

def get_keymap_spec():
return None,None,None

class ClipboardProtocolHelper(object):
def __init__(self, send_packet_cb):
self.send = send_packet_cb
Expand Down
68 changes: 34 additions & 34 deletions src/xpra/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,36 +341,6 @@ def __init__(self, clobber, sockets, password_file, pulseaudio, clipboard, randr
self._keymap.connect("keys-changed", self._keys_changed)
self._keys_changed()

#clear all modifiers before we try to call xmodmap
self._make_keymask_match([])
try:
self.signal_safe_exec(["xmodmap", "-"],
"""clear Lock
clear Shift
clear Control
clear Mod1
clear Mod2
clear Mod3
clear Mod4
clear Mod5
keycode any = Shift_L
keycode any = Control_L
keycode any = Meta_L
keycode any = Alt_L
keycode any = Hyper_L
keycode any = Super_L
add Shift = Shift_L Shift_R
add Control = Control_L Control_R
add Mod1 = Meta_L Meta_R
add Mod2 = Alt_L Alt_R
add Mod3 = Hyper_L Hyper_R
add Mod4 = Super_L Super_R
"""
# Really stupid hack to force backspace to work.
# Remove this once we have real keymap support.
+ "keycode any = BackSpace")
except OSError, e:
sys.stderr.write("Error running xmodmap: %s\n" % (e,))
self._keyname_for_mod = {
"shift": "Shift_L",
"control": "Control_L",
Expand All @@ -379,6 +349,8 @@ def __init__(self, clobber, sockets, password_file, pulseaudio, clipboard, randr
"hyper": "Hyper_L",
"alt": "Alt_L",
}
#clear all modifiers
self._make_keymask_match([])

### Clipboard handling:
if clipboard:
Expand All @@ -405,8 +377,9 @@ def __init__(self, clobber, sockets, password_file, pulseaudio, clipboard, randr
self.add_listen_socket(sock)

def set_keymap(self):
""" xkbmap_print is the output of setxkbmap -print on the client
xkbmap_query is the output of setxkbmap -query on the client
""" xkbmap_print is the output of "setxkbmap -print" on the client
xkbmap_query is the output of "setxkbmap -query" on the client
xmodmap_data is the output of "xmodmap -pke" on the client
Use those to try to setup the correct keyboard map for the client
so that all the keycodes sent will be mapped
"""
Expand Down Expand Up @@ -466,9 +439,36 @@ def exec_keymap_command(args, stdin=None):

if self.xkbmap_print:
exec_keymap_command(["xkbcomp", "-", os.environ.get("DISPLAY")], self.xkbmap_print)
if self.xmodmap_data:
exec_keymap_command(["xmodmap", "-"], self.xmodmap_data)

xmodmap_data = self.xmodmap_data
if not self.xkbmap_query and not self.xkbmap_print and not self.xmodmap_data:
""" use a default xmodmap for clients that supply nothing at all: """
xmodmap_data = """clear Lock
clear Shift
clear Control
clear Mod1
clear Mod2
clear Mod3
clear Mod4
clear Mod5
keycode any = Shift_L
keycode any = Control_L
keycode any = Meta_L
keycode any = Alt_L
keycode any = Hyper_L
keycode any = Super_L
add Shift = Shift_L Shift_R
add Control = Control_L Control_R
add Mod1 = Meta_L Meta_R
add Mod2 = Alt_L Alt_R
add Mod3 = Hyper_L Hyper_R
add Mod4 = Super_L Super_R
"""
# Really stupid hack to force backspace to work.
xmodmap_data += "keycode any = BackSpace"

if xmodmap_data:
exec_keymap_command(["xmodmap", "-"], xmodmap_data)

def signal_safe_exec(self, cmd, stdin):
""" this is a bit of a hack,
Expand Down
1 change: 0 additions & 1 deletion src/xpra/win32/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
DEFAULT_SSH_CMD = "plink"
GOT_PASSWORD_PROMPT_SUGGESTION = \
'Perhaps you need to set up Pageant, or (less secure) use --ssh="plink -pw YOUR-PASSWORD"?\n'
X11_KEYMAPS = False

def add_client_options(parser):
pass
4 changes: 4 additions & 0 deletions src/xpra/win32/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ def grok_modifier_map(display_source):
| modifier_map["num"])
return modifier_map

def get_keymap_spec():
return None,None,None


class ClipboardProtocolHelper(object):
def __init__(self, send_packet_cb):
self.send = send_packet_cb
Expand Down
1 change: 0 additions & 1 deletion src/xpra/xposix/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
XPRA_LOCAL_SERVERS_SUPPORTED = True
DEFAULT_SSH_CMD = "ssh"
GOT_PASSWORD_PROMPT_SUGGESTION = "Perhaps you need to set up your ssh agent?\n"
X11_KEYMAPS = True

def add_client_options(parser):
pass
28 changes: 28 additions & 0 deletions src/xpra/xposix/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

from xpra.xposix.xsettings import XSettingsWatcher
from xpra.xposix.xroot_props import XRootPropWatcher

from wimpiggy.log import Logger
log = Logger()

class ClientExtras(object):
def __init__(self, send_packet_cb, pulseaudio, opts):
self.send = send_packet_cb
Expand Down Expand Up @@ -46,3 +50,27 @@ def _handle_root_prop_changed(self, obj, prop, value):
self.send(["server-settings",
{self.ROOT_PROPS[prop]: value.encode("utf-8")}])


def get_keymap_spec():
def get_keyboard_data(command, arg):
# Find the client's current keymap so we can send it to the server:
try:
import subprocess
cmd = [command, arg]
process = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
(out,_) = process.communicate(None)
if process.returncode==0:
return out
log.error("'%s %s' failed with exit code %s\n" % (command, arg, process.returncode))
except Exception, e:
log.error("error running '%s %s': %s\n" % (command, arg, e))
return None
xkbmap_print = get_keyboard_data("setxkbmap", "-print")
if xkbmap_print is None:
log.error("your keyboard mapping will probably be incorrect unless you are using a 'us' layout");
xkbmap_query = get_keyboard_data("setxkbmap", "-query")
if xkbmap_query is None and xkbmap_print is not None:
log.error("the server will try to guess your keyboard mapping, which works reasonably well in most cases");
log.error("however, upgrading 'setxkbmap' to a version that supports the '-query' parameter is preferred");
xmodmap_data = get_keyboard_data("xmodmap", "-pke");
return xkbmap_print, xkbmap_query, xmodmap_data

0 comments on commit c65bfe9

Please sign in to comment.