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
This commit is contained in:
Harley Acheson 2022-02-22 08:57:22 -08:00
parent 8ae77efe4e
commit 29696fb725
3 changed files with 53 additions and 6 deletions

View File

@ -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);
/**

View File

@ -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;

View File

@ -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) {