diff options
author | Ton Roosendaal <ton@blender.org> | 2012-10-26 19:21:31 +0400 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2012-10-26 19:21:31 +0400 |
commit | 37bf6ef04405222adbfe0970e51b679ee99054ac (patch) | |
tree | 0d37b7472d27a8fb5ef7bec4af0f7a2dbc3e3bdc /source/blender/windowmanager | |
parent | d24aaf5958c7a7e4d08991ae801e39032138a1ff (diff) |
Bugfix #28734
Double clicks were never working reliably in Blender - this mostly because
it wasn't a real event, but something generated in the handler code.
Now it is an actual event - meaning it always gets handled (if you have
a keymap item for it of course), but if there's no doubleclick handling
it treats the doubleclick as a normal click.
Also cleaned code. No recursion anymore.
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 147 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_keymap.c | 5 |
2 files changed, 76 insertions, 76 deletions
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index a0090166840..c2c381e54f7 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1672,7 +1672,7 @@ static int wm_action_not_handled(int action) return action == WM_HANDLER_CONTINUE || action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL); } -static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) +static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers) { #ifndef NDEBUG const int do_debug_handler = (G.debug & G_DEBUG_EVENTS) @@ -1849,49 +1849,44 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) } } - /* test for CLICK event */ - if (wm_action_not_handled(action) && event->val == KM_RELEASE) { - wmWindow *win = CTX_wm_window(C); + if (action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL)) + wm_cursor_arrow_move(CTX_wm_window(C), event); - if (win && win->eventstate->prevtype == event->type && win->eventstate->prevval == KM_PRESS) { - /* test for double click first, - * note1: this can be problematic because single click operators can get the - * double click event but then with old mouse coords which is highly confusing, - * so check for mouse moves too. - * note2: the first click event will be handled but still used to create a - * double click event if clicking again quickly. - * If no double click events are found it will fallback to a single click. - * So a double click event can result in 2 successive single click calls - * if its not handled by the keymap - campbell */ - if ((ABS(event->x - win->eventstate->prevclickx)) <= 2 && - (ABS(event->y - win->eventstate->prevclicky)) <= 2 && - ((PIL_check_seconds_timer() - win->eventstate->prevclicktime) * 1000 < U.dbl_click_time)) - { - event->val = KM_DBL_CLICK; - /* removed this because in cases where we're this is used as a single click - * event, this will give old coords, - * since the distance is checked above, using new coords should be ok. */ - // event->x = win->eventstate->prevclickx; - // event->y = win->eventstate->prevclicky; - action |= wm_handlers_do(C, event, handlers); - } + return action; +} - if (wm_action_not_handled(action)) { +/* this calls handlers twice - to solve (double-)click events */ +static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) +{ + int action = wm_handlers_do_intern(C, event, handlers); + + /* test for CLICK events */ + if (wm_action_not_handled(action)) { + wmWindow *win = CTX_wm_window(C); + + if (win && win->eventstate->prevtype == event->type) { + + if(event->val == KM_RELEASE && win->eventstate->prevval == KM_PRESS) { event->val = KM_CLICK; - action |= wm_handlers_do(C, event, handlers); + action |= wm_handlers_do_intern(C, event, handlers); + + /* revert value if not handled */ + if (wm_action_not_handled(action)) { + event->val = KM_RELEASE; + } } - - - /* revert value if not handled */ - if (wm_action_not_handled(action)) { - event->val = KM_RELEASE; + else if(event->val == KM_DBL_CLICK) { + event->val = KM_PRESS; + action |= wm_handlers_do_intern(C, event, handlers); + + /* revert value if not handled */ + if (wm_action_not_handled(action)) { + event->val = KM_DBL_CLICK; + } } } } - if (action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL)) - wm_cursor_arrow_move(CTX_wm_window(C), event); - return action; } @@ -2185,40 +2180,6 @@ void wm_event_do_handlers(bContext *C) } } - /* store last event for this window */ - /* mousemove and timer events don't overwrite last type */ - if (!ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) && !ISTIMER(event->type)) { - if (wm_action_not_handled(action)) { - if (win->eventstate->prevtype == event->type) { - /* set click time on first click (press -> release) */ - if (win->eventstate->prevval == KM_PRESS && event->val == KM_RELEASE) { - win->eventstate->prevclicktime = PIL_check_seconds_timer(); - win->eventstate->prevclickx = event->x; - win->eventstate->prevclicky = event->y; - } - } - else { - /* reset click time if event type not the same */ - win->eventstate->prevclicktime = 0; - } - - win->eventstate->prevval = event->val; - win->eventstate->prevtype = event->type; - } - else if (event->val == KM_CLICK) { /* keep click for double click later */ - win->eventstate->prevtype = event->type; - win->eventstate->prevval = event->val; - win->eventstate->prevclicktime = PIL_check_seconds_timer(); - win->eventstate->prevclickx = event->x; - win->eventstate->prevclicky = event->y; - } - else { /* reset if not */ - win->eventstate->prevtype = -1; - win->eventstate->prevval = 0; - win->eventstate->prevclicktime = 0; - } - } - /* unlink and free here, blender-quit then frees all */ BLI_remlink(&win->queue, event); wm_event_free(event); @@ -2724,6 +2685,10 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U /* initialize and copy state (only mouse x y and modifiers) */ event = *evt; + /* copy prev state to event state */ + evt->prevval = evt->val; + evt->prevtype = evt->type; + switch (type) { /* mouse move */ case GHOST_kEventCursorMove: @@ -2806,7 +2771,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U case GHOST_kEventButtonUp: { GHOST_TEventButtonData *bd = customdata; - + + /* get value and type from ghost */ event.val = (type == GHOST_kEventButtonDown) ? KM_PRESS : KM_RELEASE; if (bd->button == GHOST_kButtonMaskLeft) @@ -2820,6 +2786,10 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U else event.type = MIDDLEMOUSE; + /* copy to event state */ + evt->val= event.val; + evt->type= event.type; + if (win->active == 0) { int cx, cy; @@ -2830,6 +2800,21 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U event.y = evt->y = cy; } + /* double click test */ + if (event.type == evt->prevtype && event.val == KM_PRESS) { + if ((ABS(event.x - evt->prevclickx)) <= 2 && + (ABS(event.y - evt->prevclicky)) <= 2 && + ((PIL_check_seconds_timer() - evt->prevclicktime) * 1000 < U.dbl_click_time)) + { + event.val = KM_DBL_CLICK; + } + } + if (event.val == KM_RELEASE) { + evt->prevclicktime = PIL_check_seconds_timer(); + evt->prevclickx = event.x; + evt->prevclicky = event.y; + } + /* add to other window if event is there (not to both!) */ owin = wm_event_cursor_other_windows(wm, win, &event); if (owin) { @@ -2860,6 +2845,10 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U memcpy(event.utf8_buf, kd->utf8_buf, sizeof(event.utf8_buf)); /* might be not null terminated*/ event.val = (type == GHOST_kEventKeyDown) ? KM_PRESS : KM_RELEASE; + /* copy to event state */ + evt->val= event.val; + evt->type= event.type; + /* exclude arrow keys, esc, etc from text input */ if (type == GHOST_kEventKeyUp) { event.ascii = '\0'; @@ -2932,6 +2921,22 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U if (event.type == ESCKEY && event.val == KM_PRESS) G.is_break = TRUE; + /* double click test */ + if (event.type == evt->prevtype && event.val == KM_PRESS) { + if ((ABS(event.x - evt->prevclickx)) <= 2 && + (ABS(event.y - evt->prevclicky)) <= 2 && + ((PIL_check_seconds_timer() - evt->prevclicktime) * 1000 < U.dbl_click_time)) + { + printf("double key click\n"); + event.val = KM_DBL_CLICK; + } + } + if (event.val == KM_RELEASE) { + evt->prevclicktime = PIL_check_seconds_timer(); + evt->prevclickx = event.x; + evt->prevclicky = event.y; + } + wm_event_add(win, &event); break; diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index bcddc984ed3..02dc77171d5 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -957,11 +957,6 @@ int WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2) return 0; if (k1->val != KM_ANY && k2->val != KM_ANY) { - /* take click, press, release conflict into account */ - if (k1->val == KM_CLICK && ELEM3(k2->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0) - return 0; - if (k2->val == KM_CLICK && ELEM3(k1->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0) - return 0; if (k1->val != k2->val) return 0; } |