* Wake the sleeping active event handler.
*/
private void wakeEventHandler() {
+ if (!started) {
+ return;
+ }
+
if (secondaryEventHandler != null) {
synchronized (secondaryEventHandler) {
secondaryEventHandler.notify();
*/
private List<TTimer> timers;
+ /**
+ * When true, the application has been started.
+ */
+ private volatile boolean started = false;
+
/**
* When true, exit the application.
*/
primaryEventHandler = new WidgetEventHandler(this, true);
(new Thread(primaryEventHandler)).start();
+ started = true;
+
while (!quit) {
synchronized (this) {
boolean doWait = false;
}
}
+ /**
+ * Post an event to process.
+ *
+ * @param event new event to add to the queue
+ */
+ public final void postEvent(final TInputEvent event) {
+ synchronized (this) {
+ synchronized (fillEventQueue) {
+ fillEventQueue.add(event);
+ }
+ if (debugThreads) {
+ System.err.println(System.currentTimeMillis() + " " +
+ Thread.currentThread() + " postEvent() wake up main");
+ }
+ this.notify();
+ }
+ }
+
/**
* Post an event to process and turn off the menu.
*
import jexer.bits.Cell;
import jexer.bits.CellAttributes;
import jexer.event.TKeypressEvent;
+import jexer.event.TMenuEvent;
import jexer.event.TMouseEvent;
import jexer.event.TResizeEvent;
+import jexer.menu.TMenu;
import jexer.tterminal.DisplayLine;
import jexer.tterminal.DisplayListener;
import jexer.tterminal.ECMA48;
newStatusBar(i18n.getString("statusBarRunning"));
}
+ /**
+ * Public constructor spawns a custom command line.
+ *
+ * @param application TApplication that manages this window
+ * @param x column relative to parent
+ * @param y row relative to parent
+ * @param commandLine the command line to execute
+ */
+ public TTerminalWindow(final TApplication application, final int x,
+ final int y, final String commandLine) {
+
+ this(application, x, y, RESIZABLE, commandLine);
+ }
+
/**
* Public constructor spawns a custom command line.
*
* Called by emulator when fresh data has come in.
*/
public void displayChanged() {
- doRepaint();
+ getApplication().postEvent(new TMenuEvent(TMenu.MID_REPAINT));
}
/**
}
}
+ /**
+ * Hook for subclasses to be notified of the shell termination.
+ */
+ public void onShellExit() {
+ getApplication().postEvent(new TMenuEvent(TMenu.MID_REPAINT));
+ }
+
/**
* Copy out variables from the emulator that TTerminal has to expose on
* screen.
clearShortcutKeypresses();
statusBar.setText(MessageFormat.format(i18n.
getString("statusBarCompleted"), rc));
+ onShellExit();
} catch (IllegalThreadStateException e) {
// The emulator thread has exited, but the shell Process
// hasn't figured that out yet. Do nothing, we will see
clearShortcutKeypresses();
statusBar.setText(MessageFormat.format(i18n.
getString("statusBarCompleted"), rc));
+ onShellExit();
} catch (IllegalThreadStateException e) {
// The shell is still running, do nothing.
}
// This is EOF
done = true;
} else {
- for (int i = 0; i < rc; i++) {
- int ch = 0;
- if (utf8) {
- ch = readBufferUTF8[i];
- } else {
- ch = readBuffer[i];
- }
+ // Don't step on UI events
+ synchronized (this) {
+ for (int i = 0; i < rc; i++) {
+ int ch = 0;
+ if (utf8) {
+ ch = readBufferUTF8[i];
+ } else {
+ ch = readBuffer[i];
+ }
- synchronized (this) {
- // Don't step on UI events
consume((char)ch);
}
}
// SQUASH
}
+ // Permit my enclosing UI to know that I updated.
+ if (displayListener != null) {
+ displayListener.displayChanged();
+ }
+
// System.err.println("*** run() exiting..."); System.err.flush();
}