summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorlambroslambrou@chromium.org <lambroslambrou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-07 02:00:42 +0000
committerlambroslambrou@chromium.org <lambroslambrou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-07 02:00:42 +0000
commit5281a6793553669943ba5b873b80dd857e87a915 (patch)
tree911982d2578661ce917b4aea8be81729ca1265d6 /remoting
parentbaecb9d990af75f4783ee3173bd17aff44e58808 (diff)
downloadchromium_src-5281a6793553669943ba5b873b80dd857e87a915.zip
chromium_src-5281a6793553669943ba5b873b80dd857e87a915.tar.gz
chromium_src-5281a6793553669943ba5b873b80dd857e87a915.tar.bz2
Suppress key-repeat on Linux host
This ensures that key-repeat is controlled by the client, not the host (so that network latency will not trigger key-repeat on the host if the release event is delayed). To test this, disable key-repeat on the client machine (on Linux, run "xset r off"). Then verify that this works over a connection to a Linux host (key presses from the client are not auto-repeated on the host). This implementation should work for both IT2Me and Me2Me. In the IT2Me case, the local user of the host machine should experience key-repeats normally. The host's global preference for auto-repeat is not permanently changed; the auto-repeat is only suppressed whilst keys are pressed from the client. BUG=115972 TEST=Manual Review URL: http://codereview.chromium.org/9614011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@125288 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r--remoting/host/event_executor_linux.cc33
-rwxr-xr-xremoting/tools/me2me_virtual_host.py16
2 files changed, 31 insertions, 18 deletions
diff --git a/remoting/host/event_executor_linux.cc b/remoting/host/event_executor_linux.cc
index 794fa71..f2e68b8 100644
--- a/remoting/host/event_executor_linux.cc
+++ b/remoting/host/event_executor_linux.cc
@@ -29,7 +29,7 @@ namespace {
class EventExecutorLinux : public EventExecutor {
public:
EventExecutorLinux(MessageLoop* message_loop, Capturer* capturer);
- virtual ~EventExecutorLinux() {};
+ virtual ~EventExecutorLinux();
bool Init();
@@ -37,6 +37,10 @@ class EventExecutorLinux : public EventExecutor {
virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE;
private:
+ // |mode| is one of the AutoRepeatModeOn, AutoRepeatModeOff,
+ // AutoRepeatModeDefault constants defined by the XChangeKeyboardControl()
+ // API.
+ void SetAutoRepeatForKey(int keycode, int mode);
void InjectScrollWheelClicks(int button, int count);
MessageLoop* message_loop_;
@@ -259,6 +263,10 @@ EventExecutorLinux::EventExecutorLinux(MessageLoop* message_loop,
height_(0) {
}
+EventExecutorLinux::~EventExecutorLinux() {
+ CHECK(pressed_keys_.empty());
+}
+
bool EventExecutorLinux::Init() {
CHECK(display_);
@@ -321,17 +329,38 @@ void EventExecutorLinux::InjectKeyEvent(const KeyEvent& event) {
<< " to keycode: " << keycode;
if (event.pressed()) {
- if (pressed_keys_.find(keycode) != pressed_keys_.end())
+ if (pressed_keys_.find(keycode) != pressed_keys_.end()) {
+ // Key is already held down, so lift the key up to ensure this repeated
+ // press takes effect.
XTestFakeKeyEvent(display_, keycode, False, CurrentTime);
+ } else {
+ // Key is not currently held down, so disable auto-repeat for this
+ // key to avoid repeated presses in case network congestion delays the
+ // key-released event from the client.
+ SetAutoRepeatForKey(keycode, AutoRepeatModeOff);
+ }
pressed_keys_.insert(keycode);
} else {
pressed_keys_.erase(keycode);
+
+ // Reset the AutoRepeatMode for the key that has been lifted. In the IT2Me
+ // case, this ensures that key-repeating will continue to work normally
+ // for the local user of the host machine. "ModeDefault" is used instead
+ // of "ModeOn", since some keys (such as Shift) should not auto-repeat.
+ SetAutoRepeatForKey(keycode, AutoRepeatModeDefault);
}
XTestFakeKeyEvent(display_, keycode, event.pressed(), CurrentTime);
XFlush(display_);
}
+void EventExecutorLinux::SetAutoRepeatForKey(int keycode, int mode) {
+ XKeyboardControl control;
+ control.key = keycode;
+ control.auto_repeat_mode = mode;
+ XChangeKeyboardControl(display_, KBKey | KBAutoRepeatMode, &control);
+}
+
void EventExecutorLinux::InjectScrollWheelClicks(int button, int count) {
for (int i = 0; i < count; i++) {
// Generate a button-down and a button-up to simulate a wheel click.
diff --git a/remoting/tools/me2me_virtual_host.py b/remoting/tools/me2me_virtual_host.py
index e6fa6bb..b0eb122 100755
--- a/remoting/tools/me2me_virtual_host.py
+++ b/remoting/tools/me2me_virtual_host.py
@@ -25,7 +25,6 @@ import socket
import subprocess
import sys
import tempfile
-import threading
import time
import urllib2
import uuid
@@ -332,14 +331,6 @@ class Desktop:
if not self.session_proc.pid:
raise Exception("Could not start X session")
- # Allow some time for the desktop session to launch before disabling
- # key-repeat, since the desktop environment may enable key-repeat during
- # initialization.
-
- # TODO(lambroslambrou): A more robust solution would be for the host
- # process to disable key-repeat in its (per-platform) event-injection code.
- threading.Timer(30, self.disable_key_repeat).start()
-
def launch_host(self, host):
# Start remoting host
args = [locate_executable(REMOTING_COMMAND),
@@ -348,13 +339,6 @@ class Desktop:
if not self.host_proc.pid:
raise Exception("Could not start remoting host")
- def disable_key_repeat(self):
- logging.info("Disabling keyboard auto-repeat")
- try:
- subprocess.call(["xset", "r", "off"], env=self.child_env)
- except OSError, e:
- logging.error("Failed to disable keyboard auto-repeat: " + str(e))
-
class PidFile:
"""Class to allow creating and deleting a file which holds the PID of the