mirror of https://github.com/adamdruppe/arsd.git
ketmar patches
This commit is contained in:
parent
5ff256380a
commit
0dbcaa6ed0
8
color.d
8
color.d
|
@ -206,7 +206,7 @@ struct Color {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a string that matches CSS syntax for websites
|
/// Makes a string that matches CSS syntax for websites
|
||||||
string toCssString() {
|
string toCssString() const {
|
||||||
if(a == 255)
|
if(a == 255)
|
||||||
return "#" ~ toHexInternal(r) ~ toHexInternal(g) ~ toHexInternal(b);
|
return "#" ~ toHexInternal(r) ~ toHexInternal(g) ~ toHexInternal(b);
|
||||||
else {
|
else {
|
||||||
|
@ -215,7 +215,7 @@ struct Color {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a hex string RRGGBBAA (aa only present if it is not 255)
|
/// Makes a hex string RRGGBBAA (aa only present if it is not 255)
|
||||||
string toString() {
|
string toString() const {
|
||||||
if(a == 255)
|
if(a == 255)
|
||||||
return toCssString()[1 .. $];
|
return toCssString()[1 .. $];
|
||||||
else
|
else
|
||||||
|
@ -223,7 +223,7 @@ struct Color {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns RRGGBBAA, even if a== 255
|
/// returns RRGGBBAA, even if a== 255
|
||||||
string toRgbaHexString() {
|
string toRgbaHexString() const {
|
||||||
return toHexInternal(r) ~ toHexInternal(g) ~ toHexInternal(b) ~ toHexInternal(a);
|
return toHexInternal(r) ~ toHexInternal(g) ~ toHexInternal(b) ~ toHexInternal(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -815,7 +815,7 @@ interface MemoryImage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An image that consists of indexes into a color palette. Use getAsTrueColorImage() if you don't care about palettes
|
/// An image that consists of indexes into a color palette. Use [getAsTrueColorImage]() if you don't care about palettes
|
||||||
class IndexedImage : MemoryImage {
|
class IndexedImage : MemoryImage {
|
||||||
bool hasAlpha;
|
bool hasAlpha;
|
||||||
|
|
||||||
|
|
94
email.d
94
email.d
|
@ -241,6 +241,7 @@ import std.conv;
|
||||||
class MimePart {
|
class MimePart {
|
||||||
string[] headers;
|
string[] headers;
|
||||||
immutable(ubyte)[] content;
|
immutable(ubyte)[] content;
|
||||||
|
immutable(ubyte)[] encodedContent; // usually valid only for GPG, and will be cleared by creator; canonical form
|
||||||
string textContent;
|
string textContent;
|
||||||
MimePart[] stuff;
|
MimePart[] stuff;
|
||||||
|
|
||||||
|
@ -251,6 +252,9 @@ class MimePart {
|
||||||
string disposition;
|
string disposition;
|
||||||
string id;
|
string id;
|
||||||
string filename;
|
string filename;
|
||||||
|
// gpg signatures
|
||||||
|
string gpgalg;
|
||||||
|
string gpgproto;
|
||||||
|
|
||||||
MimeAttachment toMimeAttachment() {
|
MimeAttachment toMimeAttachment() {
|
||||||
MimeAttachment att;
|
MimeAttachment att;
|
||||||
|
@ -265,7 +269,9 @@ class MimePart {
|
||||||
string boundary;
|
string boundary;
|
||||||
|
|
||||||
void parseContentType(string content) {
|
void parseContentType(string content) {
|
||||||
|
//{ import std.stdio; writeln("c=[", content, "]"); }
|
||||||
foreach(k, v; breakUpHeaderParts(content)) {
|
foreach(k, v; breakUpHeaderParts(content)) {
|
||||||
|
//{ import std.stdio; writeln(" k=[", k, "]; v=[", v, "]"); }
|
||||||
switch(k) {
|
switch(k) {
|
||||||
case "root":
|
case "root":
|
||||||
type = v;
|
type = v;
|
||||||
|
@ -280,6 +286,12 @@ class MimePart {
|
||||||
boundary = v;
|
boundary = v;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
case "micalg":
|
||||||
|
gpgalg = v;
|
||||||
|
break;
|
||||||
|
case "protocol":
|
||||||
|
gpgproto = v;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -381,6 +393,9 @@ class MimePart {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// store encoded content for GPG (should be cleared by caller if necessary)
|
||||||
|
encodedContent = content;
|
||||||
|
|
||||||
// decode the content..
|
// decode the content..
|
||||||
switch(transferEncoding) {
|
switch(transferEncoding) {
|
||||||
case "base64":
|
case "base64":
|
||||||
|
@ -583,6 +598,7 @@ class IncomingEmailMessage {
|
||||||
lineLoop: while(mboxLines.length) {
|
lineLoop: while(mboxLines.length) {
|
||||||
// this can needlessly convert headers too, but that won't harm anything since they are 7 bit anyway
|
// this can needlessly convert headers too, but that won't harm anything since they are 7 bit anyway
|
||||||
auto line = convertToUtf8Lossy(mboxLines[0], charset);
|
auto line = convertToUtf8Lossy(mboxLines[0], charset);
|
||||||
|
auto origline = line;
|
||||||
line = line.stripRight;
|
line = line.stripRight;
|
||||||
|
|
||||||
final switch(state) {
|
final switch(state) {
|
||||||
|
@ -627,6 +643,15 @@ class IncomingEmailMessage {
|
||||||
htmlMessageBody ~= line ~ "\n";
|
htmlMessageBody ~= line ~ "\n";
|
||||||
} else {
|
} else {
|
||||||
// plain text!
|
// plain text!
|
||||||
|
// we want trailing spaces for "format=flowed", for example, so...
|
||||||
|
line = origline;
|
||||||
|
size_t epos = line.length;
|
||||||
|
while (epos > 0) {
|
||||||
|
char ch = line.ptr[epos-1];
|
||||||
|
if (ch >= ' ' || ch == '\t') break;
|
||||||
|
--epos;
|
||||||
|
}
|
||||||
|
line = line.ptr[0..epos];
|
||||||
textMessageBody ~= line ~ "\n";
|
textMessageBody ~= line ~ "\n";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -684,6 +709,19 @@ class IncomingEmailMessage {
|
||||||
break;
|
break;
|
||||||
case "multipart/signed":
|
case "multipart/signed":
|
||||||
// FIXME: it would be cool to actually check the signature
|
// FIXME: it would be cool to actually check the signature
|
||||||
|
if (part.stuff.length) {
|
||||||
|
auto msg = part.stuff[0];
|
||||||
|
//{ import std.stdio; writeln("hdrs: ", part.stuff[0].headers); }
|
||||||
|
gpgalg = part.gpgalg;
|
||||||
|
gpgproto = part.gpgproto;
|
||||||
|
gpgmime = part;
|
||||||
|
foreach (thing; part.stuff[1 .. $]) {
|
||||||
|
attachments ~= thing.toMimeAttachment();
|
||||||
|
}
|
||||||
|
part = msg;
|
||||||
|
goto deeperInTheMimeTree;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// FIXME: correctly handle more
|
// FIXME: correctly handle more
|
||||||
if(part.stuff.length) {
|
if(part.stuff.length) {
|
||||||
|
@ -720,6 +758,53 @@ class IncomingEmailMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@property bool hasGPGSignature () const nothrow @trusted @nogc {
|
||||||
|
MimePart mime = cast(MimePart)gpgmime; // sorry
|
||||||
|
if (mime is null) return false;
|
||||||
|
if (mime.type != "multipart/signed") return false;
|
||||||
|
if (mime.stuff.length != 2) return false;
|
||||||
|
if (mime.stuff[1].type != "application/pgp-signature") return false;
|
||||||
|
if (mime.stuff[0].type.length <= 5 && mime.stuff[0].type[0..5] != "text/") return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ubyte[] extractGPGData () const nothrow @trusted {
|
||||||
|
if (!hasGPGSignature) return null;
|
||||||
|
MimePart mime = cast(MimePart)gpgmime; // sorry
|
||||||
|
char[] res;
|
||||||
|
res.reserve(mime.stuff[0].encodedContent.length); // more, actually
|
||||||
|
foreach (string s; mime.stuff[0].headers[1..$]) {
|
||||||
|
while (s.length && s[$-1] <= ' ') s = s[0..$-1];
|
||||||
|
if (s.length == 0) return null; // wtf?! empty headers?
|
||||||
|
res ~= s;
|
||||||
|
res ~= "\r\n";
|
||||||
|
}
|
||||||
|
res ~= "\r\n";
|
||||||
|
// extract content (see rfc3156)
|
||||||
|
size_t pos = 0;
|
||||||
|
auto ctt = mime.stuff[0].encodedContent;
|
||||||
|
// last CR/LF is a part of mime signature, actually, so remove it
|
||||||
|
if (ctt.length && ctt[$-1] == '\n') {
|
||||||
|
ctt = ctt[0..$-1];
|
||||||
|
if (ctt.length && ctt[$-1] == '\r') ctt = ctt[0..$-1];
|
||||||
|
}
|
||||||
|
while (pos < ctt.length) {
|
||||||
|
auto epos = pos;
|
||||||
|
while (epos < ctt.length && ctt.ptr[epos] != '\n') ++epos;
|
||||||
|
auto xpos = epos;
|
||||||
|
while (xpos > pos && ctt.ptr[xpos-1] <= ' ') --xpos; // according to rfc
|
||||||
|
res ~= ctt[pos..xpos].dup;
|
||||||
|
res ~= "\r\n"; // according to rfc
|
||||||
|
pos = epos+1;
|
||||||
|
}
|
||||||
|
return cast(ubyte[])res;
|
||||||
|
}
|
||||||
|
|
||||||
|
immutable(ubyte)[] extractGPGSignature () const nothrow @safe @nogc {
|
||||||
|
if (!hasGPGSignature) return null;
|
||||||
|
return gpgmime.stuff[1].content;
|
||||||
|
}
|
||||||
|
|
||||||
string[string] headers;
|
string[string] headers;
|
||||||
|
|
||||||
string subject;
|
string subject;
|
||||||
|
@ -733,6 +818,11 @@ class IncomingEmailMessage {
|
||||||
bool textAutoConverted;
|
bool textAutoConverted;
|
||||||
|
|
||||||
MimeAttachment[] attachments;
|
MimeAttachment[] attachments;
|
||||||
|
|
||||||
|
// gpg signature fields
|
||||||
|
string gpgalg;
|
||||||
|
string gpgproto;
|
||||||
|
MimePart gpgmime;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MboxMessages {
|
struct MboxMessages {
|
||||||
|
@ -841,9 +931,9 @@ string decodeEncodedWord(string data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
immutable(ubyte)[] decodedText;
|
immutable(ubyte)[] decodedText;
|
||||||
if(encoding == "Q")
|
if(encoding == "Q" || encoding == "q")
|
||||||
decodedText = decodeQuotedPrintable(encodedText);
|
decodedText = decodeQuotedPrintable(encodedText);
|
||||||
else if(encoding == "B")
|
else if(encoding == "B" || encoding == "b")
|
||||||
decodedText = cast(typeof(decodedText)) Base64.decode(encodedText);
|
decodedText = cast(typeof(decodedText)) Base64.decode(encodedText);
|
||||||
else
|
else
|
||||||
return originalData; // wtf
|
return originalData; // wtf
|
||||||
|
|
9
http2.d
9
http2.d
|
@ -1239,13 +1239,20 @@ class HttpApiClient() {
|
||||||
static struct HttpRequestWrapper {
|
static struct HttpRequestWrapper {
|
||||||
HttpApiClientType apiClient;
|
HttpApiClientType apiClient;
|
||||||
HttpRequest request;
|
HttpRequest request;
|
||||||
|
HttpResponse _response;
|
||||||
this(HttpApiClientType apiClient, HttpRequest request) {
|
this(HttpApiClientType apiClient, HttpRequest request) {
|
||||||
this.apiClient = apiClient;
|
this.apiClient = apiClient;
|
||||||
this.request = request;
|
this.request = request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@property HttpResponse response() {
|
||||||
|
if(_response is HttpResponse.init)
|
||||||
|
_response = request.waitForCompletion();
|
||||||
|
return _response;
|
||||||
|
}
|
||||||
|
|
||||||
var result() {
|
var result() {
|
||||||
return apiClient.throwOnError(request.waitForCompletion());
|
return apiClient.throwOnError(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
alias request this;
|
alias request this;
|
||||||
|
|
125
simpledisplay.d
125
simpledisplay.d
|
@ -521,6 +521,10 @@ version(Windows) {
|
||||||
|
|
||||||
pragma(lib, "gdi32");
|
pragma(lib, "gdi32");
|
||||||
pragma(lib, "user32");
|
pragma(lib, "user32");
|
||||||
|
} else version (Posix) {
|
||||||
|
//k8: this is hack for rdmd. sorry.
|
||||||
|
static import core.sys.linux.epoll;
|
||||||
|
static import core.sys.linux.timerfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -942,6 +946,13 @@ class SimpleWindow : CapableOfHandlingNativeEvent {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send dummy window event to ping event loop. Required to process NotificationIcon on X11, for example.
|
||||||
|
void sendDummyEvent () {
|
||||||
|
version(X11) {
|
||||||
|
if (!_closed) { impl.sendDummyEvent(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set window minimal size.
|
/// Set window minimal size.
|
||||||
void setMinSize (int minwidth, int minheight) {
|
void setMinSize (int minwidth, int minheight) {
|
||||||
if (!_closed) impl.setMinSize(minwidth, minheight);
|
if (!_closed) impl.setMinSize(minwidth, minheight);
|
||||||
|
@ -1087,6 +1098,16 @@ class SimpleWindow : CapableOfHandlingNativeEvent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Emit a beep to get user's attention.
|
||||||
|
void beep () {
|
||||||
|
version(X11) {
|
||||||
|
XBell(this.display, 100);
|
||||||
|
} else version(Windows) {
|
||||||
|
MessageBeep(0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Set this to `false` if you don't need to do `glFinish()` after `swapOpenGlBuffers()`.
|
/// Set this to `false` if you don't need to do `glFinish()` after `swapOpenGlBuffers()`.
|
||||||
/// Note that at least NVidia proprietary driver may segfault if you will modify texture fast
|
/// Note that at least NVidia proprietary driver may segfault if you will modify texture fast
|
||||||
/// enough without waiting 'em to finish their frame bussiness.
|
/// enough without waiting 'em to finish their frame bussiness.
|
||||||
|
@ -2015,6 +2036,8 @@ version(X11) {
|
||||||
|
|
||||||
///
|
///
|
||||||
class NotificationAreaIcon : CapableOfHandlingNativeEvent {
|
class NotificationAreaIcon : CapableOfHandlingNativeEvent {
|
||||||
|
Image img;
|
||||||
|
|
||||||
NativeEventHandler getNativeEventHandler() {
|
NativeEventHandler getNativeEventHandler() {
|
||||||
return delegate int(XEvent e) {
|
return delegate int(XEvent e) {
|
||||||
switch(e.type) {
|
switch(e.type) {
|
||||||
|
@ -2023,10 +2046,21 @@ version(X11) {
|
||||||
break;
|
break;
|
||||||
case EventType.ButtonPress:
|
case EventType.ButtonPress:
|
||||||
auto event = e.xbutton;
|
auto event = e.xbutton;
|
||||||
if(onClick)
|
if (onClick) {
|
||||||
onClick(event.button);
|
MouseButton mb = cast(MouseButton)0;
|
||||||
|
switch (event.button) {
|
||||||
|
case 1: mb = MouseButton.left; break; // left
|
||||||
|
case 2: mb = MouseButton.middle; break; // middle
|
||||||
|
case 3: mb = MouseButton.right; break; // right
|
||||||
|
case 4: mb = MouseButton.wheelUp; break; // scroll up
|
||||||
|
case 5: mb = MouseButton.wheelDown; break; // scroll down
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
if (mb) onClick(mb);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EventType.DestroyNotify:
|
case EventType.DestroyNotify:
|
||||||
|
active = false;
|
||||||
CapableOfHandlingNativeEvent.nativeHandleMapping.remove(nativeHandle);
|
CapableOfHandlingNativeEvent.nativeHandleMapping.remove(nativeHandle);
|
||||||
break;
|
break;
|
||||||
case EventType.ConfigureNotify:
|
case EventType.ConfigureNotify:
|
||||||
|
@ -2043,6 +2077,8 @@ version(X11) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void redraw() {
|
void redraw() {
|
||||||
|
if (!active) return;
|
||||||
|
|
||||||
auto display = XDisplayConnection.get;
|
auto display = XDisplayConnection.get;
|
||||||
auto gc = DefaultGC(display, DefaultScreen(display));
|
auto gc = DefaultGC(display, DefaultScreen(display));
|
||||||
XClearWindow(display, nativeHandle);
|
XClearWindow(display, nativeHandle);
|
||||||
|
@ -2054,12 +2090,19 @@ version(X11) {
|
||||||
XFillRectangle(display, nativeHandle,
|
XFillRectangle(display, nativeHandle,
|
||||||
gc, 0, 0, width, height);
|
gc, 0, 0, width, height);
|
||||||
|
|
||||||
XSetForeground(display, gc,
|
if (img is null) {
|
||||||
cast(uint) 0 << 16 |
|
XSetForeground(display, gc,
|
||||||
cast(uint) 127 << 8 |
|
cast(uint) 0 << 16 |
|
||||||
cast(uint) 0);
|
cast(uint) 127 << 8 |
|
||||||
XFillArc(display, nativeHandle,
|
cast(uint) 0);
|
||||||
gc, width / 4, height / 4, width * 2 / 4, height * 2 / 4, 0 * 64, 360 * 64);
|
XFillArc(display, nativeHandle,
|
||||||
|
gc, width / 4, height / 4, width * 2 / 4, height * 2 / 4, 0 * 64, 360 * 64);
|
||||||
|
} else {
|
||||||
|
if (img.usingXshm)
|
||||||
|
XShmPutImage(display, cast(Drawable)nativeHandle, gc, img.handle, 0, 0, 0, 0, img.width, img.height, false);
|
||||||
|
else
|
||||||
|
XPutImage(display, cast(Drawable)nativeHandle, gc, img.handle, 0, 0, 0, 0, img.width, img.height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Window getTrayOwner() {
|
static Window getTrayOwner() {
|
||||||
|
@ -2091,8 +2134,7 @@ version(X11) {
|
||||||
XSendEvent(XDisplayConnection.get, to, false, EventMask.NoEventMask, &ev);
|
XSendEvent(XDisplayConnection.get, to, false, EventMask.NoEventMask, &ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
private void createXWin () {
|
||||||
this(string name, MemoryImage icon, void delegate(int button) onClick) {
|
|
||||||
if(getTrayOwner() == None)
|
if(getTrayOwner() == None)
|
||||||
throw new Exception("No notification area found");
|
throw new Exception("No notification area found");
|
||||||
// create window
|
// create window
|
||||||
|
@ -2100,8 +2142,6 @@ version(X11) {
|
||||||
auto nativeWindow = XCreateWindow(display, RootWindow(display, DefaultScreen(display)), 0, 0, 16, 16, 0, 24, InputOutput, cast(Visual*) CopyFromParent, 0, null);
|
auto nativeWindow = XCreateWindow(display, RootWindow(display, DefaultScreen(display)), 0, 0, 16, 16, 0, 24, InputOutput, cast(Visual*) CopyFromParent, 0, null);
|
||||||
assert(nativeWindow);
|
assert(nativeWindow);
|
||||||
|
|
||||||
this.onClick = onClick;
|
|
||||||
|
|
||||||
nativeHandle = nativeWindow;
|
nativeHandle = nativeWindow;
|
||||||
|
|
||||||
XSelectInput(display, nativeWindow,
|
XSelectInput(display, nativeWindow,
|
||||||
|
@ -2109,20 +2149,60 @@ version(X11) {
|
||||||
|
|
||||||
sendTrayMessage(SYSTEM_TRAY_REQUEST_DOCK, nativeWindow, 0, 0);
|
sendTrayMessage(SYSTEM_TRAY_REQUEST_DOCK, nativeWindow, 0, 0);
|
||||||
CapableOfHandlingNativeEvent.nativeHandleMapping[nativeWindow] = this;
|
CapableOfHandlingNativeEvent.nativeHandleMapping[nativeWindow] = this;
|
||||||
|
active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
this(string name, MemoryImage icon, void delegate(MouseButton button) onClick) {
|
||||||
|
this.onClick = onClick;
|
||||||
|
if (icon !is null) this.img = Image.fromMemoryImage(icon);
|
||||||
|
createXWin();
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
this(string name, Image icon, void delegate(MouseButton button) onClick) {
|
||||||
|
this.onClick = onClick;
|
||||||
|
this.img = icon;
|
||||||
|
createXWin();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Window nativeHandle;
|
private Window nativeHandle;
|
||||||
private int width = 12;
|
private int width = 16;
|
||||||
private int height = 12;
|
private int height = 16;
|
||||||
|
private bool active = false;
|
||||||
|
|
||||||
void delegate(int) onClick;
|
void delegate (MouseButton button) onClick;
|
||||||
|
|
||||||
|
@property bool closed () const pure nothrow @safe @nogc { return !active; }
|
||||||
|
|
||||||
|
void close () {
|
||||||
|
if (active) {
|
||||||
|
active = false;
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@property void name(string n) {
|
@property void name(string n) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@property void icon(MemoryImage i) {
|
@property void icon(MemoryImage i) {
|
||||||
|
if (i !is null) {
|
||||||
|
this.img = Image.fromMemoryImage(i);
|
||||||
|
redraw();
|
||||||
|
} else {
|
||||||
|
if (this.img !is null) {
|
||||||
|
this.img = null;
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@property void icon (Image i) {
|
||||||
|
if (i !is img) {
|
||||||
|
img = i;
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2255,7 +2335,7 @@ version(without_opengl) {
|
||||||
Determines if you want an OpenGL context created on the new window.
|
Determines if you want an OpenGL context created on the new window.
|
||||||
|
|
||||||
|
|
||||||
See more: <a href="#topics-3d">in the 3d topic</a>.
|
See more: [#topics-3d|in the 3d topic].
|
||||||
|
|
||||||
---
|
---
|
||||||
import arsd.simpledisplay;
|
import arsd.simpledisplay;
|
||||||
|
@ -5450,6 +5530,18 @@ version(X11) {
|
||||||
XFlush(display);
|
XFlush(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sendDummyEvent () {
|
||||||
|
// here i will send dummy event to ping event queue
|
||||||
|
XEvent e;
|
||||||
|
e.xclient.type = EventType.ClientMessage;
|
||||||
|
e.xclient.window = window;
|
||||||
|
e.xclient.message_type = GetAtom!("_X11SDPY_DUMMY_EVENT_", true)(display); // let's hope nobody else will use such stupid name ;-)
|
||||||
|
e.xclient.format = 32;
|
||||||
|
e.xclient.data.l[0] = 0;
|
||||||
|
XSendEvent(display, window, false, EventMask.NoEventMask, /*cast(XEvent*)&xclient*/&e);
|
||||||
|
XFlush(display);
|
||||||
|
}
|
||||||
|
|
||||||
void setTitle(string title) {
|
void setTitle(string title) {
|
||||||
if (title.ptr is null) title = "";
|
if (title.ptr is null) title = "";
|
||||||
auto XA_UTF8 = XInternAtom(display, "UTF8_STRING".ptr, false);
|
auto XA_UTF8 = XInternAtom(display, "UTF8_STRING".ptr, false);
|
||||||
|
@ -9077,6 +9169,7 @@ version(linux) {
|
||||||
}
|
}
|
||||||
|
|
||||||
version(X11) {
|
version(X11) {
|
||||||
|
import core.stdc.locale : LC_ALL; // rdmd fix
|
||||||
__gshared bool sdx_isUTF8Locale;
|
__gshared bool sdx_isUTF8Locale;
|
||||||
|
|
||||||
// This whole crap is used to initialize X11 locale, so that you can use XIM methods later.
|
// This whole crap is used to initialize X11 locale, so that you can use XIM methods later.
|
||||||
|
|
|
@ -368,6 +368,7 @@ enum ForceOption {
|
||||||
/// Warning: do not write out escape sequences to the terminal. This won't work
|
/// Warning: do not write out escape sequences to the terminal. This won't work
|
||||||
/// on Windows and will confuse Terminal's internal state on Posix.
|
/// on Windows and will confuse Terminal's internal state on Posix.
|
||||||
struct Terminal {
|
struct Terminal {
|
||||||
|
///
|
||||||
@disable this();
|
@disable this();
|
||||||
@disable this(this);
|
@disable this(this);
|
||||||
private ConsoleOutputType type;
|
private ConsoleOutputType type;
|
||||||
|
@ -4026,11 +4027,11 @@ ubyte colorToXTermPaletteIndex(RGB color) {
|
||||||
$(TIP You can convert these to and from [arsd.color.Color] using
|
$(TIP You can convert these to and from [arsd.color.Color] using
|
||||||
`.tupleof`:
|
`.tupleof`:
|
||||||
|
|
||||||
---
|
---
|
||||||
RGB rgb;
|
RGB rgb;
|
||||||
Color c = Color(rgb.tupleof);
|
Color c = Color(rgb.tupleof);
|
||||||
|
---
|
||||||
)
|
)
|
||||||
---
|
|
||||||
+/
|
+/
|
||||||
struct RGB {
|
struct RGB {
|
||||||
ubyte r; ///
|
ubyte r; ///
|
||||||
|
|
Loading…
Reference in New Issue