aboutsummaryrefslogtreecommitdiffstats
path: root/matchbox/mb-wm-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'matchbox/mb-wm-manager.c')
-rw-r--r--matchbox/mb-wm-manager.c991
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,