From c76d26f01f6aa573c97044c802e932ec71b5f6c4 Mon Sep 17 00:00:00 2001 From: "Adam D. Ruppe" Date: Sat, 1 Feb 2020 19:05:14 -0500 Subject: [PATCH] minimal update for osx xquartz --- dub.json | 8 ++- minigui.d | 3 + simpledisplay.d | 175 ++++++++++++++++++++++++++++++++++++------------ 3 files changed, 143 insertions(+), 43 deletions(-) diff --git a/dub.json b/dub.json index 3d8ac3a..2f33418 100644 --- a/dub.json +++ b/dub.json @@ -36,8 +36,7 @@ "targetType": "library", "importPaths": ["."], "dflags": ["-mv=arsd.simpledisplay=simpledisplay.d"], - "versions-osx": [ "OSXCocoa", "allow_unimplemented_features", "without_opengl" ], - "lflags-osx": ["-framework", "Cocoa"], + "lflags-osx": ["-L/usr/X11/lib"], "dependencies": {"arsd-official:color_base":"*"}, "configurations": [ { @@ -50,6 +49,11 @@ "versions": ["without_opengl"], "libs-windows": ["gdi32"], "libs-posix": ["X11", "Xext"] + }, + { + "name": "cocoa", + "versions-osx": [ "OSXCocoa", "allow_unimplemented_features", "without_opengl" ], + "lflags-osx": ["-framework", "Cocoa"], } ], "sourceFiles": ["simpledisplay.d"] diff --git a/minigui.d b/minigui.d index 900eca0..3ab5ec6 100644 --- a/minigui.d +++ b/minigui.d @@ -604,6 +604,7 @@ private const(wchar)* toWstringzInternal(in char[] s) { return str.ptr; } +static if(SimpledisplayTimerAvailable) void setClickRepeat(Widget w, int interval, int delay = 250) { Timer timer; int delayRemaining = delay / interval; @@ -649,6 +650,8 @@ void setClickRepeat(Widget w, int interval, int delay = 250) { }); } +else +void setClickRepeat(Widget w, int interval, int delay = 250) {} enum FrameStyle { risen, diff --git a/simpledisplay.d b/simpledisplay.d index 33a94fb..5255d0b 100644 --- a/simpledisplay.d +++ b/simpledisplay.d @@ -1,5 +1,7 @@ // https://dpaste.dzfl.pl/7a77355acaec +// on Mac with X11: -L-L/usr/X11/lib + /* Event Loop would be nices: @@ -2364,7 +2366,8 @@ private: private import core.time : MonoTime; version(X11) { - __gshared int customEventFD = -1; + __gshared int customEventFDRead = -1; + __gshared int customEventFDWrite = -1; __gshared int customSignalFD = -1; } else version(Windows) { __gshared HANDLE customEventH = null; @@ -2375,7 +2378,7 @@ private: version(X11) { import core.sys.posix.unistd : write; ulong n = 1; - if (customEventFD >= 0) write(customEventFD, &n, n.sizeof); + if (customEventFDWrite >= 0) write(customEventFDWrite, &n, n.sizeof); return true; } else version(Windows) { if (customEventH !is null) SetEvent(customEventH); @@ -2746,7 +2749,7 @@ struct EventLoop { version(linux) void delegate(int, int) globalHupHandler; -version(linux) +version(Posix) void makeNonBlocking(int fd) { import fcntl = core.sys.posix.fcntl; auto flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0); @@ -2859,14 +2862,15 @@ struct EventLoopImpl { } // eventfd for custom events - if (customEventFD == -1) { - customEventFD = eventfd(0, 0); - if (customEventFD >= 0) { + if (customEventFDWrite == -1) { + customEventFDWrite = eventfd(0, 0); + customEventFDRead = customEventFDWrite; + if (customEventFDRead >= 0) { 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 = customEventFD; - ep.epoll_ctl(epollFd, ep.EPOLL_CTL_ADD, customEventFD, &ev); + ev.data.fd = customEventFDRead; + ep.epoll_ctl(epollFd, ep.EPOLL_CTL_ADD, customEventFDRead, &ev); } else { // this is something that should not be; better be safe than sorry throw new Exception("can't create eventfd for custom event processing"); @@ -2895,6 +2899,17 @@ struct EventLoopImpl { ev.data.fd = customSignalFD; ep.epoll_ctl(epollFd, ep.EPOLL_CTL_ADD, customSignalFD, &ev); } + } else version(Posix) { + prepareEventLoop(); + if (customEventFDRead == -1) { + int[2] bfr; + import core.sys.posix.unistd; + auto ret = pipe(bfr); + if(ret == -1) throw new Exception("pipe"); + customEventFDRead = bfr[0]; + customEventFDWrite = bfr[1]; + } + } SimpleWindow.processAllCustomEvents(); // process events added before event FD creation @@ -2961,8 +2976,10 @@ struct EventLoopImpl { dispose(); } - version(linux) - ref int customEventFD() { return SimpleWindow.customEventFD; } + version(Posix) + ref int customEventFDRead() { return SimpleWindow.customEventFDRead; } + version(Posix) + ref int customEventFDWrite() { return SimpleWindow.customEventFDWrite; } version(linux) ref int customSignalFD() { return SimpleWindow.customSignalFD; } version(Windows) @@ -3047,11 +3064,11 @@ struct EventLoopImpl { // // IOW handlePulse happens at most once per pulse interval. unix.read(pulseFd, &expirationCount, expirationCount.sizeof); - } else if (fd == customEventFD) { + } else if (fd == customEventFDRead) { // we have some custom events; process 'em import core.sys.posix.unistd : read; ulong n; - read(customEventFD, &n, n.sizeof); // reset counter value to zero again + read(customEventFDRead, &n, n.sizeof); // reset counter value to zero again //{ import core.stdc.stdio; printf("custom event! count=%u\n", eventQueueUsed); } //SimpleWindow.processAllCustomEvents(); } else { @@ -3109,18 +3126,72 @@ struct EventLoopImpl { // signal-based option, but I'm in no rush to write it since // I prefer the fd-based functions. while (!done && (whileCondition is null || whileCondition() == true) && notExited) { - while(!done && - (pulseTimeout == 0 || (XPending(display) > 0))) - { - this.mtLock(); - scope(exit) this.mtUnlock(); - done = doXNextEvent(this.display); + + import core.sys.posix.poll; + + pollfd[] pfds; + pollfd[32] pfdsBuffer; + auto len = PosixFdReader.mapping.length + 2; + // FIXME: i should just reuse the buffer + if(len < pfdsBuffer.length) + pfds = pfdsBuffer[0 .. len]; + else + pfds = new pollfd[](len); + + pfds[0].fd = display.fd; + pfds[0].events = POLLIN; + pfds[0].revents = 0; + + int slot = 1; + + if(customEventFDRead != -1) { + pfds[slot].fd = customEventFDRead; + pfds[slot].events = POLLIN; + pfds[slot].revents = 0; + + slot++; } - if(!done && pulseTimeout !=0) { + + foreach(fd, obj; PosixFdReader.mapping) { + if(!obj.enabled) continue; + pfds[slot].fd = fd; + pfds[slot].events = POLLIN; + pfds[slot].revents = 0; + + slot++; + } + + auto ret = poll(pfds.ptr, slot, pulseTimeout > 0 ? cast(int) pulseTimeout : -1); + if(ret == -1) throw new Exception("poll"); + + if(ret == 0) { + // FIXME it may not necessarily time out if events keep coming if(handlePulse !is null) handlePulse(); - import core.thread; - Thread.sleep(dur!"msecs"(pulseTimeout)); + } else { + foreach(s; 0 .. slot) { + if(pfds[s].revents == 0) continue; + + if(pfds[s].fd == display.fd) { + while(!done && XPending(display)) { + this.mtLock(); + scope(exit) this.mtUnlock(); + done = doXNextEvent(this.display); + } + } else if(customEventFDRead != -1 && pfds[s].fd == customEventFDRead) { + + import core.sys.posix.unistd : read; + ulong n; + read(customEventFDRead, &n, n.sizeof); + SimpleWindow.processAllCustomEvents(); + } else { + auto obj = PosixFdReader.mapping[pfds[s].fd]; + obj.ready(pfds[s].revents); + } + + ret--; + if(ret == 0) break; + } } } } @@ -4264,7 +4335,7 @@ class WindowsHandleReader { __gshared WindowsHandleReader[HANDLE] mapping; } -version(linux) +version(Posix) /// Lets you add files to the event loop for reading. Use at your own risk. class PosixFdReader { /// @@ -4302,12 +4373,18 @@ class PosixFdReader { void enable() { prepareEventLoop(); - static import ep = core.sys.linux.epoll; - ep.epoll_event ev = void; - ev.events = (captureReads ? ep.EPOLLIN : 0) | (captureWrites ? ep.EPOLLOUT : 0); - //import std.stdio; writeln("enable ", fd, " ", captureReads, " ", captureWrites); - ev.data.fd = fd; - ep.epoll_ctl(epollFd, ep.EPOLL_CTL_ADD, fd, &ev); + enabled = true; + + version(linux) { + static import ep = core.sys.linux.epoll; + ep.epoll_event ev = void; + ev.events = (captureReads ? ep.EPOLLIN : 0) | (captureWrites ? ep.EPOLLOUT : 0); + //import std.stdio; writeln("enable ", fd, " ", captureReads, " ", captureWrites); + ev.data.fd = fd; + ep.epoll_ctl(epollFd, ep.EPOLL_CTL_ADD, fd, &ev); + } else { + + } } version(with_eventloop) {} else @@ -4315,12 +4392,16 @@ class PosixFdReader { void disable() { prepareEventLoop(); - static import ep = core.sys.linux.epoll; - ep.epoll_event ev = void; - ev.events = (captureReads ? ep.EPOLLIN : 0) | (captureWrites ? ep.EPOLLOUT : 0); - //import std.stdio; writeln("disable ", fd, " ", captureReads, " ", captureWrites); - ev.data.fd = fd; - ep.epoll_ctl(epollFd, ep.EPOLL_CTL_DEL, fd, &ev); + enabled = false; + + version(linux) { + static import ep = core.sys.linux.epoll; + ep.epoll_event ev = void; + ev.events = (captureReads ? ep.EPOLLIN : 0) | (captureWrites ? ep.EPOLLOUT : 0); + //import std.stdio; writeln("disable ", fd, " ", captureReads, " ", captureWrites); + ev.data.fd = fd; + ep.epoll_ctl(epollFd, ep.EPOLL_CTL_DEL, fd, &ev); + } } version(with_eventloop) {} else @@ -4339,8 +4420,13 @@ class PosixFdReader { } void ready(uint flags) { - static import ep = core.sys.linux.epoll; - onReady(fd, (flags & ep.EPOLLIN) ? true : false, (flags & ep.EPOLLOUT) ? true : false); + version(linux) { + static import ep = core.sys.linux.epoll; + onReady(fd, (flags & ep.EPOLLIN) ? true : false, (flags & ep.EPOLLOUT) ? true : false); + } else { + import core.sys.posix.poll; + onReady(fd, (flags & POLLIN) ? true : false, (flags & POLLOUT) ? true : false); + } } void hup(uint flags) { @@ -4351,6 +4437,7 @@ class PosixFdReader { void delegate() onHup; int fd = -1; + private bool enabled; __gshared PosixFdReader[int] mapping; } @@ -9386,7 +9473,7 @@ version(X11) { // only if we are actually on the same machine does this // have any hope, and the query extension only asks if // the server can in theory, not in practice. - if(str is null || str[0] != ':') + if(str is null || (str[0] != ':' && str[0] != '/')) _xshmAvailable = false; else _xshmAvailable = XQueryExtension(XDisplayConnection.get(), "MIT-SHM", &i1, &i2, &i3) != 0; @@ -10060,10 +10147,15 @@ version(X11) { */ void closeWindow() { - if (customEventFD != -1) { + if (customEventFDRead != -1) { import core.sys.posix.unistd : close; - close(customEventFD); - customEventFD = -1; + auto same = customEventFDRead == customEventFDWrite; + + close(customEventFDRead); + if(!same) + close(customEventFDWrite); + customEventFDRead = -1; + customEventFDWrite = -1; } if(buffer) XFreePixmap(display, buffer); @@ -13260,7 +13352,8 @@ version(linux) { throw new Exception("epoll create failure"); } } - +} else version(Posix) { + void prepareEventLoop() {} } version(X11) {