diff options
Diffstat (limited to 'matchbox/mb-wm-manager.c')
-rw-r--r-- | matchbox/mb-wm-manager.c | 991 |
1 files changed, 853 insertions, 138 deletions
diff --git a/matchbox/mb-wm-manager.c b/matchbox/mb-wm-manager.c index 1d87e85..1a110ab 100644 --- a/matchbox/mb-wm-manager.c +++ b/matchbox/mb-wm-manager.c @@ -36,15 +36,6 @@ # include <X11/extensions/Xcomposite.h> #endif -/* FIXME: libmatchbox shouldn't know anything about clutter */ -#ifdef MANAGER_CLUTTER -#include <clutter/x11/clutter-x11.h> -#endif - -#if USE_GTK -# include <gdk/gdk.h> -#endif - #include <stdarg.h> #include <X11/Xmd.h> @@ -59,6 +50,80 @@ #include <X11/cursorfont.h> +#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 + +typedef struct _MBWMManagerEventSource +{ + MBWMManager *wm; + GSource source; + GPollFD event_poll_fd; +} MBWMManagerEventSource; + +static gboolean +mb_wm_manager_event_prepare (GSource *source, + int *timeout); + +static gboolean +mb_wm_manager_event_check (GSource *source); + +static gboolean +mb_wm_manager_event_dispatch (GSource *source, + GSourceFunc callback, + void *user_data); + +static GSourceFuncs event_funcs = { + mb_wm_manager_event_prepare, + mb_wm_manager_event_check, + mb_wm_manager_event_dispatch, + NULL +}; + +typedef struct _MBWMXlibFilterClosure +{ + MBWMXlibFilterFunc filter; + void *data; +} MBWMXlibFilterClosure; + static void mb_wm_process_cmdline (MBWMManager *wm); @@ -166,76 +231,6 @@ mb_wm_layout_new_real (MBWMManager *wm) return layout; } -#if USE_GTK -static GdkFilterReturn -mb_wm_gdk_xevent_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data) -{ - MBWMManager * wm = data; - XEvent * xev = (XEvent*) xevent; - - mb_wm_main_context_handle_x_event (xev, wm->main_ctx); - - if (wm->sync_type) - mb_wm_manager_sync (wm); - - return GDK_FILTER_CONTINUE; -} -#endif - -/* FIXME: libmatchbox shouldn't know anything about clutter! */ -#ifdef MANAGER_CLUTTER -#if USE_GTK -static GdkFilterReturn -mb_wm_clutter_gdk_xevent_filter (GdkXEvent *xevent, GdkEvent *event, - gpointer data) -{ - switch (clutter_x11_handle_event ((XEvent*)xevent)) - { - default: - case CLUTTER_X11_FILTER_CONTINUE: - return GDK_FILTER_CONTINUE; - case CLUTTER_X11_FILTER_TRANSLATE: - return GDK_FILTER_TRANSLATE; - case CLUTTER_X11_FILTER_REMOVE: - return GDK_FILTER_REMOVE; - } - - return GDK_FILTER_CONTINUE; -} -#else -static ClutterX11FilterReturn -mb_wm_clutter_xevent_filter (XEvent *xev, ClutterEvent *cev, gpointer data) -{ - MBWMManager * wm = data; - - mb_wm_main_context_handle_x_event (xev, wm->main_ctx); - - if (wm->sync_type) - mb_wm_manager_sync (wm); - - return CLUTTER_X11_FILTER_CONTINUE; -} -#endif -#endif - -#if MANAGER_CLUTTER || USE_GTK -static void -mb_wm_main_real (MBWMManager *wm) -{ - -#if USE_GTK - gdk_window_add_filter (NULL, mb_wm_gdk_xevent_filter, wm); -#if MANAGER_CLUTTER - gdk_window_add_filter (NULL, mb_wm_clutter_gdk_xevent_filter, NULL); -#endif - gtk_main (); -#else - clutter_x11_add_filter (mb_wm_clutter_xevent_filter, wm); - clutter_main (); -#endif -} -#endif - static void mb_wm_class_init (MBWMObjectClass *klass) { @@ -252,10 +247,6 @@ mb_wm_class_init (MBWMObjectClass *klass) wm_class->layout_new = mb_wm_layout_new_real; wm_class->get_desktop_geometry = mb_wm_real_get_desktop_geometry; -#if MANAGER_CLUTTER - wm_class->main = mb_wm_main_real; -#endif - #if MBWM_WANT_DEBUG klass->klass_name = "MBWMManager"; #endif @@ -280,7 +271,6 @@ mb_wm_destroy (MBWMObject *this) mb_wm_object_unref (MB_WM_OBJECT (wm->root_win)); mb_wm_object_unref (MB_WM_OBJECT (wm->theme)); mb_wm_object_unref (MB_WM_OBJECT (wm->layout)); - mb_wm_object_unref (MB_WM_OBJECT (wm->main_ctx)); } static int @@ -862,15 +852,564 @@ stack_sync_to_display (MBWMManager *wm) mb_wm_util_untrap_x_errors(); } +unsigned long +mb_wm_manager_add_event_handler (MBWMManager *wm, + Window xwin, + int type, + MBWMXEventFunc func, + void *userdata) +{ + static unsigned long ids = 0; + MBWMXEventFuncInfo * func_info; + + ++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) + { + wm->event_funcs.damage_notify = + g_list_append (wm->event_funcs.damage_notify, func_info); + } + else +#endif + switch (type) + { + case Expose: + break; + case MapRequest: + wm->event_funcs.map_request = + g_list_append (wm->event_funcs.map_request, func_info); + break; + case MapNotify: + wm->event_funcs.map_notify= + g_list_append (wm->event_funcs.map_notify, func_info); + break; + case UnmapNotify: + wm->event_funcs.unmap_notify= + g_list_append (wm->event_funcs.unmap_notify, func_info); + break; + case DestroyNotify: + wm->event_funcs.destroy_notify = + g_list_append (wm->event_funcs.destroy_notify, func_info); + break; + case ConfigureNotify: + wm->event_funcs.configure_notify = + g_list_append (wm->event_funcs.configure_notify, func_info); + break; + case ConfigureRequest: + wm->event_funcs.configure_request = + g_list_append (wm->event_funcs.configure_request, func_info); + break; + case KeyPress: + wm->event_funcs.key_press = + g_list_append (wm->event_funcs.key_press, func_info); + break; + case PropertyNotify: + wm->event_funcs.property_notify = + g_list_append (wm->event_funcs.property_notify, func_info); + break; + case ButtonPress: + wm->event_funcs.button_press = + g_list_append (wm->event_funcs.button_press, func_info); + break; + case ButtonRelease: + wm->event_funcs.button_release = + g_list_append (wm->event_funcs.button_release, func_info); + break; + case MotionNotify: + wm->event_funcs.motion_notify = + g_list_append (wm->event_funcs.motion_notify, func_info); + break; + case ClientMessage: + wm->event_funcs.client_message = + g_list_append (wm->event_funcs.client_message, func_info); + break; + + default: + break; + } + + return ids; +} + void -mb_wm_manager_sync (MBWMManager *wm) +mb_wm_manager_remove_event_handler (MBWMManager *wm, + int type, + unsigned long id) +{ + GList * l = NULL; + GList **l_start; + +#if ENABLE_COMPOSITE + if (type == wm->damage_event_base + XDamageNotify) + { + l_start = &wm->event_funcs.damage_notify; + } + else +#endif + switch (type) + { + case Expose: + break; + case MapRequest: + l_start = &wm->event_funcs.map_request; + break; + case MapNotify: + l_start = &wm->event_funcs.map_notify; + break; + case UnmapNotify: + l_start = &wm->event_funcs.unmap_notify; + break; + case DestroyNotify: + l_start = &wm->event_funcs.destroy_notify; + break; + case ConfigureNotify: + l_start = &wm->event_funcs.configure_notify; + break; + case ConfigureRequest: + l_start = &wm->event_funcs.configure_request; + break; + case KeyPress: + l_start = &wm->event_funcs.key_press; + break; + case PropertyNotify: + l_start = &wm->event_funcs.property_notify; + break; + case ButtonPress: + l_start = &wm->event_funcs.button_press; + break; + case ButtonRelease: + l_start = &wm->event_funcs.button_release; + break; + case MotionNotify: + l_start = &wm->event_funcs.motion_notify; + break; + case ClientMessage: + l_start = &wm->event_funcs.client_message; + break; + + default: + break; + } + + l = *l_start; + + while (l) + { + MBWMXEventFuncInfo * info = l->data; + + if (info->id == id) + { + GList * prev = l->prev; + GList * 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; + } +} + + + +static void +process_xlib_event (MBWMManager *wm, XEvent *xev) +{ + GList *iter; + Window xwin = xev->xany.window; + +#if (MBWM_WANT_DEBUG) + { + if (mbwm_debug_flags & MBWM_DEBUG_EVENT) + { + MBWindowManagerClient *ev_client; + + ev_client = mb_wm_manager_managed_window_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 = wm->event_funcs.damage_notify; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + GList * 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 = wm->event_funcs.client_message; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + GList * 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 = wm->event_funcs.map_request; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + GList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWMManagerMapRequestFunc)XE_ITER_GET_FUNC(iter) + ((XMapRequestEvent*)&xev->xmaprequest, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + case MapNotify: + iter = wm->event_funcs.map_notify; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + GList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWMManagerMapNotifyFunc)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 = wm->event_funcs.unmap_notify; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + GList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWMManagerUnmapNotifyFunc)XE_ITER_GET_FUNC(iter) + ((XUnmapEvent*)&xev->xunmap, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + case DestroyNotify: + iter = wm->event_funcs.destroy_notify; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + GList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWMManagerDestroyNotifyFunc)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 = wm->event_funcs.configure_notify; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + GList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWMManagerConfigureNotifyFunc)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 = wm->event_funcs.configure_request; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + GList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWMManagerConfigureRequestFunc)XE_ITER_GET_FUNC(iter) + ((XConfigureRequestEvent*)&xev->xconfigurerequest, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + case KeyPress: + iter = wm->event_funcs.key_press; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + GList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWMManagerKeyPressFunc)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 = wm->event_funcs.property_notify; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + GList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWMManagerPropertyNotifyFunc)XE_ITER_GET_FUNC(iter) + ((XPropertyEvent*)&xev->xproperty, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + case ButtonPress: + iter = wm->event_funcs.button_press; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + GList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWMManagerButtonPressFunc)XE_ITER_GET_FUNC(iter) + ((XButtonEvent*)&xev->xbutton, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + case ButtonRelease: + iter = wm->event_funcs.button_release; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + GList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWMManagerButtonReleaseFunc)XE_ITER_GET_FUNC(iter) + ((XButtonEvent*)&xev->xbutton, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + case MotionNotify: + iter = wm->event_funcs.motion_notify; + + while (iter) + { + Window msg_xwin = XE_ITER_GET_XWIN(iter); + GList * next = iter->next; + + if (msg_xwin == None || msg_xwin == xwin) + { + if (!(MBWMManagerMotionNotifyFunc)XE_ITER_GET_FUNC(iter) + ((XMotionEvent*)&xev->xmotion, + XE_ITER_GET_DATA(iter))) + break; + } + + iter = next; + } + break; + } +} + +static void +process_events (MBWMManager *wm) +{ + XEvent *xevent; + + while (xevent = g_queue_pop_tail (wm->event_queue)) + { + process_xlib_event (wm, xevent); + g_slice_free (XEvent, xevent); + } +} + +static void +manager_update (MBWMManager *wm) { /* Sync all changes to display */ MBWindowManagerClient *client = NULL; + process_events (wm); + + if (!wm->sync_type) + return; + MBWM_MARK(); MBWM_TRACE (); + /* XXX: really? why do we do this‽ */ XGrabServer(wm->xdpy); /* First of all, make sure stack is correct */ @@ -1216,46 +1755,35 @@ mb_wm_manager_managed_window_from_frame (MBWMManager *wm, Window frame) return NULL; } -/* - * Run the main loop; there are three options dependent on how we were - * configured at build time: - * - * * If configured without glib main loop integration, we defer to our own - * main loop implementation provided by MBWMMainContext. - * - * * If configured with glib main loop integration: - * - * * If there is an implemetation for the MBWMManager main() virtual - * function, we call it. - * - * * Otherwise, start a normal glib main loop. - */ void -mb_wm_manager_main_loop(MBWMManager *wm) +mb_wm_manager_main_loop (MBWMManager *wm) { -#if !USE_GLIB_MAINLOOP - mb_wm_main_context_loop (wm->main_ctx); -#else - MBWMManagerClass * wm_class = - MB_WM_MANAGER_CLASS (MB_WM_OBJECT_GET_CLASS (wm)); + GMainLoop * loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (loop); + g_main_loop_unref (loop); +} -#if !MANAGER_CLUTTER - if (!wm_class->main) - { - GMainLoop * loop = g_main_loop_new (NULL, FALSE); +static gboolean +do_manager_update (MBWMManager *wm) +{ + wm->do_update_idle = 0; - g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, - mb_wm_main_context_gloop_xevent, wm->main_ctx, NULL); + manager_update (wm); + return FALSE; +} - g_main_loop_run (loop); - g_main_loop_unref (loop); - } - else -#endif - { - wm_class->main (wm); - } -#endif +void +mb_wm_manager_queue_update (MBWMManager *wm) +{ + /* Note we use a priority slightly higher than the default + * because we need to ensure we consume the events queued + * by a source that has DEFUALT_IDLE priority */ + if (!wm->do_update_idle) + wm->do_update_idle = + g_idle_add_full (G_PRIORITY_HIGH_IDLE, + (GSourceFunc)do_manager_update, + wm, + NULL); } void @@ -1378,7 +1906,7 @@ static void mb_wm_get_desktop_geometry (MBWMManager *wm, MBGeometry * geom) { MBWMManagerClass *wm_class; - + wm_class = (MBWMManagerClass *) MB_WM_OBJECT_GET_CLASS (wm); MBWM_ASSERT (wm_class->get_desktop_geometry); @@ -1497,15 +2025,202 @@ mb_wm_manager_init_comp_extensions (MBWMManager *wm) } #endif +static gboolean +check_xpending (MBWMManager *wm) +{ + return XPending (wm->xdpy); +} + +static gboolean +events_pending (MBWMManager *wm) +{ + return !g_queue_is_empty (wm->event_queue); +} + +static gboolean +mb_wm_manager_event_prepare (GSource *source, + int *timeout) +{ + MBWMManagerEventSource *event_source = (MBWMManagerEventSource *)source; + MBWMManager *wm = event_source->wm; + + gboolean retval; + + /* TODO: mb_wm_threads_enter (); */ + + *timeout = -1; + retval = check_xpending (wm); + + /* TODO: mb_wm_threads_leave (); */ + + return retval; +} + +static gboolean +mb_wm_manager_event_check (GSource *source) +{ + MBWMManagerEventSource *event_source = (MBWMManagerEventSource *)source; + MBWMManager *wm = event_source->wm; + gboolean retval; + + /* TODO: mb_wm_threads_enter (); */ + + if (event_source->event_poll_fd.revents & G_IO_IN) + retval = check_xpending (wm); + else + retval = FALSE; + + /* TODO: mb_wm_threads_leave (); */ + + return retval; +} + +static gboolean +event_translate (MBWMManager *wm, + XEvent *xevent) +{ + GList *l; + + for (l = wm->xlib_event_filters; l; l = l->next) + { + MBWMXlibFilterClosure *closure = l->data; + if (closure->filter (xevent, closure->data) == MB_WM_XLIB_FILTER_REMOVE) + return FALSE; + } + + return TRUE; +} + +static gboolean +queue_event (MBWMManager *wm, XEvent *xevent) +{ + if (event_translate (wm, xevent)) + { + XEvent *copy = g_slice_copy (sizeof (XEvent), xevent); + /* push directly here to avoid copy of queue_put */ + g_queue_push_head (wm->event_queue, copy); + mb_wm_manager_queue_update (wm); + return TRUE; + } + else + return FALSE; +} + +gboolean +mb_wm_manager_handle_xlib_event (MBWMManager *wm, XEvent *xev) +{ + return queue_event (wm, xev); +} + +static void +queue_events (MBWMManager *wm) +{ + Display *xdisplay = wm->xdpy; + + while (XPending (xdisplay)) + { + XEvent xevent; + XNextEvent (xdisplay, &xevent); + + queue_event (wm, &xevent); + } +} + +static gboolean +mb_wm_manager_event_dispatch (GSource *source, + GSourceFunc callback, + void *user_data) +{ + MBWMManagerEventSource *event_source = (MBWMManagerEventSource *)source; + MBWMManager *wm = event_source->wm; + + /* TODO: mb_wm_threads_enter (); */ + + queue_events (wm); + + /* TODO: mb_wm_threads_leave (); */ + + return TRUE; +} + +static GSource * +mb_wm_manager_event_source_new (MBWMManager *wm) +{ + GSource *source = g_source_new (&event_funcs, + sizeof (MBWMManagerEventSource)); + MBWMManagerEventSource *event_source = (MBWMManagerEventSource *) source; + + event_source->wm = wm; + +#if GLIB_CHECK_VERSION (2, 25, 8) + g_source_set_name (source, "Matchbox X11 Event"); +#endif + + event_source->event_poll_fd.fd = ConnectionNumber (wm->xdpy); + event_source->event_poll_fd.events = G_IO_IN; + + g_source_add_poll (source, &event_source->event_poll_fd); + g_source_set_can_recurse (source, TRUE); + + return source; +} + +void +mb_wm_manager_disable_x11_event_retrieval (MBWMManager *wm) +{ + wm->event_retrieval_disabled = TRUE; +} + +void +mb_wm_manager_xlib_add_filter (MBWMManager *wm, + MBWMXlibFilterFunc filter, + void *data) +{ + MBWMXlibFilterClosure *closure; + + closure = g_slice_new (MBWMXlibFilterClosure); + closure->filter = filter; + closure->data = data; + + wm->xlib_event_filters = g_list_prepend (wm->xlib_event_filters, closure); +} + +void +mv_wm_manager_xlib_remove_filter (MBWMManager *wm, + MBWMXlibFilterFunc func, + void *data) +{ + GList *l; + + for (l = wm->xlib_event_filters; l; l = l->next) + { + MBWMXlibFilterClosure *closure = l->data; + + if (closure->filter == func && closure->data == data) + { + g_slice_free (MBWMXlibFilterClosure, closure); + wm->xlib_event_filters = + g_list_delete_link (wm->xlib_event_filters, l); + return; + } + } +} + /* * This function must be called before the MBWMManager object can be * used. */ static void -_mb_wm_manager_run (MBWMManager * wm, MBWMCompMgr *compositor) +_mb_wm_manager_start (MBWMManager * wm, MBWMCompMgr *compositor) { MBWMManagerClass *wm_class; + if (!wm->event_retrieval_disabled) + { + wm->event_source = mb_wm_manager_event_source_new (wm); + g_source_attach (wm->event_source, NULL); + } + wm_class = (MBWMManagerClass *) MB_WM_OBJECT_GET_CLASS (wm); mb_wm_manager_set_theme_from_path (wm, wm->theme_path); @@ -1537,16 +2252,16 @@ _mb_wm_manager_run (MBWMManager * wm, MBWMCompMgr *compositor) } void -mb_wm_manager_run (MBWMManager *window_manager) +mb_wm_manager_start (MBWMManager *window_manager) { - _mb_wm_manager_run (window_manager, NULL); + _mb_wm_manager_start (window_manager, NULL); } void -mb_wm_manager_run_with_compositor (MBWMManager *window_manager, +mb_wm_manager_start_with_compositor (MBWMManager *window_manager, MBWMCompMgr *compositor) { - _mb_wm_manager_run (window_manager, compositor); + _mb_wm_manager_start (window_manager, compositor); } @@ -1602,6 +2317,8 @@ mb_wm_manager_init (MBWMObject *this, va_list vap) mb_wm_atoms_init(wm); + wm->event_queue = g_queue_new (); + #if ENABLE_COMPOSITE if (!mb_wm_manager_init_comp_extensions (wm)) return 0; @@ -1611,65 +2328,63 @@ mb_wm_manager_init (MBWMObject *this, va_list vap) mb_wm_update_root_win_rectangles (wm); - wm->main_ctx = mb_wm_main_context_new (wm); - - mb_wm_main_context_x_event_handler_add (wm->main_ctx, + mb_wm_manager_add_event_handler (wm, None, MapRequest, (MBWMXEventFunc)mb_wm_handle_map_request, wm); #if ENABLE_COMPOSITE - mb_wm_main_context_x_event_handler_add (wm->main_ctx, + mb_wm_manager_add_event_handler (wm, None, MapNotify, (MBWMXEventFunc)mb_wm_handle_map_notify, wm); - mb_wm_main_context_x_event_handler_add (wm->main_ctx, + mb_wm_manager_add_event_handler (wm, None, ConfigureNotify, (MBWMXEventFunc)mb_wm_handle_composite_config_notify, wm); #endif - mb_wm_main_context_x_event_handler_add (wm->main_ctx, + mb_wm_manager_add_event_handler (wm, wm->root_win->xwindow, ConfigureNotify, (MBWMXEventFunc)mb_wm_handle_root_config_notify, wm); - mb_wm_main_context_x_event_handler_add (wm->main_ctx, + mb_wm_manager_add_event_handler (wm, None, ConfigureRequest, (MBWMXEventFunc)mb_wm_handle_config_request, wm); - mb_wm_main_context_x_event_handler_add (wm->main_ctx, + mb_wm_manager_add_event_handler (wm, None, PropertyNotify, (MBWMXEventFunc)mb_wm_handle_property_notify, wm); - mb_wm_main_context_x_event_handler_add (wm->main_ctx, + mb_wm_manager_add_event_handler (wm, None, DestroyNotify, (MBWMXEventFunc)mb_wm_handle_destroy_notify, wm); - mb_wm_main_context_x_event_handler_add (wm->main_ctx, + mb_wm_manager_add_event_handler (wm, None, UnmapNotify, (MBWMXEventFunc)mb_wm_handle_unmap_notify, wm); - mb_wm_main_context_x_event_handler_add (wm->main_ctx, + mb_wm_manager_add_event_handler (wm, None, KeyPress, (MBWMXEventFunc)mb_wm_handle_key_press, wm); - mb_wm_main_context_x_event_handler_add (wm->main_ctx, + mb_wm_manager_add_event_handler (wm, None, ButtonPress, (MBWMXEventFunc)mb_wm_handle_button_press, |