From 29696fb7252b88ecda0a5e724bb333b545e77c1e Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Tue, 22 Feb 2022 08:57:22 -0800 Subject: UI: ActionZone Swap Areas Between Windows Allow SCREEN_OT_area_swap to operate between different Blender windows, and other minor feedback improvements. See D14135 for more details and demonstrations. Differential Revision: https://developer.blender.org/D14135 Reviewed by Campbell Barton --- source/blender/editors/include/ED_screen.h | 6 ++++++ source/blender/editors/screen/area.c | 32 ++++++++++++++++++++++++++++++ source/blender/editors/screen/screen_ops.c | 21 ++++++++++++++------ 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 5b439cb0978..c89df9c3789 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -250,6 +250,12 @@ void ED_area_offscreen_free(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *area); +/** + * Search all screens, even non-active or overlapping (multiple windows), return the most-likely + * area of interest. xy is relative to active window, like all similar functions. + */ +ScrArea *ED_area_find_under_cursor(const struct bContext *C, int spacetype, const int xy[2]); + ScrArea *ED_screen_areas_iter_first(const struct wmWindow *win, const bScreen *screen); ScrArea *ED_screen_areas_iter_next(const bScreen *screen, const ScrArea *area); /** diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 95534d2a036..a64948b5864 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -3438,6 +3438,38 @@ bool ED_area_is_global(const ScrArea *area) return area->global != NULL; } +ScrArea *ED_area_find_under_cursor(const bContext *C, int spacetype, const int xy[2]) +{ + bScreen *screen = CTX_wm_screen(C); + wmWindow *win = CTX_wm_window(C); + wmWindowManager *wm = CTX_wm_manager(C); + + ScrArea *area = NULL; + + if (win->parent) { + /* If active window is a child, check itself first. */ + area = BKE_screen_find_area_xy(screen, spacetype, xy); + } + + if (!area) { + /* Check all windows except the active one. */ + int scr_pos[2]; + wmWindow *r_win = WM_window_find_under_cursor(wm, win, win, xy, scr_pos); + if (r_win) { + win = r_win; + screen = WM_window_get_active_screen(win); + area = BKE_screen_find_area_xy(screen, spacetype, scr_pos); + } + } + + if (!area && !win->parent) { + /* If active window is a parent window, check itself last. */ + area = BKE_screen_find_area_xy(screen, spacetype, xy); + } + + return area; +} + ScrArea *ED_screen_areas_iter_first(const wmWindow *win, const bScreen *screen) { ScrArea *global_area = win->global_areas.areabase.first; diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 75c704b5f7b..b912b02852f 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -1008,9 +1008,6 @@ static void actionzone_exit(wmOperator *op) static void actionzone_apply(bContext *C, wmOperator *op, int type) { wmWindow *win = CTX_wm_window(C); - sActionzoneData *sad = op->customdata; - - sad->modifier = RNA_int_get(op->ptr, "modifier"); wmEvent event; wm_event_init_from_window(win, &event); @@ -1051,6 +1048,7 @@ static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event) sad->az = az; sad->x = event->xy[0]; sad->y = event->xy[1]; + sad->modifier = RNA_int_get(op->ptr, "modifier"); /* region azone directly reacts on mouse clicks */ if (ELEM(sad->az->type, AZONE_REGION, AZONE_FULLSCREEN)) { @@ -1114,7 +1112,17 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event) /* What area are we now in? */ ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->xy); - if (area == sad->sa1) { + if (sad->modifier == 1) { + /* Duplicate area into new window. */ + WM_cursor_set(win, WM_CURSOR_EDIT); + is_gesture = (delta_max > area_threshold); + } + else if (sad->modifier == 2) { + /* Swap areas. */ + WM_cursor_set(win, WM_CURSOR_SWAP_AREA); + is_gesture = true; + } + else if (area == sad->sa1) { /* Same area, so possible split. */ WM_cursor_set(win, SCREEN_DIR_IS_VERTICAL(sad->gesture_dir) ? WM_CURSOR_H_SPLIT : @@ -1320,8 +1328,9 @@ static int area_swap_modal(bContext *C, wmOperator *op, const wmEvent *event) switch (event->type) { case MOUSEMOVE: - /* second area, for join */ - sad->sa2 = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, event->xy); + /* Second area to swap with. */ + sad->sa2 = ED_area_find_under_cursor(C, SPACE_TYPE_ANY, event->xy); + WM_cursor_set(CTX_wm_window(C), (sad->sa2) ? WM_CURSOR_SWAP_AREA : WM_CURSOR_STOP); break; case LEFTMOUSE: /* release LMB */ if (event->val == KM_RELEASE) { -- cgit v1.2.3