diff options
author | Campbell Barton <ideasman42@gmail.com> | 2015-04-27 11:53:45 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2015-04-27 12:17:07 +0300 |
commit | 3f80accfb34dd10e70380139941bcaf62702a6f8 (patch) | |
tree | fddd2e77a2b2880c11cbb4ee70bd05d7286d136c | |
parent | 5df939fd15213548346558e76bd2cdc22ebe21a4 (diff) |
Fix T44011: Ruler/Knife/Loop-cut fail in quad-view
This is a kind of sloppy-focus,
resolving long standing bug with loop-cut/knife/ruler /w quad-view.
Where activating a tool would lock onto one of quad-views,
especially problematic when activating from the toolbar or menus.
-rw-r--r-- | source/blender/blenkernel/BKE_screen.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/screen.c | 17 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_knife.c | 12 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_loopcut.c | 4 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_ruler.c | 18 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_screen_types.h | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_windowmanager_types.h | 10 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_wm.c | 4 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 35 | ||||
-rw-r--r-- | source/blender/windowmanager/wm_event_system.h | 1 |
10 files changed, 91 insertions, 13 deletions
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 43499933d16..bb764540da9 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -280,6 +280,7 @@ void BKE_screen_area_free(struct ScrArea *sa); struct ARegion *BKE_area_find_region_type(struct ScrArea *sa, int type); struct ARegion *BKE_area_find_region_active_win(struct ScrArea *sa); +struct ARegion *BKE_area_find_region_xy(struct ScrArea *sa, const int regiontype, int x, int y); struct ScrArea *BKE_screen_find_area_from_space(struct bScreen *sc, struct SpaceLink *sl) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2); struct ScrArea *BKE_screen_find_big_area(struct bScreen *sc, const int spacetype, const short min); struct ScrArea *BKE_screen_find_area_xy(struct bScreen *sc, const int spacetype, int x, int y); diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 3c43bfa2920..36fd598cc70 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -405,6 +405,23 @@ ARegion *BKE_area_find_region_active_win(ScrArea *sa) return NULL; } +ARegion *BKE_area_find_region_xy(ScrArea *sa, const int regiontype, int x, int y) +{ + ARegion *ar_found = NULL; + if (sa) { + ARegion *ar; + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if ((regiontype == RGN_TYPE_ANY) || (ar->regiontype == regiontype)) { + if (BLI_rcti_isect_pt(&ar->winrct, x, y)) { + ar_found = ar; + break; + } + } + } + } + return ar_found; +} + /** * \note, ideally we can get the area from the context, * there are a few places however where this isn't practical. diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index df91679b5f0..4f8839005c9 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -3051,6 +3051,8 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event) knifetool_init(C, kcd, only_select, cut_through, true); + op->flag |= OP_IS_MODAL_CURSOR_REGION; + /* add a modal handler for this operator - handles loop selection */ WM_cursor_modal_set(CTX_wm_window(C), BC_KNIFECURSOR); WM_event_add_modal_handler(C, op); @@ -3143,6 +3145,9 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_FINISHED; } + em_setup_viewcontext(C, &kcd->vc); + kcd->ar = kcd->vc.ar; + view3d_operator_needs_opengl(C); ED_view3d_init_mats_rv3d(obedit, kcd->vc.rv3d); /* needed to initialize clipping */ @@ -3302,6 +3307,13 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event) } } + if (kcd->mode == MODE_DRAGGING) { + op->flag &= ~OP_IS_MODAL_CURSOR_REGION; + } + else { + op->flag |= OP_IS_MODAL_CURSOR_REGION; + } + if (do_refresh) { /* we don't really need to update mval, * but this happens to be the best way to refresh at the moment */ diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index a4ea2ab3921..c7f9522ab3f 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -553,6 +553,7 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) /* add a modal handler for this operator - handles loop selection */ if (is_interactive) { + op->flag |= OP_IS_MODAL_CURSOR_REGION; WM_event_add_modal_handler(C, op); } @@ -639,6 +640,9 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) bool show_cuts = false; const bool has_numinput = hasNumInput(&lcd->num); + em_setup_viewcontext(C, &lcd->vc); + lcd->ar = lcd->vc.ar; + view3d_operator_needs_opengl(C); /* using the keyboard to input the number of cuts */ diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c index eba31866f54..addda0a8b66 100644 --- a/source/blender/editors/space_view3d/view3d_ruler.c +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -187,6 +187,7 @@ typedef struct RulerInfo { /* wm state */ wmWindow *win; + ScrArea *sa; ARegion *ar; void *draw_handle_pixel; } RulerInfo; @@ -435,7 +436,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a UnitSettings *unit = &scene->unit; RulerItem *ruler_item; RulerInfo *ruler_info = arg; - RegionView3D *rv3d = ruler_info->ar->regiondata; + RegionView3D *rv3d = ar->regiondata; // ARegion *ar = ruler_info->ar; const float cap_size = 4.0f; const float bg_margin = 4.0f * U.pixelsize; @@ -798,12 +799,14 @@ static int view3d_ruler_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE op->customdata = ruler_info; ruler_info->win = win; - ruler_info->ar = ar; + ruler_info->sa = sa; ruler_info->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ruler_info_draw_pixel, ruler_info, REGION_DRAW_POST_PIXEL); view3d_ruler_header_update(sa); + op->flag |= OP_IS_MODAL_CURSOR_REGION; + WM_cursor_modal_set(win, BC_CROSSCURSOR); WM_event_add_modal_handler(C, op); @@ -829,11 +832,13 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event) RegionView3D *rv3d = ar->regiondata; /* its possible to change spaces while running the operator [#34894] */ - if (UNLIKELY(ar != CTX_wm_region(C))) { + if (UNLIKELY(sa != ruler_info->sa)) { exit_code = OPERATOR_FINISHED; goto exit; } + ruler_info->ar = ar; + switch (event->type) { case LEFTMOUSE: if (event->val == KM_RELEASE) { @@ -1019,6 +1024,13 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event) } + if (ruler_info->state == RULER_STATE_DRAG) { + op->flag &= ~OP_IS_MODAL_CURSOR_REGION; + } + else { + op->flag |= OP_IS_MODAL_CURSOR_REGION; + } + if (do_draw) { view3d_ruler_header_update(sa); diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 13365adeb58..eb76c90c0fc 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -374,6 +374,8 @@ enum { RGN_TYPE_TOOL_PROPS = 6, RGN_TYPE_PREVIEW = 7 }; +/* use for function args */ +#define RGN_TYPE_ANY -1 /* region alignment */ #define RGN_ALIGN_NONE 0 diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 4aa49eea2e8..51ed8bb6c0d 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -390,10 +390,16 @@ enum { /* wmOperator flag */ enum { - OP_IS_MODAL_GRAB_CURSOR = (1 << 0), /* low level flag so exec() operators can tell if they were invoked, use with care. * typically this shouldn't make any difference, but it rare cases its needed (see smooth-view) */ - OP_IS_INVOKE = (1 << 1), + OP_IS_INVOKE = (1 << 0), + + /* When the cursor is grabbed */ + OP_IS_MODAL_GRAB_CURSOR = (1 << 1), + + /* allow modal operators to have the region under the cursor for their context + * (the regiontype is maintained to prevent errors) */ + OP_IS_MODAL_CURSOR_REGION = (1 << 2), }; #endif /* __DNA_WINDOWMANAGER_TYPES_H__ */ diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index ded4ea02a9b..3b8ddd011c0 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -1416,6 +1416,10 @@ static void rna_def_operator_options_runtime(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_INVOKE); RNA_def_property_ui_text(prop, "Invoke", "True when invoked (even if only the execute callbacks available)"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop = RNA_def_property(srna, "use_cursor_region", PROP_BOOLEAN, PROP_BOOLEAN); + RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_MODAL_CURSOR_REGION); + RNA_def_property_ui_text(prop, "Focus Region", "Enable to use the region under the cursor for modal execution"); } static void rna_def_operator(BlenderRNA *brna) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 8c97d399385..830feed2fc7 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1337,7 +1337,7 @@ void wm_event_free_handler(wmEventHandler *handler) } /* only set context when area/region is part of screen */ -static void wm_handler_op_context(bContext *C, wmEventHandler *handler) +static void wm_handler_op_context(bContext *C, wmEventHandler *handler, const wmEvent *event) { bScreen *screen = CTX_wm_screen(C); @@ -1358,10 +1358,27 @@ static void wm_handler_op_context(bContext *C, wmEventHandler *handler) } else { ARegion *ar; + wmOperator *op = handler->op ? (handler->op->opm ? handler->op->opm : handler->op) : NULL; CTX_wm_area_set(C, sa); - for (ar = sa->regionbase.first; ar; ar = ar->next) - if (ar == handler->op_region) - break; + + if (op && (op->flag & OP_IS_MODAL_CURSOR_REGION)) { + ar = BKE_area_find_region_xy(sa, handler->op_region_type, event->x, event->y); + if (ar) { + handler->op_region = ar; + } + } + else { + ar = NULL; + } + + if (ar == NULL) { + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar == handler->op_region) { + break; + } + } + } + /* XXX no warning print here, after full-area and back regions are remade */ if (ar) CTX_wm_region_set(C, ar); @@ -1379,11 +1396,12 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers) /* C is zero on freeing database, modal handlers then already were freed */ while ((handler = BLI_pophead(handlers))) { if (handler->op) { + wmWindow *win = CTX_wm_window(C); if (handler->op->type->cancel) { ScrArea *area = CTX_wm_area(C); ARegion *region = CTX_wm_region(C); - wm_handler_op_context(C, handler); + wm_handler_op_context(C, handler, win->eventstate); if (handler->op->type->flag & OPTYPE_UNDO) wm->op_undo_depth++; @@ -1397,7 +1415,7 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers) CTX_wm_region_set(C, region); } - WM_cursor_grab_disable(CTX_wm_window(C), NULL); + WM_cursor_grab_disable(win, NULL); WM_operator_free(handler->op); } else if (handler->ui_remove) { @@ -1569,7 +1587,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand ARegion *region = CTX_wm_region(C); bool dbl_click_disabled = false; - wm_handler_op_context(C, handler); + wm_handler_op_context(C, handler, event); wm_region_mouse_co(C, event); wm_event_modalkeymap(C, op, event, &dbl_click_disabled); @@ -1717,7 +1735,7 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand ED_screen_full_prevspace(C, CTX_wm_area(C)); } - wm_handler_op_context(C, handler); + wm_handler_op_context(C, handler, CTX_wm_window(C)->eventstate); /* needed for UI_popup_menu_reports */ @@ -2534,6 +2552,7 @@ wmEventHandler *WM_event_add_modal_handler(bContext *C, wmOperator *op) handler->op_area = CTX_wm_area(C); /* means frozen screen context for modal handlers! */ handler->op_region = CTX_wm_region(C); + handler->op_region_type = handler->op_region ? handler->op_region->regiontype : -1; BLI_addhead(&win->modalhandlers, handler); diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h index f89177a82ea..a097343d037 100644 --- a/source/blender/windowmanager/wm_event_system.h +++ b/source/blender/windowmanager/wm_event_system.h @@ -56,6 +56,7 @@ typedef struct wmEventHandler { wmOperator *op; /* for derived/modal handlers */ struct ScrArea *op_area; /* for derived/modal handlers */ struct ARegion *op_region; /* for derived/modal handlers */ + short op_region_type; /* for derived/modal handlers */ /* ui handler */ wmUIHandlerFunc ui_handle; /* callback receiving events */ |