*/
private ArrayList<String> params;
- /**
- * params[paramI] is being appended to.
- */
- private int paramI;
-
/**
* States in the input parser.
*/
*/
private long escapeTime;
+ /**
+ * The time we last checked the window size. We try not to spawn stty
+ * more than once per second.
+ */
+ private long windowSizeTime;
+
/**
* true if mouse1 was down. Used to report mouse1 on the release event.
*/
*/
private PrintWriter output;
+ /**
+ * The listening object that run() wakes up on new input.
+ */
+ private Object listener;
+
/**
* When true, the terminal is sending non-UTF8 bytes when reporting mouse
* events.
/**
* Constructor sets up state for getEvent().
*
+ * @param listener the object this backend needs to wake up when new
+ * input comes in
* @param input an InputStream connected to the remote user, or null for
* System.in. If System.in is used, then on non-Windows systems it will
* be put in raw mode; shutdown() will (blindly!) put System.in in cooked
* @throws UnsupportedEncodingException if an exception is thrown when
* creating the InputStreamReader
*/
- public ECMA48Terminal(final InputStream input,
+ public ECMA48Terminal(final Object listener, final InputStream input,
final OutputStream output) throws UnsupportedEncodingException {
reset();
mouse2 = false;
mouse3 = false;
stopReaderThread = false;
+ this.listener = listener;
if (input == null) {
// inputStream = System.in;
private void reset() {
state = ParseState.GROUND;
params = new ArrayList<String>();
- paramI = 0;
params.clear();
params.add("");
}
*
* @param queue list to append new events to
*/
- public void getIdleEvents(final List<TInputEvent> queue) {
+ private void getIdleEvents(final List<TInputEvent> queue) {
+ Date now = new Date();
// Check for new window size
- sessionInfo.queryWindowSize();
- int newWidth = sessionInfo.getWindowWidth();
- int newHeight = sessionInfo.getWindowHeight();
- if ((newWidth != windowResize.getWidth())
- || (newHeight != windowResize.getHeight())
- ) {
- TResizeEvent event = new TResizeEvent(TResizeEvent.Type.SCREEN,
- newWidth, newHeight);
- windowResize = new TResizeEvent(TResizeEvent.Type.SCREEN,
- newWidth, newHeight);
- synchronized (eventQueue) {
- eventQueue.add(event);
+ long windowSizeDelay = now.getTime() - windowSizeTime;
+ if (windowSizeDelay > 1000) {
+ sessionInfo.queryWindowSize();
+ int newWidth = sessionInfo.getWindowWidth();
+ int newHeight = sessionInfo.getWindowHeight();
+ if ((newWidth != windowResize.getWidth())
+ || (newHeight != windowResize.getHeight())
+ ) {
+ TResizeEvent event = new TResizeEvent(TResizeEvent.Type.SCREEN,
+ newWidth, newHeight);
+ windowResize = new TResizeEvent(TResizeEvent.Type.SCREEN,
+ newWidth, newHeight);
+ queue.add(event);
}
+ windowSizeTime = now.getTime();
}
- synchronized (eventQueue) {
- if (eventQueue.size() > 0) {
- synchronized (queue) {
- queue.addAll(eventQueue);
- }
- eventQueue.clear();
+ // ESCDELAY type timeout
+ if (state == ParseState.ESCAPE) {
+ long escDelay = now.getTime() - escapeTime;
+ if (escDelay > 100) {
+ // After 0.1 seconds, assume a true escape character
+ queue.add(controlChar((char)0x1B, false));
+ reset();
}
}
}
case CSI_ENTRY:
// Numbers - parameter values
if ((ch >= '0') && (ch <= '9')) {
- params.set(paramI, params.get(paramI) + ch);
+ params.set(params.size() - 1,
+ params.get(params.size() - 1) + ch);
state = ParseState.CSI_PARAM;
return;
}
// Parameter separator
if (ch == ';') {
- paramI++;
- params.set(paramI, "");
+ params.add("");
return;
}
case CSI_PARAM:
// Numbers - parameter values
if ((ch >= '0') && (ch <= '9')) {
- params.set(paramI, params.get(paramI) + ch);
+ params.set(params.size() - 1,
+ params.get(params.size() - 1) + ch);
state = ParseState.CSI_PARAM;
return;
}
// Parameter separator
if (ch == ';') {
- paramI++;
- params.set(paramI, "");
+ params.add("");
return;
}
return;
case MOUSE:
- params.set(0, params.get(paramI) + ch);
+ params.set(0, params.get(params.size() - 1) + ch);
if (params.get(0).length() == 3) {
// We have enough to generate a mouse event
events.add(parseMouse());
synchronized (eventQueue) {
eventQueue.addAll(events);
}
- // Now wake up the backend
- synchronized (this) {
- this.notifyAll();
+ synchronized (listener) {
+ listener.notifyAll();
}
events.clear();
}
}
}
} else {
+ getIdleEvents(events);
+ if (events.size() > 0) {
+ synchronized (eventQueue) {
+ eventQueue.addAll(events);
+ }
+ events.clear();
+ synchronized (listener) {
+ listener.notifyAll();
+ }
+ }
+
// Wait 10 millis for more data
Thread.sleep(10);
}