diff options
Diffstat (limited to 'matchbox2/mb-wm-main-context.c')
-rw-r--r-- | matchbox2/mb-wm-main-context.c | 1116 |
1 files changed, 1116 insertions, 0 deletions
diff --git a/matchbox2/mb-wm-main-context.c b/matchbox2/mb-wm-main-context.c new file mode 100644 index 0000000..71d5d6c --- /dev/null +++ b/matchbox2/mb-wm-main-context.c @@ -0,0 +1,1116 @@ +#include "mb-wm-main-context.h" + +#include <sys/time.h> +#include <poll.h> +#include <limits.h> +#include <fcntl.h> + +#if ENABLE_COMPOSITE +#include <X11/extensions/Xdamage.h> +#endif + +#define MBWM_CTX_MAX_TIMEOUT 100 + +#if MBWM_WANT_DEBUG + +static const char *MBWMDEBUGEvents[] = { + "error", + "reply", + "KeyPress", + "KeyRelease", + "ButtonPress", + "ButtonRelease", + "MotionNotify", + "EnterNotify", + "LeaveNotify", + "FocusIn", + "FocusOut", + "KeymapNotify", + "Expose", + "GraphicsExpose", + "NoExpose", + "VisibilityNotify", + "CreateNotify", + "DestroyNotify", + "UnmapNotify", + "MapNotify", + "MapRequest", + "ReparentNotify", + "ConfigureNotify", + "ConfigureRequest", + "GravityNotify", + "ResizeRequest", + "CirculateNotify", + "CirculateRequest", + "PropertyNotify", + "SelectionClear", + "SelectionRequest", + "SelectionNotify", + "ColormapNotify", + "ClientMessage", + "MappingNotify", +}; + +#endif + +static Bool +mb_wm_main_context_check_timeouts (MBWMMainContext *ctx); + +static Bool +mb_wm_main_context_check_fd_watches (MBWMMainContext * ctx); + +static Bool +mb_wm_main_context_spin_xevent (MBWMMainContext *ctx); + +struct MBWMTimeOutEventInfo +{ + int ms; + MBWindowManagerTimeOutFunc func; + void *userdata; + unsigned long id; + struct timeval triggers; + +}; + +struct MBWMFdWatchInfo{ + MBWMIOChannel *channel; + MBWMIOCondition events; + MBWindowManagerFdWatchFunc func; + void *userdata; + unsigned long id; +}; + +static void +mb_wm_main_context_class_init (MBWMObjectClass *klass) +{ +#if MBWM_WANT_DEBUG + klass->klass_name = "MBWMMainContext"; +#endif +} + +static void +mb_wm_main_context_destroy (MBWMObject *this) +{ +} + +#if USE_GLIB_MAINLOOP +gboolean +mb_wm_main_context_gloop_xevent (gpointer userdata) +{ + MBWMMainContext * ctx = userdata; + MBWindowManager * wm = ctx->wm; + + while (mb_wm_main_context_spin_xevent (ctx)); + + if (wm->sync_type) + mb_wm_sync (wm); + + return TRUE; +} +#endif + +static int +mb_wm_main_context_init (MBWMObject *this, va_list vap) +{ + MBWMMainContext *ctx = MB_WM_MAIN_CONTEXT (this); + MBWindowManager *wm = NULL; + MBWMObjectProp prop; + + prop = va_arg(vap, MBWMObjectProp); + while (prop) + { + if (prop == MBWMObjectPropWm) + { + wm = va_arg(vap, MBWindowManager *); + break; + } + else + MBWMO_PROP_EAT (vap, prop); + + prop = va_arg (vap, MBWMObjectProp); + } + + ctx->wm = wm; + + return 1; +} + +int +mb_wm_main_context_class_type () +{ + static int type = 0; + + if (UNLIKELY(type == 0)) + { + static MBWMObjectClassInfo info = { + sizeof (MBWMMainContextClass), + sizeof (MBWMMainContext), + mb_wm_main_context_init, + mb_wm_main_context_destroy, + mb_wm_main_context_class_init + }; + type = mb_wm_object_register_class (&info, MB_WM_TYPE_OBJECT, 0); + } + + return type; +} + +MBWMMainContext* +mb_wm_main_context_new (MBWindowManager *wm) +{ + MBWMMainContext *ctx; + + ctx = MB_WM_MAIN_CONTEXT (mb_wm_object_new (MB_WM_TYPE_MAIN_CONTEXT, + MBWMObjectPropWm, wm, + NULL)); + + return ctx; +} + +Bool +mb_wm_main_context_handle_x_event (XEvent *xev, + MBWMMainContext *ctx) +{ + MBWindowManager *wm = ctx->wm; + MBWMList *iter; + Window xwin = xev->xany.window; + +#if (MBWM_WANT_DEBUG) + { + if (mbwm_debug_flags & MBWM_DEBUG_EVENT) + { + MBWindowManagerClient *ev_client; + + ev_client = mb_wm_managed_client_from_xwindow(wm, xev->xany.window); + + printf (" @ XEvent: '%s:%i' for %lx %s%s\n", + xev->type < sizeof (MBWMDEBUGEvents)/sizeof(MBWMDEBUGEvents[0]) + ? MBWMDEBUGEvents[xev->type] : "unknown", + xev->type, + xev->xany.window, + xev->xany.window == wm->root_win->xwindow ? "(root)" : "", + ev_client ? ev_client->name : "" + ); + } + } +#endif + +#define XE_ITER_GET_FUNC(i) (((MBWMXEventFuncInfo *)((i)->data))->func) +#define XE_ITER_GET_DATA(i) ((MBWMXEventFuncInfo *)((i)->data))->userdata +#define XE_ITER_GET_XWIN(i) ((MBWMXEventFuncInfo *)((i)->data))->xwindow + +#if ENABLE_COMPOSITE + if (xev->type == wm->damage_event_base + XDamageNotify) + { + iter = ctx->event_funcs.damage_notify; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + MBWMList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWMXEventFunc)XE_ITER_GET_FUNC(iter) + (xev, XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + } + else +#endif + switch (xev->type) + { + case ClientMessage: + /* + * TODO -- perhaps this should not be special-cased. + */ + if (xev->xany.window == wm->root_win->xwindow || + ((XClientMessageEvent *)xev)->message_type == + wm->atoms[MBWM_ATOM_NET_ACTIVE_WINDOW] || + ((XClientMessageEvent *)xev)->message_type == + wm->atoms[MBWM_ATOM_NET_WM_STATE]) + { + mb_wm_root_window_handle_message (wm->root_win, + (XClientMessageEvent *)xev); + } + + iter = ctx->event_funcs.client_message; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + MBWMList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWindowManagerClientMessageFunc)XE_ITER_GET_FUNC(iter) + ((XClientMessageEvent*)&xev->xclient, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + case Expose: + break; + case MapRequest: + iter = ctx->event_funcs.map_request; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + MBWMList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWindowManagerMapRequestFunc)XE_ITER_GET_FUNC(iter) + ((XMapRequestEvent*)&xev->xmaprequest, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + case MapNotify: + iter = ctx->event_funcs.map_notify; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + MBWMList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWindowManagerMapNotifyFunc)XE_ITER_GET_FUNC(iter) + ((XMapEvent*)&xev->xmap, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + case UnmapNotify: +#if MBWM_WANT_DEBUG + if (mbwm_debug_flags & MBWM_DEBUG_EVENT) + { + XUnmapEvent * uev = & xev->xunmap; + printf (" window %x, event %x, %d\n", + uev->window, + uev->event, + uev->from_configure); + } +#endif + xwin = xev->xunmap.window; + iter = ctx->event_funcs.unmap_notify; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + MBWMList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWindowManagerUnmapNotifyFunc)XE_ITER_GET_FUNC(iter) + ((XUnmapEvent*)&xev->xunmap, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + case DestroyNotify: + iter = ctx->event_funcs.destroy_notify; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + MBWMList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWindowManagerDestroyNotifyFunc)XE_ITER_GET_FUNC(iter) + ((XDestroyWindowEvent*)&xev->xdestroywindow, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + case ConfigureNotify: +#if MBWM_WANT_DEBUG + if (mbwm_debug_flags & MBWM_DEBUG_EVENT) + { + XConfigureEvent * cev = & xev->xconfigure; + printf (" window %x, event %x, [%d,%d;%dx%d]\n", + cev->window, + cev->event, + cev->x, + cev->y, + cev->width, + cev->height); + } +#endif + xwin = xev->xconfigure.window; + iter = ctx->event_funcs.configure_notify; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + MBWMList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWindowManagerConfigureNotifyFunc)XE_ITER_GET_FUNC(iter) + ((XConfigureEvent*)&xev->xconfigure, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + case ConfigureRequest: +#if MBWM_WANT_DEBUG + if (mbwm_debug_flags & MBWM_DEBUG_EVENT) + { + XConfigureRequestEvent * cev = & xev->xconfigurerequest; + printf (" window %x, parent %x, [%d,%d;%dx%d]\n", + cev->window, + cev->parent, + cev->x, + cev->y, + cev->width, + cev->height); + } +#endif + xwin = xev->xconfigurerequest.window; + iter = ctx->event_funcs.configure_request; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + MBWMList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWindowManagerConfigureRequestFunc)XE_ITER_GET_FUNC(iter) + ((XConfigureRequestEvent*)&xev->xconfigurerequest, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + case KeyPress: + iter = ctx->event_funcs.key_press; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + MBWMList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWindowManagerKeyPressFunc)XE_ITER_GET_FUNC(iter) + ((XKeyEvent*)&xev->xkey, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + case PropertyNotify: +#if MBWM_WANT_DEBUG + if (mbwm_debug_flags & MBWM_DEBUG_EVENT) + { + XPropertyEvent * pev = & xev->xproperty; + char * prop = XGetAtomName (wm->xdpy, pev->atom); + printf (" window %x, prop %s, state %d\n", + pev->window, + prop, + pev->state); + + if (prop) + XFree (prop); + } +#endif + xwin = xev->xproperty.window; + iter = ctx->event_funcs.property_notify; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + MBWMList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWindowManagerPropertyNotifyFunc)XE_ITER_GET_FUNC(iter) + ((XPropertyEvent*)&xev->xproperty, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + case ButtonPress: + iter = ctx->event_funcs.button_press; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + MBWMList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWindowManagerButtonPressFunc)XE_ITER_GET_FUNC(iter) + ((XButtonEvent*)&xev->xbutton, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + case ButtonRelease: + iter = ctx->event_funcs.button_release; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + MBWMList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWindowManagerButtonReleaseFunc)XE_ITER_GET_FUNC(iter) + ((XButtonEvent*)&xev->xbutton, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + case MotionNotify: + iter = ctx->event_funcs.motion_notify; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + MBWMList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWindowManagerMotionNotifyFunc)XE_ITER_GET_FUNC(iter) + ((XMotionEvent*)&xev->xmotion, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + } + + return False; +} + +static Bool +mb_wm_main_context_spin_xevent (MBWMMainContext *ctx) +{ + MBWindowManager * wm = ctx->wm; + XEvent xev; + + if (!XEventsQueued (wm->xdpy, QueuedAfterFlush)) + return False; + + XNextEvent(wm->xdpy, &xev); + + mb_wm_main_context_handle_x_event (&xev, ctx); + + return (XEventsQueued (wm->xdpy, QueuedAfterReading) != 0); +} + +static Bool +mb_wm_main_context_spin_xevent_blocking (MBWMMainContext *ctx) +{ + MBWindowManager * wm = ctx->wm; + XEvent xev; + + XNextEvent(wm->xdpy, &xev); + + mb_wm_main_context_handle_x_event (&xev, ctx); + + return (XEventsQueued (wm->xdpy, QueuedAfterReading) != 0); +} + +void +mb_wm_main_context_loop (MBWMMainContext *ctx) +{ +#if ! USE_GLIB_MAINLOOP + MBWindowManager * wm = ctx->wm; + + while (True) + { + Bool sources; + + sources = mb_wm_main_context_check_timeouts (ctx); + sources |= mb_wm_main_context_check_fd_watches (ctx); + + if (!sources) + { + /* No timeouts, idles, etc. -- wait for next + * X event + */ + mb_wm_main_context_spin_xevent_blocking (ctx); + } + else + { + /* Process any pending xevents */ + while (mb_wm_main_context_spin_xevent (ctx)); + } + + if (wm->sync_type) + mb_wm_sync (wm); + } +#endif +} + +Bool +mb_wm_main_context_spin_loop (MBWMMainContext *ctx) +{ +#if USE_GLIB_MAINLOOP + g_main_context_iteration (NULL, FALSE); + return g_main_context_pending (NULL); +#else + return mb_wm_main_context_spin_xevent (ctx); +#endif +} + + +unsigned long +mb_wm_main_context_x_event_handler_add (MBWMMainContext *ctx, + Window xwin, + int type, + MBWMXEventFunc func, + void *userdata) +{ + static unsigned long ids = 0; + MBWMXEventFuncInfo * func_info; +#if ENABLE_COMPOSITE + MBWindowManager * wm = ctx->wm; +#endif + + ++ids; + + func_info = mb_wm_util_malloc0(sizeof(MBWMXEventFuncInfo)); + func_info->func = func; + func_info->xwindow = xwin; + func_info->userdata = userdata; + func_info->id = ids; + +#if ENABLE_COMPOSITE + if (type == wm->damage_event_base + XDamageNotify) + { + ctx->event_funcs.damage_notify = + mb_wm_util_list_append (ctx->event_funcs.damage_notify, func_info); + } + else +#endif + switch (type) + { + case Expose: + break; + case MapRequest: + ctx->event_funcs.map_request = + mb_wm_util_list_append (ctx->event_funcs.map_request, func_info); + break; + case MapNotify: + ctx->event_funcs.map_notify= + mb_wm_util_list_append (ctx->event_funcs.map_notify, func_info); + break; + case UnmapNotify: + ctx->event_funcs.unmap_notify= + mb_wm_util_list_append (ctx->event_funcs.unmap_notify, func_info); + break; + case DestroyNotify: + ctx->event_funcs.destroy_notify = + mb_wm_util_list_append (ctx->event_funcs.destroy_notify, func_info); + break; + case ConfigureNotify: + ctx->event_funcs.configure_notify = + mb_wm_util_list_append (ctx->event_funcs.configure_notify, func_info); + break; + case ConfigureRequest: + ctx->event_funcs.configure_request = + mb_wm_util_list_append (ctx->event_funcs.configure_request, func_info); + break; + case KeyPress: + ctx->event_funcs.key_press = + mb_wm_util_list_append (ctx->event_funcs.key_press, func_info); + break; + case PropertyNotify: + ctx->event_funcs.property_notify = + mb_wm_util_list_append (ctx->event_funcs.property_notify, func_info); + break; + case ButtonPress: + ctx->event_funcs.button_press = + mb_wm_util_list_append (ctx->event_funcs.button_press, func_info); + break; + case ButtonRelease: + ctx->event_funcs.button_release = + mb_wm_util_list_append (ctx->event_funcs.button_release, func_info); + break; + case MotionNotify: + ctx->event_funcs.motion_notify = + mb_wm_util_list_append (ctx->event_funcs.motion_notify, func_info); + break; + case ClientMessage: + ctx->event_funcs.client_message = + mb_wm_util_list_append (ctx->event_funcs.client_message, func_info); + break; + + default: + break; + } + + return ids; +} + +void +mb_wm_main_context_x_event_handler_remove (MBWMMainContext *ctx, + int type, + unsigned long id) +{ + MBWMList * l = NULL; + MBWMList **l_start; + +#if ENABLE_COMPOSITE + MBWindowManager * wm = ctx->wm; + + if (type == wm->damage_event_base + XDamageNotify) + { + l_start = &ctx->event_funcs.damage_notify; + } + else +#endif + switch (type) + { + case Expose: + break; + case MapRequest: + l_start = &ctx->event_funcs.map_request; + break; + case MapNotify: + l_start = &ctx->event_funcs.map_notify; + break; + case UnmapNotify: + l_start = &ctx->event_funcs.unmap_notify; + break; + case DestroyNotify: + l_start = &ctx->event_funcs.destroy_notify; + break; + case ConfigureNotify: + l_start = &ctx->event_funcs.configure_notify; + break; + case ConfigureRequest: + l_start = &ctx->event_funcs.configure_request; + break; + case KeyPress: + l_start = &ctx->event_funcs.key_press; + break; + case PropertyNotify: + l_start = &ctx->event_funcs.property_notify; + break; + case ButtonPress: + l_start = &ctx->event_funcs.button_press; + break; + case ButtonRelease: + l_start = &ctx->event_funcs.button_release; + break; + case MotionNotify: + l_start = &ctx->event_funcs.motion_notify; + break; + case ClientMessage: + l_start = &ctx->event_funcs.client_message; + break; + + default: + break; + } + + l = *l_start; + + while (l) + { + MBWMXEventFuncInfo * info = l->data; + + if (info->id == id) + { + MBWMList * prev = l->prev; + MBWMList * next = l->next; + + if (prev) + prev->next = next; + else + *l_start = next; + + if (next) + next->prev = prev; + + free (info); + free (l); + + return; + } + + l = l->next; + } +} + +#if ! USE_GLIB_MAINLOOP +static void +mb_wm_main_context_timeout_setup (MBWMTimeOutEventInfo * tinfo, + struct timeval * current_time) +{ + int sec = tinfo->ms / 1000; + int usec = (tinfo->ms - sec *1000) * 1000; + + sec += current_time->tv_sec; + usec += current_time->tv_usec; + + if (usec >= 1000000) + { + usec -= 1000000; + sec++; + } + + tinfo->triggers.tv_sec = sec; + tinfo->triggers.tv_usec = usec; +} + +static Bool +mb_wm_main_context_handle_timeout (MBWMTimeOutEventInfo *tinfo, + struct timeval *current_time) +{ + if (tinfo->triggers.tv_sec < current_time->tv_sec || + (tinfo->triggers.tv_sec == current_time->tv_sec && + tinfo->triggers.tv_usec <= current_time->tv_usec)) + { + if (!tinfo->func (tinfo->userdata)) + return False; + + mb_wm_main_context_timeout_setup (tinfo, current_time); + } + + return True; +} + +/* + * Returns false if no timeouts are present + */ +static Bool +mb_wm_main_context_check_timeouts (MBWMMainContext *ctx) +{ + MBWMList * l = mb_wm_util_list_get_first(ctx->event_funcs.timeout); + struct timeval current_time; + + if (!l) + return False; + + gettimeofday (¤t_time, NULL); + + while (l) + { + MBWMTimeOutEventInfo * tinfo = l->data; + unsigned long tid = tinfo->id; + + if (!mb_wm_main_context_handle_timeout (tinfo, ¤t_time)) + { + /* Timeout handler notified it can be removed, do so now */ + mb_wm_main_context_timeout_handler_remove (ctx,tid); + /* To avoid race condition, restart at front of list */ + l = mb_wm_util_list_get_first(ctx->event_funcs.timeout); + } + else + l = mb_wm_util_list_next(l); + } + return True; +} +#endif /* !USE_GLIB_MAINLOOP */ + +unsigned long +mb_wm_main_context_timeout_handler_add (MBWMMainContext *ctx, + int ms, + MBWindowManagerTimeOutFunc func, + void *userdata) +{ +#if ! USE_GLIB_MAINLOOP + static unsigned long ids = 0; + MBWMTimeOutEventInfo * tinfo; + struct timeval current_time; + + ++ids; + + tinfo = mb_wm_util_malloc0 (sizeof (MBWMTimeOutEventInfo)); + tinfo->func = func; + tinfo->id = ids; + tinfo->ms = ms; + tinfo->userdata = userdata; + + gettimeofday (¤t_time, NULL); + mb_wm_main_context_timeout_setup (tinfo, ¤t_time); + + ctx->event_funcs.timeout = + mb_wm_util_list_append (ctx->event_funcs.timeout, tinfo); + + return ids; + +#else + return g_timeout_add (ms, func, userdata); +#endif +} + +void +mb_wm_main_context_timeout_handler_remove (MBWMMainContext *ctx, + unsigned long id) +{ +#if ! USE_GLIB_MAINLOOP + MBWMList * l = ctx->event_funcs.timeout; + + while (l) + { + MBWMTimeOutEventInfo * info = l->data; + + if (info->id == id) + { + /* Reset list head after entry removal */ + ctx->event_funcs.timeout = + mb_wm_util_list_remove(ctx->event_funcs.timeout, l->data); + return; + } + + l = mb_wm_util_list_next(l); + } +#else + g_source_remove (id); +#endif +} + +unsigned long +mb_wm_main_context_fd_watch_add (MBWMMainContext *ctx, + MBWMIOChannel *channel, + MBWMIOCondition events, + MBWindowManagerFdWatchFunc func, + void *userdata) +{ +#if ! USE_GLIB_MAINLOOP + static unsigned long ids = 0; + MBWMFdWatchInfo * finfo; + struct pollfd * fds; + + ++ids; + + finfo = mb_wm_util_malloc0 (sizeof (MBWMFdWatchInfo)); + finfo->func = func; + finfo->id = ids; + finfo->channel = channel; + finfo->events = events; + finfo->userdata = userdata; + + ctx->event_funcs.fd_watch = + mb_wm_util_list_append (ctx->event_funcs.fd_watch, finfo); + + ctx->n_poll_fds++; + ctx->poll_fds = realloc (ctx->poll_fds, sizeof (struct pollfd)); + + fds = ctx->poll_fds + (ctx->n_poll_fds - 1); + fds->fd = *channel; + fds->events = events; + + return ids; + +#else + return g_io_add_watch (channel, events, func, userdata); +#endif +} + +void +mb_wm_main_context_fd_watch_remove (MBWMMainContext *ctx, + unsigned long id) +{ +#if ! USE_GLIB_MAINLOOP + MBWMList * l = ctx->event_funcs.fd_watch; + + while (l) + { + MBWMFdWatchInfo * info = l->data; + + if (info->id == id) + { + MBWMList * prev = l->prev; + MBWMList * next = l->next; + + if (prev) + prev->next = next; + else + ctx->event_funcs.fd_watch = next; + + if (next) + next->prev = prev; + + free (info); + free (l); + + return; + } + + l = l->next; + } + + ctx->n_poll_fds--; + ctx->poll_cache_dirty = True; +#else + g_source_remove (id); +#endif +} + +MBWMIOChannel * +mb_wm_main_context_io_channel_new (int fd) +{ +#if ! USE_GLIB_MAINLOOP + MBWMIOChannel * c = mb_wm_util_malloc0 (sizeof (MBWMIOChannel)); + *c = fd; + return c; +#else + return g_io_channel_unix_new (fd); +#endif +} + + +void +mb_wm_main_context_io_channel_destroy (MBWMIOChannel * channel) +{ +#if ! USE_GLIB_MAINLOOP + if (channel) + free (channel); +#else + g_io_channel_unref (channel); +#endif +} + +int +mb_wm_main_context_io_channel_get_fd (MBWMIOChannel * channel) +{ +#if ! USE_GLIB_MAINLOOP + return *channel; +#else + g_io_channel_unix_get_fd (channel); +#endif +} + +#if ! USE_GLIB_MAINLOOP +static void +mb_wm_main_context_setup_poll_cache (MBWMMainContext *ctx) +{ + MBWMList *l = ctx->event_funcs.fd_watch; + int i = 0; + + if (!ctx->poll_cache_dirty) + return; + + ctx->poll_fds = realloc (ctx->poll_fds, ctx->n_poll_fds); + + while (l) + { + MBWMFdWatchInfo *info = l->data; + + ctx->poll_fds[i].fd = *(info->channel); + ctx->poll_fds[i].events = info->events; + + l = l->next; + ++i; + } + + ctx->poll_cache_dirty = False; +} + +static Bool +mb_wm_main_context_check_fd_watches (MBWMMainContext * ctx) +{ + int ret; + int i = 0; + MBWMList * l = ctx->event_funcs.fd_watch; + Bool removal = False; + + if (!ctx->n_poll_fds) + return False; + + mb_wm_main_context_setup_poll_cache (ctx); + + ret = poll (ctx->poll_fds, ctx->n_poll_fds, 0); + + if (ret < 0) + { + MBWM_DBG ("Poll failed."); + return True; + } + + if (ret == 0) + return True; + + while (l) + { + MBWMFdWatchInfo *info = l->data; + + if (ctx->poll_fds[i].revents & ctx->poll_fds[i].events) + { + Bool zap = !info->func (info->channel, ctx->poll_fds[i].revents, + info->userdata); + + if (zap) + { + MBWMList * prev = l->prev; + MBWMList * next = l->next; + + if (prev) + prev->next = next; + else + ctx->event_funcs.fd_watch = next; + + if (next) + next->prev = prev; + + free (info); + free (l); + + ctx->n_poll_fds--; + + removal = True; + + l = next; + } + else + l = l->next; + } + else + l = l->next; + + ++i; + } + + ctx->poll_cache_dirty = removal; + + return True; +} +#endif |