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.
This commit is contained in:
Robert Bragg
2010-08-19 04:36:22 +01:00
parent 4105968374
commit ea84bd26d7
19 changed files with 1247 additions and 1802 deletions

View File

@@ -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}
"

View File

@@ -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>

View File

@@ -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));

View File

@@ -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?");

View File

@@ -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?");

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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@

View File

@@ -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,70 +263,38 @@ mb_wm_decor_press_handler (XButtonEvent *xev,
GrabModeAsync,
None, None, CurrentTime) == GrabSuccess)
{
DecorGrabClosure *closure = g_slice_new (DecorGrabClosure);
MBGeometry geom;
decor->release_cb_id = mb_wm_main_context_x_event_handler_add (
wm->main_ctx,
mb_wm_client_get_coverage (decor->parent_client, &geom);
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);
}
}
return retval;
}
static Bool
mb_wm_decor_reparent (MBWMDecor *decor);
static Bool
mb_wm_decor_sync_window (MBWMDecor *decor)
{
@@ -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
@@ -740,6 +730,101 @@ mb_wm_decor_button_get_theme_data (MBWMDecorButton * button)
return button->themedata;
}
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)
if (xev->window != decor->xwin)
return True;
l = mb_wm_client_get_transients (decor->parent_client);
/* Ignore events on the main window decor if transients other than
* input methods are present
*/
while (l)
{
int xmin, ymin, xmax, ymax;
l = mb_wm_client_get_transients (decor->parent_client);
MBWindowManagerClient * c = l->data;
/* Ignore events on the main window decor if transients other than
* input methods are present
*/
while (l)
{
MBWindowManagerClient * c = l->data;
if (MB_WM_CLIENT_CLIENT_TYPE (c) != MBWMClientTypeInput &&
mb_wm_client_is_modal (c))
{
g_list_free (l);
return True;
}
if (MB_WM_CLIENT_CLIENT_TYPE (c) != MBWMClientTypeInput &&
mb_wm_client_is_modal (c))
{
retval = True;
goto done;
}
l = l->next;
}
g_list_free (l);
l = l->next;
}
xmin = button->geom.x;
ymin = button->geom.y;
xmax = button->geom.x + button->geom.width;
ymax = button->geom.y + button->geom.height;
xmin = button->geom.x;
ymin = button->geom.y;
xmax = button->geom.x + button->geom.width;
ymax = button->geom.y + button->geom.height;
if (xev->x < xmin ||
xev->x > xmax ||
xev->y < ymin ||
xev->y > ymax)
return True;
if (xev->x < xmin ||
xev->x > xmax ||
xev->y < ymin ||
xev->y > ymax)
{
retval = True;
goto done;
}
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);
XSync (wm->xdpy, False); /* Necessary */
if (button->press)
button->press(wm, button, button->userdata);
else
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);
}
}
}
}
retval = False;
if (button->state != MBWMDecorButtonStatePressed)
{
button->state = MBWMDecorButtonStatePressed;
mb_wm_theme_paint_button (wm->theme, button);
}
done:
g_list_free (l);
return retval;
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);
XSync (wm->xdpy, False); /* Necessary */
if (button->press)
button->press(wm, button, button->userdata);
else
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)
{
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);
}
}
}
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,

View File

@@ -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;

File diff suppressed because it is too large Load Diff

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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);

View File

@@ -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;

View File

@@ -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