diff options
Diffstat (limited to 'matchbox/mb-wm-decor.c')
-rw-r--r-- | matchbox/mb-wm-decor.c | 541 |
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, |