mirror of https://github.com/adamdruppe/arsd.git
tons of stuff
This commit is contained in:
parent
c5cec0c805
commit
7873768fd1
21
minigui.d
21
minigui.d
|
@ -4359,9 +4359,13 @@ class MainWindow : Window {
|
||||||
}
|
}
|
||||||
void setMenuAndToolbarFromAnnotatedCode_internal(T)(ref T t) {
|
void setMenuAndToolbarFromAnnotatedCode_internal(T)(ref T t) {
|
||||||
Action[] toolbarActions;
|
Action[] toolbarActions;
|
||||||
auto menuBar = new MenuBar();
|
auto menuBar = this.menuBar is null ? new MenuBar() : this.menuBar;
|
||||||
Menu[string] mcs;
|
Menu[string] mcs;
|
||||||
|
|
||||||
|
foreach(menu; menuBar.subMenus) {
|
||||||
|
mcs[menu.label] = menu;
|
||||||
|
}
|
||||||
|
|
||||||
void delegate() triggering;
|
void delegate() triggering;
|
||||||
|
|
||||||
foreach(memberName; __traits(derivedMembers, T)) {
|
foreach(memberName; __traits(derivedMembers, T)) {
|
||||||
|
@ -4482,6 +4486,12 @@ class MainWindow : Window {
|
||||||
MenuBar menuBar() { return _menu; }
|
MenuBar menuBar() { return _menu; }
|
||||||
///
|
///
|
||||||
MenuBar menuBar(MenuBar m) {
|
MenuBar menuBar(MenuBar m) {
|
||||||
|
if(m is _menu) {
|
||||||
|
version(custom_widgets)
|
||||||
|
recomputeChildLayout();
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
if(_menu !is null) {
|
if(_menu !is null) {
|
||||||
// make sure it is sanely removed
|
// make sure it is sanely removed
|
||||||
// FIXME
|
// FIXME
|
||||||
|
@ -4758,6 +4768,7 @@ class ToolButton : Button {
|
||||||
///
|
///
|
||||||
class MenuBar : Widget {
|
class MenuBar : Widget {
|
||||||
MenuItem[] items;
|
MenuItem[] items;
|
||||||
|
Menu[] subMenus;
|
||||||
|
|
||||||
version(win32_widgets) {
|
version(win32_widgets) {
|
||||||
HMENU handle;
|
HMENU handle;
|
||||||
|
@ -4796,7 +4807,10 @@ class MenuBar : Widget {
|
||||||
|
|
||||||
///
|
///
|
||||||
Menu addItem(Menu item) {
|
Menu addItem(Menu item) {
|
||||||
auto mbItem = new MenuItem(item.label, this.parentWindow);
|
|
||||||
|
subMenus ~= item;
|
||||||
|
|
||||||
|
auto mbItem = new MenuItem(item.label, null);// this.parentWindow); // I'ma add the child down below so hopefully this isn't too insane
|
||||||
|
|
||||||
addChild(mbItem);
|
addChild(mbItem);
|
||||||
items ~= mbItem;
|
items ~= mbItem;
|
||||||
|
@ -5335,8 +5349,9 @@ class MenuItem : MouseActivatedWidget {
|
||||||
override int minHeight() { return Window.lineHeight + 4; }
|
override int minHeight() { return Window.lineHeight + 4; }
|
||||||
override int minWidth() { return Window.lineHeight * cast(int) label.length + 8; }
|
override int minWidth() { return Window.lineHeight * cast(int) label.length + 8; }
|
||||||
override int maxWidth() {
|
override int maxWidth() {
|
||||||
if(cast(MenuBar) parent)
|
if(cast(MenuBar) parent) {
|
||||||
return Window.lineHeight / 2 * cast(int) label.length + 8;
|
return Window.lineHeight / 2 * cast(int) label.length + 8;
|
||||||
|
}
|
||||||
return int.max;
|
return int.max;
|
||||||
}
|
}
|
||||||
///
|
///
|
||||||
|
|
255
terminal.d
255
terminal.d
|
@ -138,11 +138,36 @@ version(demos) unittest {
|
||||||
|
|
||||||
// FIXME: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686016%28v=vs.85%29.aspx
|
// FIXME: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686016%28v=vs.85%29.aspx
|
||||||
|
|
||||||
|
|
||||||
|
/++
|
||||||
|
A function the sigint handler will call (if overridden - which is the
|
||||||
|
case when [RealTimeConsoleInput] is active on Posix or if you compile with
|
||||||
|
`TerminalDirectToEmulator` version on any platform at this time) in addition
|
||||||
|
to the library's default handling, which is to set a flag for the event loop
|
||||||
|
to inform you.
|
||||||
|
|
||||||
|
Remember, this is called from a signal handler and/or from a separate thread,
|
||||||
|
so you are not allowed to do much with it and need care when setting TLS variables.
|
||||||
|
|
||||||
|
I suggest you only set a `__gshared bool` flag as many other operations will risk
|
||||||
|
undefined behavior.
|
||||||
|
|
||||||
|
$(WARNING
|
||||||
|
This function is never called on the default Windows console
|
||||||
|
configuration in the current implementation. You can use
|
||||||
|
`-version=TerminalDirectToEmulator` to guarantee it is called there
|
||||||
|
too by causing the library to pop up a gui window for your application.
|
||||||
|
)
|
||||||
|
|
||||||
|
History:
|
||||||
|
Added March 30, 2020. Included in release v7.1.0.
|
||||||
|
|
||||||
|
+/
|
||||||
|
__gshared void delegate() nothrow @nogc sigIntExtension;
|
||||||
|
|
||||||
|
|
||||||
version(TerminalDirectToEmulator) {
|
version(TerminalDirectToEmulator) {
|
||||||
__gshared bool windowSizeChanged = false;
|
version=WithEncapsulatedSignals;
|
||||||
__gshared bool interrupted = false; /// you might periodically check this in a long operation and abort if it is set. Remember it is volatile. It is also sent through the input event loop via RealTimeConsoleInput
|
|
||||||
__gshared bool hangedUp = false; /// similar to interrupted.
|
|
||||||
version=WithSignals;
|
|
||||||
} else version(Posix) {
|
} else version(Posix) {
|
||||||
enum SIGWINCH = 28;
|
enum SIGWINCH = 28;
|
||||||
__gshared bool windowSizeChanged = false;
|
__gshared bool windowSizeChanged = false;
|
||||||
|
@ -172,6 +197,9 @@ version(TerminalDirectToEmulator) {
|
||||||
send(SignalFired());
|
send(SignalFired());
|
||||||
catch(Exception) {}
|
catch(Exception) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(sigIntExtension)
|
||||||
|
sigIntExtension();
|
||||||
}
|
}
|
||||||
extern(C)
|
extern(C)
|
||||||
void hangupSignalHandler(int sigNumber) nothrow {
|
void hangupSignalHandler(int sigNumber) nothrow {
|
||||||
|
@ -183,7 +211,6 @@ version(TerminalDirectToEmulator) {
|
||||||
catch(Exception) {}
|
catch(Exception) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parts of this were taken from Robik's ConsoleD
|
// parts of this were taken from Robik's ConsoleD
|
||||||
|
@ -475,6 +502,12 @@ struct Terminal {
|
||||||
@disable this(this);
|
@disable this(this);
|
||||||
private ConsoleOutputType type;
|
private ConsoleOutputType type;
|
||||||
|
|
||||||
|
version(TerminalDirectToEmulator) {
|
||||||
|
private bool windowSizeChanged = false;
|
||||||
|
private bool interrupted = false; /// you might periodically check this in a long operation and abort if it is set. Remember it is volatile. It is also sent through the input event loop via RealTimeConsoleInput
|
||||||
|
private bool hangedUp = false; /// similar to interrupted.
|
||||||
|
}
|
||||||
|
|
||||||
private TerminalCursor currentCursor_;
|
private TerminalCursor currentCursor_;
|
||||||
version(Windows) private CONSOLE_CURSOR_INFO originalCursorInfo;
|
version(Windows) private CONSOLE_CURSOR_INFO originalCursorInfo;
|
||||||
|
|
||||||
|
@ -1029,6 +1062,20 @@ struct Terminal {
|
||||||
|
|
||||||
version(TerminalDirectToEmulator) {
|
version(TerminalDirectToEmulator) {
|
||||||
TerminalEmulatorWidget tew;
|
TerminalEmulatorWidget tew;
|
||||||
|
private __gshared Window mainWindow;
|
||||||
|
import core.thread;
|
||||||
|
version(Posix)
|
||||||
|
ThreadID threadId;
|
||||||
|
else version(Windows)
|
||||||
|
HANDLE threadId;
|
||||||
|
private __gshared Thread guiThread;
|
||||||
|
|
||||||
|
private static class NewTerminalEvent {
|
||||||
|
Terminal* t;
|
||||||
|
this(Terminal* t) {
|
||||||
|
this.t = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
version(TerminalDirectToEmulator)
|
version(TerminalDirectToEmulator)
|
||||||
|
@ -1043,17 +1090,39 @@ struct Terminal {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tcaps = uint.max; // all capabilities
|
tcaps = uint.max; // all capabilities
|
||||||
import core.thread;
|
import core.thread;
|
||||||
|
|
||||||
auto thread = new Thread( {
|
version(Posix)
|
||||||
auto window = new TerminalEmulatorWindow(&this);
|
threadId = Thread.getThis.id;
|
||||||
tew = window.tew;
|
else version(Windows)
|
||||||
window.loop();
|
threadId = GetCurrentThread();
|
||||||
});
|
|
||||||
|
if(guiThread is null) {
|
||||||
|
guiThread = new Thread( {
|
||||||
|
auto window = new TerminalEmulatorWindow(&this);
|
||||||
|
mainWindow = window;
|
||||||
|
mainWindow.win.addEventListener((NewTerminalEvent t) {
|
||||||
|
auto nw = new TerminalEmulatorWindow(t.t);
|
||||||
|
t.t.tew = nw.tew;
|
||||||
|
t.t = null;
|
||||||
|
nw.show();
|
||||||
|
});
|
||||||
|
tew = window.tew;
|
||||||
|
window.loop();
|
||||||
|
});
|
||||||
|
guiThread.start();
|
||||||
|
guiThread.priority = Thread.PRIORITY_MAX; // gui thread needs responsiveness
|
||||||
|
} else {
|
||||||
|
// FIXME: 64 bit builds on linux segfault with multiple terminals
|
||||||
|
// so that isn't really supported as of yet.
|
||||||
|
while(cast(shared) mainWindow is null) {
|
||||||
|
import core.thread;
|
||||||
|
Thread.sleep(5.msecs);
|
||||||
|
}
|
||||||
|
mainWindow.win.postEvent(new NewTerminalEvent(&this));
|
||||||
|
}
|
||||||
|
|
||||||
thread.start();
|
|
||||||
// need to wait until it is properly initialized
|
// need to wait until it is properly initialized
|
||||||
while(cast(shared) tew is null) {
|
while(cast(shared) tew is null) {
|
||||||
import core.thread;
|
import core.thread;
|
||||||
|
@ -1202,6 +1271,7 @@ struct Terminal {
|
||||||
version(TerminalDirectToEmulator) {
|
version(TerminalDirectToEmulator) {
|
||||||
writeln("\n\n<exited>");
|
writeln("\n\n<exited>");
|
||||||
setTitle(tew.terminalEmulator.currentTitle ~ " <exited>");
|
setTitle(tew.terminalEmulator.currentTitle ~ " <exited>");
|
||||||
|
tew.term = null;
|
||||||
} else
|
} else
|
||||||
if(terminalInFamily("xterm", "rxvt", "screen", "tmux")) {
|
if(terminalInFamily("xterm", "rxvt", "screen", "tmux")) {
|
||||||
writeStringRaw("\033[23;0t"); // restore window title from the stack
|
writeStringRaw("\033[23;0t"); // restore window title from the stack
|
||||||
|
@ -1229,7 +1299,6 @@ struct Terminal {
|
||||||
SetConsoleActiveScreenBuffer(stdo);
|
SetConsoleActiveScreenBuffer(stdo);
|
||||||
if(hConsole !is stdo)
|
if(hConsole !is stdo)
|
||||||
CloseHandle(hConsole);
|
CloseHandle(hConsole);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2250,6 +2319,9 @@ struct RealTimeConsoleInput {
|
||||||
bool timedCheckForInput(int milliseconds) {
|
bool timedCheckForInput(int milliseconds) {
|
||||||
if(inputQueue.length || timedCheckForInput_bypassingBuffer(milliseconds))
|
if(inputQueue.length || timedCheckForInput_bypassingBuffer(milliseconds))
|
||||||
return true;
|
return true;
|
||||||
|
version(WithEncapsulatedSignals)
|
||||||
|
if(terminal.interrupted || terminal.windowSizeChanged || terminal.hangedUp)
|
||||||
|
return true;
|
||||||
version(WithSignals)
|
version(WithSignals)
|
||||||
if(interrupted || windowSizeChanged || hangedUp)
|
if(interrupted || windowSizeChanged || hangedUp)
|
||||||
return true;
|
return true;
|
||||||
|
@ -2269,7 +2341,7 @@ struct RealTimeConsoleInput {
|
||||||
// it was notified, but it could be left over from stuff we
|
// it was notified, but it could be left over from stuff we
|
||||||
// already processed... so gonna check the blocking conditions here too
|
// already processed... so gonna check the blocking conditions here too
|
||||||
// (FIXME: this sucks and is surely a race condition of pain)
|
// (FIXME: this sucks and is surely a race condition of pain)
|
||||||
return terminal.tew.terminalEmulator.pendingForApplication.length || interrupted || windowSizeChanged || hangedUp;
|
return terminal.tew.terminalEmulator.pendingForApplication.length || terminal.interrupted || terminal.windowSizeChanged || terminal.hangedUp;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
} else version(Win32Console) {
|
} else version(Win32Console) {
|
||||||
|
@ -2432,7 +2504,9 @@ struct RealTimeConsoleInput {
|
||||||
auto oldHeight = terminal.height;
|
auto oldHeight = terminal.height;
|
||||||
terminal.updateSize();
|
terminal.updateSize();
|
||||||
version(WithSignals)
|
version(WithSignals)
|
||||||
windowSizeChanged = false;
|
windowSizeChanged = false;
|
||||||
|
version(WithEncapsulatedSignals)
|
||||||
|
terminal.windowSizeChanged = false;
|
||||||
return InputEvent(SizeChangedEvent(oldWidth, oldHeight, terminal.width, terminal.height), terminal);
|
return InputEvent(SizeChangedEvent(oldWidth, oldHeight, terminal.width, terminal.height), terminal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2452,21 +2526,36 @@ struct RealTimeConsoleInput {
|
||||||
terminal.flush();
|
terminal.flush();
|
||||||
|
|
||||||
wait_for_more:
|
wait_for_more:
|
||||||
version(WithSignals)
|
version(WithSignals) {
|
||||||
if(interrupted) {
|
if(interrupted) {
|
||||||
interrupted = false;
|
interrupted = false;
|
||||||
return InputEvent(UserInterruptionEvent(), terminal);
|
return InputEvent(UserInterruptionEvent(), terminal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hangedUp) {
|
||||||
|
hangedUp = false;
|
||||||
|
return InputEvent(HangupEvent(), terminal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(windowSizeChanged) {
|
||||||
|
return checkWindowSizeChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
version(WithSignals)
|
version(WithEncapsulatedSignals) {
|
||||||
if(hangedUp) {
|
if(terminal.interrupted) {
|
||||||
hangedUp = false;
|
terminal.interrupted = false;
|
||||||
return InputEvent(HangupEvent(), terminal);
|
return InputEvent(UserInterruptionEvent(), terminal);
|
||||||
}
|
}
|
||||||
|
|
||||||
version(WithSignals)
|
if(terminal.hangedUp) {
|
||||||
if(windowSizeChanged) {
|
terminal.hangedUp = false;
|
||||||
return checkWindowSizeChanged();
|
return InputEvent(HangupEvent(), terminal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(terminal.windowSizeChanged) {
|
||||||
|
return checkWindowSizeChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(inputQueue.length) {
|
if(inputQueue.length) {
|
||||||
|
@ -5707,6 +5796,8 @@ version(TerminalDirectToEmulator) {
|
||||||
|
|
||||||
Test for its presence before using with `static if(arsd.terminal.IntegratedEmulator)`.
|
Test for its presence before using with `static if(arsd.terminal.IntegratedEmulator)`.
|
||||||
|
|
||||||
|
All settings here must be set BEFORE you construct any [Terminal] instances.
|
||||||
|
|
||||||
History:
|
History:
|
||||||
Added March 7, 2020.
|
Added March 7, 2020.
|
||||||
+/
|
+/
|
||||||
|
@ -5735,6 +5826,37 @@ version(TerminalDirectToEmulator) {
|
||||||
int initialWidth = 80;
|
int initialWidth = 80;
|
||||||
/// ditto
|
/// ditto
|
||||||
int initialHeight = 40;
|
int initialHeight = 40;
|
||||||
|
|
||||||
|
/++
|
||||||
|
Gives you a chance to modify the window as it is constructed. Intended
|
||||||
|
to let you add custom menu options.
|
||||||
|
|
||||||
|
---
|
||||||
|
import arsd.terminal;
|
||||||
|
integratedTerminalEmulatorConfiguration.menuExtensionsConstructor = (TerminalEmulatorWindow window) {
|
||||||
|
import arsd.minigui; // for the menu related UDAs
|
||||||
|
class Commands {
|
||||||
|
@menu("Help") {
|
||||||
|
void Topics() {
|
||||||
|
auto window = new Window(); // make a help window of some sort
|
||||||
|
window.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
@separator
|
||||||
|
|
||||||
|
void About() {
|
||||||
|
messageBox("My Application v 1.0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.setMenuAndToolbarFromAnnotatedCode(new Commands());
|
||||||
|
};
|
||||||
|
---
|
||||||
|
|
||||||
|
History:
|
||||||
|
Added March 29, 2020. Included in release v7.1.0.
|
||||||
|
+/
|
||||||
|
void delegate(TerminalEmulatorWindow) menuExtensionsConstructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/+
|
/+
|
||||||
|
@ -5748,9 +5870,19 @@ version(TerminalDirectToEmulator) {
|
||||||
import arsd.terminalemulator;
|
import arsd.terminalemulator;
|
||||||
import arsd.minigui;
|
import arsd.minigui;
|
||||||
|
|
||||||
private class TerminalEmulatorWindow : MainWindow {
|
/++
|
||||||
|
Represents the window that the library pops up for you.
|
||||||
|
+/
|
||||||
|
final class TerminalEmulatorWindow : MainWindow {
|
||||||
|
|
||||||
this(Terminal* term) {
|
/++
|
||||||
|
Gives access to the underlying terminal emulation object.
|
||||||
|
+/
|
||||||
|
TerminalEmulator terminalEmulator() {
|
||||||
|
return tew.terminalEmulator;
|
||||||
|
}
|
||||||
|
|
||||||
|
private this(Terminal* term) {
|
||||||
super("Terminal Application", integratedTerminalEmulatorConfiguration.initialWidth * integratedTerminalEmulatorConfiguration.fontSize / 2, integratedTerminalEmulatorConfiguration.initialHeight * integratedTerminalEmulatorConfiguration.fontSize);
|
super("Terminal Application", integratedTerminalEmulatorConfiguration.initialWidth * integratedTerminalEmulatorConfiguration.fontSize / 2, integratedTerminalEmulatorConfiguration.initialHeight * integratedTerminalEmulatorConfiguration.fontSize);
|
||||||
|
|
||||||
smw = new ScrollMessageWidget(this);
|
smw = new ScrollMessageWidget(this);
|
||||||
|
@ -5765,10 +5897,12 @@ version(TerminalDirectToEmulator) {
|
||||||
smw.setTotalArea(1, 1);
|
smw.setTotalArea(1, 1);
|
||||||
|
|
||||||
setMenuAndToolbarFromAnnotatedCode(this);
|
setMenuAndToolbarFromAnnotatedCode(this);
|
||||||
|
if(integratedTerminalEmulatorConfiguration.menuExtensionsConstructor)
|
||||||
|
integratedTerminalEmulatorConfiguration.menuExtensionsConstructor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
TerminalEmulatorWidget tew;
|
private TerminalEmulatorWidget tew;
|
||||||
ScrollMessageWidget smw;
|
private ScrollMessageWidget smw;
|
||||||
|
|
||||||
@menu("&History") {
|
@menu("&History") {
|
||||||
@tip("Saves the currently visible content to a file")
|
@tip("Saves the currently visible content to a file")
|
||||||
|
@ -5838,12 +5972,10 @@ version(TerminalDirectToEmulator) {
|
||||||
@menu("&Edit") {
|
@menu("&Edit") {
|
||||||
void Copy() {
|
void Copy() {
|
||||||
tew.terminalEmulator.copyToClipboard(tew.terminalEmulator.getSelectedText());
|
tew.terminalEmulator.copyToClipboard(tew.terminalEmulator.getSelectedText());
|
||||||
//messageBox("copy", tew.terminalEmulator.getSelectedText());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Paste() {
|
void Paste() {
|
||||||
tew.terminalEmulator.pasteFromClipboard(&tew.terminalEmulator.sendPasteData);
|
tew.terminalEmulator.pasteFromClipboard(&tew.terminalEmulator.sendPasteData);
|
||||||
//messageBox("paste", "idk");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5862,15 +5994,15 @@ version(TerminalDirectToEmulator) {
|
||||||
override Menu contextMenu(int x, int y) {
|
override Menu contextMenu(int x, int y) {
|
||||||
if(ctx is null) {
|
if(ctx is null) {
|
||||||
ctx = new Menu("");
|
ctx = new Menu("");
|
||||||
auto i = ctx.addItem(new MenuItem("Copy"));
|
ctx.addItem(new MenuItem(new Action("Copy", 0, {
|
||||||
i.addEventListener("triggered", {
|
|
||||||
terminalEmulator.copyToClipboard(terminalEmulator.getSelectedText());
|
terminalEmulator.copyToClipboard(terminalEmulator.getSelectedText());
|
||||||
|
})));
|
||||||
});
|
ctx.addItem(new MenuItem(new Action("Paste", 0, {
|
||||||
i = ctx.addItem(new MenuItem("Paste"));
|
|
||||||
i.addEventListener("triggered", {
|
|
||||||
terminalEmulator.pasteFromClipboard(&terminalEmulator.sendPasteData);
|
terminalEmulator.pasteFromClipboard(&terminalEmulator.sendPasteData);
|
||||||
});
|
})));
|
||||||
|
ctx.addItem(new MenuItem(new Action("Toggle Scroll Lock", 0, {
|
||||||
|
terminalEmulator.toggleScrollLock();
|
||||||
|
})));
|
||||||
}
|
}
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
@ -5882,7 +6014,12 @@ version(TerminalDirectToEmulator) {
|
||||||
super(parent);
|
super(parent);
|
||||||
this.parentWindow.win.onClosing = {
|
this.parentWindow.win.onClosing = {
|
||||||
if(term)
|
if(term)
|
||||||
hangedUp = true;
|
term.hangedUp = true;
|
||||||
|
|
||||||
|
// try to get it to terminate slightly more forcibly too, if possible
|
||||||
|
if(sigIntExtension)
|
||||||
|
sigIntExtension();
|
||||||
|
|
||||||
terminalEmulator.outgoingSignal.notify();
|
terminalEmulator.outgoingSignal.notify();
|
||||||
terminalEmulator.incomingSignal.notify();
|
terminalEmulator.incomingSignal.notify();
|
||||||
};
|
};
|
||||||
|
@ -5947,7 +6084,7 @@ version(TerminalDirectToEmulator) {
|
||||||
}
|
}
|
||||||
clearScreenRequested = true;
|
clearScreenRequested = true;
|
||||||
if(widget && widget.term)
|
if(widget && widget.term)
|
||||||
windowSizeChanged = true;
|
widget.term.windowSizeChanged = true;
|
||||||
outgoingSignal.notify();
|
outgoingSignal.notify();
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
|
@ -6036,6 +6173,8 @@ version(TerminalDirectToEmulator) {
|
||||||
|
|
||||||
override void sendRawInput(in ubyte[] data) {
|
override void sendRawInput(in ubyte[] data) {
|
||||||
void send(in ubyte[] data) {
|
void send(in ubyte[] data) {
|
||||||
|
if(data.length == 0)
|
||||||
|
return;
|
||||||
super.sendRawInput(data);
|
super.sendRawInput(data);
|
||||||
if(echo)
|
if(echo)
|
||||||
sendToApplication(data);
|
sendToApplication(data);
|
||||||
|
@ -6049,9 +6188,6 @@ version(TerminalDirectToEmulator) {
|
||||||
send(data[last .. idx]);
|
send(data[last .. idx]);
|
||||||
send(crlf[]);
|
send(crlf[]);
|
||||||
last = idx + 1;
|
last = idx + 1;
|
||||||
} else if(ch == 3) {
|
|
||||||
if(widget && widget.term)
|
|
||||||
interrupted = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6192,9 +6328,34 @@ version(TerminalDirectToEmulator) {
|
||||||
if(c == '\n') c = '\r'; // terminal seem to expect enter to send 13 instead of 10
|
if(c == '\n') c = '\r'; // terminal seem to expect enter to send 13 instead of 10
|
||||||
auto data = str[0 .. encode(str, c)];
|
auto data = str[0 .. encode(str, c)];
|
||||||
|
|
||||||
// on X11, the delete key can send a 127 character too, but that shouldn't be sent to the terminal since xterm shoots \033[3~ instead, which we handle in the KeyEvent handler.
|
|
||||||
if(c != 127)
|
if(c == 0x1c) /* ctrl+\, force quit */ {
|
||||||
|
version(Posix) {
|
||||||
|
import core.sys.posix.signal;
|
||||||
|
pthread_kill(widget.term.threadId, SIGQUIT); // or SIGKILL even?
|
||||||
|
|
||||||
|
assert(0);
|
||||||
|
//import core.sys.posix.pthread;
|
||||||
|
//pthread_cancel(widget.term.threadId);
|
||||||
|
//widget.term = null;
|
||||||
|
} else version(Windows) {
|
||||||
|
import core.sys.windows.windows;
|
||||||
|
auto hnd = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, TRUE, GetCurrentProcessId());
|
||||||
|
TerminateProcess(hnd, -1);
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
} else if(c == 3) /* ctrl+c, interrupt */ {
|
||||||
|
if(sigIntExtension)
|
||||||
|
sigIntExtension();
|
||||||
|
|
||||||
|
if(widget && widget.term) {
|
||||||
|
widget.term.interrupted = true;
|
||||||
|
outgoingSignal.notify();
|
||||||
|
}
|
||||||
|
} else if(c != 127) {
|
||||||
|
// on X11, the delete key can send a 127 character too, but that shouldn't be sent to the terminal since xterm shoots \033[3~ instead, which we handle in the KeyEvent handler.
|
||||||
sendToApplication(data);
|
sendToApplication(data);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue