2 Unix SMB/CIFS implementation.
4 main select loop and event handling
6 plugin for using a gtk application's event loop
8 Copyright (C) Stefan Metzmacher 2005
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "lib/events/events.h"
27 #include "lib/events/events_internal.h"
29 #include "gtk/common/select.h"
31 /* as gtk_main() doesn't take a parameter nor return one,
32 we need to have a global event context structure for our
35 static struct event_context
*gtk_event_context_global
;
37 static int gtk_event_context_destructor(void *ptr
)
39 gtk_event_context_global
= NULL
;
44 create a gtk_event_context structure.
46 static int gtk_event_context_init(struct event_context
*ev
, void *private_data
)
48 talloc_set_destructor(ev
, gtk_event_context_destructor
);
59 static gboolean
gtk_event_fd_handler(GIOChannel
*source
, GIOCondition condition
, gpointer data
)
61 struct fd_event
*fde
= talloc_get_type(data
, struct fd_event
);
62 struct gtk_fd_event
*gtk_fd
= talloc_get_type(fde
->additional_data
,
66 if (condition
& (G_IO_IN
|G_IO_PRI
|G_IO_ERR
|G_IO_HUP
))
67 flags
|= EVENT_FD_READ
;
68 if (condition
& G_IO_OUT
)
69 flags
|= EVENT_FD_WRITE
;
71 gtk_fd
->running
= True
;
72 fde
->handler(fde
->event_ctx
, fde
, flags
, fde
->private_data
);
73 gtk_fd
->running
= False
;
75 if (gtk_fd
->free_after_run
) {
86 static int gtk_event_fd_destructor(void *ptr
)
88 struct fd_event
*fde
= talloc_get_type(ptr
, struct fd_event
);
89 struct gtk_fd_event
*gtk_fd
= talloc_get_type(fde
->additional_data
,
92 if (gtk_fd
->running
) {
93 /* the event is running reject the talloc_free()
94 as it's done by the gtk_event_timed_handler()
96 gtk_fd
->free_after_run
= True
;
101 /* only if any flag is set we have really registered an event */
102 g_source_remove(gtk_fd
->fd_id
);
104 g_io_channel_unref(gtk_fd
->channel
);
111 return NULL on failure (memory allocation error)
113 static struct fd_event
*gtk_event_add_fd(struct event_context
*ev
, TALLOC_CTX
*mem_ctx
,
114 int fd
, uint16_t flags
,
115 event_fd_handler_t handler
,
118 struct fd_event
*fde
;
119 struct gtk_fd_event
*gtk_fd
;
122 GIOCondition condition
= 0;
124 fde
= talloc(mem_ctx
?mem_ctx
:ev
, struct fd_event
);
125 if (!fde
) return NULL
;
127 gtk_fd
= talloc(fde
, struct gtk_fd_event
);
128 if (gtk_fd
== NULL
) {
136 fde
->handler
= handler
;
137 fde
->private_data
= private_data
;
138 fde
->additional_data
= gtk_fd
;
140 channel
= g_io_channel_unix_new(fde
->fd
);
141 if (channel
== NULL
) {
146 if (fde
->flags
& EVENT_FD_READ
)
147 condition
|= G_IO_IN
;
148 if (fde
->flags
& EVENT_FD_WRITE
)
149 condition
|= G_IO_OUT
;
152 /* only register the event when at least one flag is set
153 as condition == 0 means wait for any event and is not the same
156 fd_id
= g_io_add_watch(channel
, condition
, gtk_event_fd_handler
, fde
);
159 gtk_fd
->running
= False
;
160 gtk_fd
->free_after_run
= False
;
161 gtk_fd
->channel
= channel
;
162 gtk_fd
->fd_id
= fd_id
;
164 talloc_set_destructor(fde
, gtk_event_fd_destructor
);
170 return the fd event flags
172 static uint16_t gtk_event_get_fd_flags(struct fd_event
*fde
)
180 set the fd event flags
182 static void gtk_event_set_fd_flags(struct fd_event
*fde
, uint16_t flags
)
184 struct gtk_fd_event
*gtk_fd
= talloc_get_type(fde
->additional_data
,
185 struct gtk_fd_event
);
186 GIOCondition condition
= 0;
190 if (fde
->flags
== flags
) return;
192 if (flags
& EVENT_FD_READ
)
193 condition
|= G_IO_IN
;
194 if (flags
& EVENT_FD_WRITE
)
195 condition
|= G_IO_OUT
;
197 /* only register the event when at least one flag is set
198 as condition == 0 means wait for any event and is not the same
202 g_source_remove(gtk_fd
->fd_id
);
205 gtk_fd
->fd_id
= g_io_add_watch(gtk_fd
->channel
, condition
, gtk_event_fd_handler
, fde
);
211 struct gtk_timed_event
{
216 static gboolean
gtk_event_timed_handler(gpointer data
)
218 struct timed_event
*te
= talloc_get_type(data
, struct timed_event
);
219 struct gtk_timed_event
*gtk_te
= talloc_get_type(te
->additional_data
,
220 struct gtk_timed_event
);
221 struct timeval t
= timeval_current();
223 gtk_te
->running
= True
;
224 te
->handler(te
->event_ctx
, te
, t
, te
->private_data
);
225 gtk_te
->running
= False
;
229 /* return FALSE mean this event should be removed */
234 destroy a timed event
236 static int gtk_event_timed_destructor(void *ptr
)
238 struct timed_event
*te
= talloc_get_type(ptr
, struct timed_event
);
239 struct gtk_timed_event
*gtk_te
= talloc_get_type(te
->additional_data
,
240 struct gtk_timed_event
);
242 if (gtk_te
->running
) {
243 /* the event is running reject the talloc_free()
244 as it's done by the gtk_event_timed_handler()
249 g_source_remove(gtk_te
->te_id
);
256 return NULL on failure (memory allocation error)
258 static struct timed_event
*gtk_event_add_timed(struct event_context
*ev
, TALLOC_CTX
*mem_ctx
,
259 struct timeval next_event
,
260 event_timed_handler_t handler
,
263 struct timed_event
*te
;
264 struct gtk_timed_event
*gtk_te
;
265 struct timeval cur_tv
, diff_tv
;
268 te
= talloc(mem_ctx
?mem_ctx
:ev
, struct timed_event
);
269 if (te
== NULL
) return NULL
;
271 gtk_te
= talloc(te
, struct gtk_timed_event
);
272 if (gtk_te
== NULL
) {
278 te
->next_event
= next_event
;
279 te
->handler
= handler
;
280 te
->private_data
= private_data
;
281 te
->additional_data
= gtk_te
;
283 cur_tv
= timeval_current();
284 diff_tv
= timeval_diff(&next_event
, &cur_tv
);
285 timeout
= ((diff_tv
.tv_usec
+999)/1000)+(diff_tv
.tv_sec
*1000);
287 gtk_te
->te_id
= g_timeout_add(timeout
, gtk_event_timed_handler
, te
);
288 gtk_te
->running
= False
;
290 talloc_set_destructor(te
, gtk_event_timed_destructor
);
296 do a single event loop
298 static int gtk_event_loop_once(struct event_context
*ev
)
301 * gtk_main_iteration ()
303 * gboolean gtk_main_iteration (void);
305 * Runs a single iteration of the mainloop. If no events
306 * are waiting to be processed GTK+ will block until the
307 * next event is noticed. If you don't want to block look
308 * at gtk_main_iteration_do() or check if any events are
309 * pending with gtk_events_pending() first.
311 * Returns : TRUE if gtk_main_quit() has been called for the innermost mainloop.
315 ret
= gtk_main_iteration();
316 if (ret
== gtk_true()) {
326 static int gtk_event_loop_wait(struct event_context
*ev
)
331 * void gtk_main (void);
333 * Runs the main loop until gtk_main_quit() is called.
334 * You can nest calls to gtk_main(). In that case
335 * gtk_main_quit() will make the innermost invocation
336 * of the main loop return.
342 static const struct event_ops gtk_event_ops
= {
343 .context_init
= gtk_event_context_init
,
344 .add_fd
= gtk_event_add_fd
,
345 .get_fd_flags
= gtk_event_get_fd_flags
,
346 .set_fd_flags
= gtk_event_set_fd_flags
,
347 .add_timed
= gtk_event_add_timed
,
348 .loop_once
= gtk_event_loop_once
,
349 .loop_wait
= gtk_event_loop_wait
,
352 int gtk_event_loop(void)
356 gtk_event_context_global
= event_context_init_ops(NULL
, >k_event_ops
, NULL
);
357 if (!gtk_event_context_global
) return -1;
359 ret
= event_loop_wait(gtk_event_context_global
);
361 talloc_free(gtk_event_context_global
);
366 struct event_context
*gtk_event_context(void)
368 return gtk_event_context_global
;