From 1c5175f911e188836e7c9a85e63da0aef35dcda8 Mon Sep 17 00:00:00 2001 From: "Adam D. Ruppe" Date: Mon, 19 Nov 2018 11:41:35 -0500 Subject: [PATCH] terminal + sdpy integration --- simpledisplay.d | 59 ++++++++++++++++++++++++++++++++++++++++++++++++- terminal.d | 18 +++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/simpledisplay.d b/simpledisplay.d index 3d63a46..921a78d 100644 --- a/simpledisplay.d +++ b/simpledisplay.d @@ -2584,6 +2584,12 @@ struct EventLoop { this(long pulseTimeout, void delegate() handlePulse) { if(impl is null) impl = new EventLoopImpl(pulseTimeout, handlePulse); + else { + if(pulseTimeout) { + impl.pulseTimeout = pulseTimeout; + impl.handlePulse = handlePulse; + } + } impl.refcount++; } @@ -2954,7 +2960,10 @@ struct EventLoopImpl { SimpleWindow.processAllCustomEvents(); // anyway enum WAIT_OBJECT_0 = 0; if(waitResult >= WAIT_OBJECT_0 && waitResult < handles.length + WAIT_OBJECT_0) { - // process handles[waitResult - WAIT_OBJECT_0]; + auto h = handles[waitResult - WAIT_OBJECT_0]; + if(auto e = h in WindowsHandleReader.mapping) { + (*e).ready(); + } } else if(waitResult == handles.length + WAIT_OBJECT_0) { // message ready while(PeekMessage(&message, null, 0, 0, PM_NOREMOVE)) // need to peek since sometimes MsgWaitForMultipleObjectsEx returns even though GetMessage can block. tbh i don't fully understand it but the docs say it is foreground activation @@ -3991,6 +4000,54 @@ class Timer { } } +version(Windows) +/// Lets you add HANDLEs to the event loop. Not meant to be used for async I/O per se, but for other handles (it can only handle a few handles at a time.) +class WindowsHandleReader { + /// + this(void delegate() onReady, HANDLE handle) { + this.onReady = onReady; + this.handle = handle; + + mapping[handle] = this; + + enable(); + } + + /// + void enable() { + auto el = EventLoop.get().impl; + el.handles ~= handle; + } + + /// + void disable() { + auto el = EventLoop.get().impl; + for(int i = 0; i < el.handles.length; i++) { + if(el.handles[i] is handle) { + el.handles[i] = el.handles[$-1]; + el.handles = el.handles[0 .. $-1]; + return; + } + } + } + + void dispose() { + disable(); + mapping.remove(handle); + handle = null; + } + + void ready() { + if(onReady) + onReady(); + } + + HANDLE handle; + void delegate() onReady; + + __gshared WindowsHandleReader[HANDLE] mapping; +} + version(linux) /// Lets you add files to the event loop for reading. Use at your own risk. class PosixFdReader { diff --git a/terminal.d b/terminal.d index fb8390e..49ab246 100644 --- a/terminal.d +++ b/terminal.d @@ -1579,6 +1579,24 @@ struct RealTimeConsoleInput { } } + void fdReadyReader() { + auto queue = readNextEvents(); + foreach(event; queue) + userEventHandler(event); + } + + void delegate(InputEvent) userEventHandler; + + void integrateWithSimpleDisplayEventLoop()(void delegate(InputEvent) userEventHandler) { + this.userEventHandler = userEventHandler; + import arsd.simpledisplay; + version(Windows) + auto listener = new WindowsHandleReader(&fdReadyReader, terminal.hConsole); + else version(linux) + auto listener = new PosixFdReader(&fdReadyReader, fdIn); + else static assert(0, "sdpy event loop integration not implemented on this platform"); + } + version(with_eventloop) { version(Posix) void signalFired(SignalFired) {