dynamic load of xlib

This commit is contained in:
Adam D. Ruppe 2020-06-30 18:02:03 -04:00
parent ae17d5a497
commit 0755efc96d
6 changed files with 831 additions and 555 deletions

View File

@ -42,14 +42,12 @@
"configurations": [
{
"name": "normal",
"libs-posix": ["X11", "Xext", "GL", "GLU"],
"libs-windows": ["gdi32", "opengl32", "glu32"]
"libs-windows": ["gdi32"]
},
{
"name": "without-opengl",
"versions": ["without_opengl"],
"libs-windows": ["gdi32"],
"libs-posix": ["X11", "Xext"]
"libs-windows": ["gdi32"]
},
{
"name": "cocoa",
@ -308,6 +306,7 @@
"name": "terminal",
"description": "Cross-platform Terminal I/O with color, mouse support, real time input, etc.",
"targetType": "library",
"libs-windows": ["user32"],
"sourceFiles": ["terminal.d"],
"importPaths": ["."],
"dflags": ["-mv=arsd.terminal=terminal.d"],

View File

@ -2706,7 +2706,7 @@ public nothrow @trusted @nogc:
/// Inverts this matrix.
/// If inverted matrix cannot be calculated, `this.valid` fill be `false`.
ref NVGMatrix invert () {
ref NVGMatrix invert () return {
float[6] inv = void;
immutable double det = cast(double)mat.ptr[0]*mat.ptr[3]-cast(double)mat.ptr[2]*mat.ptr[1];
if (det > -1e-6 && det < 1e-6) {
@ -2725,40 +2725,40 @@ public nothrow @trusted @nogc:
}
/// Sets this matrix to identity matrix.
ref NVGMatrix identity () { version(aliced) pragma(inline, true); mat[] = IdentityMat[]; return this; }
ref NVGMatrix identity () return { version(aliced) pragma(inline, true); mat[] = IdentityMat[]; return this; }
/// Translate this matrix.
ref NVGMatrix translate (in float tx, in float ty) {
ref NVGMatrix translate (in float tx, in float ty) return {
version(aliced) pragma(inline, true);
return this.mul(Translated(tx, ty));
}
/// Scale this matrix.
ref NVGMatrix scale (in float sx, in float sy) {
ref NVGMatrix scale (in float sx, in float sy) return {
version(aliced) pragma(inline, true);
return this.mul(Scaled(sx, sy));
}
/// Rotate this matrix.
ref NVGMatrix rotate (in float a) {
ref NVGMatrix rotate (in float a) return {
version(aliced) pragma(inline, true);
return this.mul(Rotated(a));
}
/// Skew this matrix by X axis.
ref NVGMatrix skewX (in float a) {
ref NVGMatrix skewX (in float a) return {
version(aliced) pragma(inline, true);
return this.mul(SkewedX(a));
}
/// Skew this matrix by Y axis.
ref NVGMatrix skewY (in float a) {
ref NVGMatrix skewY (in float a) return {
version(aliced) pragma(inline, true);
return this.mul(SkewedY(a));
}
/// Skew this matrix by both axes.
ref NVGMatrix skewY (in float ax, in float ay) {
ref NVGMatrix skewY (in float ax, in float ay) return {
version(aliced) pragma(inline, true);
return this.mul(SkewedXY(ax, ay));
}
@ -2826,15 +2826,15 @@ public nothrow @trusted @nogc:
float tx () const { pragma(inline, true); return mat.ptr[4]; } /// Returns x translation of this matrix.
float ty () const { pragma(inline, true); return mat.ptr[5]; } /// Returns y translation of this matrix.
ref NVGMatrix scaleX (in float v) { pragma(inline, true); return scaleRotateTransform(v, scaleY, rotation, tx, ty); } /// Sets x scaling of this matrix.
ref NVGMatrix scaleY (in float v) { pragma(inline, true); return scaleRotateTransform(scaleX, v, rotation, tx, ty); } /// Sets y scaling of this matrix.
ref NVGMatrix rotation (in float v) { pragma(inline, true); return scaleRotateTransform(scaleX, scaleY, v, tx, ty); } /// Sets rotation of this matrix.
ref NVGMatrix tx (in float v) { pragma(inline, true); mat.ptr[4] = v; return this; } /// Sets x translation of this matrix.
ref NVGMatrix ty (in float v) { pragma(inline, true); mat.ptr[5] = v; return this; } /// Sets y translation of this matrix.
ref NVGMatrix scaleX (in float v) return { pragma(inline, true); return scaleRotateTransform(v, scaleY, rotation, tx, ty); } /// Sets x scaling of this matrix.
ref NVGMatrix scaleY (in float v) return { pragma(inline, true); return scaleRotateTransform(scaleX, v, rotation, tx, ty); } /// Sets y scaling of this matrix.
ref NVGMatrix rotation (in float v) return { pragma(inline, true); return scaleRotateTransform(scaleX, scaleY, v, tx, ty); } /// Sets rotation of this matrix.
ref NVGMatrix tx (in float v) return { pragma(inline, true); mat.ptr[4] = v; return this; } /// Sets x translation of this matrix.
ref NVGMatrix ty (in float v) return { pragma(inline, true); mat.ptr[5] = v; return this; } /// Sets y translation of this matrix.
/// Utility function to be used in `setXXX()`.
/// This is the same as doing: `mat.identity.rotate(a).scale(xs, ys).translate(tx, ty)`, only faster
ref NVGMatrix scaleRotateTransform (in float xscale, in float yscale, in float a, in float tx, in float ty) {
ref NVGMatrix scaleRotateTransform (in float xscale, in float yscale, in float a, in float tx, in float ty) return {
immutable float cs = nvg__cosf(a), sn = nvg__sinf(a);
mat.ptr[0] = xscale*cs; mat.ptr[1] = yscale*sn;
mat.ptr[2] = xscale*-sn; mat.ptr[3] = yscale*cs;
@ -2843,7 +2843,7 @@ public nothrow @trusted @nogc:
}
/// This is the same as doing: `mat.identity.rotate(a).translate(tx, ty)`, only faster
ref NVGMatrix rotateTransform (in float a, in float tx, in float ty) {
ref NVGMatrix rotateTransform (in float a, in float tx, in float ty) return {
immutable float cs = nvg__cosf(a), sn = nvg__sinf(a);
mat.ptr[0] = cs; mat.ptr[1] = sn;
mat.ptr[2] = -sn; mat.ptr[3] = cs;

View File

@ -1,6 +1,8 @@
/*
FIXME: i kinda do want a catch type filter.
FIXME: i kinda do want a catch type filter e.g. catch(Exception f)
FIXME: I also kinda want implicit construction of structs at times.
REPL plan:
easy movement to/from a real editor

File diff suppressed because it is too large Load Diff

View File

@ -168,7 +168,9 @@ __gshared void delegate() nothrow @nogc sigIntExtension;
version(TerminalDirectToEmulator) {
version=WithEncapsulatedSignals;
} else version(Posix) {
}
version(Posix) {
enum SIGWINCH = 28;
__gshared bool windowSizeChanged = false;
__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
@ -236,6 +238,8 @@ version(Win32Console) {
enum GREEN_BIT = 2;
enum BLUE_BIT = 1;
}
pragma(lib, "user32");
}
version(Posix) {
@ -735,6 +739,7 @@ struct Terminal {
string[string] termcap;
void readTermcap(string t = null) {
version(TerminalDirectToEmulator)
if(usingDirectEmulator)
t = "xterm";
import std.process;
import std.string;
@ -1054,9 +1059,10 @@ struct Terminal {
bool hasDefaultDarkBackground() {
version(Win32Console) {
return !(defaultBackgroundColor & 0xf);
} else version(TerminalDirectToEmulator) {
return integratedTerminalEmulatorConfiguration.defaultBackground.g < 100;
} else {
version(TerminalDirectToEmulator)
if(usingDirectEmulator)
return integratedTerminalEmulatorConfiguration.defaultBackground.g < 100;
// FIXME: there is probably a better way to do this
// but like idk how reliable it is.
if(terminalInFamily("linux"))
@ -1082,6 +1088,8 @@ struct Terminal {
this.t = t;
}
}
bool usingDirectEmulator;
}
version(TerminalDirectToEmulator)
@ -1096,6 +1104,32 @@ struct Terminal {
return;
}
import arsd.simpledisplay;
static if(UsingSimpledisplayX11) {
try {
if(arsd.simpledisplay.librariesSuccessfullyLoaded) {
XDisplayConnection.get();
this.usingDirectEmulator = true;
} else if(!integratedTerminalEmulatorConfiguration.fallbackToDegradedTerminal) {
throw new Exception("Unable to load X libraries to create custom terminal.");
}
} catch(Exception e) {
if(!integratedTerminalEmulatorConfiguration.fallbackToDegradedTerminal)
throw e;
}
} else {
this.usingDirectEmulator = true;
}
if(!usingDirectEmulator) {
version(Posix)
posixInitialize(type, 0, 1, null);
else
throw new Exception("Total wtf - are you on a windows system without a gui?!?");
return;
}
tcaps = uint.max; // all capabilities
import core.thread;
@ -1159,6 +1193,11 @@ struct Terminal {
* ditto on getSizeOverride. That's there so you can do something instead of ioctl.
*/
this(ConsoleOutputType type, int fdIn = 0, int fdOut = 1, int[] delegate() getSizeOverride = null) {
posixInitialize(type, fdIn, fdOut, getSizeOverride);
}
version(Posix)
private void posixInitialize(ConsoleOutputType type, int fdIn = 0, int fdOut = 1, int[] delegate() getSizeOverride = null) {
this.fdIn = fdIn;
this.fdOut = fdOut;
this.getSizeOverride = getSizeOverride;
@ -1199,7 +1238,7 @@ struct Terminal {
return Terminal(ConsoleOutputType.cellular);
}
version(Win32Console) {
version(Windows) {
HANDLE hConsole;
CONSOLE_SCREEN_BUFFER_INFO originalSbi;
}
@ -1283,12 +1322,18 @@ struct Terminal {
doTermcap("te");
}
version(TerminalDirectToEmulator) {
writeln("\n\n<exited>");
setTitle(tew.terminalEmulator.currentTitle ~ " <exited>");
tew.term = null;
if(usingDirectEmulator) {
writeln("\n\n<exited>");
setTitle(tew.terminalEmulator.currentTitle ~ " <exited>");
tew.term = null;
if(integratedTerminalEmulatorConfiguration.closeOnExit)
tew.parentWindow.close();
if(integratedTerminalEmulatorConfiguration.closeOnExit)
tew.parentWindow.close();
} else {
if(terminalInFamily("xterm", "rxvt", "screen", "tmux")) {
writeStringRaw("\033[23;0t"); // restore window title from the stack
}
}
} else
if(terminalInFamily("xterm", "rxvt", "screen", "tmux")) {
writeStringRaw("\033[23;0t"); // restore window title from the stack
@ -1371,7 +1416,10 @@ struct Terminal {
// fallback to 16 color for term that i know don't take it well
import std.process;
import std.string;
version(TerminalDirectToEmulator) {} else
version(TerminalDirectToEmulator)
if(usingDirectEmulator)
goto skip_approximation;
if(environment.get("TERM") == "rxvt" || environment.get("TERM") == "linux") {
// not likely supported, use 16 color fallback
auto setTof = approximate16Color(foreground);
@ -1386,6 +1434,8 @@ struct Terminal {
return false;
}
skip_approximation:
// otherwise, assume it is probably supported and give it a try
writeStringRaw(format("\033[38;5;%dm\033[48;5;%dm",
colorToXTermPaletteIndex(foreground),
@ -1698,9 +1748,19 @@ struct Terminal {
return;
version(TerminalDirectToEmulator) {
tew.sendRawInput(cast(ubyte[]) writeBuffer);
writeBuffer = null;
} else version(Posix) {
if(usingDirectEmulator) {
tew.sendRawInput(cast(ubyte[]) writeBuffer);
writeBuffer = null;
} else {
interiorFlush();
}
} else {
interiorFlush();
}
}
private void interiorFlush() {
version(Posix) {
if(_writeDelegate !is null) {
_writeDelegate(writeBuffer);
} else {
@ -1730,8 +1790,17 @@ struct Terminal {
int[] getSize() {
version(TerminalDirectToEmulator) {
return [tew.terminalEmulator.width, tew.terminalEmulator.height];
} else version(Windows) {
if(usingDirectEmulator)
return [tew.terminalEmulator.width, tew.terminalEmulator.height];
else
return getSizeInternal();
} else {
return getSizeInternal();
}
}
private int[] getSizeInternal() {
version(Windows) {
CONSOLE_SCREEN_BUFFER_INFO info;
GetConsoleScreenBufferInfo( hConsole, &info );
@ -2100,7 +2169,7 @@ struct RealTimeConsoleInput {
// so this hack is just to give some room for that to happen without destroying the rest of the world
}
version(Win32Console) {
version(Windows) {
private DWORD oldInput;
private DWORD oldOutput;
HANDLE inputHandle;
@ -2115,9 +2184,13 @@ struct RealTimeConsoleInput {
this.flags = flags;
this.terminal = terminal;
version(Win32Console) {
version(Windows) {
inputHandle = GetStdHandle(STD_INPUT_HANDLE);
}
version(Win32Console) {
GetConsoleMode(inputHandle, &oldInput);
DWORD mode = 0;
@ -2145,54 +2218,12 @@ struct RealTimeConsoleInput {
}
version(TerminalDirectToEmulator) {
terminal.tew.terminalEmulator.echo = (flags & ConsoleInputFlags.echo) ? true : false;
if(terminal.usingDirectEmulator)
terminal.tew.terminalEmulator.echo = (flags & ConsoleInputFlags.echo) ? true : false;
else version(Posix)
posixInit();
} else version(Posix) {
this.fdIn = terminal.fdIn;
this.fdOut = terminal.fdOut;
if(fdIn != -1) {
tcgetattr(fdIn, &old);
auto n = old;
auto f = ICANON;
if(!(flags & ConsoleInputFlags.echo))
f |= ECHO;
// \033Z or \033[c
n.c_lflag &= ~f;
tcsetattr(fdIn, TCSANOW, &n);
}
// some weird bug breaks this, https://github.com/robik/ConsoleD/issues/3
//destructor ~= { tcsetattr(fdIn, TCSANOW, &old); };
if(flags & ConsoleInputFlags.size) {
import core.sys.posix.signal;
sigaction_t n;
n.sa_handler = &sizeSignalHandler;
n.sa_mask = cast(sigset_t) 0;
n.sa_flags = 0;
sigaction(SIGWINCH, &n, &oldSigWinch);
}
{
import core.sys.posix.signal;
sigaction_t n;
n.sa_handler = &interruptSignalHandler;
n.sa_mask = cast(sigset_t) 0;
n.sa_flags = 0;
sigaction(SIGINT, &n, &oldSigIntr);
}
{
import core.sys.posix.signal;
sigaction_t n;
n.sa_handler = &hangupSignalHandler;
n.sa_mask = cast(sigset_t) 0;
n.sa_flags = 0;
sigaction(SIGHUP, &n, &oldHupIntr);
}
posixInit();
}
if(UseVtSequences) {
@ -2259,6 +2290,56 @@ struct RealTimeConsoleInput {
}
}
version(Posix)
private void posixInit() {
this.fdIn = terminal.fdIn;
this.fdOut = terminal.fdOut;
if(fdIn != -1) {
tcgetattr(fdIn, &old);
auto n = old;
auto f = ICANON;
if(!(flags & ConsoleInputFlags.echo))
f |= ECHO;
// \033Z or \033[c
n.c_lflag &= ~f;
tcsetattr(fdIn, TCSANOW, &n);
}
// some weird bug breaks this, https://github.com/robik/ConsoleD/issues/3
//destructor ~= { tcsetattr(fdIn, TCSANOW, &old); };
if(flags & ConsoleInputFlags.size) {
import core.sys.posix.signal;
sigaction_t n;
n.sa_handler = &sizeSignalHandler;
n.sa_mask = cast(sigset_t) 0;
n.sa_flags = 0;
sigaction(SIGWINCH, &n, &oldSigWinch);
}
{
import core.sys.posix.signal;
sigaction_t n;
n.sa_handler = &interruptSignalHandler;
n.sa_mask = cast(sigset_t) 0;
n.sa_flags = 0;
sigaction(SIGINT, &n, &oldSigIntr);
}
{
import core.sys.posix.signal;
sigaction_t n;
n.sa_handler = &hangupSignalHandler;
n.sa_mask = cast(sigset_t) 0;
n.sa_flags = 0;
sigaction(SIGHUP, &n, &oldHupIntr);
}
}
void fdReadyReader() {
auto queue = readNextEvents();
foreach(event; queue)
@ -2318,13 +2399,15 @@ struct RealTimeConsoleInput {
// the delegate thing doesn't actually work for this... for some reason
version(TerminalDirectToEmulator) { } else
version(Posix)
version(TerminalDirectToEmulator) {
if(terminal && terminal.usingDirectEmulator)
goto skip_extra;
}
version(Posix) {
if(fdIn != -1)
tcsetattr(fdIn, TCSANOW, &old);
version(TerminalDirectToEmulator) { } else
version(Posix) {
if(flags & ConsoleInputFlags.size) {
// restoration
sigaction(SIGWINCH, &oldSigWinch, null);
@ -2333,6 +2416,8 @@ struct RealTimeConsoleInput {
sigaction(SIGHUP, &oldHupIntr, null);
}
skip_extra:
// we're just undoing everything the constructor did, in reverse order, same criteria
foreach_reverse(d; destructor)
d();
@ -2375,6 +2460,9 @@ struct RealTimeConsoleInput {
bool timedCheckForInput_bypassingBuffer(int milliseconds) {
version(TerminalDirectToEmulator) {
if(!terminal.usingDirectEmulator)
return timedCheckForInput_bypassingBuffer_impl(milliseconds);
import core.time;
if(terminal.tew.terminalEmulator.pendingForApplication.length)
return true;
@ -2385,7 +2473,12 @@ struct RealTimeConsoleInput {
return terminal.tew.terminalEmulator.pendingForApplication.length || terminal.interrupted || terminal.windowSizeChanged || terminal.hangedUp;
else
return false;
} else version(Win32Console) {
} else
return timedCheckForInput_bypassingBuffer_impl(milliseconds);
}
private bool timedCheckForInput_bypassingBuffer_impl(int milliseconds) {
version(Windows) {
auto response = WaitForSingleObject(inputHandle, milliseconds);
if(response == 0)
return true; // the object is ready
@ -2458,6 +2551,8 @@ struct RealTimeConsoleInput {
//int inputBufferPosition;
int nextRaw(bool interruptable = false) {
version(TerminalDirectToEmulator) {
if(!terminal.usingDirectEmulator)
return nextRaw_impl(interruptable);
moar:
//if(interruptable && inputQueue.length)
//return -1;
@ -2474,7 +2569,11 @@ struct RealTimeConsoleInput {
terminal.tew.terminalEmulator.pendingForApplication = terminal.tew.terminalEmulator.pendingForApplication[1 .. $];
return a;
}
} else version(Posix) {
} else
return nextRaw_impl(interruptable);
}
private int nextRaw_impl(bool interruptable = false) {
version(Posix) {
if(fdIn == -1)
return 0;
@ -4640,14 +4739,20 @@ class LineGetter {
// then get the current cursor position to start fresh
version(TerminalDirectToEmulator) {
if(!terminal.usingDirectEmulator)
return updateCursorPosition_impl();
startOfLineX = terminal.tew.terminalEmulator.cursorX;
startOfLineY = terminal.tew.terminalEmulator.cursorY;
} else version(Win32Console) {
} else
updateCursorPosition_impl();
}
private void updateCursorPosition_impl() {
version(Win32Console) {
CONSOLE_SCREEN_BUFFER_INFO info;
GetConsoleScreenBufferInfo(terminal.hConsole, &info);
startOfLineX = info.dwCursorPosition.X;
startOfLineY = info.dwCursorPosition.Y;
} else {
} else version(Posix) {
// request current cursor position
// we have to turn off cooked mode to get this answer, otherwise it will all
@ -5968,6 +6073,25 @@ version(TerminalDirectToEmulator) {
Added March 29, 2020. Included in release v7.1.0.
+/
void delegate(TerminalEmulatorWindow) menuExtensionsConstructor;
/++
Set this to true if you want [Terminal] to fallback to the user's
existing native terminal in the event that creating the custom terminal
is impossible for whatever reason.
If your application must have all advanced features, set this to `false`.
Otherwise, be sure you handle the absence of advanced features in your
application by checking methods like [Terminal.inlineImagesSupported],
etc., and only use things you can gracefully degrade without.
If this is set to false, `Terminal`'s constructor will throw if the gui fails
instead of carrying on with the stdout terminal (if possible).
History:
Added June 28, 2020. Included in release v8.1.0.
+/
bool fallbackToDegradedTerminal = true;
}
/+

View File

@ -821,7 +821,7 @@ class TerminalEmulator {
hasNonCharacterData = false;
chStore = c;
}
ref TextAttributes attributes() {
ref TextAttributes attributes() return {
assert(!hasNonCharacterData);
return attributesStore;
}