1 // Copyright © 2017 Rémi Thebault 2 module wayland.server.eventloop; 3 4 import wayland.native.server; 5 import wayland.native.util; 6 import wayland.util; 7 8 class WlEventLoop : Native!wl_event_loop 9 { 10 mixin nativeImpl!(wl_event_loop); 11 12 alias DestroyDg = void delegate(WlEventLoop loop); 13 alias FdDg = int delegate (int fd, uint mask); 14 alias TimerDg = int delegate (); 15 alias SignalDg = int delegate (int sigNum); 16 alias IdleDg = void delegate (); 17 18 private wl_listener _destroyListener; 19 private DestroyDg _onDestroy; 20 21 this (wl_event_loop* native) 22 { 23 _native = native; 24 ObjectCache.set(native, this); 25 26 wl_list_init(&_destroyListener.link); 27 _destroyListener.notify = &wl_d_eventloop_destroy; 28 wl_event_loop_add_destroy_listener(native, &_destroyListener); 29 } 30 31 this() 32 { 33 this(wl_event_loop_create()); 34 } 35 36 void destroy() 37 { 38 wl_event_loop_destroy(_native); 39 } 40 41 @property void destroyListener(DestroyDg dg) 42 { 43 _onDestroy = dg; 44 } 45 46 @property int fd() 47 { 48 return wl_event_loop_get_fd(native); 49 } 50 51 int dispatch(int timeout) 52 { 53 return wl_event_loop_dispatch(native, timeout); 54 } 55 56 void dispatchIdle() 57 { 58 wl_event_loop_dispatch_idle(native); 59 } 60 61 WlFdEventSource addFd(int fd, uint mask, FdDg dg) 62 { 63 return new WlFdEventSource(native, fd, mask, dg); 64 } 65 66 WlTimerEventSource addTimer(TimerDg dg) 67 { 68 return new WlTimerEventSource(native, dg); 69 } 70 71 WlSignalEventSource addSignal(int signalNum, SignalDg dg) 72 { 73 return new WlSignalEventSource(native, signalNum, dg); 74 } 75 76 WlIdleEventSource addIdle(IdleDg dg) 77 { 78 return new WlIdleEventSource(native, dg); 79 } 80 } 81 82 abstract class WlEventSource : Native!wl_event_source 83 { 84 mixin nativeImpl!(wl_event_source); 85 86 this(wl_event_source* native) 87 { 88 _native = native; 89 } 90 91 int remove () 92 { 93 return wl_event_source_remove(native); 94 } 95 96 void check() 97 { 98 wl_event_source_check(native); 99 } 100 } 101 102 class WlFdEventSource : WlEventSource 103 { 104 private WlEventLoop.FdDg dg; 105 106 this (wl_event_loop* nativeLoop, int fd, uint mask, WlEventLoop.FdDg dg) 107 { 108 this.dg = dg; 109 super(wl_event_loop_add_fd( 110 nativeLoop, fd, mask, &wl_d_eventloop_fd, cast(void*)this 111 )); 112 } 113 114 int update(uint mask) 115 { 116 return wl_event_source_fd_update(native, mask); 117 } 118 } 119 120 class WlTimerEventSource : WlEventSource 121 { 122 private WlEventLoop.TimerDg dg; 123 124 this (wl_event_loop* nativeLoop, WlEventLoop.TimerDg dg) 125 { 126 this.dg = dg; 127 super(wl_event_loop_add_timer( 128 nativeLoop, &wl_d_eventloop_timer, cast(void*)this 129 )); 130 } 131 132 int update(uint msDelay) 133 { 134 return wl_event_source_timer_update(native, msDelay); 135 } 136 } 137 138 class WlSignalEventSource : WlEventSource 139 { 140 private WlEventLoop.SignalDg dg; 141 142 this (wl_event_loop* nativeLoop, int signalNum, WlEventLoop.SignalDg dg) 143 { 144 this.dg = dg; 145 super(wl_event_loop_add_signal( 146 nativeLoop, signalNum, &wl_d_eventloop_signal, cast(void*)this 147 )); 148 } 149 } 150 151 class WlIdleEventSource : WlEventSource 152 { 153 private WlEventLoop.IdleDg dg; 154 155 this (wl_event_loop* nativeLoop, WlEventLoop.IdleDg dg) 156 { 157 this.dg = dg; 158 super(wl_event_loop_add_idle( 159 nativeLoop, &wl_d_eventloop_idle, cast(void*)this 160 )); 161 } 162 } 163 164 165 private extern(C) nothrow 166 { 167 168 void wl_d_eventloop_destroy(wl_listener*, void* data) 169 { 170 nothrowFnWrapper!({ 171 auto el = cast(WlEventLoop)ObjectCache.get(data); 172 assert(el, "wl_d_eventloop_destroy: could not get event loop from cache"); 173 if (el._onDestroy) el._onDestroy(el); 174 ObjectCache.remove(data); 175 }); 176 } 177 178 int wl_d_eventloop_fd(int fd, uint mask, void* data) 179 { 180 return nothrowFnWrapper!({ 181 auto src = cast(WlFdEventSource)data; 182 return src.dg(fd, mask); 183 }); 184 } 185 186 int wl_d_eventloop_timer(void* data) 187 { 188 return nothrowFnWrapper!({ 189 auto src = cast(WlTimerEventSource)data; 190 return src.dg(); 191 }); 192 } 193 194 int wl_d_eventloop_signal(int sigNumber, void* data) 195 { 196 return nothrowFnWrapper!({ 197 auto src = cast(WlSignalEventSource)data; 198 return src.dg(sigNumber); 199 }); 200 } 201 202 void wl_d_eventloop_idle(void* data) 203 { 204 nothrowFnWrapper!({ 205 auto src = cast(WlIdleEventSource)data; 206 src.dg(); 207 }); 208 } 209 }