hterm 1.53: Add 'alt-gr-mode' preference.
* Add a preference to select the preferred AltGr heuristic. This replaces the
change from 1.52, which prevented the use of Ctrl-Alt-... on all platforms.
The new preference takes one of the following values:
null: Autodetect based on navigator.locale:
'en-us' => 'none', else => 'right-alt'
'none': Disable any AltGr related munging.
'ctrl-alt': Assume Ctrl+Alt means AltGr.
'left-alt': Assume left Alt means AltGr.
'right-alt': Assume right Alt means AltGr.
The default value is null. Autodection won't work in many cases, and the
left-alt/right-alt tracking will have issues if the window loses focus
while the alt key is down, but this may be the best we can do on the web.
Change-Id: I47b7e156262c57e8ce2ce265f89f90b1aba48d88
Reviewed-on: https://chromium-review.googlesource.com/254331
Reviewed-by: Marius Schilder <mschilder@chromium.org>
Commit-Queue: Marius Schilder <mschilder@chromium.org>
Tested-by: Marius Schilder <mschilder@chromium.org>
diff --git a/hterm/doc/changelog.txt b/hterm/doc/changelog.txt
index 944c856..fb9d4c8 100644
--- a/hterm/doc/changelog.txt
+++ b/hterm/doc/changelog.txt
@@ -1,3 +1,20 @@
+1.53, 2015-02-26, Add 'alt-gr-mode' preference.
+
+* Add a preference to select the preferred AltGr heuristic. This replaces the
+ change from 1.52, which prevented the use of Ctrl-Alt-... on all platforms.
+ The new preference takes one of the following values:
+
+ null: Autodetect based on navigator.locale:
+ 'en-us' => 'none', else => 'right-alt'
+ 'none': Disable any AltGr related munging.
+ 'ctrl-alt': Assume Ctrl+Alt means AltGr.
+ 'left-alt': Assume left Alt means AltGr.
+ 'right-alt': Assume right Alt means AltGr.
+
+ The default value is null. Autodection won't work in many cases, and the
+ left-alt/right-alt tracking will have issues if the window loses focus
+ while the alt key is down, but this may be the best we can do on the web.
+
1.52, 2015-02-18, Treat Ctrl-Alt as AltGr
* Assume that Ctrl-Alt-[Printable] means AltGr-[Printable]. After this change,
diff --git a/hterm/js/hterm_keyboard.js b/hterm/js/hterm_keyboard.js
index d21ed3d..f6cf6a5 100644
--- a/hterm/js/hterm_keyboard.js
+++ b/hterm/js/hterm_keyboard.js
@@ -39,6 +39,14 @@
this.keyMap = new hterm.Keyboard.KeyMap(this);
/**
+ * none: Disable any AltGr related munging.
+ * ctrl-alt: Assume Ctrl+Alt means AltGr.
+ * left-alt: Assume left Alt means AltGr.
+ * right-alt: Assume right Alt means AltGr.
+ */
+ this.altGrMode = 'none';
+
+ /**
* If true, Shift-Insert will fall through to the browser as a paste.
* If false, the keystroke will be sent to the host.
*/
@@ -147,9 +155,11 @@
/**
* Used to keep track of the current alt-key state, which is necessary for
- * the altBackspaceIsMetaBackspace preference above.
+ * the altBackspaceIsMetaBackspace preference above and for the altGrMode
+ * preference. This is a bitmap with where bit positions correspond to the
+ * "location" property of the key event.
*/
- this.altIsPressed = false;
+ this.altKeyPressed = 0;
/**
* If true, Chrome OS media keys will be mapped to their F-key equivalent.
@@ -326,12 +336,13 @@
};
hterm.Keyboard.prototype.onBlur_ = function(e) {
- this.altIsPressed = false;
+ this.altKeyPressed = 0;
};
hterm.Keyboard.prototype.onKeyUp_ = function(e) {
if (e.keyCode == 18)
- this.altIsPressed = false;
+ this.altKeyPressed = this.altKeyPressed & ~(1 << (e.location - 1));
+
if (e.keyCode == 27)
this.preventChromeAppNonShiftDefault_(e);
};
@@ -341,7 +352,8 @@
*/
hterm.Keyboard.prototype.onKeyDown_ = function(e) {
if (e.keyCode == 18)
- this.altIsPressed = true;
+ this.altKeyPressed = this.altKeyPressed | (1 << (e.location - 1));
+
if (e.keyCode == 27)
this.preventChromeAppNonShiftDefault_(e);
@@ -387,11 +399,29 @@
// In the key-map, we surround the keyCap for non-printables in "[...]"
var isPrintable = !(/^\[\w+\]$/.test(keyDef.keyCap));
- if (isPrintable && control && alt) {
- // ctrl-alt-printable means altGr on the web. We clear out the control and
- // alt modifiers and wait to see the charCode in the keydown event.
- control = false;
- alt = false;
+ switch (this.altGrMode) {
+ case 'ctrl-alt':
+ if (isPrintable && control && alt) {
+ // ctrl-alt-printable means altGr. We clear out the control and
+ // alt modifiers and wait to see the charCode in the keydown event.
+ control = false;
+ alt = false;
+ }
+ break;
+
+ case 'right-alt':
+ if (isPrintable && (this.terminal.keyboard.altKeyPressed & 2)) {
+ control = false;
+ alt = false;
+ }
+ break;
+
+ case 'left-alt':
+ if (isPrintable && (this.terminal.keyboard.altKeyPressed & 1)) {
+ control = false;
+ alt = false;
+ }
+ break;
}
var action;
diff --git a/hterm/js/hterm_keyboard_keymap.js b/hterm/js/hterm_keyboard_keymap.js
index fe57770..a8ed5d1 100644
--- a/hterm/js/hterm_keyboard_keymap.js
+++ b/hterm/js/hterm_keyboard_keymap.js
@@ -129,7 +129,7 @@
var action = (e.shiftKey || e.ctrlKey || e.altKey || e.metaKey ||
!self.keyboard.applicationKeypad) ? a : b;
return resolve(action, e, k);
- }
+ };
}
// If mod or not application cursor a, else b. The keys that care about
@@ -139,21 +139,21 @@
var action = (e.shiftKey || e.ctrlKey || e.altKey || e.metaKey ||
!self.keyboard.applicationCursor) ? a : b;
return resolve(action, e, k);
- }
+ };
}
// If not backspace-sends-backspace keypad a, else b.
function bs(a, b) {
return function(e, k) {
- var action = !self.keyboard.backspaceSendsBackspace ? a : b
+ var action = !self.keyboard.backspaceSendsBackspace ? a : b;
return resolve(action, e, k);
- }
+ };
}
// If not e.shiftKey a, else b.
function sh(a, b) {
return function(e, k) {
- var action = !e.shiftKey ? a : b
+ var action = !e.shiftKey ? a : b;
// Clear e.shiftKey so that the keyboard code doesn't try to apply
// additional modifiers to the sequence.
@@ -161,15 +161,15 @@
e.shiftKey = false;
return resolve(action, e, k);
- }
+ };
}
// If not e.altKey a, else b.
function alt(a, b) {
return function(e, k) {
- var action = !e.altKey ? a : b
+ var action = !e.altKey ? a : b;
return resolve(action, e, k);
- }
+ };
}
// If no modifiers a, else b.
@@ -177,7 +177,7 @@
return function(e, k) {
var action = !(e.shiftKey || e.ctrlKey || e.altKey || e.metaKey) ? a : b;
return resolve(action, e, k);
- }
+ };
}
// Compute a control character for a given character.
@@ -430,7 +430,7 @@
*/
hterm.Keyboard.KeyMap.prototype.onKeyDel_ = function(e) {
if (this.keyboard.altBackspaceIsMetaBackspace &&
- this.keyboard.altIsPressed && !e.altKey)
+ this.keyboard.altKeyPressed && !e.altKey)
return '\x1b\x7f';
return '\x1b[3~';
};
diff --git a/hterm/js/hterm_preference_manager.js b/hterm/js/hterm_preference_manager.js
index 4450e65..3f913de 100644
--- a/hterm/js/hterm_preference_manager.js
+++ b/hterm/js/hterm_preference_manager.js
@@ -22,6 +22,18 @@
hterm.PreferenceManager.defaultPreferences = {
/**
+ * Select an AltGr detection hack^Wheuristic.
+ *
+ * null: Autodetect based on navigator.language:
+ * 'en-us' => 'none', else => 'right-alt'
+ * 'none': Disable any AltGr related munging.
+ * 'ctrl-alt': Assume Ctrl+Alt means AltGr.
+ * 'left-alt': Assume left Alt means AltGr.
+ * 'right-alt': Assume right Alt means AltGr.
+ */
+ 'alt-gr-mode': null,
+
+ /**
* If set, undoes the Chrome OS Alt-Backspace->DEL remap, so that
* alt-backspace indeed is alt-backspace.
*/
diff --git a/hterm/js/hterm_terminal.js b/hterm/js/hterm_terminal.js
index b4f42fa..0960666 100644
--- a/hterm/js/hterm_terminal.js
+++ b/hterm/js/hterm_terminal.js
@@ -194,6 +194,25 @@
this.prefs_ = new hterm.PreferenceManager(this.profileId_);
this.prefs_.addObservers(null, {
+ 'alt-gr-mode': function(v) {
+ if (v == null) {
+ if (navigator.language.toLowerCase() == 'en-us') {
+ v = 'none';
+ } else {
+ v = 'right-alt';
+ }
+ } else if (typeof v == 'string') {
+ v = v.toLowerCase();
+ } else {
+ v = 'none';
+ }
+
+ if (!/^(none|ctrl-alt|left-alt|right-alt)$/.test(v))
+ v = 'none';
+
+ terminal.keyboard.altGrMode = v;
+ },
+
'alt-backspace-is-meta-backspace': function(v) {
terminal.keyboard.altBackspaceIsMetaBackspace = v;
},