summaryrefslogtreecommitdiff
path: root/ecore/src/e_events.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--ecore/src/e_events.c430
1 files changed, 430 insertions, 0 deletions
diff --git a/ecore/src/e_events.c b/ecore/src/e_events.c
new file mode 100644
index 0000000..0a8f442
--- /dev/null
+++ b/ecore/src/e_events.c
@@ -0,0 +1,430 @@
+#include "Ecore.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* glocal (yes global/local) variabels for events */
+Ecore_Event_Fd_Handler *fd_handlers = NULL;
+Ecore_Event_Ipc_Handler *ipc_handlers = NULL;
+Ecore_Event_Pid_Handler *pid_handlers = NULL;
+Ecore_Event_Timer *timers = NULL;
+
+Ecore_Event *events = NULL;
+Ecore_Event *last_event = NULL;
+
+int __quit_ev_loop = 0;
+
+/* local functions for event handling */
+static void ecore_handle_event_timer(void);
+static void ecore_handle_zero_event_timer(void);
+
+/* public functions */
+
+/* add an event to the end of the event queue */
+void
+ecore_add_event(Ecore_Event_Type type, void *event,
+ void (*ev_free) (void *event))
+{
+ Ecore_Event *ev;
+
+ ev = NEW(Ecore_Event, 1);
+ ev->type = type;
+ ev->ignore = 0;
+ ev->event = event;
+ ev->next = NULL;
+ ev->ev_free = ev_free;
+ if (!events)
+ events = ev;
+ else
+ last_event->next = ev;
+ last_event = ev;
+}
+
+/* delete an event from the event queue */
+void
+ecore_del_event(void *event)
+{
+ Ecore_Event *ev, *pev;
+
+ pev = NULL;
+ ev = events;
+ while (ev)
+ {
+ if (ev->event == event)
+ {
+ if (pev)
+ pev->next = ev->next;
+ else
+ events = ev->next;
+ if (!ev->next)
+ last_event = pev;
+ if ((ev->event) && (ev->ev_free))
+ (*ev->ev_free) (ev->event);
+ FREE(ev);
+ return;
+ }
+ pev = ev;
+ ev = ev->next;
+ }
+}
+
+void
+ecore_del_all_events(void)
+{
+ Ecore_Event *ev, *pev;
+
+ ev = events;
+ while (ev)
+ {
+ pev = ev;
+ ev = ev->next;
+ if ((pev->event) && (pev->ev_free))
+ pev->ev_free(pev->event);
+ FREE(pev);
+ }
+ events = NULL;
+ last_event = NULL;
+}
+
+Ecore_Event *
+ecore_get_last_event(void)
+{
+ return last_event;
+}
+
+/* add a callback handler if fd is active for reading */
+void
+ecore_add_event_fd(int fd, void (*func) (int fd))
+{
+ Ecore_Event_Fd_Handler *fd_h;
+
+ /* new handler struct */
+ fd_h = NEW(Ecore_Event_Fd_Handler, 1);
+ fd_h->next = fd_handlers;
+ fd_h->fd = fd;
+ fd_h->func = func;
+ fd_handlers = fd_h;
+}
+
+/* delete handler for fd */
+void
+ecore_del_event_fd(int fd)
+{
+ START_LIST_DEL(Ecore_Event_Fd_Handler, fd_handlers, (_p->fd == fd));
+ FREE(_p);
+ END_LIST_DEL;
+}
+
+void
+ecore_add_event_pid(pid_t pid, void (*func) (pid_t pid))
+{
+ Ecore_Event_Pid_Handler *pid_h;
+
+ /* delete the old handler */
+ ecore_del_event_pid(pid);
+ /* new handler struct */
+ pid_h = NEW(Ecore_Event_Pid_Handler, 1);
+ pid_h->next = pid_handlers;
+ pid_h->pid = pid;
+ pid_h->func = func;
+ pid_handlers = pid_h;
+}
+
+void
+ecore_del_event_pid(pid_t pid)
+{
+ START_LIST_DEL(Ecore_Event_Pid_Handler, pid_handlers, (_p->pid == pid));
+ FREE(_p);
+ END_LIST_DEL;
+}
+
+void
+ecore_add_event_ipc(int ipc, void (*func) (int ipc))
+{
+ Ecore_Event_Ipc_Handler *ipc_h;
+
+ /* delete the old handler */
+ ecore_del_event_ipc(ipc);
+ /* new handler struct */
+ ipc_h = NEW(Ecore_Event_Ipc_Handler, 1);
+ ipc_h->next = ipc_handlers;
+ ipc_h->ipc = ipc;
+ ipc_h->func = func;
+ ipc_handlers = ipc_h;
+}
+
+void
+ecore_del_event_ipc(int ipc)
+{
+ START_LIST_DEL(Ecore_Event_Ipc_Handler, ipc_handlers, (_p->ipc == ipc));
+ FREE(_p);
+ END_LIST_DEL;
+}
+
+/* sit in this loop forever and process events */
+void
+ecore_event_loop(void)
+{
+ int fdcount, fdsize, ipccount, ipcsize;
+ int timed_out, were_events;
+ double time1, time2, prev_time = 0.0;
+ struct timeval tval;
+ fd_set fdset, ipcset;
+ Ecore_Event_Fd_Handler *fd_h;
+ Ecore_Event_Pid_Handler *pid_h;
+ Ecore_Event_Ipc_Handler *ipc_h;
+
+ /* init some of the time variables */
+ time1 = ecore_get_time();
+ time2 = time1 - prev_time;
+ prev_time = time1;
+ while (__quit_ev_loop == 0)
+ {
+ /* state setup */
+ timed_out = 0;
+ were_events = 0;
+
+ /* setup fd array from list of listening fd's */
+ fdsize = 0;
+ FD_ZERO(&fdset);
+ /* for ever fd handler add the fd to the array and incriment fdsize */
+ for (fd_h = fd_handlers; fd_h; fd_h = fd_h->next)
+ {
+ FD_SET(fd_h->fd, &fdset);
+ if (fd_h->fd > fdsize)
+ fdsize = fd_h->fd;
+ }
+ fdcount = 1;
+ ipcsize = 0;
+ FD_ZERO(&ipcset);
+ /* for ever fd handler add the fd to the array and incriment fdsize */
+ for (ipc_h = ipc_handlers; ipc_h; ipc_h = ipc_h->next)
+ {
+ FD_SET(ipc_h->ipc, &ipcset);
+ if (ipc_h->ipc > ipcsize)
+ ipcsize = ipc_h->ipc;
+ }
+ ipccount = 1;
+ /* if there are timers setup adjust timeout value and select */
+ if (timers)
+ {
+ if (timers->just_added)
+ {
+ timers->just_added = 0;
+ time1 = timers->in;
+ }
+ else
+ {
+ time1 = timers->in - time2;
+ if (time1 < 0.0)
+ time1 = 0.0;
+ timers->in = time1;
+ }
+ tval.tv_sec = (long)time1;
+ tval.tv_usec = (long)((time1 - ((double)tval.tv_sec)) * 1000000);
+ if (tval.tv_sec < 0)
+ tval.tv_sec = 0;
+ if (tval.tv_usec <= 1000)
+ tval.tv_usec = 1000;
+ ecore_handle_zero_event_timer();
+ if ((!ecore_events_pending()) && (!ecore_event_signal_events_pending()))
+ fdcount = select(fdsize + 1, &fdset, NULL, NULL, &tval);
+ }
+ /* no timers - just sit and block */
+ else
+ {
+ if ((!ecore_events_pending()) && (!ecore_event_signal_events_pending()))
+ fdcount = select(fdsize + 1, &fdset, NULL, NULL, NULL);
+ }
+ for (pid_h = pid_handlers; pid_h; pid_h = pid_h->next)
+ pid_h->func(pid_h->pid);
+
+ /* see if we have any new ipc connections */
+ tval.tv_sec = 0;
+ tval.tv_usec = 0;
+ ipccount += select(ipcsize + 1, &ipcset, NULL, NULL, &tval);
+
+ /* return < 0 - error or signal interrupt */
+ if (fdcount < 0)
+ {
+ /* error */
+ if ((errno == ENOMEM) || (errno == EINVAL) || (errno == EBADF))
+ {
+ fprintf(stderr, "Lost connection to X display.\n");
+ exit(1);
+ }
+ }
+ /* timers are available and its a timeout */
+ if ((timers) && (fdcount == 0))
+ {
+ ecore_handle_event_timer();
+ timed_out = 1;
+ }
+ if (fdcount < 0)
+ fdcount = 0;
+ if (ecore_events_pending())
+ {
+ fdcount++;
+ FD_SET(ecore_x_get_fd(), &fdset);
+ }
+ /* fd's are active */
+ if (fdcount > 0)
+ {
+ /* for every fd handler - if its fd is set - call the func */
+ for (fd_h = fd_handlers; fd_h;)
+ {
+ Ecore_Event_Fd_Handler *fdh;
+
+ fdh = fd_h;
+ fd_h = fd_h->next;
+ if (FD_ISSET(fdh->fd, &fdset))
+ fdh->func(fdh->fd);
+ }
+ }
+
+ /* ipc clients are active */
+ if (ipccount > 0)
+ {
+ for (ipc_h = ipc_handlers; ipc_h;)
+ {
+ Ecore_Event_Ipc_Handler *ipch;
+
+ ipch = ipc_h;
+ ipc_h = ipc_h->next;
+ if (FD_ISSET(ipch->ipc, &ipcset))
+ ipch->func(ipch->ipc);
+ }
+ }
+ if (events)
+ ecore_event_filter(events);
+ if (events)
+ {
+ ecore_event_filter_events_handle(events);
+ were_events = 1;
+ }
+ ecore_del_all_events();
+ if ((timed_out) || (were_events))
+ ecore_event_filter_idle_handle();
+ ecore_flush();
+ time1 = ecore_get_time();
+ time2 = time1 - prev_time;
+ prev_time = time1;
+ }
+ __quit_ev_loop = 0;
+}
+
+/* set a flag to 0 so that we can quit the event loop and shutdown
+ * properly */
+void
+ecore_event_loop_quit(void)
+{
+ __quit_ev_loop = 1;
+}
+
+/* add a timeout funcitont o be called in "in" seconds with name name */
+void
+ecore_add_event_timer(char *name, double in, void (*func) (int val, void *data),
+ int val, void *data)
+{
+ Ecore_Event_Timer *timer, *ptr, *pptr;
+ double tally;
+
+ if (name)
+ ecore_del_event_timer(name);
+ timer = NEW(Ecore_Event_Timer, 1);
+ timer->next = NULL;
+ timer->func = func;
+ timer->data = data;
+ timer->val = val;
+ timer->just_added = 1;
+ timer->in = in;
+ timer->name = strdup(name);
+ if (!timers)
+ timers = timer;
+ else
+ {
+ pptr = NULL;
+ ptr = timers;
+ tally = 0.0;
+ while (ptr)
+ {
+ tally += ptr->in;
+ if (tally > in)
+ {
+ tally -= ptr->in;
+ timer->next = ptr;
+ if (pptr)
+ pptr->next = timer;
+ else
+ timers = timer;
+ timer->in -= tally;
+ if (timer->next)
+ timer->next->in -= timer->in;
+ return;
+ }
+ pptr = ptr;
+ ptr = ptr->next;
+ }
+ if (pptr)
+ pptr->next = timer;
+ else
+ timers = timer;
+ timer->in -= tally;
+ }
+}
+
+/* delete a timer timeout entry named "name" */
+void *
+ecore_del_event_timer(char *name)
+{
+ Ecore_Event_Timer *timer, *ptr, *pptr;
+
+ pptr = NULL;
+ ptr = timers;
+ while (ptr)
+ {
+ timer = ptr;
+ if (!strcmp(timer->name, name))
+ {
+ void *data;
+
+ if (pptr)
+ pptr->next = timer->next;
+ else
+ timers = timer->next;
+ if (timer->next)
+ timer->next->in += timer->in;
+ IF_FREE(timer->name);
+ data = timer->data;
+ FREE(timer);
+ return data;
+ }
+ pptr = ptr;
+ ptr = ptr->next;
+ }
+ return NULL;
+}
+
+/* private functions */
+static void
+ecore_handle_event_timer(void)
+{
+ Ecore_Event_Timer *timer;
+
+ if (!timers)
+ return;
+ timer = timers;
+ timers = timer->next;
+ (*(timer->func)) (timer->val, timer->data);
+ IF_FREE(timer->name);
+ FREE(timer);
+}
+
+static void
+ecore_handle_zero_event_timer(void)
+{
+ while ((timers) && (timers->in == 0.0))
+ ecore_handle_event_timer();
+}