aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Bragg <robert@linux.intel.com>2010-08-19 04:36:22 +0100
committerRobert Bragg <robert@linux.intel.com>2010-12-09 22:46:47 +0000
commitea84bd26d72ae05bfa9aef2cc8000919421641be (patch)
treee4b8d900e7ed31647b3b2cd31571ec2925be932d
parent41059683747e80790218b3bf67f71df5c56f39a7 (diff)
downloadlibmatchboxwm2-ea84bd26d72ae05bfa9aef2cc8000919421641be.tar.gz
libmatchboxwm2-ea84bd26d72ae05bfa9aef2cc8000919421641be.tar.bz2
libmatchboxwm2-ea84bd26d72ae05bfa9aef2cc8000919421641be.zip
Overhaul our mainloop integration
This removes mb-wm-main-context.c since we now just use a glib mainloop context instead. The new mainloop integration API allows matchbox to be fed X events from an external toolkit so core matchbox no longer needs to have any gtk specific event source integration code, since it should be straightforward for a gtk based wm/compositor to decide to take ownership of event fetching and pass those events through to matchbox manually if they want. In the process of removing references to the mb-wm-main-context API it was necessary to refactor how we handle mouse grabs for moving and resizing windows. Previously we would do an X grab and then then immediately enter a tight loop, polling for X mouse events and handling them until something triggers an ungrab and then resume fetching events in the normal way. Now though when we do the mouse grab we just use mb_wm_manager_add_event_handler to register a temporary interest in mouse events and mb_wm_manager_remove_event_handler when the grab is finished. This means we can continue to use the normal event delivery mechanism during a grab and more importantly we don't block the mainloop which would really upset window managers and compositors needing to process other asynchronous events during a grab.
-rw-r--r--configure.ac28
-rw-r--r--doc/MBWM2-Overview.xml15
-rw-r--r--managers/clutter/matchbox-window-manager-2-clutter.c38
-rw-r--r--managers/maemo/matchbox-window-manager-2-maemo.c2
-rw-r--r--managers/simple/matchbox-window-manager-2-simple.c13
-rw-r--r--managers/xrender/matchbox-window-manager-2-xrender.c15
-rw-r--r--matchbox/Makefile.am2
-rw-r--r--matchbox/matchbox.h1
-rw-r--r--matchbox/mb-wm-client.c11
-rw-r--r--matchbox/mb-wm-comp-mgr.c4
-rw-r--r--matchbox/mb-wm-config.h.in6
-rw-r--r--matchbox/mb-wm-decor.c541
-rw-r--r--matchbox/mb-wm-decor.h3
-rw-r--r--matchbox/mb-wm-main-context.c1116
-rw-r--r--matchbox/mb-wm-main-context.h150
-rw-r--r--matchbox/mb-wm-manager.c991
-rw-r--r--matchbox/mb-wm-manager.h73
-rw-r--r--matchbox/mb-wm-object.h2
-rw-r--r--matchbox/mb-wm-types.h24
19 files changed, 1240 insertions, 1795 deletions
diff --git a/configure.ac b/configure.ac
index d814d44..3ca9697 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,18 +62,10 @@ AC_ARG_WITH(pango,
[ --with-pango Use of pango for text layout],
[use_pango=$withval], [use_pango=no])
-AC_ARG_WITH(gtk,
- [ --with-gtk With GTK integration support],
- [use_gtk=$withval], [use_gtk=no])
-
AC_ARG_ENABLE(compositing,
[ --enable-compositing Enable support for compositing],
[compositing=$enableval], [compositing=no])
-AC_ARG_ENABLE(glib-main-loop,
- [ --enable-glib-main-loop Enable use of glib main loop],
- [gmloop=$enableval], [gmloop=no])
-
AC_ARG_ENABLE(matchbox-remote,
[ --enable-matchbox-remote Enable matchbox remote control utility],
[matchbox_remote=$enableval], [matchbox_remote=no])
@@ -99,10 +91,6 @@ if ! test "x$use_pango" = "xyes" -o "x$use_pango" = "xyes"; then
needed_pkgs="$needed_pkgs xft "
fi
-if test "x$use_gtk" = "xyes"; then
- needed_pkgs="$needed_pkgs gtk+-2.0 "
-fi
-
if test "x$png_theme" = "xyes"; then
needed_pkgs="$needed_pkgs libpng12 "
fi
@@ -137,7 +125,6 @@ for manager in $included_managers; do
;;
clutter )
needed_pkgs="$needed_pkgs $clutter_package xcomposite xdamage "
- gmloop="yes"
;;
esac
@@ -157,12 +144,6 @@ if test "x$want_debug" = "xyes"; then
fi
AC_SUBST(MBWM_WANT_DEBUG)
-USE_GLIB_MAINLOOP=0
-if test "x$gmloop" = "xyes"; then
- USE_GLIB_MAINLOOP=1
-fi
-AC_SUBST(USE_GLIB_MAINLOOP)
-
USE_PANGO=0
if test "$use_pango" = yes; then
USE_PANGO=1
@@ -184,13 +165,6 @@ if test "$use_png" != yes; then
fi
AC_SUBST(THEME_SIMPLE)
-USE_GTK=0
-AM_CONDITIONAL(USE_GTK, test "x$use_gtk" = "xyes")
-if test "$use_gtk" = yes; then
- USE_GTK=1
-fi
-AC_SUBST(USE_GTK)
-
PKG_CHECK_MODULES(MBWM, $needed_pkgs)
MBWM_PKGREQUIRES="$MBWM_PKGREQUIRES $needed_pkgs"
AC_SUBST(MBWM_PKGREQUIRES)
@@ -311,7 +285,6 @@ echo "
Themes:
PNG theme : ${png_theme}
- GTK integration : ${use_gtk}
Pango integration : ${use_pango}
Managers:
@@ -321,7 +294,6 @@ echo "
Miscel:
Compositing support : ${compositing}
- Glib main loop : ${gmloop}
Build matchbox-remote : ${matchbox_remote}
Debugging output : ${want_debug}
"
diff --git a/doc/MBWM2-Overview.xml b/doc/MBWM2-Overview.xml
index d8c2c6b..afcab2e 100644
--- a/doc/MBWM2-Overview.xml
+++ b/doc/MBWM2-Overview.xml
@@ -312,21 +312,6 @@
</section>
- <section id="MBWMMainContext">
- <title>MBWMMainContext</title>
-
- <para>MBWMMainContext is an object encapsulating main loop
- functionality. It provides API for adding timeouts, custom x-event
- handlers and FD watches.
- </para>
-
- <para>Optionally, the MBWMMainContext allows for the use of a GLib main
- loop, making it possible to integrate the MBWM2 with other components that
- use (and rely on) the GLib main loop. For this functionality,
- --enable-glib-main-loop should be used at configure time.
- </para>
- </section>
-
<section id="MBWindowManager">
<title>MBWindowManager</title>
diff --git a/managers/clutter/matchbox-window-manager-2-clutter.c b/managers/clutter/matchbox-window-manager-2-clutter.c
index ab3b227..68d0431 100644
--- a/managers/clutter/matchbox-window-manager-2-clutter.c
+++ b/managers/clutter/matchbox-window-manager-2-clutter.c
@@ -4,10 +4,6 @@
#include <matchbox/matchbox.h>
#include <signal.h>
-#if USE_GTK
-#include <gdk/gdkx.h>
-#endif
-
enum {
KEY_ACTION_PAGE_NEXT,
KEY_ACTION_PAGE_PREV,
@@ -76,6 +72,15 @@ key_binding_func (MBWMManager *wm,
}
}
+ClutterX11FilterReturn
+forward_xevent (XEvent *xevent,
+ ClutterEvent *event,
+ void *user_data)
+{
+ mb_wm_manager_handle_xlib_event (wm, xevent);
+ return CLUTTER_X11_FILTER_CONTINUE;
+}
+
int
main(int argc, char **argv)
{
@@ -91,35 +96,22 @@ main(int argc, char **argv)
mb_wm_object_init();
-#if USE_GTK
- printf ("initializing gtk\n");
-
- gtk_init (&argc, &argv);
- dpy = GDK_DISPLAY();
-#endif
-
- /*
- * If using clutter, we share the display connection, and hook
- * our xevent handler into the clutter main loop.
- *
- * If we are also doing gtk integration, we need to make clutter to
- * use the gtk display connection.
+ /* We share Clutter's display connection, and hook our xevent
+ * handler into the clutter main loop.
*/
if (dpy)
clutter_x11_set_display (dpy);
-#if USE_GTK
- clutter_x11_disable_event_retrieval ();
-#endif
-
clutter_init (&argc, &argv);
if (!dpy)
dpy = clutter_x11_get_default_display ();
+ clutter_x11_add_filter (forward_xevent, wm);
+
wm = mb_wm_manager_new_with_dpy (argc, argv, dpy);
compositor = mb_wm_comp_mgr_clutter_new (wm);
- mb_wm_manager_run_with_compositor (wm, compositor);
+ mb_wm_manager_start_with_compositor (wm, compositor);
mb_wm_object_unref (MB_WM_OBJECT (compositor));
if (wm == NULL)
@@ -143,7 +135,7 @@ main(int argc, char **argv)
NULL,
(void*)KEY_ACTION_PAGE_PREV);
- mb_wm_manager_main_loop(wm);
+ clutter_main ();
mb_wm_object_unref (MB_WM_OBJECT (wm));
diff --git a/managers/maemo/matchbox-window-manager-2-maemo.c b/managers/maemo/matchbox-window-manager-2-maemo.c
index 577a1b2..c24559e 100644
--- a/managers/maemo/matchbox-window-manager-2-maemo.c
+++ b/managers/maemo/matchbox-window-manager-2-maemo.c
@@ -102,7 +102,7 @@ main(int argc, char **argv)
mb_wm_object_init();
wm = maemo_window_manager_new(argc, argv);
- mb_wm_manager_run (wm);
+ mb_wm_manager_start (wm);
if (wm == NULL)
mb_wm_util_fatal_error("OOM?");
diff --git a/managers/simple/matchbox-window-manager-2-simple.c b/managers/simple/matchbox-window-manager-2-simple.c
index 8881895..52445cc 100644
--- a/managers/simple/matchbox-window-manager-2-simple.c
+++ b/managers/simple/matchbox-window-manager-2-simple.c
@@ -1,10 +1,6 @@
#include <matchbox/matchbox.h>
#include <signal.h>
-#if USE_GTK
-#include <gdk/gdkx.h>
-#endif
-
enum {
KEY_ACTION_PAGE_NEXT,
KEY_ACTION_PAGE_PREV,
@@ -87,15 +83,8 @@ main(int argc, char **argv)
mb_wm_object_init();
-#if USE_GTK
- printf ("initializing gtk\n");
-
- gtk_init (&argc, &argv);
- dpy = GDK_DISPLAY();
-#endif
-
wm = mb_wm_manager_new_with_dpy (argc, argv, dpy);
- mb_wm_manager_run (wm);
+ mb_wm_manager_start (wm);
if (wm == NULL)
mb_wm_util_fatal_error("OOM?");
diff --git a/managers/xrender/matchbox-window-manager-2-xrender.c b/managers/xrender/matchbox-window-manager-2-xrender.c
index 70e6855..cdde66b 100644
--- a/managers/xrender/matchbox-window-manager-2-xrender.c
+++ b/managers/xrender/matchbox-window-manager-2-xrender.c
@@ -4,10 +4,6 @@
#include <matchbox/matchbox.h>
#include <signal.h>
-#if USE_GTK
-#include <gdk/gdkx.h>
-#endif
-
enum {
KEY_ACTION_PAGE_NEXT,
KEY_ACTION_PAGE_PREV,
@@ -91,19 +87,10 @@ main(int argc, char **argv)
mb_wm_object_init();
-#if USE_GTK
- printf ("initializing gtk\n");
-
- gtk_init (&argc, &argv);
- dpy = GDK_DISPLAY();
-
- wm = mb_wm_manager_new_with_dpy (argc, argv, dpy);
-#else
wm = mb_wm_manager_new (argc, argv);
-#endif
compositor = mb_wm_comp_mgr_xrender_new (wm);
- mb_wm_manager_run_with_compositor (wm, compositor);
+ mb_wm_manager_start_with_compositor (wm, compositor);
mb_wm_object_unref (MB_WM_OBJECT (compositor));
if (wm == NULL)
diff --git a/matchbox/Makefile.am b/matchbox/Makefile.am
index 8ad2c05..f0cb6f9 100644
--- a/matchbox/Makefile.am
+++ b/matchbox/Makefile.am
@@ -37,8 +37,6 @@ source = \
mb-wm-decor.c \
mb-wm-manager.h \
mb-wm-manager.c \
- mb-wm-main-context.h \
- mb-wm-main-context.c \
xas.h \
xas.c
diff --git a/matchbox/matchbox.h b/matchbox/matchbox.h
index 0a745eb..0c703b2 100644
--- a/matchbox/matchbox.h
+++ b/matchbox/matchbox.h
@@ -66,5 +66,4 @@
#include <matchbox/mb-wm-layout.h>
#include <matchbox/mb-wm-stack.h>
#include <matchbox/mb-wm-manager.h>
-#include <matchbox/mb-wm-main-context.h>
#endif
diff --git a/matchbox/mb-wm-client.c b/matchbox/mb-wm-client.c
index 8dd0746..13c1964 100644
--- a/matchbox/mb-wm-client.c
+++ b/matchbox/mb-wm-client.c
@@ -754,7 +754,6 @@ void
mb_wm_client_ping_start (MBWindowManagerClient *client)
{
MBWMManager * wm = client->wmref;
- MBWMMainContext * ctx = wm->main_ctx;
MBWMClientWindowProtos protos = client->window->protos;
if (!(protos & MBWMClientWindowProtosPing))
@@ -764,9 +763,9 @@ mb_wm_client_ping_start (MBWindowManagerClient *client)
return;
client->ping_cb_id =
- mb_wm_main_context_timeout_handler_add (ctx, client->ping_timeout,
- mb_wm_client_ping_timeout_cb,
- client);
+ g_timeout_add (client->ping_timeout,
+ mb_wm_client_ping_timeout_cb,
+ client);
mb_wm_client_deliver_ping_protocol (client);
}
@@ -774,12 +773,10 @@ mb_wm_client_ping_start (MBWindowManagerClient *client)
void
mb_wm_client_ping_stop (MBWindowManagerClient *client)
{
- MBWMMainContext * ctx = client->wmref->main_ctx;
-
if (!client->ping_cb_id)
return;
- mb_wm_main_context_timeout_handler_remove (ctx, client->ping_cb_id);
+ g_source_remove (client->ping_cb_id);
client->ping_cb_id = 0;
}
diff --git a/matchbox/mb-wm-comp-mgr.c b/matchbox/mb-wm-comp-mgr.c
index 4ce51a6..ce69eb8 100644
--- a/matchbox/mb-wm-comp-mgr.c
+++ b/matchbox/mb-wm-comp-mgr.c
@@ -439,7 +439,7 @@ mb_wm_comp_mgr_turn_on (MBWMCompMgr *mgr)
klass->turn_on (mgr);
mgr->damage_cb_id =
- mb_wm_main_context_x_event_handler_add (wm->main_ctx,
+ mb_wm_manager_add_event_handler (wm,
None,
wm->damage_event_base + XDamageNotify,
(MBWMXEventFunc)klass->handle_damage,
@@ -458,7 +458,7 @@ mb_wm_comp_mgr_turn_off (MBWMCompMgr *mgr)
MBWM_ASSERT (klass->turn_off != NULL);
klass->turn_off (mgr);
- mb_wm_main_context_x_event_handler_remove (wm->main_ctx,
+ mb_wm_manager_remove_event_handler (wm,
wm->damage_event_base + XDamageNotify,
mgr->damage_cb_id);
diff --git a/matchbox/mb-wm-config.h.in b/matchbox/mb-wm-config.h.in
index 8c8de50..4413352 100644
--- a/matchbox/mb-wm-config.h.in
+++ b/matchbox/mb-wm-config.h.in
@@ -23,12 +23,6 @@
/* Include at least one of the default compositing manager backends */
#define COMP_MGR_BACKEND @COMP_MGR_BACKEND@
-/* Use glib main loop */
-#define USE_GLIB_MAINLOOP @USE_GLIB_MAINLOOP@
-
-/* GTK Integration */
-#define USE_GTK @USE_GTK@
-
/* Debugging stuff */
#define MBWM_WANT_DEBUG @MBWM_WANT_DEBUG@
diff --git a/matchbox/mb-wm-decor.c b/matchbox/mb-wm-decor.c
index 51f674e..74bf664 100644
--- a/matchbox/mb-wm-decor.c
+++ b/matchbox/mb-wm-decor.c
@@ -192,24 +192,58 @@ mb_wm_decor_resize (MBWMDecor *decor)
decor->pack_end_x = btn_x_end;
}
-static Bool
-mb_wm_decor_reparent (MBWMDecor *decor);
+typedef struct
+{
+ MBWMDecor *decor;
+ int orig_x, orig_y;
+ int orig_p_x, orig_p_y;
+} DecorGrabClosure;
static Bool
-mb_wm_decor_release_handler (XButtonEvent *xev,
- void *userdata)
+mb_wm_decor_grab_handler (XEvent *xev,
+ void *userdata)
{
- MBWMDecor *decor = userdata;
+ DecorGrabClosure *closure = userdata;
+ MBWMDecor *decor = closure->decor;
MBWMManager *wm = decor->parent_client->wmref;
- mb_wm_main_context_x_event_handler_remove (wm->main_ctx, ButtonRelease,
- decor->release_cb_id);
+ switch (xev->type)
+ {
+ case MotionNotify:
+ {
+ XMotionEvent *pev = (XMotionEvent*)xev;
+ MBGeometry geom;
- decor->release_cb_id = 0;
+ int diff_x = pev->x_root - closure->orig_p_x;
+ int diff_y = pev->y_root - closure->orig_p_y;
- XUngrabPointer (wm->xdpy, CurrentTime);
+ geom.x = closure->orig_x + diff_x;
+ geom.y = closure->orig_y + diff_y;
- return False;
+ mb_wm_client_request_geometry (decor->parent_client,
+ &geom,
+ MBWMClientReqGeomIsViaUserAction);
+ }
+ break;
+ case ButtonRelease:
+ {
+ XUngrabPointer (wm->xdpy, CurrentTime);
+
+ mb_wm_manager_remove_event_handler (wm, ButtonRelease,
+ decor->release_cb_id);
+ decor->release_cb_id = 0;
+ mb_wm_manager_remove_event_handler (wm, MotionNotify,
+ decor->motion_cb_id);
+ decor->motion_cb_id = 0;
+
+ g_slice_free (DecorGrabClosure, closure);
+ return False;
+ }
+ default:
+ ;
+ }
+
+ return True;
}
static Bool
@@ -222,29 +256,6 @@ mb_wm_decor_press_handler (XButtonEvent *xev,
if (xev->window == decor->xwin)
{
- XEvent ev;
- MBGeometry geom;
- int orig_x, orig_y;
- int orig_p_x, orig_p_y;
-
- mb_wm_client_get_coverage (decor->parent_client, &geom);
-
- orig_x = geom.x;
- orig_y = geom.y;
- orig_p_x = xev->x_root;
- orig_p_y = xev->y_root;
-
- /*
- * This is bit tricky: we do a normal pointer drag and pull out any
- * pointer events out of the queue; when we get a MotionEvent, we
- * move the client window. However, for the move to propagete on screen
- * (particularly with a compositor) we need to spin the main loop so
- * that any queued up ConfigureNotify events get processed;
- * unfortunately, this invariably results in the ButtonRelease event
- * landing in the main loop and not in our sub-loop here. So, on the
- * ButtonPress we install a ButtonRelease callback into the main loop
- * and use that to release the grab.
- */
if (XGrabPointer(wm->xdpy, xev->subwindow, False,
ButtonPressMask|ButtonReleaseMask|
PointerMotionMask|EnterWindowMask|LeaveWindowMask,
@@ -252,64 +263,29 @@ mb_wm_decor_press_handler (XButtonEvent *xev,
GrabModeAsync,
None, None, CurrentTime) == GrabSuccess)
{
+ DecorGrabClosure *closure = g_slice_new (DecorGrabClosure);
+ MBGeometry geom;
+
+ mb_wm_client_get_coverage (decor->parent_client, &geom);
- decor->release_cb_id = mb_wm_main_context_x_event_handler_add (
- wm->main_ctx,
+ closure->decor = decor;
+ closure->orig_x = geom.x;
+ closure->orig_y = geom.y;
+ closure->orig_p_x = xev->x_root;
+ closure->orig_p_y = xev->y_root;
+
+ decor->release_cb_id = mb_wm_manager_add_event_handler (
+ wm,
decor->xwin,
ButtonRelease,
- (MBWMXEventFunc)mb_wm_decor_release_handler,
- decor);
-
- for (;;)
- {
- /*
- * If we have no release_cb installed, i.e., the ButtonRelease
- * has already happened, quit this loop.
- */
- if (!decor->release_cb_id)
- break;
-
- XMaskEvent(wm->xdpy,
- ButtonPressMask|ButtonReleaseMask|
- PointerMotionMask|EnterWindowMask|
- LeaveWindowMask,
- &ev);
-
- switch (ev.type)
- {
- case MotionNotify:
- {
- Bool events_pending;
- int event_count = 5; /*Limit how much we spin the loop*/
- XMotionEvent *pev = (XMotionEvent*)&ev;
- int diff_x = pev->x_root - orig_p_x;
- int diff_y = pev->y_root - orig_p_y;
-
- geom.x = orig_x + diff_x;
- geom.y = orig_y + diff_y;
-
- mb_wm_client_request_geometry (decor->parent_client,
- &geom,
- MBWMClientReqGeomIsViaUserAction);
-
- do
- {
- events_pending =
- mb_wm_main_context_spin_loop (wm->main_ctx);
-
- --event_count;
- } while (events_pending && event_count);
- }
- break;
- case ButtonRelease:
- {
- XUngrabPointer (wm->xdpy, CurrentTime);
- return False;
- }
- default:
- ;
- }
- }
+ (MBWMXEventFunc)mb_wm_decor_grab_handler,
+ closure);
+ decor->motion_cb_id = mb_wm_manager_add_event_handler (
+ wm,
+ decor->xwin,
+ MotionNotify,
+ (MBWMXEventFunc)mb_wm_decor_grab_handler,
+ closure);
}
}
@@ -317,6 +293,9 @@ mb_wm_decor_press_handler (XButtonEvent *xev,
}
static Bool
+mb_wm_decor_reparent (MBWMDecor *decor);
+
+static Bool
mb_wm_decor_sync_window (MBWMDecor *decor)
{
MBWMManager *wm;
@@ -373,7 +352,7 @@ mb_wm_decor_sync_window (MBWMDecor *decor)
decor->parent_client->layout_hints & LayoutPrefMovable)
{
decor->press_cb_id =
- mb_wm_main_context_x_event_handler_add (wm->main_ctx,
+ mb_wm_manager_add_event_handler (wm,
decor->xwin,
ButtonPress,
(MBWMXEventFunc)mb_wm_decor_press_handler,
@@ -641,7 +620,7 @@ mb_wm_decor_destroy (MBWMObject* obj)
{
MBWMDecor * decor = MB_WM_DECOR(obj);
GList * l = decor->buttons;
- MBWMMainContext * ctx = decor->parent_client->wmref->main_ctx;
+ MBWMManager * wm = decor->parent_client->wmref;
if (decor->themedata && decor->destroy_themedata)
{
@@ -661,8 +640,19 @@ mb_wm_decor_destroy (MBWMObject* obj)
}
if (decor->press_cb_id)
- mb_wm_main_context_x_event_handler_remove (ctx, ButtonPress,
- decor->press_cb_id);
+ mb_wm_manager_remove_event_handler (wm, ButtonPress, decor->press_cb_id);
+
+ if (decor->release_cb_id)
+ mb_wm_manager_remove_event_handler (wm, ButtonRelease, decor->release_cb_id);
+
+ if (decor->motion_cb_id)
+ mb_wm_manager_remove_event_handler (wm, MotionNotify, decor->motion_cb_id);
+
+ if (decor->enter_cb_id)
+ mb_wm_manager_remove_event_handler (wm, EnterNotify, decor->enter_cb_id);
+
+ if (decor->leave_cb_id)
+ mb_wm_manager_remove_event_handler (wm, LeaveNotify, decor->leave_cb_id);
}
void
@@ -741,6 +731,101 @@ mb_wm_decor_button_get_theme_data (MBWMDecorButton * button)
}
static Bool
+button_grab_handler (XEvent *xev, void *userdata)
+{
+ MBWMDecorButton *button = userdata;
+ MBWMDecor *decor = button->decor;
+ MBWMManager *wm = decor->parent_client->wmref;
+ int xmin, ymin, xmax, ymax;
+
+ xmin = button->geom.x;
+ ymin = button->geom.y;
+ xmax = button->geom.x + button->geom.width;
+ ymax = button->geom.y + button->geom.height;
+
+ switch (xev->type)
+ {
+ case MotionNotify:
+ {
+ XMotionEvent *pev = (XMotionEvent*)xev;
+
+ if (pev->x < xmin || pev->x > xmax ||
+ pev->y < ymin || pev->y > ymax)
+ {
+ if (button->state == MBWMDecorButtonStatePressed)
+ {
+ button->state =
+ MBWMDecorButtonStateInactive;
+ mb_wm_theme_paint_button (wm->theme,button);
+ }
+ }
+ else
+ {
+ if (button->state != MBWMDecorButtonStatePressed)
+ {
+ button->state = MBWMDecorButtonStatePressed;
+ mb_wm_theme_paint_button (wm->theme,button);
+ }
+ }
+ }
+ break;
+ case EnterNotify:
+ if (button->state == MBWMDecorButtonStateInactive)
+ {
+ button->state = MBWMDecorButtonStatePressed;
+ mb_wm_theme_paint_button (wm->theme, button);
+ }
+ break;
+ case LeaveNotify:
+ if (button->state != MBWMDecorButtonStateInactive)
+ {
+ button->state = MBWMDecorButtonStateInactive;
+ mb_wm_theme_paint_button (wm->theme, button);
+ }
+ break;
+ case ButtonRelease:
+ {
+ XButtonEvent *pev = (XButtonEvent*)xev;
+
+ if (button->state != MBWMDecorButtonStateInactive)
+ {
+ button->state = MBWMDecorButtonStateInactive;
+ mb_wm_theme_paint_button (wm->theme, button);
+ }
+
+ XUngrabPointer (wm->xdpy, CurrentTime);
+ XSync (wm->xdpy, False); /* necessary */
+
+ if (pev->x < xmin || pev->x > xmax ||
+ pev->y < ymin || pev->y > ymax)
+ return False;
+
+ if (button->release)
+ button->release(wm, button, button->userdata);
+ else
+ mb_wm_decor_button_stock_button_action (button);
+
+ mb_wm_manager_remove_event_handler (wm, MotionNotify,
+ decor->motion_cb_id);
+ decor->motion_cb_id = 0;
+ mb_wm_manager_remove_event_handler (wm, EnterNotify,
+ decor->enter_cb_id);
+ decor->enter_cb_id = 0;
+ mb_wm_manager_remove_event_handler (wm, LeaveNotify,
+ decor->leave_cb_id);
+ decor->leave_cb_id = 0;
+ mb_wm_manager_remove_event_handler (wm, ButtonRelease,
+ decor->release_cb_id);
+ decor->release_cb_id = 0;
+
+ return False;
+ }
+ }
+
+ return True;
+}
+
+static Bool
mb_wm_decor_button_press_handler (XButtonEvent *xev,
void *userdata)
{
@@ -749,193 +834,116 @@ mb_wm_decor_button_press_handler (XButtonEvent *xev,
MBWMManager *wm = decor->parent_client->wmref;
GList *l = NULL;
Bool retval = True;
+ int xmin, ymin, xmax, ymax;
- if (xev->window == decor->xwin)
- {
- int xmin, ymin, xmax, ymax;
- l = mb_wm_client_get_transients (decor->parent_client);
+ if (xev->window != decor->xwin)
+ return True;
- /* Ignore events on the main window decor if transients other than
- * input methods are present
- */
- while (l)
- {
- MBWindowManagerClient * c = l->data;
+ l = mb_wm_client_get_transients (decor->parent_client);
- if (MB_WM_CLIENT_CLIENT_TYPE (c) != MBWMClientTypeInput &&
- mb_wm_client_is_modal (c))
- {
- retval = True;
- goto done;
- }
+ /* Ignore events on the main window decor if transients other than
+ * input methods are present
+ */
+ while (l)
+ {
+ MBWindowManagerClient * c = l->data;
- l = l->next;
- }
+ if (MB_WM_CLIENT_CLIENT_TYPE (c) != MBWMClientTypeInput &&
+ mb_wm_client_is_modal (c))
+ {
+ g_list_free (l);
+ return True;
+ }
- xmin = button->geom.x;
- ymin = button->geom.y;
- xmax = button->geom.x + button->geom.width;
- ymax = button->geom.y + button->geom.height;
+ l = l->next;
+ }
+ g_list_free (l);
- if (xev->x < xmin ||
- xev->x > xmax ||
- xev->y < ymin ||
- xev->y > ymax)
- {
- retval = True;
- goto done;
- }
+ xmin = button->geom.x;
+ ymin = button->geom.y;
+ xmax = button->geom.x + button->geom.width;
+ ymax = button->geom.y + button->geom.height;
- if (button->state != MBWMDecorButtonStatePressed)
- {
- button->state = MBWMDecorButtonStatePressed;
- mb_wm_theme_paint_button (wm->theme, button);
- }
+ if (xev->x < xmin ||
+ xev->x > xmax ||
+ xev->y < ymin ||
+ xev->y > ymax)
+ return True;
- if (button->press_activated)
- {
- XUngrabPointer(wm->xdpy, CurrentTime);
+ if (button->state != MBWMDecorButtonStatePressed)
+ {
+ button->state = MBWMDecorButtonStatePressed;
+ mb_wm_theme_paint_button (wm->theme, button);
+ }
+
+ if (button->press_activated)
+ {
+ XUngrabPointer(wm->xdpy, CurrentTime);
- mb_wm_client_deliver_message (decor->parent_client,
- wm->atoms[MBWM_ATOM_MB_GRAB_TRANSFER],
- xev->time,
- xev->subwindow,
- xev->button, 0, 0);
+ mb_wm_client_deliver_message (decor->parent_client,
+ wm->atoms[MBWM_ATOM_MB_GRAB_TRANSFER],
+ xev->time,
+ xev->subwindow,
+ xev->button, 0, 0);
- XSync (wm->xdpy, False); /* Necessary */
+ XSync (wm->xdpy, False); /* Necessary */
- if (button->press)
- button->press(wm, button, button->userdata);
- else
- mb_wm_decor_button_stock_button_action (button);
- }
+ if (button->press)
+ button->press(wm, button, button->userdata);
else
- {
- XEvent ev;
+ mb_wm_decor_button_stock_button_action (button);
+ }
+ else
+ {
+ XEvent ev;
- /*
- * First, call the custom function if any.
- */
- if (button->press)
- button->press(wm, button, button->userdata);
-
- if (XGrabPointer(wm->xdpy, xev->subwindow, False,
- ButtonPressMask|ButtonReleaseMask|
- PointerMotionMask|EnterWindowMask|LeaveWindowMask,
- GrabModeAsync,
- GrabModeAsync,
- None, None, CurrentTime) == GrabSuccess)
- {
- if (button->state == MBWMDecorButtonStateInactive)
- {
- button->state = MBWMDecorButtonStatePressed;
- mb_wm_theme_paint_button (wm->theme, button);
- }
-
- for (;;)
- {
- /*
- * First of all, we make sure that all events are flushed
- * out (this is necessary to ensure that all the events we
- * are interested in are actually intercepted here).
- */
- XSync (wm->xdpy, False);
-
- if (XCheckMaskEvent(wm->xdpy,
- ButtonPressMask|ButtonReleaseMask|
- PointerMotionMask|EnterWindowMask|
- LeaveWindowMask,
- &ev))
- {
- switch (ev.type)
- {
- case MotionNotify:
- {
- XMotionEvent *pev = (XMotionEvent*)&ev;
-
- if (pev->x < xmin || pev->x > xmax ||
- pev->y < ymin || pev->y > ymax)
- {
- if (button->state ==
- MBWMDecorButtonStatePressed)
- {
- button->state =
- MBWMDecorButtonStateInactive;
- mb_wm_theme_paint_button (wm->theme,button);
- }
- }
- else
- {
- if (button->state !=
- MBWMDecorButtonStatePressed)
- {
- button->state = MBWMDecorButtonStatePressed;
- mb_wm_theme_paint_button (wm->theme,button);
- }
- }
- }
- break;
- case EnterNotify:
- if (button->state == MBWMDecorButtonStateInactive)
- {
- button->state = MBWMDecorButtonStatePressed;
- mb_wm_theme_paint_button (wm->theme, button);
- }
- break;
- case LeaveNotify:
- if (button->state != MBWMDecorButtonStateInactive)
- {
- button->state = MBWMDecorButtonStateInactive;
- mb_wm_theme_paint_button (wm->theme, button);
- }
- break;
- case ButtonRelease:
- {
- XButtonEvent *pev = (XButtonEvent*)&ev;
-
- if (button->state != MBWMDecorButtonStateInactive)
- {
- button->state = MBWMDecorButtonStateInactive;
- mb_wm_theme_paint_button (wm->theme, button);
- }
-
- XUngrabPointer (wm->xdpy, CurrentTime);
- XSync (wm->xdpy, False); /* necessary */
-
- if (pev->x < xmin || pev->x > xmax ||
- pev->y < ymin || pev->y > ymax)
- {
- retval = False;
- goto done;
- }
-
- if (button->release)
- button->release(wm, button, button->userdata);
- else
- mb_wm_decor_button_stock_button_action (button);
-
- return False;
- }
- }
- }
- else
- {
- /*
- * No pending X event, so spin the main loop (this allows
- * things like timers to work.
- */
- mb_wm_main_context_spin_loop (wm->main_ctx);
- }
- }
- }
- }
+ /*
+ * First, call the custom function if any.
+ */
+ if (button->press)
+ button->press(wm, button, button->userdata);
- retval = False;
+ if (XGrabPointer(wm->xdpy, xev->subwindow, False,
+ ButtonPressMask|ButtonReleaseMask|
+ PointerMotionMask|EnterWindowMask|LeaveWindowMask,
+ GrabModeAsync,
+ GrabModeAsync,
+ None, None, CurrentTime) == GrabSuccess)
+ {
+ decor->motion_cb_id = mb_wm_manager_add_event_handler (
+ wm,
+ decor->xwin,
+ MotionNotify,
+ (MBWMXEventFunc)button_grab_handler,
+ button);
+ decor->enter_cb_id = mb_wm_manager_add_event_handler (
+ wm,
+ decor->xwin,
+ EnterNotify,
+ (MBWMXEventFunc)button_grab_handler,
+ button);
+ decor->leave_cb_id = mb_wm_manager_add_event_handler (
+ wm,
+ decor->xwin,
+ LeaveNotify,
+ (MBWMXEventFunc)button_grab_handler,
+ button);
+ decor->release_cb_id = mb_wm_manager_add_event_handler (
+ wm,
+ decor->xwin,
+ ButtonRelease,
+ (MBWMXEventFunc)button_grab_handler,
+ button);
+
+ if (button->state == MBWMDecorButtonStateInactive)
+ {
+ button->state = MBWMDecorButtonStatePressed;
+ mb_wm_theme_paint_button (wm->theme, button);
+ }
+ }
}
- done:
- g_list_free (l);
- return retval;
+ return True;
}
static void
@@ -1052,7 +1060,7 @@ static void
mb_wm_decor_button_destroy (MBWMObject* obj)
{
MBWMDecorButton * button = MB_WM_DECOR_BUTTON (obj);
- MBWMMainContext * ctx = button->decor->parent_client->wmref->main_ctx;
+ MBWMManager * wm = button->decor->parent_client->wmref;
if (button->userdata && button->destroy_userdata)
{
@@ -1068,8 +1076,7 @@ mb_wm_decor_button_destroy (MBWMObject* obj)
button->destroy_themedata = NULL;
}
- mb_wm_main_context_x_event_handler_remove (ctx, ButtonPress,
- button->press_cb_id);
+ mb_wm_manager_remove_event_handler (wm, ButtonPress, button->press_cb_id);
}
static void
@@ -1079,7 +1086,7 @@ mb_wm_decor_button_realize (MBWMDecorButton *button)
MBWMManager *wm = decor->parent_client->wmref;
button->press_cb_id =
- mb_wm_main_context_x_event_handler_add (wm->main_ctx,
+ mb_wm_manager_add_event_handler (wm,
decor->xwin,
ButtonPress,
(MBWMXEventFunc)mb_wm_decor_button_press_handler,
diff --git a/matchbox/mb-wm-decor.h b/matchbox/mb-wm-decor.h
index a25ffdb..b8b3d10 100644
--- a/matchbox/mb-wm-decor.h
+++ b/matchbox/mb-wm-decor.h
@@ -73,6 +73,9 @@ struct MBWMDecor
unsigned long press_cb_id;
unsigned long release_cb_id;
+ unsigned long motion_cb_id;
+ unsigned long enter_cb_id;
+ unsigned long leave_cb_id;
void *themedata;
MBWMDecorDestroyUserData destroy_themedata;
diff --git a/matchbox/mb-wm-main-context.c b/matchbox/mb-wm-main-context.c
deleted file mode 100644
index d9e7819..0000000
--- a/matchbox/mb-wm-main-context.c
+++ /dev/null
@@ -1,1116 +0,0 @@
-#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;
- MBWMManagerTimeOutFunc func;
- void *userdata;
- unsigned long id;
- struct timeval triggers;
-
-};
-
-struct MBWMFdWatchInfo{
- MBWMIOChannel *channel;
- MBWMIOCondition events;
- MBWMManagerFdWatchFunc 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;
- MBWMManager * wm = ctx->wm;
-
- while (mb_wm_main_context_spin_xevent (ctx));
-
- if (wm->sync_type)
- mb_wm_manager_sync (wm);
-
- return TRUE;
-}
-#endif
-
-static int
-mb_wm_main_context_init (MBWMObject *this, va_list vap)
-{
- MBWMMainContext *ctx = MB_WM_MAIN_CONTEXT (this);
- MBWMManager *wm = NULL;
- MBWMObjectProp prop;
-
- prop = va_arg(vap, MBWMObjectProp);
- while (prop)
- {
- if (prop == MBWMObjectPropWm)
- {
- wm = va_arg(vap, MBWMManager *);
- 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 (MBWMManager *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)
-{
- MBWMManager *wm = ctx->wm;
- 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 = ctx->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 = ctx->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 = ctx->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 = ctx->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 = ctx->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 = ctx->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 = ctx->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 = ctx->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 = ctx->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 = ctx->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 = ctx->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 = ctx->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 = ctx->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;
- }
-
- return False;
-}
-
-static Bool
-mb_wm_main_context_spin_xevent (MBWMMainContext *ctx)
-{
- MBWMManager * 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)
-{
- MBWMManager * 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
- MBWMManager * 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_manager_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
- MBWMManager * 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 =
- g_list_append (ctx->event_funcs.damage_notify, func_info);
- }
- else
-#endif
- switch (type)
- {
- case Expose:
- break;
- case MapRequest:
- ctx->event_funcs.map_request =
- g_list_append (ctx->event_funcs.map_request, func_info);
- break;
- case MapNotify:
- ctx->event_funcs.map_notify=
- g_list_append (ctx->event_funcs.map_notify, func_info);
- break;
- case UnmapNotify:
- ctx->event_funcs.unmap_notify=
- g_list_append (ctx->event_funcs.unmap_notify, func_info);
- break;
- case DestroyNotify:
- ctx->event_funcs.destroy_notify =
- g_list_append (ctx->event_funcs.destroy_notify, func_info);
- break;
- case ConfigureNotify:
- ctx->event_funcs.configure_notify =
- g_list_append (ctx->event_funcs.configure_notify, func_info);
- break;
- case ConfigureRequest:
- ctx->event_funcs.configure_request =
- g_list_append (ctx->event_funcs.configure_request, func_info);
- break;
- case KeyPress:
- ctx->event_funcs.key_press =
- g_list_append (ctx->event_funcs.key_press, func_info);
- break;
- case PropertyNotify:
- ctx->event_funcs.property_notify =
- g_list_append (ctx->event_funcs.property_notify, func_info);
- break;
- case ButtonPress:
- ctx->event_funcs.button_press =
- g_list_append (ctx->event_funcs.button_press, func_info);
- break;
- case ButtonRelease:
- ctx->event_funcs.button_release =
- g_list_append (ctx->event_funcs.button_release, func_info);
- break;
- case MotionNotify:
- ctx->event_funcs.motion_notify =
- g_list_append (ctx->event_funcs.motion_notify, func_info);
- break;
- case ClientMessage:
- ctx->event_funcs.client_message =
- g_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)
-{
- GList * l = NULL;
- GList **l_start;
-
-#if ENABLE_COMPOSITE
- MBWMManager * 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)
- {
- 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;
- }
-}
-
-#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)
-{
- GList * l = g_list_first(ctx->event_funcs.timeout);
- struct timeval current_time;
-
- if (!l)
- return False;
-
- gettimeofday (&current_time, NULL);
-
- while (l)
- {
- MBWMTimeOutEventInfo * tinfo = l->data;
- unsigned long tid = tinfo->id;
-
- if (!mb_wm_main_context_handle_timeout (tinfo, &current_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 = g_list_first(ctx->event_funcs.timeout);
- }
- else
- l = g_list_next(l);
- }
- return True;
-}
-#endif /* !USE_GLIB_MAINLOOP */
-
-unsigned long
-mb_wm_main_context_timeout_handler_add (MBWMMainContext *ctx,
- int ms,
- MBWMManagerTimeOutFunc 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 (&current_time, NULL);
- mb_wm_main_context_timeout_setup (tinfo, &current_time);
-
- ctx->event_funcs.timeout =
- g_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
- GList * 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 =
- g_list_remove(ctx->event_funcs.timeout, l->data);
- return;
- }
-
- l = g_list_next(l);
- }
-#else
- g_source_remove (id);
-#endif
-}
-
-unsigned long
-mb_wm_main_context_fd_watch_add (MBWMMainContext *ctx,
- MBWMIOChannel *channel,
- MBWMIOCondition events,
- MBWMManagerFdWatchFunc 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 =
- g_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
- GList * l = ctx->event_funcs.fd_watch;
-
- while (l)
- {
- MBWMFdWatchInfo * info = l->data;
-
- if (info->id == id)
- {
- GList * prev = l->prev;
- GList * 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)
-{
- GList *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;
- GList * 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)
- {
- GList * prev = l->prev;
- GList * 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
diff --git a/matchbox/mb-wm-main-context.h b/matchbox/mb-wm-main-context.h
deleted file mode 100644
index 6a84cc2..0000000
--- a/matchbox/mb-wm-main-context.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Matchbox Window Manager II - A lightweight window manager not for the
- * desktop.
- *
- * Authored By Matthew Allum <mallum@o-hand.com>
- *
- * Copyright (c) 2005 OpenedHand Ltd - http://o-hand.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _HAVE_MB_MAIN_CONTEXT_H
-#define _HAVE_MB_MAIN_CONTEXT_H
-
-#include <matchbox/mb-wm-object.h>
-#include <matchbox/mb-wm-manager.h>
-#include <poll.h>
-
-#define MB_WM_MAIN_CONTEXT(c) ((MBWMMainContext*)(c))
-#define MB_WM_MAIN_CONTEXT_CLASS(c) ((MBWMMainContextClass*)(c))
-#define MB_WM_TYPE_MAIN_CONTEXT (mb_wm_main_context_class_type ())
-#define MB_WM_IS_MAIN_CONTEXT(c) (MB_WM_OBJECT_TYPE(c)==MB_WM_TYPE_MAIN_CONTEXT)
-
-/* XXX: we have a circular dependency between mb-wm-main-context.h
- * and mb-window-manager.h */
-#ifndef MB_WM_MAIN_CONTEXT_TYPEDEF_DEFINED
-typedef struct MBWMMainContext MBWMMainContext;
-#define MB_WM_MAIN_CONTEXT_TYPEDEF_DEFINED
-#endif
-typedef struct MBWMMainContextClass MBWMMainContextClass;
-
-typedef Bool (*MBWMMainContextXEventFunc) (XEvent * xev, void * userdata);
-
-typedef struct MBWMEventFuncs
-{
- /* FIXME: figure our X wrap / unwrap mechanism */
- GList *map_notify;
- GList *unmap_notify;
- GList *map_request;
- GList *destroy_notify;
- GList *configure_request;
- GList *configure_notify;
- GList *key_press;
- GList *property_notify;
- GList *button_press;
- GList *button_release;
- GList *motion_notify;
- GList *client_message;
-
-#if ENABLE_COMPOSITE
- GList *damage_notify;
-#endif
-
-#if ! USE_GLIB_MAINLOOP
- GList *timeout;
- GList *fd_watch;
-#endif
-}
-MBWMEventFuncs;
-
-struct MBWMMainContext
-{
- MBWMObject parent;
-
- MBWMManager *wm;
-
- MBWMEventFuncs event_funcs;
- struct pollfd *poll_fds;
- int n_poll_fds;
- Bool poll_cache_dirty;
-};
-
-struct MBWMMainContextClass
-{
- MBWMObjectClass parent;
-};
-
-int
-mb_wm_main_context_class_type ();
-
-MBWMMainContext*
-mb_wm_main_context_new(MBWMManager *wm);
-
-unsigned long
-mb_wm_main_context_x_event_handler_add (MBWMMainContext *ctx,
- Window xwin,
- int type,
- MBWMXEventFunc func,
- void *userdata);
-
-void
-mb_wm_main_context_x_event_handler_remove (MBWMMainContext *ctx,
- int type,
- unsigned long id);
-
-unsigned long
-mb_wm_main_context_timeout_handler_add (MBWMMainContext *ctx,
- int ms,
- MBWMManagerTimeOutFunc func,
- void *userdata);
-
-void
-mb_wm_main_context_timeout_handler_remove (MBWMMainContext *ctx,
- unsigned long id);
-
-MBWMIOChannel *
-mb_wm_main_context_io_channel_new (int fd);
-
-void
-mb_wm_main_context_io_channel_destroy (MBWMIOChannel * channel);
-
-int
-mb_wm_main_context_io_channel_get_fd (MBWMIOChannel * channel);
-
-unsigned long
-mb_wm_main_context_fd_watch_add (MBWMMainContext *ctx,
- MBWMIOChannel *channel,
- MBWMIOCondition events,
- MBWMManagerFdWatchFunc func,
- void *userdata);
-
-void
-mb_wm_main_context_fd_watch_remove (MBWMMainContext *ctx,
- unsigned long id);
-
-#if USE_GLIB_MAINLOOP
-gboolean
-mb_wm_main_context_gloop_xevent (gpointer userdata);
-#endif
-
-Bool
-mb_wm_main_context_handle_x_event (XEvent *xev,
- MBWMMainContext *ctx);
-
-void
-mb_wm_main_context_loop (MBWMMainContext *ctx);
-
-Bool
-mb_wm_main_context_spin_loop (MBWMMainContext *ctx);
-
-#endif
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,
diff --git a/matchbox/mb-wm-manager.h b/matchbox/mb-wm-manager.h
index 72a27a2..4f143ab 100644
--- a/matchbox/mb-wm-manager.h
+++ b/matchbox/mb-wm-manager.h
@@ -22,24 +22,17 @@
#define _HAVE_MB_WM_MANAGER_H
#include <matchbox/mb-wm-config.h>
+#include <matchbox/mb-wm-types.h>
#include <matchbox/mb-wm-object.h>
#include <matchbox/mb-wm-keys.h>
#include <matchbox/mb-wm-root-window.h>
#include <matchbox/mb-wm-theme.h>
#include <matchbox/mb-wm-layout.h>
-#include <matchbox/mb-wm-main-context.h>
#if ENABLE_COMPOSITE
#include <matchbox/mb-wm-comp-mgr.h>
#endif
#include <matchbox/xas.h>
-/* XXX: we have a circular dependency between mb-wm-main-context.h
- * and mb-window-manager.h */
-#ifndef MB_WM_MAIN_CONTEXT_TYPEDEF_DEFINED
-typedef struct MBWMMainContext MBWMMainContext;
-#define MB_WM_MAIN_CONTEXT_TYPEDEF_DEFINED
-#endif
-
#define MB_WM_MANAGER(c) ((MBWMManager*)(c))
#define MB_WM_MANAGER_CLASS(c) ((MBWMManagerClass*)(c))
#define MB_WM_TYPE_MANAGER (mb_wm_manager_class_type ())
@@ -66,6 +59,28 @@ typedef enum
_MBWMManagerCursorLast
} MBWMManagerCursor;
+typedef Bool (*MBWMManagerEventFunc) (XEvent * xev, void * userdata);
+
+typedef struct MBWMEventFuncs
+{
+ /* FIXME: figure our X wrap / unwrap mechanism */
+ GList *map_notify;
+ GList *unmap_notify;
+ GList *map_request;
+ GList *destroy_notify;
+ GList *configure_request;
+ GList *configure_notify;
+ GList *key_press;
+ GList *property_notify;
+ GList *button_press;
+ GList *button_release;
+ GList *motion_notify;
+ GList *client_message;
+
+#if ENABLE_COMPOSITE
+ GList *damage_notify;
+#endif
+} MBWMEventFuncs;
struct MBWMManager
{
@@ -75,6 +90,13 @@ struct MBWMManager
unsigned int xdpy_width, xdpy_height;
int xscreen;
+ GList *xlib_event_filters;
+ GQueue *event_queue;
+ gboolean event_retrieval_disabled;
+ GSource *event_source;
+ unsigned int do_update_idle;
+ MBWMEventFuncs event_funcs;
+
MBWindowManagerClient *stack_top, *stack_bottom;
GList *clients;
MBWindowManagerClient *desktop;
@@ -99,7 +121,6 @@ struct MBWMManager
MBWMTheme *theme;
MBWMLayout *layout;
- MBWMMainContext *main_ctx;
MBWMManagerFlag flags;
#if ENABLE_COMPOSITE
MBWMCompMgr *comp_mgr;
@@ -136,8 +157,6 @@ struct MBWMManagerClass
MBWMTheme * (*theme_new) (MBWMManager *wm, const char * path);
void (*get_desktop_geometry) (MBWMManager *wm, MBGeometry *geom);
-
- void (*main) (MBWMManager *wm);
};
/**
@@ -157,10 +176,26 @@ MBWMManager *
mb_wm_manager_new_with_dpy (int argc, char **argv, Display * dpy);
void
-mb_wm_manager_run (MBWMManager * wm);
+mb_wm_manager_disable_x11_event_retrieval (MBWMManager *wm);
void
-mb_wm_manager_run_with_compositor (MBWMManager * wm, MBWMCompMgr *compositor);
+mb_wm_manager_xlib_add_filter (MBWMManager *wm,
+ MBWMXlibFilterFunc filter,
+ void *data);
+
+void
+mv_wm_manager_xlib_remove_filter (MBWMManager *wm,
+ MBWMXlibFilterFunc func,
+ void *data);
+
+gboolean
+mb_wm_manager_handle_xlib_event (MBWMManager *wm, XEvent *xev);
+
+void
+mb_wm_manager_start (MBWMManager * wm);
+
+void
+mb_wm_manager_start_with_compositor (MBWMManager * wm, MBWMCompMgr *compositor);
void
mb_wm_manager_set_layout (MBWMManager *wm, MBWMLayout *layout);
@@ -242,6 +277,18 @@ mb_wm_manager_compositing_enabled (MBWMManager * wm);
MBWMModality
mb_wm_manager_get_modality_type (MBWMManager * wm);
+unsigned long
+mb_wm_manager_add_event_handler (MBWMManager *wm,
+ Window xwin,
+ int type,
+ MBWMXEventFunc func,
+ void *userdata);
+
+void
+mb_wm_manager_remove_event_handler (MBWMManager *wm,
+ int type,
+ unsigned long id);
+
void
mb_wm_manager_sync (MBWMManager *wm);
diff --git a/matchbox/mb-wm-object.h b/matchbox/mb-wm-object.h
index e43a45e..e4abb2a 100644
--- a/matchbox/mb-wm-object.h
+++ b/matchbox/mb-wm-object.h
@@ -22,6 +22,8 @@
#define _HAVE_MB_OBJECT_H
#include <stdarg.h>
+#include <glib.h>
+
#include <matchbox/mb-wm-object-props.h>
typedef struct MBWMObject MBWMObject;
diff --git a/matchbox/mb-wm-types.h b/matchbox/mb-wm-types.h
index 5111f2b..0e8b503 100644
--- a/matchbox/mb-wm-types.h
+++ b/matchbox/mb-wm-types.h
@@ -382,4 +382,28 @@ typedef enum MBWMModality
#define MB_CMD_COMPOSITE 8
#define MB_CMB_KEYS_RELOAD 9
+/**
+ * MBWMXlibFilterReturn:
+ * @MB_WM_XLIB_FILTER_CONTINUE: The event was not handled, continues the
+ * processing
+ * @MB_WM_XLIB_FILTER_REMOVE: Remove the event, stops the processing
+ *
+ * Return values for the #MBWMXlibFilterFunc function.
+ */
+typedef enum _MBWMXlibFilterReturn {
+ MB_WM_XLIB_FILTER_CONTINUE,
+ MB_WM_XLIB_FILTER_REMOVE
+} MBWMXlibFilterReturn;
+
+/**
+ * MBWMXlibFilterFunc:
+ *
+ * A callback function that can be registered with
+ * _mb_wm_manager_xlib_add_filter. The function should return
+ * %MB_WM_XLIB_FILTER_REMOVE if it wants to prevent further processing
+ * or %MB_WM_XLIB_FILTER_CONTINUE otherwise.
+ */
+typedef MBWMXlibFilterReturn (* MBWMXlibFilterFunc) (XEvent *xevent,
+ void *data);
+
#endif