diff options
Diffstat (limited to 'source/blender/windowmanager/intern/wm_event_system.c')
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 236 |
1 files changed, 153 insertions, 83 deletions
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index c0e3b19c716..b2647626f3a 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -66,6 +66,8 @@ #include "RNA_access.h" +#include "BIF_gl.h" + #include "UI_interface.h" #include "PIL_time.h" @@ -82,16 +84,21 @@ # include "RNA_enum_types.h" #endif +static void update_tablet_data(wmWindow *win, wmEvent *event); + static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports, short context, short poll_only); /* ************ event management ************** */ -void wm_event_add(wmWindow *win, wmEvent *event_to_add) +void wm_event_add(wmWindow *win, const wmEvent *event_to_add) { - wmEvent *event = MEM_callocN(sizeof(wmEvent), "wmEvent"); + wmEvent *event = MEM_mallocN(sizeof(wmEvent), "wmEvent"); *event = *event_to_add; + + update_tablet_data(win, event); + BLI_addtail(&win->queue, event); } @@ -106,6 +113,11 @@ void wm_event_free(wmEvent *event) MEM_freeN(event->customdata); } } + + if (event->tablet_data) { + MEM_freeN(event->tablet_data); + } + MEM_freeN(event); } @@ -270,7 +282,7 @@ void wm_event_do_notifiers(bContext *C) /* XXX context in notifiers? */ CTX_wm_window_set(C, win); - /* printf("notifier win %d screen %s cat %x\n", win->winid, win->screen->id.name+2, note->category); */ + /* printf("notifier win %d screen %s cat %x\n", win->winid, win->screen->id.name + 2, note->category); */ ED_screen_do_listen(C, note); for (ar = win->screen->regionbase.first; ar; ar = ar->next) { @@ -338,7 +350,7 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve ARegion *region = CTX_wm_region(C); ARegion *menu = CTX_wm_menu(C); static int do_wheel_ui = TRUE; - int is_wheel = ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE); + int is_wheel = ELEM3(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, MOUSEPAN); int retval; /* UI code doesn't handle return values - it just always returns break. @@ -441,10 +453,26 @@ static void wm_operator_print(bContext *C, wmOperator *op) MEM_freeN(buf); } +/** + * Sets the active region for this space from the context. + * + * \see #BKE_area_find_region_active_win + */ +void WM_operator_region_active_win_set(bContext *C) +{ + ScrArea *sa = CTX_wm_area(C); + if (sa) { + ARegion *ar = CTX_wm_region(C); + if (ar && ar->regiontype == RGN_TYPE_WINDOW) { + sa->region_active_win = BLI_findindex(&sa->regionbase, ar); + } + } +} + /* for debugging only, getting inspecting events manually is tedious */ #ifndef NDEBUG -void WM_event_print(wmEvent *event) +void WM_event_print(const wmEvent *event) { if (event) { const char *unknown = "UNKNOWN"; @@ -561,10 +589,16 @@ static void wm_operator_finished(bContext *C, wmOperator *op, int repeat) MEM_freeN(buf); } - if (wm_operator_register_check(wm, op->type)) + if (wm_operator_register_check(wm, op->type)) { + /* take ownership of reports (in case python provided own) */ + op->reports->flag |= RPT_FREE; + wm_operator_register(C, op); - else + WM_operator_region_active_win_set(C); + } + else { WM_operator_free(op); + } } } @@ -904,6 +938,9 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, wm_operator_finished(C, op, 0); } else if (retval & OPERATOR_RUNNING_MODAL) { + /* take ownership of reports (in case python provided own) */ + op->reports->flag |= RPT_FREE; + /* grab cursor during blocking modal ops (X11) * Also check for macro */ @@ -1033,7 +1070,14 @@ static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA } if (!(ar && ar->regiontype == type) && area) { - ARegion *ar1 = BKE_area_find_region_type(area, type); + ARegion *ar1; + if (type == RGN_TYPE_WINDOW) { + ar1 = BKE_area_find_region_active_win(area); + } + else { + ar1 = BKE_area_find_region_type(area, type); + } + if (ar1) CTX_wm_region_set(C, ar1); } @@ -1132,13 +1176,6 @@ int WM_operator_call_py(bContext *C, wmOperatorType *ot, short context, if (!is_undo && wm && (wm == CTX_wm_manager(C))) wm->op_undo_depth--; - /* keep the reports around if needed later */ - if ((retval & OPERATOR_RUNNING_MODAL) || - ((retval & OPERATOR_FINISHED) && wm_operator_register_check(CTX_wm_manager(C), ot))) - { - reports->flag |= RPT_FREE; /* let blender manage freeing */ - } - return retval; } @@ -1343,6 +1380,15 @@ static void wm_event_modalkeymap(const bContext *C, wmOperator *op, wmEvent *eve } } } + else { + /* modal keymap checking returns handled events fine, but all hardcoded modal + * handling typically swallows all events (OPERATOR_RUNNING_MODAL). + * This bypass just disables support for double clicks in hardcoded modal handlers */ + if (event->val == KM_DBL_CLICK) { + event->prevval = event->val; + event->val = KM_PRESS; + } + } } /* bad hacking event system... better restore event type for checking of KM_CLICK for example */ @@ -1355,6 +1401,8 @@ static void wm_event_modalmap_end(wmEvent *event) event->val = event->prevval; event->prevval = 0; } + else if (event->prevval == KM_DBL_CLICK) + event->val = KM_DBL_CLICK; } @@ -1394,20 +1442,10 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand if (ot->flag & OPTYPE_UNDO) wm->op_undo_depth--; - /* putting back screen context, reval can pass trough after modal failures! */ - if ((retval & OPERATOR_PASS_THROUGH) || wm_event_always_pass(event)) { - CTX_wm_area_set(C, area); - CTX_wm_region_set(C, region); - } - else { - /* this special cases is for areas and regions that get removed */ - CTX_wm_area_set(C, NULL); - CTX_wm_region_set(C, NULL); - } - if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) wm_operator_reports(C, op, retval, FALSE); + /* important to run 'wm_operator_finished' before NULLing the context members */ if (retval & OPERATOR_FINISHED) { wm_operator_finished(C, op, 0); handler->op = NULL; @@ -1417,6 +1455,17 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand handler->op = NULL; } + /* putting back screen context, reval can pass trough after modal failures! */ + if ((retval & OPERATOR_PASS_THROUGH) || wm_event_always_pass(event)) { + CTX_wm_area_set(C, area); + CTX_wm_region_set(C, region); + } + else { + /* this special cases is for areas and regions that get removed */ + CTX_wm_area_set(C, NULL); + CTX_wm_region_set(C, NULL); + } + /* remove modal handler, operator itself should have been canceled and freed */ if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) { WM_cursor_grab_disable(CTX_wm_window(C), NULL); @@ -1640,9 +1689,9 @@ static int wm_action_not_handled(int action) static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers) { #ifndef NDEBUG - const int do_debug_handler = (G.debug & G_DEBUG_HANDLERS) + const int do_debug_handler = (G.debug & G_DEBUG_HANDLERS) && /* comment this out to flood the console! (if you really want to test) */ - && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) + !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) ; #endif wmWindowManager *wm = CTX_wm_manager(C); @@ -1716,6 +1765,10 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers break; } else { + if (action & WM_HANDLER_HANDLED) + if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) + printf("%s: handled - and pass on! '%s'\n", __func__, kmi->idname); + #ifndef NDEBUG if (do_debug_handler) { printf("%s: un-handled '%s'...", __func__, kmi->idname); @@ -2180,16 +2233,23 @@ void wm_event_do_handlers(bContext *C) /* update key configuration after handling events */ WM_keyconfig_update(wm); + + if (G.debug) { + GLenum error = glGetError(); + if (error != GL_NO_ERROR) { + printf("GL error: %s\n", gluErrorString(error)); + } + } } /* ********** filesector handling ************ */ -void WM_event_fileselect_event(bContext *C, void *ophandle, int eventval) +void WM_event_fileselect_event(wmWindowManager *wm, void *ophandle, int eventval) { /* add to all windows! */ wmWindow *win; - for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) { + for (win = wm->windows.first; win; win = win->next) { wmEvent event = *win->eventstate; event.type = EVT_FILESELECT; @@ -2211,6 +2271,7 @@ void WM_event_fileselect_event(bContext *C, void *ophandle, int eventval) void WM_event_add_fileselect(bContext *C, wmOperator *op) { wmEventHandler *handler, *handlernext; + wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); int full = 1; // XXX preset? @@ -2242,7 +2303,7 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op) op->type->check(C, op); /* ignore return value */ } - WM_event_fileselect_event(C, op, full ? EVT_FILESELECT_FULL_OPEN : EVT_FILESELECT_OPEN); + WM_event_fileselect_event(wm, op, full ? EVT_FILESELECT_FULL_OPEN : EVT_FILESELECT_OPEN); } #if 0 @@ -2427,14 +2488,14 @@ void WM_event_add_mousemove_window(wmWindow *window) } /* for modal callbacks, check configuration for how to interpret exit with tweaks */ -int WM_modal_tweak_exit(wmEvent *evt, int tweak_event) +int WM_modal_tweak_exit(const wmEvent *event, int tweak_event) { /* if the release-confirm userpref setting is enabled, * tweak events can be canceled when mouse is released */ if (U.flag & USER_RELEASECONFIRM) { /* option on, so can exit with km-release */ - if (evt->val == KM_RELEASE) { + if (event->val == KM_RELEASE) { switch (tweak_event) { case EVT_TWEAK_L: case EVT_TWEAK_M: @@ -2455,7 +2516,7 @@ int WM_modal_tweak_exit(wmEvent *evt, int tweak_event) * some items (i.e. markers) being tweaked may end up getting * dropped all over */ - if (evt->val != KM_RELEASE) + if (event->val != KM_RELEASE) return 1; } @@ -2632,9 +2693,12 @@ static void update_tablet_data(wmWindow *win, wmEvent *event) wmtab->Xtilt = td->Xtilt; wmtab->Ytilt = td->Ytilt; - event->custom = EVT_DATA_TABLET; - event->customdata = wmtab; - event->customdatafree = 1; + event->tablet_data = wmtab; + // printf("%s: using tablet %.5f\n", __func__, wmtab->Pressure); + } + else { + event->tablet_data = NULL; + // printf("%s: not using tablet\n", __func__); } } @@ -2682,15 +2746,17 @@ static void attach_ndof_data(wmEvent *event, const GHOST_TEventNDOFMotionData *g } /* imperfect but probably usable... draw/enable drags to other windows */ -static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *evt) +static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *event) { - int mx = evt->x, my = evt->y; + int mx = event->x, my = event->y; if (wm->windows.first == wm->windows.last) return NULL; - /* top window bar... */ - if (mx < 0 || my < 0 || mx > win->sizex || my > win->sizey + 30) { + /* in order to use window size and mouse position (pixels), we have to use a WM function */ + + /* check if outside, include top window bar... */ + if (mx < 0 || my < 0 || mx > WM_window_pixels_x(win) || my > WM_window_pixels_y(win) + 30) { wmWindow *owin; wmEventHandler *handler; @@ -2701,18 +2767,21 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi return NULL; /* to desktop space */ - mx += (int)win->posx; - my += (int)win->posy; + mx += (int) (U.pixelsize * win->posx); + my += (int) (U.pixelsize * win->posy); /* check other windows to see if it has mouse inside */ for (owin = wm->windows.first; owin; owin = owin->next) { if (owin != win) { - if (mx - owin->posx >= 0 && my - owin->posy >= 0 && - mx - owin->posx <= owin->sizex && my - owin->posy <= owin->sizey) + int posx = (int) (U.pixelsize * owin->posx); + int posy = (int) (U.pixelsize * owin->posy); + + if (mx - posx >= 0 && owin->posy >= 0 && + mx - posx <= WM_window_pixels_x(owin) && my - posy <= WM_window_pixels_y(owin)) { - evt->x = mx - (int)owin->posx; - evt->y = my - (int)owin->posy; + event->x = mx - (int)(U.pixelsize * owin->posx); + event->y = my - (int)(U.pixelsize * owin->posy); return owin; } @@ -2722,6 +2791,24 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi return NULL; } +static bool wm_event_is_double_click(wmEvent *event, wmEvent *event_state) +{ + if ((event->type == event_state->prevtype) && + (event_state->prevval == KM_RELEASE) && + (event->val == KM_PRESS)) + { + if ((ISMOUSE(event->type) == false) || ((ABS(event->x - event_state->prevclickx)) <= 2 && + (ABS(event->y - event_state->prevclicky)) <= 2)) + { + if ((PIL_check_seconds_timer() - event_state->prevclicktime) * 1000 < U.dbl_click_time) { + return true; + } + } + } + + return false; +} + /* windows store own event queues, no bContext here */ /* time is in 1000s of seconds, from ghost */ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int UNUSED(time), void *customdata) @@ -2731,18 +2818,16 @@ 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; - + switch (type) { /* mouse move, also to inactive window (X11 does this) */ case GHOST_kEventCursorMove: { GHOST_TEventCursorData *cd = customdata; wmEvent *lastevent = win->queue.last; - int cx, cy; - GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy); - evt->x = cx; - evt->y = (win->sizey - 1) - cy; + evt->x = cd->x; + evt->y = cd->y; event.x = evt->x; event.y = evt->y; @@ -2755,7 +2840,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U if (lastevent && lastevent->type == MOUSEMOVE) lastevent->type = INBETWEEN_MOUSEMOVE; - update_tablet_data(win, &event); wm_event_add(win, &event); /* also add to other window if event is there, this makes overdraws disappear nicely */ @@ -2768,7 +2852,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U oevent.y = owin->eventstate->y = event.y; oevent.type = MOUSEMOVE; - update_tablet_data(owin, &oevent); wm_event_add(owin, &oevent); } @@ -2780,6 +2863,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U switch (pd->subtype) { case GHOST_kTrackpadEventMagnify: event.type = MOUSEZOOM; + pd->deltaX = -pd->deltaX; + pd->deltaY = -pd->deltaY; break; case GHOST_kTrackpadEventRotate: event.type = MOUSEROTATE; @@ -2790,20 +2875,14 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U break; } - { - int cx, cy; - GHOST_ScreenToClient(win->ghostwin, pd->x, pd->y, &cx, &cy); - event.x = evt->x = cx; - event.y = evt->y = (win->sizey - 1) - cy; - } - + event.x = evt->x = pd->x; + event.y = evt->y = pd->y; event.val = 0; /* Use prevx/prevy so we can calculate the delta later */ event.prevx = event.x - pd->deltaX; event.prevy = event.y - (-pd->deltaY); - update_tablet_data(win, &event); wm_event_add(win, &event); break; } @@ -2848,15 +2927,10 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U } /* 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)) - { - if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) ) - printf("%s Send double click\n", __func__); - event.val = KM_DBL_CLICK; - } + if (wm_event_is_double_click(&event, evt)) { + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) ) + printf("%s Send double click\n", __func__); + event.val = KM_DBL_CLICK; } if (event.val == KM_PRESS) { evt->prevclicktime = PIL_check_seconds_timer(); @@ -2874,11 +2948,9 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U oevent.type = event.type; oevent.val = event.val; - update_tablet_data(owin, &oevent); wm_event_add(owin, &oevent); } else { - update_tablet_data(win, &event); wm_event_add(win, &event); } @@ -2962,15 +3034,10 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U /* double click test */ /* if previous event was same type, and previous was release, and now it presses... */ - if (event.type == evt->prevtype && evt->prevval == KM_RELEASE && 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)) - { - if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) ) - printf("%s Send double click\n", __func__); - evt->val = event.val = KM_DBL_CLICK; - } + if (wm_event_is_double_click(&event, evt)) { + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) ) + printf("%s Send double click\n", __func__); + evt->val = event.val = KM_DBL_CLICK; } /* this case happens on holding a key pressed, it should not generate @@ -2979,7 +3046,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U event.keymodifier = 0; /* this case happened with an external numpad, it's not really clear - * why, but it's also impossible to map a key modifier to an unknwon + * why, but it's also impossible to map a key modifier to an unknown * key, so it shouldn't harm */ if (event.keymodifier == UNKNOWNKEY) event.keymodifier = 0; @@ -3080,4 +3147,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U } +#if 0 + WM_event_print(&event); +#endif } |