X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fmouse.c;h=6d532518d57e7f962161d356d9e422cf906694e7;hb=38bef0a38bf907a54c193ab063b4830788398edc;hp=493e1000c1eb546674053154896504cfae599935;hpb=fbc7607fbd1a380428a53094e727ac7631871bd4;p=chaz%2Fopenbox diff --git a/openbox/mouse.c b/openbox/mouse.c index 493e1000..6d532518 100644 --- a/openbox/mouse.c +++ b/openbox/mouse.c @@ -46,6 +46,9 @@ typedef struct { /* Array of GSList*s of ObMouseBinding*s. */ static GSList *bound_contexts[OB_FRAME_NUM_CONTEXTS]; +/* TRUE when we have a grab on the pointer and need to reply the pointer event + to send it to other applications */ +static gboolean replay_pointer_needed; ObFrameContext mouse_button_frame_context(ObFrameContext context, guint button, @@ -142,21 +145,21 @@ static void grab_all_clients(gboolean grab) mouse_grab_for_client(it->data, grab); } -void mouse_unbind_all() +void mouse_unbind_all(void) { gint i; GSList *it; - + for(i = 0; i < OB_FRAME_NUM_CONTEXTS; ++i) { for (it = bound_contexts[i]; it; it = g_slist_next(it)) { ObMouseBinding *b = it->data; gint j; for (j = 0; j < OB_NUM_MOUSE_ACTIONS; ++j) { - GSList *it; + GSList *jt; - for (it = b->actions[j]; it; it = g_slist_next(it)) - actions_act_unref(it->data); + for (jt = b->actions[j]; jt; jt = g_slist_next(jt)) + actions_act_unref(jt->data); g_slist_free(b->actions[j]); } g_free(b); @@ -196,10 +199,19 @@ static gboolean fire_binding(ObMouseAction a, ObFrameContext context, if (it == NULL) return FALSE; actions_run_acts(b->actions[a], mouse_action_to_user_action(a), - state, x, y, context, c); + state, x, y, button, context, c); return TRUE; } +void mouse_replay_pointer() +{ + if (replay_pointer_needed) { + /* replay the pointer event before any windows move */ + XAllowEvents(ob_display, ReplayPointer, event_curtime); + replay_pointer_needed = FALSE; + } +} + void mouse_event(ObClient *client, XEvent *e) { static Time ltime; @@ -225,6 +237,22 @@ void mouse_event(ObClient *client, XEvent *e) button = e->xbutton.button; state = e->xbutton.state; + /* if the binding was in a client context, then we need to call + XAllowEvents with ReplayPointer at some point, to send the event + through to the client. when this happens though depends. if + windows are going to be moved on screen, then the click will end + up going somewhere wrong, set that we need it, and if nothing + else causes the replay pointer to be run, then we will do it + after all the actions are finished. + + (We do it after all the actions because FocusIn interrupts + dragging for kdesktop, so if we send the button event now, and + then they get a focus event after, it breaks. Instead, wait to send + the button press until after the actions when possible.) + */ + if (CLIENT_CONTEXT(context, client)) + replay_pointer_needed = TRUE; + fire_binding(OB_MOUSE_ACTION_PRESS, context, client, e->xbutton.state, e->xbutton.button, @@ -235,11 +263,13 @@ void mouse_event(ObClient *client, XEvent *e) if (grab_on_pointer()) button = 0; - if (CLIENT_CONTEXT(context, client)) { - /* Replay the event, so it goes to the client*/ - XAllowEvents(ob_display, ReplayPointer, event_curtime); - /* Fall through to the release case! */ - } else + /* replay the pointer event if it hasn't been replayed yet (i.e. no + windows were moved) */ + mouse_replay_pointer(); + + /* in the client context, we won't get a button release because of the + way it is grabbed, so just fake one */ + if (!CLIENT_CONTEXT(context, client)) break; case ButtonRelease: