ctrl+c on Linux now triggers a clean exit via event loop - major change

This commit is contained in:
Adam D. Ruppe 2019-04-20 12:21:57 -04:00
parent 83db97a467
commit 101c81cd7c
1 changed files with 62 additions and 3 deletions

View File

@ -1351,6 +1351,14 @@ class SimpleWindow : CapableOfHandlingNativeEvent, CapableOfBeingDrawnUpon {
is the drawable space inside; it excludes the title bar, etc.)
Windows based on images will not be resizable and do not use OpenGL.
It will draw the image in upon creation, but this will be overwritten
upon any draws, including the initial window visible event.
You probably do not want to use this and it may be removed from
the library eventually, or I might change it to be a "permanent"
background image; one that is automatically drawn on it before any
other drawing event. idk.
+/
this(Image image, string title = null) {
this(image.width, image.height, title);
@ -2345,6 +2353,7 @@ private:
version(X11) {
__gshared int customEventFD = -1;
__gshared int customSignalFD = -1;
} else version(Windows) {
__gshared HANDLE customEventH = null;
}
@ -2713,6 +2722,11 @@ struct EventLoop {
impl.notExited = false;
}
ref void delegate(int) signalHandler() {
assert(impl !is null);
return impl.signalHandler;
}
static EventLoopImpl* impl;
}
@ -2741,6 +2755,8 @@ struct EventLoopImpl {
static import unix = core.sys.posix.unistd;
static import err = core.stdc.errno;
import core.sys.linux.timerfd;
void delegate(int) signalHandler;
}
version(X11) {
@ -2843,6 +2859,29 @@ struct EventLoopImpl {
throw new Exception("can't create eventfd for custom event processing");
}
}
if (customSignalFD == -1) {
import core.sys.linux.sys.signalfd;
sigset_t sigset;
auto err = sigemptyset(&sigset);
assert(!err);
err = sigaddset(&sigset, SIGINT);
assert(!err);
err = sigaddset(&sigset, SIGHUP);
assert(!err);
err = sigprocmask(SIG_BLOCK, &sigset, null);
assert(!err);
customSignalFD = signalfd(-1, &sigset, SFD_NONBLOCK);
assert(customSignalFD != -1);
ep.epoll_event ev = void;
{ import core.stdc.string : memset; memset(&ev, 0, ev.sizeof); } // this makes valgrind happy
ev.events = ep.EPOLLIN;
ev.data.fd = customSignalFD;
ep.epoll_ctl(epollFd, ep.EPOLL_CTL_ADD, customSignalFD, &ev);
}
}
SimpleWindow.processAllCustomEvents(); // process events added before event FD creation
@ -2909,8 +2948,10 @@ struct EventLoopImpl {
dispose();
}
version(X11)
version(linux)
ref int customEventFD() { return SimpleWindow.customEventFD; }
version(linux)
ref int customSignalFD() { return SimpleWindow.customSignalFD; }
version(Windows)
ref auto customEventH() { return SimpleWindow.customEventH; }
@ -2985,6 +3026,21 @@ struct EventLoopImpl {
read(customEventFD, &n, n.sizeof); // reset counter value to zero again
//{ import core.stdc.stdio; printf("custom event! count=%u\n", eventQueueUsed); }
//SimpleWindow.processAllCustomEvents();
} else if (fd == customSignalFD) {
version(linux) {
import core.sys.linux.sys.signalfd;
import core.sys.posix.unistd : read;
signalfd_siginfo info;
read(customSignalFD, &info, info.sizeof);
auto sig = info.ssi_signo;
if(EventLoop.get.signalHandler !is null) {
EventLoop.get.signalHandler()(sig);
} else {
EventLoop.get.exit();
}
}
} else {
// some other timer
version(sdddd) { import std.stdio; writeln("unknown fd: ", fd); }
@ -4628,8 +4684,8 @@ version(X11) {
setX11Selection!"SECONDARY"(window, text);
}
///
void setX11Selection(string atomName)(SimpleWindow window, string text) {
/// The `after` delegate is called after a client requests the UTF8_STRING thing. it is a mega-hack right now!
void setX11Selection(string atomName)(SimpleWindow window, string text, void delegate() after = null) {
assert(window !is null);
auto display = XDisplayConnection.get();
@ -4673,6 +4729,9 @@ version(X11) {
event.target,
8 /* bits */, 0 /* PropModeReplace */,
text.ptr, cast(int) text.length);
if(after)
after();
} else {
selectionEvent.property = None; // I don't know how to handle this type...
}