aboutsummaryrefslogtreecommitdiffstats
path: root/matchbox/mb-wm-decor.c
diff options
context:
space:
mode:
Diffstat (limited to 'matchbox/mb-wm-decor.c')
-rw-r--r--matchbox/mb-wm-decor.c541
1 files changed, 274 insertions, 267 deletions
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,