aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenny Root <kenny@the-b.org>2009-01-24 12:08:53 +0000
committerKenny Root <kenny@the-b.org>2009-01-24 12:08:53 +0000
commit370d4a0b3b3622b6036a18d028b6c48bcd7e43c6 (patch)
tree9183c307e7de01a15a5818bb90464580054f71f5
parentb6393bcc8d7b82b7f2704d8c208b33f4c0b9691a (diff)
downloadconnectbot-370d4a0b3b3622b6036a18d028b6c48bcd7e43c6.tar.gz
connectbot-370d4a0b3b3622b6036a18d028b6c48bcd7e43c6.tar.bz2
connectbot-370d4a0b3b3622b6036a18d028b6c48bcd7e43c6.zip
Allow shift- and alt-lock states (untested since emulator doesn't send shift or alt key codes)
* 1st press toggles on for next key, 2nd press locks, 3rd press turns off meta state * Different cursor indicators for each roughly equivalent to standard Android * Move Relay to subclass to reduce indent madness
-rw-r--r--src/org/connectbot/TerminalView.java29
-rw-r--r--src/org/connectbot/service/TerminalBridge.java431
2 files changed, 269 insertions, 191 deletions
diff --git a/src/org/connectbot/TerminalView.java b/src/org/connectbot/TerminalView.java
index 4250e0a..9c199e3 100644
--- a/src/org/connectbot/TerminalView.java
+++ b/src/org/connectbot/TerminalView.java
@@ -47,6 +47,7 @@ public class TerminalView extends View implements FontSizeChangedListener {
public final TerminalBridge bridge;
private final Paint paint;
private final Paint cursorPaint;
+ private final Paint cursorStrokePaint;
// Cursor paints to distinguish modes
private Path ctrlCursor, altCursor, shiftCursor;
@@ -73,6 +74,10 @@ public class TerminalView extends View implements FontSizeChangedListener {
cursorPaint.setXfermode(new PixelXorXfermode(bridge.color[TerminalBridge.COLOR_BG_STD]));
cursorPaint.setAntiAlias(true);
+ cursorStrokePaint = new Paint(cursorPaint);
+ cursorStrokePaint.setStrokeWidth(0.1f);
+ cursorStrokePaint.setStyle(Paint.Style.STROKE);
+
/*
* Set up our cursor indicators on a 1x1 Path object which we can later
* transform to our character width and height
@@ -81,19 +86,16 @@ public class TerminalView extends View implements FontSizeChangedListener {
shiftCursor = new Path();
shiftCursor.lineTo(0.5f, 0.33f);
shiftCursor.lineTo(1.0f, 0.0f);
- shiftCursor.close();
altCursor = new Path();
altCursor.moveTo(0.0f, 1.0f);
altCursor.lineTo(0.5f, 0.66f);
altCursor.lineTo(1.0f, 1.0f);
- altCursor.close();
ctrlCursor = new Path();
ctrlCursor.moveTo(0.0f, 0.25f);
ctrlCursor.lineTo(1.0f, 0.5f);
ctrlCursor.lineTo(0.0f, 0.75f);
- ctrlCursor.close();
// For creating the transform when the terminal resizes
tempSrc = new RectF();
@@ -116,9 +118,15 @@ public class TerminalView extends View implements FontSizeChangedListener {
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
bridge.parentChanged(this);
+
+ scaleCursors();
}
public void onFontSizeChanged(float size) {
+ scaleCursors();
+ }
+
+ private void scaleCursors() {
// Create a scale matrix to scale our 1x1 representation of the cursor
tempDst.set(0.0f, 0.0f, bridge.charWidth, bridge.charHeight);
scaleMatrix.setRectToRect(tempSrc, tempDst, scaleType);
@@ -151,11 +159,20 @@ public class TerminalView extends View implements FontSizeChangedListener {
canvas.concat(scaleMatrix);
int metaState = bridge.getMetaState();
- if ((metaState & TerminalBridge.META_SHIFT_ON) == TerminalBridge.META_SHIFT_ON)
+
+ if ((metaState & TerminalBridge.META_SHIFT_ON) != 0)
+ canvas.drawPath(shiftCursor, cursorStrokePaint);
+ else if ((metaState & TerminalBridge.META_SHIFT_LOCK) != 0)
canvas.drawPath(shiftCursor, cursorPaint);
- if ((metaState & TerminalBridge.META_ALT_ON) == TerminalBridge.META_ALT_ON)
+
+ if ((metaState & TerminalBridge.META_ALT_ON) != 0)
+ canvas.drawPath(altCursor, cursorStrokePaint);
+ else if ((metaState & TerminalBridge.META_ALT_LOCK) != 0)
canvas.drawPath(altCursor, cursorPaint);
- if ((metaState & TerminalBridge.META_CTRL_ON) == TerminalBridge.META_CTRL_ON)
+
+ if ((metaState & TerminalBridge.META_CTRL_ON) != 0)
+ canvas.drawPath(ctrlCursor, cursorStrokePaint);
+ else if ((metaState & TerminalBridge.META_CTRL_LOCK) != 0)
canvas.drawPath(ctrlCursor, cursorPaint);
// Restore previous clip region
diff --git a/src/org/connectbot/service/TerminalBridge.java b/src/org/connectbot/service/TerminalBridge.java
index f75b1a3..4933db3 100644
--- a/src/org/connectbot/service/TerminalBridge.java
+++ b/src/org/connectbot/service/TerminalBridge.java
@@ -132,15 +132,25 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
private TerminalView parent = null;
private Canvas canvas = new Canvas();
- private boolean ctrlPressed = false;
- private boolean altPressed = false;
- private boolean shiftPressed = false;
- private boolean slashKeyPressed = false;
- private boolean tabKeyPressed = false;
-
- public final static int META_CTRL_ON = 0x01;
- public final static int META_ALT_ON = 0x02;
- public final static int META_SHIFT_ON = 0x04;
+ private int metaState = 0;
+
+ public final static int META_CTRL_ON = 0x01;
+ public final static int META_CTRL_LOCK = 0x02;
+ public final static int META_ALT_ON = 0x04;
+ public final static int META_ALT_LOCK = 0x08;
+ public final static int META_SHIFT_ON = 0x10;
+ public final static int META_SHIFT_LOCK = 0x20;
+ public final static int META_SLASH = 0x40;
+ public final static int META_TAB = 0x80;
+
+ // The bit mask of momentary and lock states for each
+ public final static int META_CTRL_MASK = META_CTRL_ON | META_CTRL_LOCK;
+ public final static int META_ALT_MASK = META_ALT_ON | META_ALT_LOCK;
+ public final static int META_SHIFT_MASK = META_SHIFT_ON | META_SHIFT_LOCK;
+
+ // All the transient key codes
+ public final static int META_TRANSIENT = META_CTRL_ON | META_ALT_ON
+ | META_SHIFT_ON;
private boolean pubkeysExhausted = false;
@@ -183,6 +193,138 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
protected ConnectionInfo connectionInfo;
+ /**
+ * @author kenny
+ *
+ */
+ private final class Relay implements Runnable {
+ public void run() {
+ final String encoding = host.getEncoding();
+
+ byte[] b = new byte[BUFFER_SIZE];
+
+ Charset charset = Charset.forName(encoding);
+
+ /* Set up character set decoder to report any byte sequences
+ * which are malformed so we can try to resume decoding it
+ * on the next packet received.
+ *
+ * UTF-8 byte sequences have a tendency to get truncated at
+ * times.
+ */
+ CharsetDecoder cd = charset.newDecoder();
+ cd.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ cd.onMalformedInput(CodingErrorAction.REPORT);
+
+ CharsetDecoder replacer = charset.newDecoder();
+ replacer.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ replacer.onMalformedInput(CodingErrorAction.REPLACE);
+
+ ByteBuffer bb;
+ CharBuffer cb = CharBuffer.allocate(BUFFER_SIZE);
+
+ int n = 0;
+ int offset = 0;
+
+ int conditions = ChannelCondition.STDOUT_DATA
+ | ChannelCondition.STDERR_DATA
+ | ChannelCondition.CLOSED
+ | ChannelCondition.EOF;
+ int newConditions = 0;
+
+ while((newConditions & ChannelCondition.CLOSED) == 0) {
+ try {
+ newConditions = session.waitForCondition(conditions, 0);
+ if ((newConditions & ChannelCondition.STDOUT_DATA) != 0) {
+ while (stdout.available() > 0) {
+ n = offset + stdout.read(b, offset, BUFFER_SIZE - offset);
+
+ bb = ByteBuffer.wrap(b, 0, n);
+ CoderResult cr = cd.decode(bb, cb, true);
+
+ if (cr.isMalformed()) {
+ int curpos = bb.position() - cr.length();
+
+ if (curpos > 0) {
+ /* There is good data before the malformed section, so
+ * pass this on immediately.
+ */
+ ((vt320)buffer).putString(cb.array(), 0, cb.position());
+ }
+
+ while (bb.position() < n) {
+ bb = ByteBuffer.wrap(b, curpos, cr.length());
+
+ cb.clear();
+ replacer.decode(bb, cb, true);
+
+ ((vt320) buffer).putString(cb.array(), 0, cb.position());
+
+ curpos += cr.length();
+
+ bb = ByteBuffer.wrap(b, curpos, n - curpos);
+
+ cb.clear();
+ cr = cd.decode(bb, cb, true);
+ }
+
+ if (cr.isMalformed()) {
+ /* If we still have malformed input, save the bytes for the next
+ * read and try to parse it again.
+ */
+ offset = n - bb.position() + cr.length();
+ if ((bb.position() - cr.length()) < offset) {
+ byte tmp[] = new byte[offset];
+ System.arraycopy(b, bb.position() - cr.length(), tmp, 0, offset);
+ System.arraycopy(tmp, 0, b, 0, offset);
+ } else {
+ System.arraycopy(b, bb.position() - cr.length(), b, 0, offset);
+ }
+ Log.d(TAG, String.format("Copying out %d chars at %d: 0x%02x",
+ offset, bb.position() - cr.length(),
+ b[bb.position() - cr.length()]
+ ));
+ } else {
+ // After discarding the previous offset, we only have valid data.
+ ((vt320)buffer).putString(cb.array(), 0, cb.position());
+ offset = 0;
+ }
+ } else {
+ // No errors at all.
+ ((vt320)buffer).putString(cb.array(), 0, cb.position());
+ offset = 0;
+ }
+
+ cb.clear();
+ }
+ redraw();
+ }
+
+ if ((newConditions & ChannelCondition.STDERR_DATA) != 0) {
+ while (stderr.available() > 0) {
+ n = stderr.read(b);
+ bb = ByteBuffer.wrap(b, 0, n);
+ replacer.decode(bb, cb, false);
+ // TODO I don't know.. do we want this? We were ignoring it before
+ Log.d(TAG, String.format("Read data from stderr: %s", new String(cb.array(), 0, cb.position())));
+ cb.clear();
+ }
+ }
+
+ if ((newConditions & ChannelCondition.EOF) != 0) {
+ // The other side closed our channel, so let's disconnect.
+ // TODO review whether any tunnel is in use currently.
+ dispatchDisconnect(false);
+ break;
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Problem while handling incoming data in relay thread", e);
+ break;
+ }
+ }
+ }
+ }
+
public class HostKeyVerifier implements ServerHostKeyVerifier {
public boolean verifyServerHostKey(String hostname, int port, String serverHostKeyAlgorithm, byte[] serverHostKey) throws Exception {
@@ -302,7 +444,6 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
selectionArea = new SelectionArea();
- // TODO Change this when hosts are beans as well
portForwards = manager.hostdb.getPortForwardsForHost(host);
// prepare the ssh connection for opening
@@ -599,133 +740,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
stderr = session.getStderr();
// create thread to relay incoming connection data to buffer
- relay = new Thread(new Runnable() {
- public void run() {
- final String encoding = host.getEncoding();
-
- byte[] b = new byte[BUFFER_SIZE];
-
- Charset charset = Charset.forName(encoding);
-
- /* Set up character set decoder to report any byte sequences
- * which are malformed so we can try to resume decoding it
- * on the next packet received.
- *
- * UTF-8 byte sequences have a tendency to get truncated at
- * times.
- */
- CharsetDecoder cd = charset.newDecoder();
- cd.onUnmappableCharacter(CodingErrorAction.REPLACE);
- cd.onMalformedInput(CodingErrorAction.REPORT);
-
- CharsetDecoder replacer = charset.newDecoder();
- replacer.onUnmappableCharacter(CodingErrorAction.REPLACE);
- replacer.onMalformedInput(CodingErrorAction.REPLACE);
-
- ByteBuffer bb;
- CharBuffer cb = CharBuffer.allocate(BUFFER_SIZE);
-
- int n = 0;
- int offset = 0;
-
- int conditions = ChannelCondition.STDOUT_DATA
- | ChannelCondition.STDERR_DATA
- | ChannelCondition.CLOSED
- | ChannelCondition.EOF;
- int newConditions = 0;
-
- while((newConditions & ChannelCondition.CLOSED) == 0) {
- try {
- newConditions = session.waitForCondition(conditions, 0);
- if ((newConditions & ChannelCondition.STDOUT_DATA) != 0) {
- while (stdout.available() > 0) {
- n = offset + stdout.read(b, offset, BUFFER_SIZE - offset);
-
- bb = ByteBuffer.wrap(b, 0, n);
- CoderResult cr = cd.decode(bb, cb, true);
-
- if (cr.isMalformed()) {
- int curpos = bb.position() - cr.length();
-
- if (curpos > 0) {
- /* There is good data before the malformed section, so
- * pass this on immediately.
- */
- ((vt320)buffer).putString(cb.array(), 0, cb.position());
- }
-
- while (bb.position() < n) {
- bb = ByteBuffer.wrap(b, curpos, cr.length());
-
- cb.clear();
- replacer.decode(bb, cb, true);
-
- ((vt320) buffer).putString(cb.array(), 0, cb.position());
-
- curpos += cr.length();
-
- bb = ByteBuffer.wrap(b, curpos, n - curpos);
-
- cb.clear();
- cr = cd.decode(bb, cb, true);
- }
-
- if (cr.isMalformed()) {
- /* If we still have malformed input, save the bytes for the next
- * read and try to parse it again.
- */
- offset = n - bb.position() + cr.length();
- if ((bb.position() - cr.length()) < offset) {
- byte tmp[] = new byte[offset];
- System.arraycopy(b, bb.position() - cr.length(), tmp, 0, offset);
- System.arraycopy(tmp, 0, b, 0, offset);
- } else {
- System.arraycopy(b, bb.position() - cr.length(), b, 0, offset);
- }
- Log.d(TAG, String.format("Copying out %d chars at %d: 0x%02x",
- offset, bb.position() - cr.length(),
- b[bb.position() - cr.length()]
- ));
- } else {
- // After discarding the previous offset, we only have valid data.
- ((vt320)buffer).putString(cb.array(), 0, cb.position());
- offset = 0;
- }
- } else {
- // No errors at all.
- ((vt320)buffer).putString(cb.array(), 0, cb.position());
- offset = 0;
- }
-
- cb.clear();
- }
- redraw();
- }
-
- if ((newConditions & ChannelCondition.STDERR_DATA) != 0) {
- while (stderr.available() > 0) {
- n = stderr.read(b);
- bb = ByteBuffer.wrap(b, 0, n);
- replacer.decode(bb, cb, false);
- // TODO I don't know.. do we want this? We were ignoring it before
- Log.d(TAG, String.format("Read data from stderr: %s", new String(cb.array(), 0, cb.position())));
- cb.clear();
- }
- }
-
- if ((newConditions & ChannelCondition.EOF) != 0) {
- // The other side closed our channel, so let's disconnect.
- // TODO review whether any tunnel is in use currently.
- dispatchDisconnect(false);
- break;
- }
- } catch (IOException e) {
- Log.e(TAG, "Problem while handling incoming data in relay thread", e);
- break;
- }
- }
- }
- });
+ relay = new Thread(new Relay());
relay.start();
// force font-size to make sure we resizePTY as needed
@@ -819,18 +834,26 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
return false;
if ("Use right-side keys".equals(keymode)) {
- if (keyCode == KeyEvent.KEYCODE_ALT_RIGHT && slashKeyPressed) {
+ if (keyCode == KeyEvent.KEYCODE_ALT_RIGHT
+ && (metaState & META_SLASH) != 0) {
+ metaState &= metaState ^ META_SLASH ^ META_TRANSIENT;
stdin.write('/');
return true;
- } else if (keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT && tabKeyPressed) {
+ } else if (keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT
+ && (metaState & META_TAB) != 0) {
+ metaState &= metaState ^ META_TAB ^ META_TRANSIENT;
stdin.write(0x09);
return true;
}
} else if ("Use left-side keys".equals(keymode)) {
- if (keyCode == KeyEvent.KEYCODE_ALT_LEFT && slashKeyPressed) {
+ if (keyCode == KeyEvent.KEYCODE_ALT_LEFT
+ && (metaState & META_SLASH) != 0) {
+ metaState &= metaState ^ META_SLASH ^ META_TRANSIENT;
stdin.write('/');
return true;
- } else if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT && tabKeyPressed) {
+ } else if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
+ && (metaState & META_TAB) != 0) {
+ metaState &= metaState ^ META_TAB ^ META_TRANSIENT;
stdin.write(0x09);
return true;
}
@@ -840,7 +863,6 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
}
// check for terminal resizing keys
- // TODO: see if there is a way to make sure we dont "blip"
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
forcedSize = false;
setFontSize(fontSize + 2);
@@ -864,25 +886,25 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
// otherwise pass through to existing session
// print normal keys
if (printing) {
- int metaState = event.getMetaState();
+ int curMetaState = event.getMetaState();
- slashKeyPressed = tabKeyPressed = false;
+ metaState &= metaState ^ META_SLASH ^ META_TAB;
- if (shiftPressed) {
- metaState |= KeyEvent.META_SHIFT_ON;
- shiftPressed = false;
+ if ((metaState & META_SHIFT_MASK) != 0) {
+ curMetaState |= KeyEvent.META_SHIFT_ON;
+ metaState &= metaState ^ META_SHIFT_ON;
redraw();
}
- if (altPressed) {
- metaState |= KeyEvent.META_ALT_ON;
- altPressed = false;
+ if ((metaState & META_ALT_MASK) != 0) {
+ curMetaState |= KeyEvent.META_ALT_ON;
+ metaState &= metaState ^ META_ALT_ON;
redraw();
}
- int key = keymap.get(keyCode, metaState);
+ int key = keymap.get(keyCode, curMetaState);
- if (ctrlPressed) {
+ if ((metaState & META_CTRL_MASK) != 0) {
// Support CTRL-a through CTRL-z
if (key >= 0x61 && key <= 0x7A)
key -= 0x60;
@@ -891,13 +913,14 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
key -= 0x40;
else if (key == 0x20)
key = 0x00;
- ctrlPressed = false;
+
+ metaState &= metaState ^ META_CTRL_ON;
+
redraw();
}
// handle pressing f-keys
- if((event.getMetaState() & KeyEvent.META_SHIFT_ON) != 0) {
- //Log.d(TAG, "yay pressing an fkey");
+ if ((curMetaState & KeyEvent.META_SHIFT_ON) != 0) {
switch(key) {
case '!': ((vt320)buffer).keyPressed(vt320.KEY_F1, ' ', 0); return true;
case '@': ((vt320)buffer).keyPressed(vt320.KEY_F2, ' ', 0); return true;
@@ -920,35 +943,31 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
if("Use right-side keys".equals(keymode)) {
switch(keyCode) {
case KeyEvent.KEYCODE_ALT_RIGHT:
- slashKeyPressed = true;
+ metaState |= META_SLASH;
return true;
case KeyEvent.KEYCODE_SHIFT_RIGHT:
- tabKeyPressed = true;
+ metaState |= META_TAB;
return true;
case KeyEvent.KEYCODE_SHIFT_LEFT:
- shiftPressed = true;
- redraw();
+ metaPress(META_SHIFT_ON);
return true;
case KeyEvent.KEYCODE_ALT_LEFT:
- altPressed = true;
- redraw();
+ metaPress(META_ALT_ON);
return true;
}
} else if("Use left-side keys".equals(keymode)) {
switch(keyCode) {
case KeyEvent.KEYCODE_ALT_LEFT:
- slashKeyPressed = true;
+ metaState |= META_SLASH;
return true;
case KeyEvent.KEYCODE_SHIFT_LEFT:
- tabKeyPressed = true;
+ metaState |= META_TAB;
return true;
case KeyEvent.KEYCODE_SHIFT_RIGHT:
- shiftPressed = true;
- redraw();
+ metaPress(META_SHIFT_ON);
return true;
case KeyEvent.KEYCODE_ALT_RIGHT:
- altPressed = true;
- redraw();
+ metaPress(META_ALT_ON);
return true;
}
}
@@ -971,12 +990,18 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
}
- //((vt320)buffer).keyTyped('a', 'a', vt320.KEY_CONTROL);
- //((vt320)buffer).keyTyped(' ', ' ', 0);
break;
- case KeyEvent.KEYCODE_DEL: stdin.write(0x08); return true;
- case KeyEvent.KEYCODE_ENTER: ((vt320)buffer).keyTyped(vt320.KEY_ENTER, ' ', event.getMetaState()); return true;
+ case KeyEvent.KEYCODE_DEL:
+ ((vt320) buffer).keyPressed(vt320.KEY_BACK_SPACE, ' ',
+ getStateForBuffer());
+ metaState &= metaState ^ META_TRANSIENT;
+ return true;
+ case KeyEvent.KEYCODE_ENTER:
+ ((vt320)buffer).keyTyped(vt320.KEY_ENTER, ' ', getStateForBuffer());
+ metaState &= metaState ^ META_TRANSIENT;
+ return true;
+
case KeyEvent.KEYCODE_DPAD_LEFT:
if (selectingForCopy) {
if (selectionArea.isSelectingOrigin())
@@ -985,7 +1010,9 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
selectionArea.decrementRight();
redraw();
} else {
- ((vt320)buffer).keyPressed(vt320.KEY_LEFT, ' ', event.getMetaState());
+ ((vt320) buffer).keyPressed(vt320.KEY_LEFT, ' ',
+ getStateForBuffer());
+ metaState &= metaState ^ META_TRANSIENT;
tryKeyVibrate();
}
return true;
@@ -998,7 +1025,9 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
selectionArea.decrementBottom();
redraw();
} else {
- ((vt320)buffer).keyPressed(vt320.KEY_UP, ' ', event.getMetaState());
+ ((vt320) buffer).keyPressed(vt320.KEY_UP, ' ',
+ getStateForBuffer());
+ metaState &= metaState ^ META_TRANSIENT;
tryKeyVibrate();
}
return true;
@@ -1011,7 +1040,9 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
selectionArea.incrementBottom();
redraw();
} else {
- ((vt320)buffer).keyPressed(vt320.KEY_DOWN, ' ', event.getMetaState());
+ ((vt320) buffer).keyPressed(vt320.KEY_DOWN, ' ',
+ getStateForBuffer());
+ metaState &= metaState ^ META_TRANSIENT;
tryKeyVibrate();
}
return true;
@@ -1024,7 +1055,9 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
selectionArea.incrementRight();
redraw();
} else {
- ((vt320)buffer).keyPressed(vt320.KEY_RIGHT, ' ', event.getMetaState());
+ ((vt320) buffer).keyPressed(vt320.KEY_RIGHT, ' ',
+ getStateForBuffer());
+ metaState &= metaState ^ META_TRANSIENT;
tryKeyVibrate();
}
return true;
@@ -1039,19 +1072,20 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
String copiedText = selectionArea.copyFrom(buffer);
clipboard.setText(copiedText);
- parent.notifyUser(parent.getContext().getString(R.string.console_copy_done,
- copiedText.length()));
+ parent.notifyUser(parent.getContext().getString(
+ R.string.console_copy_done,
+ copiedText.length()));
selectingForCopy = false;
selectionArea.reset();
}
}
} else {
- if (ctrlPressed) {
+ if ((metaState & META_CTRL_ON) != 0) {
((vt320)buffer).keyTyped(vt320.KEY_ESCAPE, ' ', 0);
- ctrlPressed = false;
+ metaState &= metaState ^ META_CTRL_ON;
} else
- ctrlPressed = true;
+ metaState |= META_CTRL_ON;
}
redraw();
@@ -1076,14 +1110,41 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
return false;
}
+ /**
+ * Handle meta key presses where the key can be locked on.
+ * <p>
+ * 1st press: next key to have meta state<br />
+ * 2nd press: meta state is locked on<br />
+ * 3rd press: disable meta state
+ *
+ * @param code
+ */
+ private void metaPress(int code) {
+ if ((metaState & (code << 1)) != 0) {
+ metaState &= metaState ^ (code << 1);
+ } else if ((metaState & code) != 0) {
+ metaState &= metaState ^ code;
+ metaState |= code << 1;
+ } else
+ metaState |= code;
+ redraw();
+ }
+
public int getMetaState() {
- int state = 0;
+ return metaState;
+ }
+
+ private int getStateForBuffer() {
+ int bufferState = 0;
- if (ctrlPressed) state |= META_CTRL_ON;
- if (altPressed) state |= META_ALT_ON;
- if (shiftPressed) state |= META_SHIFT_ON;
+ if ((metaState & META_CTRL_MASK) != 0)
+ bufferState |= vt320.KEY_CONTROL;
+ if ((metaState & META_SHIFT_MASK) != 0)
+ bufferState |= vt320.KEY_SHIFT;
+ if ((metaState & META_ALT_MASK) != 0)
+ bufferState |= vt320.KEY_ALT;
- return state;
+ return bufferState;
}
public void setSelectingForCopy(boolean selectingForCopy) {