diff options
Diffstat (limited to 'source/blender/windowmanager/intern/wm_event_system.c')
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 220 |
1 files changed, 177 insertions, 43 deletions
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index f26ee0e73ec..06bf6ff2482 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -39,6 +39,7 @@ #include "DNA_screen_types.h" #include "DNA_scene_types.h" #include "DNA_windowmanager_types.h" +#include "DNA_workspace_types.h" #include "DNA_userdef_types.h" #include "MEM_guardedalloc.h" @@ -53,10 +54,12 @@ #include "BKE_context.h" #include "BKE_idprop.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" +#include "BKE_workspace.h" #include "BKE_sound.h" @@ -68,8 +71,6 @@ #include "RNA_access.h" -#include "GPU_debug.h" - #include "UI_interface.h" #include "PIL_time.h" @@ -276,6 +277,7 @@ void wm_event_do_notifiers(bContext *C) /* cache & catch WM level notifiers, such as frame change, scene/screen set */ for (win = wm->windows.first; win; win = win->next) { + Scene *scene = WM_window_get_active_scene(win); bool do_anim = false; CTX_wm_window_set(C, win); @@ -293,17 +295,31 @@ void wm_event_do_notifiers(bContext *C) } if (note->window == win) { if (note->category == NC_SCREEN) { - if (note->data == ND_SCREENBROWSE) { + if (note->data == ND_WORKSPACE_SET) { + WorkSpace *ref_ws = note->reference; + + UI_popup_handlers_remove_all(C, &win->modalhandlers); + + ED_workspace_change(ref_ws, C, wm, win); + if (G.debug & G_DEBUG_EVENTS) + printf("%s: Workspace set %p\n", __func__, note->reference); + } + else if (note->data == ND_LAYOUTBROWSE) { + bScreen *ref_screen = BKE_workspace_layout_screen_get(note->reference); + /* free popup handlers only [#35434] */ UI_popup_handlers_remove_all(C, &win->modalhandlers); - ED_screen_set(C, note->reference); // XXX hrms, think this over! + ED_screen_change(C, ref_screen); /* XXX hrms, think this over! */ if (G.debug & G_DEBUG_EVENTS) printf("%s: screen set %p\n", __func__, note->reference); } - else if (note->data == ND_SCREENDELETE) { - ED_screen_delete(C, note->reference); // XXX hrms, think this over! + else if (note->data == ND_LAYOUTDELETE) { + WorkSpace *workspace = WM_window_get_active_workspace(win); + WorkSpaceLayout *layout = note->reference; + + ED_workspace_layout_delete(workspace, layout, C); // XXX hrms, think this over! if (G.debug & G_DEBUG_EVENTS) printf("%s: screen delete %p\n", __func__, note->reference); } @@ -311,7 +327,7 @@ void wm_event_do_notifiers(bContext *C) } if (note->window == win || - (note->window == NULL && (note->reference == NULL || note->reference == win->screen->scene))) + (note->window == NULL && (note->reference == NULL || note->reference == scene))) { if (note->category == NC_SCENE) { if (note->data == ND_FRAME) @@ -319,7 +335,8 @@ void wm_event_do_notifiers(bContext *C) } } if (ELEM(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_WM)) { - ED_info_stats_clear(win->screen->scene); + SceneLayer *sl = BKE_scene_layer_context_active(scene); + ED_info_stats_clear(sl); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL); } } @@ -331,7 +348,7 @@ void wm_event_do_notifiers(bContext *C) if (G.is_rendering == false) { /* depsgraph gets called, might send more notifiers */ - ED_update_for_newframe(CTX_data_main(C), win->screen->scene, 1); + ED_update_for_newframe(CTX_data_main(C), scene, 1); } } } @@ -339,12 +356,19 @@ void wm_event_do_notifiers(bContext *C) /* the notifiers are sent without context, to keep it clean */ while ((note = BLI_pophead(&wm->queue))) { for (win = wm->windows.first; win; win = win->next) { - + Scene *scene = WM_window_get_active_scene(win); + bScreen *screen = WM_window_get_active_screen(win); + /* filter out notifiers */ - if (note->category == NC_SCREEN && note->reference && note->reference != win->screen) { + if (note->category == NC_SCREEN && + note->reference && + note->reference != screen && + note->reference != WM_window_get_active_workspace(win) && + note->reference != WM_window_get_active_layout(win)) + { /* pass */ } - else if (note->category == NC_SCENE && note->reference && note->reference != win->screen->scene) { + else if (note->category == NC_SCENE && note->reference && note->reference != scene) { /* pass */ } else { @@ -357,14 +381,14 @@ void wm_event_do_notifiers(bContext *C) /* 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) { - ED_region_do_listen(win->screen, NULL, ar, note); + for (ar = screen->regionbase.first; ar; ar = ar->next) { + ED_region_do_listen(screen, NULL, ar, note, scene); } - for (sa = win->screen->areabase.first; sa; sa = sa->next) { - ED_area_do_listen(win->screen, sa, note); + for (sa = screen->areabase.first; sa; sa = sa->next) { + ED_area_do_listen(screen, sa, note, scene); for (ar = sa->regionbase.first; ar; ar = ar->next) { - ED_region_do_listen(win->screen, sa, ar, note); + ED_region_do_listen(screen, sa, ar, note, scene); } } } @@ -372,18 +396,23 @@ void wm_event_do_notifiers(bContext *C) MEM_freeN(note); } - + /* combine datamasks so 1 win doesn't disable UV's in another [#26448] */ for (win = wm->windows.first; win; win = win->next) { - win_combine_v3d_datamask |= ED_view3d_screen_datamask(win->screen); + const Scene *scene = WM_window_get_active_scene(win); + const bScreen *screen = WM_window_get_active_screen(win); + + win_combine_v3d_datamask |= ED_view3d_screen_datamask(scene, screen); } /* cached: editor refresh callbacks now, they get context */ for (win = wm->windows.first; win; win = win->next) { + const bScreen *screen = WM_window_get_active_screen(win); + Scene *scene = WM_window_get_active_scene(win); ScrArea *sa; CTX_wm_window_set(C, win); - for (sa = win->screen->areabase.first; sa; sa = sa->next) { + for (sa = screen->areabase.first; sa; sa = sa->next) { if (sa->do_refresh) { CTX_wm_area_set(C, sa); ED_area_do_refresh(C, sa); @@ -396,12 +425,12 @@ void wm_event_do_notifiers(bContext *C) Main *bmain = CTX_data_main(C); /* copied to set's in scene_update_tagged_recursive() */ - win->screen->scene->customdata_mask = win_combine_v3d_datamask; + scene->customdata_mask = win_combine_v3d_datamask; /* XXX, hack so operators can enforce datamasks [#26482], gl render */ - win->screen->scene->customdata_mask |= win->screen->scene->customdata_mask_modal; + scene->customdata_mask |= scene->customdata_mask_modal; - BKE_scene_update_tagged(bmain->eval_ctx, bmain, win->screen->scene); + BKE_scene_update_tagged(bmain->eval_ctx, bmain, scene); } } @@ -1693,7 +1722,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand wm_handler_op_context(C, handler, event); wm_region_mouse_co(C, event); wm_event_modalkeymap(C, op, event, &dbl_click_disabled); - + if (ot->flag & OPTYPE_UNDO) wm->op_undo_depth++; @@ -1742,6 +1771,9 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand CTX_wm_region_set(C, NULL); } + /* update manipulators during modal handlers */ + wm_manipulatormaps_handled_modal_update(C, event, handler); + /* 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); @@ -2114,6 +2146,71 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers } } } + else if (handler->manipulator_map) { + ScrArea *area = CTX_wm_area(C); + ARegion *region = CTX_wm_region(C); + wmManipulatorMap *mmap = handler->manipulator_map; + wmManipulator *mpr = wm_manipulatormap_highlight_get(mmap); + + wm_manipulatormap_handler_context(C, handler); + wm_region_mouse_co(C, event); + + /* handle manipulator highlighting */ + if (event->type == MOUSEMOVE && !wm_manipulatormap_active_get(mmap)) { + int part; + mpr = wm_manipulatormap_highlight_find(mmap, C, event, &part); + wm_manipulatormap_highlight_set(mmap, C, mpr, part); + } + /* handle user configurable manipulator-map keymap */ + else if (mpr) { + /* get user customized keymap from default one */ + const wmManipulatorGroup *highlightgroup = mpr->parent_mgroup; + const wmKeyMap *keymap = WM_keymap_active(wm, highlightgroup->type->keymap); + wmKeyMapItem *kmi; + + PRINT("%s: checking '%s' ...", __func__, keymap->idname); + + if (!keymap->poll || keymap->poll(C)) { + PRINT("pass\n"); + for (kmi = keymap->items.first; kmi; kmi = kmi->next) { + if (wm_eventmatch(event, kmi)) { + wmOperator *op = handler->op; + + PRINT("%s: item matched '%s'\n", __func__, kmi->idname); + + /* weak, but allows interactive callback to not use rawkey */ + event->keymap_idname = kmi->idname; + + /* handler->op is called later, we want keymap op to be triggered here */ + handler->op = NULL; + action |= wm_handler_operator_call(C, handlers, handler, event, kmi->ptr); + handler->op = op; + + if (action & WM_HANDLER_BREAK) { + 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); + } + else { + PRINT("%s: un-handled '%s'\n", __func__, kmi->idname); + } + } + } + } + } + else { + PRINT("fail\n"); + } + } + + /* restore the area */ + CTX_wm_area_set(C, area); + CTX_wm_region_set(C, region); + + if (handler->op) { + action |= wm_handler_operator_call(C, handlers, handler, event, NULL); + } + } else { /* modal, swallows all */ action |= wm_handler_operator_call(C, handlers, handler, event, NULL); @@ -2287,17 +2384,19 @@ static void wm_paintcursor_test(bContext *C, const wmEvent *event) static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *event) { + bScreen *screen = WM_window_get_active_screen(win); + if (BLI_listbase_is_empty(&wm->drags)) { return; } if (event->type == MOUSEMOVE || ISKEYMODIFIER(event->type)) { - win->screen->do_draw_drag = true; + screen->do_draw_drag = true; } else if (event->type == ESCKEY) { WM_drag_free_list(&wm->drags); - win->screen->do_draw_drag = true; + screen->do_draw_drag = true; } else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { event->type = EVT_DROP; @@ -2313,16 +2412,16 @@ static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *even event->customdatafree = 1; /* clear drop icon */ - win->screen->do_draw_drag = true; + screen->do_draw_drag = true; /* restore cursor (disabled, see wm_dragdrop.c) */ // WM_cursor_modal_restore(win); } /* overlap fails otherwise */ - if (win->screen->do_draw_drag) + if (screen->do_draw_drag) if (win->drawmethod == USER_DRAW_OVERLAP) - win->screen->do_draw = true; + screen->do_draw = true; } @@ -2352,22 +2451,28 @@ void wm_event_do_handlers(bContext *C) /* update key configuration before handling events */ WM_keyconfig_update(wm); + WM_manipulatorconfig_update(CTX_data_main(C)); for (win = wm->windows.first; win; win = win->next) { + bScreen *screen = WM_window_get_active_screen(win); wmEvent *event; - - if (win->screen == NULL) + + /* some safty checks - these should always be set! */ + BLI_assert(WM_window_get_active_scene(win)); + BLI_assert(WM_window_get_active_screen(win)); + BLI_assert(WM_window_get_active_workspace(win)); + + if (screen == NULL) wm_event_free_all(win); else { - Scene *scene = win->screen->scene; + Scene *scene = WM_window_get_active_scene(win); if (scene) { - int is_playing_sound = BKE_sound_scene_playing(win->screen->scene); + int is_playing_sound = BKE_sound_scene_playing(scene); if (is_playing_sound != -1) { bool is_playing_screen; CTX_wm_window_set(C, win); - CTX_wm_screen_set(C, win->screen); CTX_data_scene_set(C, scene); is_playing_screen = (ED_screen_animation_playing(wm) != NULL); @@ -2400,6 +2505,9 @@ void wm_event_do_handlers(bContext *C) while ( (event = win->queue.first) ) { int action = WM_HANDLER_CONTINUE; + /* active screen might change during handlers, update pointer */ + screen = WM_window_get_active_screen(win); + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { printf("\n%s: Handling event\n", __func__); WM_event_print(event); @@ -2457,12 +2565,12 @@ void wm_event_do_handlers(bContext *C) } #endif - for (sa = win->screen->areabase.first; sa; sa = sa->next) { + for (sa = screen->areabase.first; sa; sa = sa->next) { /* after restoring a screen from SCREENMAXIMIZED we have to wait * with the screen handling till the region coordinates are updated */ - if (win->screen->skip_handling == true) { + if (screen->skip_handling == true) { /* restore for the next iteration of wm_event_do_handlers */ - win->screen->skip_handling = false; + screen->skip_handling = false; break; } @@ -2556,8 +2664,7 @@ void wm_event_do_handlers(bContext *C) /* update key configuration after handling events */ WM_keyconfig_update(wm); - - GPU_ASSERT_NO_GL_ERRORS("wm_event_do_handlers"); + WM_manipulatorconfig_update(CTX_data_main(C)); } /* ********** filesector handling ************ */ @@ -2594,7 +2701,7 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op) wmWindow *win = CTX_wm_window(C); /* only allow 1 file selector open per window */ - for (handler = win->modalhandlers.first; handler; handler = handlernext) { + for (handler = win->handlers.first; handler; handler = handlernext) { handlernext = handler->next; if (handler->type == WM_HANDLER_FILESELECT) { @@ -2608,7 +2715,7 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op) if (sfile->op == handler->op) { CTX_wm_area_set(C, sa); - wm_handler_fileselect_do(C, &win->modalhandlers, handler, EVT_FILESELECT_CANCEL); + wm_handler_fileselect_do(C, &win->handlers, handler, EVT_FILESELECT_CANCEL); break; } } @@ -2616,7 +2723,7 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op) /* if not found we stop the handler without changing the screen */ if (!sa) - wm_handler_fileselect_do(C, &win->modalhandlers, handler, EVT_FILESELECT_EXTERNAL_CANCEL); + wm_handler_fileselect_do(C, &win->handlers, handler, EVT_FILESELECT_EXTERNAL_CANCEL); } } @@ -2627,7 +2734,7 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op) handler->op_area = CTX_wm_area(C); handler->op_region = CTX_wm_region(C); - BLI_addhead(&win->modalhandlers, handler); + BLI_addhead(&win->handlers, handler); /* check props once before invoking if check is available * ensures initial properties are valid */ @@ -2670,6 +2777,33 @@ wmEventHandler *WM_event_add_modal_handler(bContext *C, wmOperator *op) return handler; } +/** + * Modal handlers store a pointer to an area which might be freed while the handler runs. + * Use this function to NULL all handler pointers to \a old_area. + */ +void WM_event_modal_handler_area_replace(wmWindow *win, const ScrArea *old_area, ScrArea *new_area) +{ + for (wmEventHandler *handler = win->modalhandlers.first; handler; handler = handler->next) { + if (handler->op_area == old_area) { + handler->op_area = new_area; + } + } +} + +/** + * Modal handlers store a pointer to a region which might be freed while the handler runs. + * Use this function to NULL all handler pointers to \a old_region. + */ +void WM_event_modal_handler_region_replace(wmWindow *win, const ARegion *old_region, ARegion *new_region) +{ + for (wmEventHandler *handler = win->modalhandlers.first; handler; handler = handler->next) { + if (handler->op_region == old_region) { + handler->op_region = new_region; + handler->op_region_type = new_region ? new_region->regiontype : RGN_TYPE_WINDOW; + } + } +} + wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap) { wmEventHandler *handler; |