Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix restoration of Terminal at close, fixes #819 #830

Merged
merged 1 commit into from
Mar 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,15 @@ private String computeGroupPost(List<Candidate> c, boolean autoGroup, boolean gr
public void testConEmuLineReaderClearScreen() throws IOException {
System.setProperty("org.jline.terminal.conemu.disable-activate", "false");
StringWriter sw = new StringWriter();
AbstractWindowsTerminal terminal = new AbstractWindowsTerminal(new BufferedWriter(sw), "name", TYPE_WINDOWS_CONEMU, Charset.defaultCharset(),
false, Terminal.SignalHandler.SIG_DFL) {
AbstractWindowsTerminal<?> terminal = new AbstractWindowsTerminal<Object>(new BufferedWriter(sw), "name", TYPE_WINDOWS_CONEMU, Charset.defaultCharset(),
false, Terminal.SignalHandler.SIG_DFL, null, null) {
@Override
protected int getConsoleMode() {
protected int getConsoleMode(Object console) {
return 0;
}

@Override
protected void setConsoleMode(int mode) {
protected void setConsoleMode(Object console, int mode) {
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,21 +78,21 @@ private void process(TestTerminal terminal, int c) {
}
}

private static class TestTerminal extends AbstractWindowsTerminal {
private static class TestTerminal extends AbstractWindowsTerminal<Object> {
public TestTerminal(StringWriter sw) throws IOException {
super(new AnsiWriter(new BufferedWriter(sw)), "name",
AbstractWindowsTerminal.TYPE_DUMB,
Charset.defaultCharset(),
false, SignalHandler.SIG_DFL);
false, SignalHandler.SIG_DFL, null, null);
}

@Override
protected int getConsoleMode() {
protected int getConsoleMode(Object console) {
return 0;
}

@Override
protected void setConsoleMode(int mode) {
protected void setConsoleMode(Object console, int mode) {
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
import static org.fusesource.jansi.internal.Kernel32.WaitForSingleObject;
import static org.fusesource.jansi.internal.Kernel32.readConsoleInputHelper;

public class JansiWinSysTerminal extends AbstractWindowsTerminal {
public class JansiWinSysTerminal extends AbstractWindowsTerminal<Long> {

private static final long consoleIn = GetStdHandle(STD_INPUT_HANDLE);
private static final long consoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
Expand Down Expand Up @@ -115,18 +115,13 @@ public static boolean isWindowsSystemStream(TerminalProvider.Stream stream) {
return Kernel32.GetConsoleMode(console, mode) != 0;
}

private long console;
private long outputHandle;

JansiWinSysTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler,
long console, long outputHandle) throws IOException {
super(writer, name, type, encoding, nativeSignals, signalHandler);
this.console = console;
this.outputHandle = outputHandle;
long inConsole, long outConsole) throws IOException {
super(writer, name, type, encoding, nativeSignals, signalHandler, inConsole, outConsole);
}

@Override
protected int getConsoleMode() {
protected int getConsoleMode(Long console) {
int[] mode = new int[1];
if (Kernel32.GetConsoleMode(console, mode) == 0) {
return -1;
Expand All @@ -135,28 +130,28 @@ protected int getConsoleMode() {
}

@Override
protected void setConsoleMode(int mode) {
protected void setConsoleMode(Long console, int mode) {
Kernel32.SetConsoleMode(console, mode);
}

public Size getSize() {
CONSOLE_SCREEN_BUFFER_INFO info = new CONSOLE_SCREEN_BUFFER_INFO();
Kernel32.GetConsoleScreenBufferInfo(outputHandle, info);
Kernel32.GetConsoleScreenBufferInfo(outConsole, info);
return new Size(info.windowWidth(), info.windowHeight());
}

@Override
public Size getBufferSize() {
CONSOLE_SCREEN_BUFFER_INFO info = new CONSOLE_SCREEN_BUFFER_INFO();
Kernel32.GetConsoleScreenBufferInfo(outputHandle, info);
Kernel32.GetConsoleScreenBufferInfo(outConsole, info);
return new Size(info.size.x, info.size.y);
}

protected boolean processConsoleInput() throws IOException {
INPUT_RECORD[] events;
if (console != INVALID_HANDLE_VALUE
&& WaitForSingleObject(console, 100) == 0) {
events = readConsoleInputHelper(console, 1, false);
if (inConsole != INVALID_HANDLE_VALUE
&& WaitForSingleObject(inConsole, 100) == 0) {
events = readConsoleInputHelper(inConsole, 1, false);
} else {
return false;
}
Expand Down Expand Up @@ -228,7 +223,7 @@ private void processMouseEvent(Kernel32.MOUSE_EVENT_RECORD mouseEvent) throws IO
@Override
public Cursor getCursorPosition(IntConsumer discarded) {
CONSOLE_SCREEN_BUFFER_INFO info = new CONSOLE_SCREEN_BUFFER_INFO();
if (GetConsoleScreenBufferInfo(outputHandle, info) == 0) {
if (GetConsoleScreenBufferInfo(outConsole, info) == 0) {
throw new IOError(new IOException("Could not get the cursor position: " + getLastErrorMessage()));
}
return new Cursor(info.cursorPosition.x, info.cursorPosition.y);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
import org.jline.terminal.Size;
import org.jline.terminal.impl.AbstractWindowsTerminal;
import org.jline.terminal.spi.TerminalProvider;
import org.jline.utils.InfoCmp;
import org.jline.utils.InfoCmp.Capability;
import org.jline.utils.OSUtils;

public class JnaWinSysTerminal extends AbstractWindowsTerminal {
public class JnaWinSysTerminal extends AbstractWindowsTerminal<Pointer> {

private static final Pointer consoleIn = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_INPUT_HANDLE);
private static final Pointer consoleOut = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_OUTPUT_HANDLE);
Expand Down Expand Up @@ -71,7 +71,7 @@ public static JnaWinSysTerminal createTerminal(String name, String type, boolean
}
}
}
JnaWinSysTerminal terminal = new JnaWinSysTerminal(writer, name, type, encoding, nativeSignals, signalHandler);
JnaWinSysTerminal terminal = new JnaWinSysTerminal(writer, name, type, encoding, nativeSignals, signalHandler, JnaWinSysTerminal.consoleIn, console);
// Start input pump thread
if (!paused) {
terminal.resume();
Expand All @@ -96,26 +96,27 @@ public static boolean isWindowsSystemStream(TerminalProvider.Stream stream) {
}
}

JnaWinSysTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler) throws IOException {
super(writer, name, type, encoding, nativeSignals, signalHandler);
strings.put(InfoCmp.Capability.key_mouse, "\\E[M");
JnaWinSysTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler,
Pointer inConsole, Pointer outConsole) throws IOException {
super(writer, name, type, encoding, nativeSignals, signalHandler, inConsole, outConsole);
this.strings.put(Capability.key_mouse, "\\E[M");
}

@Override
protected int getConsoleMode() {
protected int getConsoleMode(Pointer console) {
IntByReference mode = new IntByReference();
Kernel32.INSTANCE.GetConsoleMode(consoleIn, mode);
Kernel32.INSTANCE.GetConsoleMode(console, mode);
return mode.getValue();
}

@Override
protected void setConsoleMode(int mode) {
Kernel32.INSTANCE.SetConsoleMode(consoleIn, mode);
protected void setConsoleMode(Pointer console, int mode) {
Kernel32.INSTANCE.SetConsoleMode(console, mode);
}

public Size getSize() {
Kernel32.CONSOLE_SCREEN_BUFFER_INFO info = new Kernel32.CONSOLE_SCREEN_BUFFER_INFO();
Kernel32.INSTANCE.GetConsoleScreenBufferInfo(consoleOut, info);
Kernel32.INSTANCE.GetConsoleScreenBufferInfo(outConsole, info);
return new Size(info.windowWidth(), info.windowHeight());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import java.io.PrintWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -43,7 +42,7 @@
* the writer() becomes the primary output, while the output() is bridged
* to the writer() using a WriterOutputStream wrapper.
*/
public abstract class AbstractWindowsTerminal extends AbstractTerminal {
public abstract class AbstractWindowsTerminal<Console> extends AbstractTerminal {

public static final String TYPE_WINDOWS = "windows";
public static final String TYPE_WINDOWS_256_COLOR = "windows-256color";
Expand All @@ -70,7 +69,10 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
protected final Map<Signal, Object> nativeHandlers = new HashMap<>();
protected final ShutdownHooks.Task closer;
protected final Attributes attributes = new Attributes();
protected final int originalConsoleMode;
protected final Console inConsole;
protected final Console outConsole;
protected final int originalInConsoleMode;
protected final int originalOutConsoleMode;

protected final Object lock = new Object();
protected boolean paused = true;
Expand All @@ -80,17 +82,21 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
protected boolean focusTracking = false;
private volatile boolean closing;

public AbstractWindowsTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler) throws IOException {
public AbstractWindowsTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler,
Console inConsole, Console outConsole) throws IOException {
super(name, type, encoding, signalHandler);
NonBlockingPumpReader reader = NonBlocking.nonBlockingPumpReader();
this.slaveInputPipe = reader.getWriter();
this.reader = reader;
this.input = NonBlocking.nonBlockingStream(reader, encoding());
this.writer = new PrintWriter(writer);
this.output = new WriterOutputStream(writer, encoding());
this.inConsole = inConsole;
this.outConsole = outConsole;
parseInfoCmp();
// Attributes
originalConsoleMode = getConsoleMode();
this.originalInConsoleMode = getConsoleMode(inConsole);
this.originalOutConsoleMode = getConsoleMode(outConsole);
attributes.setLocalFlag(Attributes.LocalFlag.ISIG, true);
attributes.setControlChar(Attributes.ControlChar.VINTR, ctrl('C'));
attributes.setControlChar(Attributes.ControlChar.VEOF, ctrl('D'));
Expand Down Expand Up @@ -147,7 +153,7 @@ public OutputStream output() {
}

public Attributes getAttributes() {
int mode = getConsoleMode();
int mode = getConsoleMode(inConsole);
if ((mode & ENABLE_ECHO_INPUT) != 0) {
attributes.setLocalFlag(Attributes.LocalFlag.ECHO, true);
}
Expand All @@ -173,7 +179,7 @@ protected void updateConsoleMode() {
if (tracking != MouseTracking.Off) {
mode |= ENABLE_MOUSE_INPUT;
}
setConsoleMode(mode);
setConsoleMode(inConsole, mode);
}

protected int ctrl(char key) {
Expand All @@ -196,7 +202,8 @@ protected void doClose() throws IOException {
}
reader.close();
writer.close();
setConsoleMode(originalConsoleMode);
setConsoleMode(inConsole, originalInConsoleMode);
setConsoleMode(outConsole, originalOutConsoleMode);
}

static final int SHIFT_FLAG = 0x01;
Expand Down Expand Up @@ -487,9 +494,9 @@ public boolean trackMouse(MouseTracking tracking) {
return true;
}

protected abstract int getConsoleMode();
protected abstract int getConsoleMode(Console console);

protected abstract void setConsoleMode(int mode);
protected abstract void setConsoleMode(Console console, int mode);

/**
* Read a single input event from the input buffer and process it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ public class AbstractWindowsTerminalTest {
public void testWriterBuffering() throws Exception {
System.setProperty("org.jline.terminal.conemu.disable-activate", "true");
StringWriter sw = new StringWriter();
Terminal terminal = new AbstractWindowsTerminal(new AnsiWriter(new BufferedWriter(sw)), "name", TYPE_WINDOWS, Charset.defaultCharset(),
false, Terminal.SignalHandler.SIG_DFL) {
Terminal terminal = new AbstractWindowsTerminal<Object>(new AnsiWriter(new BufferedWriter(sw)), "name", TYPE_WINDOWS, Charset.defaultCharset(),
false, Terminal.SignalHandler.SIG_DFL, null, null) {
@Override
protected int getConsoleMode() {
protected int getConsoleMode(Object console) {
return 0;
}
@Override
protected void setConsoleMode(int mode) {
protected void setConsoleMode(Object console, int mode) {
}
@Override
protected boolean processConsoleInput() throws IOException {
Expand Down