1 // Copyright © 2017-2021 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 }