Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/screen')
-rw-r--r--source/blender/editors/screen/area.c58
-rw-r--r--source/blender/editors/screen/glutil.c24
-rw-r--r--source/blender/editors/screen/screen_context.c1
-rw-r--r--source/blender/editors/screen/screen_edit.c56
-rw-r--r--source/blender/editors/screen/screen_intern.h15
-rw-r--r--source/blender/editors/screen/screen_ops.c6
-rw-r--r--source/blender/editors/screen/workspace_edit.c31
-rw-r--r--source/blender/editors/screen/workspace_layout_edit.c60
8 files changed, 133 insertions, 118 deletions
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 95f5bdbc394..63729b40571 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -291,7 +291,7 @@ static void region_draw_azone_tab_arrow(ScrArea *area, ARegion *region, AZone *a
/* Workaround for different color spaces between normal areas and the ones using GPUViewports. */
float alpha = WM_region_use_viewport(area, region) ? 0.6f : 0.4f;
- float color[4] = {0.05f, 0.05f, 0.05f, alpha};
+ const float color[4] = {0.05f, 0.05f, 0.05f, alpha};
UI_draw_roundbox_aa(
true, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, color);
@@ -813,7 +813,7 @@ void ED_workspace_status_text(bContext *C, const char *str)
/* ************************************************************ */
-static void area_azone_initialize(wmWindow *win, const bScreen *screen, ScrArea *area)
+static void area_azone_init(wmWindow *win, const bScreen *screen, ScrArea *area)
{
AZone *az;
@@ -883,7 +883,7 @@ static void area_azone_initialize(wmWindow *win, const bScreen *screen, ScrArea
}
}
-static void fullscreen_azone_initialize(ScrArea *area, ARegion *region)
+static void fullscreen_azone_init(ScrArea *area, ARegion *region)
{
AZone *az;
@@ -1007,10 +1007,10 @@ static bool region_azone_edge_poll(const ARegion *region, const bool is_fullscre
return true;
}
-static void region_azone_edge_initialize(ScrArea *area,
- ARegion *region,
- AZEdge edge,
- const bool is_fullscreen)
+static void region_azone_edge_init(ScrArea *area,
+ ARegion *region,
+ AZEdge edge,
+ const bool is_fullscreen)
{
AZone *az = NULL;
const bool is_hidden = (region->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL));
@@ -1033,9 +1033,9 @@ static void region_azone_edge_initialize(ScrArea *area,
}
}
-static void region_azone_scrollbar_initialize(ScrArea *area,
- ARegion *region,
- AZScrollDirection direction)
+static void region_azone_scrollbar_init(ScrArea *area,
+ ARegion *region,
+ AZScrollDirection direction)
{
rcti scroller_vert = (direction == AZ_SCROLL_VERT) ? region->v2d.vert : region->v2d.hor;
AZone *az = MEM_callocN(sizeof(*az), __func__);
@@ -1061,16 +1061,16 @@ static void region_azone_scrollbar_initialize(ScrArea *area,
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
}
-static void region_azones_scrollbars_initialize(ScrArea *area, ARegion *region)
+static void region_azones_scrollbars_init(ScrArea *area, ARegion *region)
{
const View2D *v2d = &region->v2d;
if ((v2d->scroll & V2D_SCROLL_VERTICAL) && ((v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) == 0)) {
- region_azone_scrollbar_initialize(area, region, AZ_SCROLL_VERT);
+ region_azone_scrollbar_init(area, region, AZ_SCROLL_VERT);
}
if ((v2d->scroll & V2D_SCROLL_HORIZONTAL) &&
((v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) == 0)) {
- region_azone_scrollbar_initialize(area, region, AZ_SCROLL_HOR);
+ region_azone_scrollbar_init(area, region, AZ_SCROLL_HOR);
}
}
@@ -1083,16 +1083,16 @@ static void region_azones_add_edge(ScrArea *area,
/* edge code (t b l r) is along which area edge azone will be drawn */
if (alignment == RGN_ALIGN_TOP) {
- region_azone_edge_initialize(area, region, AE_BOTTOM_TO_TOPLEFT, is_fullscreen);
+ region_azone_edge_init(area, region, AE_BOTTOM_TO_TOPLEFT, is_fullscreen);
}
else if (alignment == RGN_ALIGN_BOTTOM) {
- region_azone_edge_initialize(area, region, AE_TOP_TO_BOTTOMRIGHT, is_fullscreen);
+ region_azone_edge_init(area, region, AE_TOP_TO_BOTTOMRIGHT, is_fullscreen);
}
else if (alignment == RGN_ALIGN_RIGHT) {
- region_azone_edge_initialize(area, region, AE_LEFT_TO_TOPRIGHT, is_fullscreen);
+ region_azone_edge_init(area, region, AE_LEFT_TO_TOPRIGHT, is_fullscreen);
}
else if (alignment == RGN_ALIGN_LEFT) {
- region_azone_edge_initialize(area, region, AE_RIGHT_TO_TOPLEFT, is_fullscreen);
+ region_azone_edge_init(area, region, AE_RIGHT_TO_TOPLEFT, is_fullscreen);
}
}
@@ -1116,10 +1116,10 @@ static void region_azones_add(const bScreen *screen, ScrArea *area, ARegion *reg
}
if (is_fullscreen) {
- fullscreen_azone_initialize(area, region);
+ fullscreen_azone_init(area, region);
}
- region_azones_scrollbars_initialize(area, region);
+ region_azones_scrollbars_init(area, region);
}
/* dir is direction to check, not the splitting edge direction! */
@@ -1828,7 +1828,7 @@ void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *ar
region_rect_recursive(area, area->regionbase.first, &rect, &overlap_rect, 0);
/* Dynamically sized regions may have changed region sizes, so we have to force azone update. */
- area_azone_initialize(win, screen, area);
+ area_azone_init(win, screen, area);
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
region_subwindow(region);
@@ -1847,7 +1847,7 @@ void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *ar
}
/* called in screen_refresh, or screens_init, also area size changes */
-void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *area)
+void ED_area_init(wmWindowManager *wm, wmWindow *win, ScrArea *area)
{
WorkSpace *workspace = WM_window_get_active_workspace(win);
const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
@@ -1890,7 +1890,7 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *area)
}
/* clear all azones, add the area triangle widgets */
- area_azone_initialize(win, screen, area);
+ area_azone_init(win, screen, area);
/* region windows, default and own handlers */
for (region = area->regionbase.first; region; region = region->next) {
@@ -1944,7 +1944,7 @@ void ED_region_update_rect(ARegion *region)
}
/* externally called for floating regions like menus */
-void ED_region_floating_initialize(ARegion *region)
+void ED_region_floating_init(ARegion *region)
{
BLI_assert(region->alignment == RGN_ALIGN_FLOAT);
@@ -1980,7 +1980,7 @@ void ED_region_visibility_change_update(bContext *C, ScrArea *area, ARegion *reg
WM_event_remove_handlers(C, &region->handlers);
}
- ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), area);
+ ED_area_init(CTX_wm_manager(C), CTX_wm_window(C), area);
ED_area_tag_redraw(area);
}
@@ -2066,8 +2066,8 @@ void ED_area_swapspace(bContext *C, ScrArea *sa1, ScrArea *sa2)
ED_area_data_copy(tmp, sa1, false);
ED_area_data_copy(sa1, sa2, true);
ED_area_data_copy(sa2, tmp, true);
- ED_area_initialize(CTX_wm_manager(C), win, sa1);
- ED_area_initialize(CTX_wm_manager(C), win, sa2);
+ ED_area_init(CTX_wm_manager(C), win, sa1);
+ ED_area_init(CTX_wm_manager(C), win, sa2);
BKE_screen_area_free(tmp);
MEM_freeN(tmp);
@@ -2126,7 +2126,7 @@ void ED_area_newspace(bContext *C, ScrArea *area, int type, const bool skip_regi
area->spacetype = type;
area->type = st;
- /* If st->new may be called, don't use context until then. The
+ /* If st->create may be called, don't use context until then. The
* area->type->context() callback has changed but data may be invalid
* (e.g. with properties editor) until space-data is properly created */
@@ -2166,7 +2166,7 @@ void ED_area_newspace(bContext *C, ScrArea *area, int type, const bool skip_regi
if (st) {
/* Don't get scene from context here which may depend on space-data. */
Scene *scene = WM_window_get_active_scene(win);
- sl = st->new (area, scene);
+ sl = st->create(area, scene);
BLI_addhead(&area->spacedata, sl);
/* swap regions */
@@ -2204,7 +2204,7 @@ void ED_area_newspace(bContext *C, ScrArea *area, int type, const bool skip_regi
}
}
- ED_area_initialize(CTX_wm_manager(C), win, area);
+ ED_area_init(CTX_wm_manager(C), win, area);
/* tell WM to refresh, cursor types etc */
WM_event_add_mousemove(win);
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 07a122c7094..bcbb735d93d 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -106,13 +106,13 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state,
float clip_max_y,
float xzoom,
float yzoom,
- float color[4])
+ const float color[4])
{
int subpart_x, subpart_y, tex_w = 256, tex_h = 256;
int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y;
int components;
const bool use_clipping = ((clip_min_x < clip_max_x) && (clip_min_y < clip_max_y));
- float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ const float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
if (ELEM(gpu_format, GPU_RGBA8, GPU_RGBA16F)) {
components = 4;
@@ -203,21 +203,21 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state,
* at edges of full image. */
if (subpart_w < tex_w) {
void *data = DATA(src_y, src_x + subpart_w - 1);
- int offset[2] = {subpart_w, 0};
- int extent[2] = {1, subpart_h};
+ const int offset[2] = {subpart_w, 0};
+ const int extent[2] = {1, subpart_h};
GPU_texture_update_sub(tex, gpu_data, data, UNPACK2(offset), 0, UNPACK2(extent), 0);
}
if (subpart_h < tex_h) {
void *data = DATA(src_y + subpart_h - 1, src_x);
- int offset[2] = {0, subpart_h};
- int extent[2] = {subpart_w, 1};
+ const int offset[2] = {0, subpart_h};
+ const int extent[2] = {subpart_w, 1};
GPU_texture_update_sub(tex, gpu_data, data, UNPACK2(offset), 0, UNPACK2(extent), 0);
}
if (subpart_w < tex_w && subpart_h < tex_h) {
void *data = DATA(src_y + subpart_h - 1, src_x + subpart_w - 1);
- int offset[2] = {subpart_w, subpart_h};
- int extent[2] = {1, 1};
+ const int offset[2] = {subpart_w, subpart_h};
+ const int extent[2] = {1, 1};
GPU_texture_update_sub(tex, gpu_data, data, UNPACK2(offset), 0, UNPACK2(extent), 0);
}
#undef DATA
@@ -272,7 +272,7 @@ void immDrawPixelsTexScaled(IMMDrawPixelsTexState *state,
float scaleY,
float xzoom,
float yzoom,
- float color[4])
+ const float color[4])
{
immDrawPixelsTexScaled_clipping(state,
x,
@@ -303,7 +303,7 @@ void immDrawPixelsTex(IMMDrawPixelsTexState *state,
void *rect,
float xzoom,
float yzoom,
- float color[4])
+ const float color[4])
{
immDrawPixelsTexScaled_clipping(state,
x,
@@ -338,7 +338,7 @@ void immDrawPixelsTex_clipping(IMMDrawPixelsTexState *state,
float clip_max_y,
float xzoom,
float yzoom,
- float color[4])
+ const float color[4])
{
immDrawPixelsTexScaled_clipping(state,
x,
@@ -566,7 +566,7 @@ int ED_draw_imbuf_method(ImBuf *ibuf)
if (U.image_draw_method == IMAGE_DRAW_METHOD_AUTO) {
/* Use faster GLSL when CPU to GPU transfer is unlikely to be a bottleneck,
* otherwise do color management on CPU side. */
- const size_t threshold = 2048 * 2048 * 4 * sizeof(float);
+ const size_t threshold = sizeof(float[4]) * 2048 * 2048;
const size_t data_size = (ibuf->rect_float) ? sizeof(float) : sizeof(uchar);
const size_t size = ibuf->x * ibuf->y * ibuf->channels * data_size;
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index 7983ac889ef..c17a34f97b9 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -475,7 +475,6 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
CTX_data_id_pointer_set(result, &obpose->id);
}
return 1;
- return -1; /* found but not available */
}
if (CTX_data_equals(member, "sequences")) {
Editing *ed = BKE_sequencer_editing_get(scene, false);
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index b6f210d7f13..06e800433b1 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -516,7 +516,7 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
ED_screen_areas_iter (win, screen, area) {
/* set spacetype and region callbacks, calls init() */
/* sets subwindows for regions, adds handlers */
- ED_area_initialize(wm, win, area);
+ ED_area_init(wm, win, area);
}
/* wake up animtimer */
@@ -536,7 +536,7 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
}
/* file read, set all screens, ... */
-void ED_screens_initialize(Main *bmain, wmWindowManager *wm)
+void ED_screens_init(Main *bmain, wmWindowManager *wm)
{
wmWindow *win;
@@ -897,7 +897,7 @@ static void screen_global_area_refresh(wmWindow *win,
else {
area = screen_area_create_with_geometry(&win->global_areas, rect, space_type);
SpaceType *stype = BKE_spacetype_from_id(space_type);
- SpaceLink *slink = stype->new (area, WM_window_get_active_scene(win));
+ SpaceLink *slink = stype->create(area, WM_window_get_active_scene(win));
area->regionbase = slink->regionbase;
@@ -985,39 +985,15 @@ void ED_screen_global_areas_refresh(wmWindow *win)
/* -------------------------------------------------------------------- */
/* Screen changing */
-static bScreen *screen_fullscreen_find_associated_normal_screen(const Main *bmain, bScreen *screen)
-{
- for (bScreen *screen_iter = bmain->screens.first; screen_iter;
- screen_iter = screen_iter->id.next) {
- if ((screen_iter != screen) && ELEM(screen_iter->state, SCREENMAXIMIZED, SCREENFULL)) {
- ScrArea *area = screen_iter->areabase.first;
- if (area && area->full == screen) {
- return screen_iter;
- }
- }
- }
-
- return screen;
-}
-
/**
* \return the screen to activate.
* \warning The returned screen may not always equal \a screen_new!
*/
-bScreen *screen_change_prepare(
+void screen_change_prepare(
bScreen *screen_old, bScreen *screen_new, Main *bmain, bContext *C, wmWindow *win)
{
- /* validate screen, it's called with notifier reference */
- if (BLI_findindex(&bmain->screens, screen_new) == -1) {
- return NULL;
- }
-
- screen_new = screen_fullscreen_find_associated_normal_screen(bmain, screen_new);
-
- /* check for valid winid */
- if (!(screen_new->winid == 0 || screen_new->winid == win->winid)) {
- return NULL;
- }
+ UNUSED_VARS_NDEBUG(bmain);
+ BLI_assert(BLI_findindex(&bmain->screens, screen_new) != -1);
if (screen_old != screen_new) {
wmTimer *wt = screen_old->animtimer;
@@ -1038,11 +1014,7 @@ bScreen *screen_change_prepare(
if (wt) {
screen_new->animtimer = wt;
}
-
- return screen_new;
}
-
- return NULL;
}
void screen_change_update(bContext *C, wmWindow *win, bScreen *screen)
@@ -1075,12 +1047,20 @@ bool ED_screen_change(bContext *C, bScreen *screen)
{
Main *bmain = CTX_data_main(C);
wmWindow *win = CTX_wm_window(C);
+ WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
+ WorkSpaceLayout *layout = BKE_workspace_layout_find(workspace, screen);
bScreen *screen_old = CTX_wm_screen(C);
- bScreen *screen_new = screen_change_prepare(screen_old, screen, bmain, C, win);
- if (screen_new) {
- WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
- WM_window_set_active_screen(win, workspace, screen);
+ /* Get the actual layout/screen to be activated (guaranteed to be unused, even if that means
+ * having to duplicate an existing one). */
+ WorkSpaceLayout *layout_new = ED_workspace_screen_change_ensure_unused_layout(
+ bmain, workspace, layout, layout, win);
+ bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new);
+
+ screen_change_prepare(screen_old, screen_new, bmain, C, win);
+
+ if (screen_old != screen_new) {
+ WM_window_set_active_screen(win, workspace, screen_new);
screen_change_update(C, win, screen_new);
return true;
diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h
index 2d42313d528..a5b5e222ae9 100644
--- a/source/blender/editors/screen/screen_intern.h
+++ b/source/blender/editors/screen/screen_intern.h
@@ -21,8 +21,7 @@
* \ingroup edscr
*/
-#ifndef __SCREEN_INTERN_H__
-#define __SCREEN_INTERN_H__
+#pragma once
struct Main;
struct bContext;
@@ -50,11 +49,11 @@ bScreen *screen_add(struct Main *bmain, const char *name, const rcti *rect);
void screen_data_copy(bScreen *to, bScreen *from);
void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new);
void screen_change_update(struct bContext *C, wmWindow *win, bScreen *screen);
-bScreen *screen_change_prepare(bScreen *screen_old,
- bScreen *screen_new,
- struct Main *bmain,
- struct bContext *C,
- wmWindow *win);
+void screen_change_prepare(bScreen *screen_old,
+ bScreen *screen_new,
+ struct Main *bmain,
+ struct bContext *C,
+ wmWindow *win);
ScrArea *area_split(
const wmWindow *win, bScreen *screen, ScrArea *area, char dir, float fac, int merge);
int screen_area_join(struct bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2);
@@ -97,5 +96,3 @@ void SCREEN_OT_screenshot(struct wmOperatorType *ot);
/* workspace_layout_edit.c */
bool workspace_layout_set_poll(const struct WorkSpaceLayout *layout);
-
-#endif /* __SCREEN_INTERN_H__ */
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index fde1498bc5e..b002b23a7f3 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -4414,7 +4414,7 @@ static void screen_animation_region_tag_redraw(ScrArea *area,
* We do need to redraw when this area is in full screen as no other areas
* will be tagged for redrawing. */
if ((region->regiontype == RGN_TYPE_WINDOW) &&
- (ELEM(area->spacetype, SPACE_GRAPH, SPACE_NLA, SPACE_ACTION, SPACE_SEQ)) && !area->full) {
+ (ELEM(area->spacetype, SPACE_GRAPH, SPACE_NLA, SPACE_ACTION)) && !area->full) {
return;
}
ED_region_tag_redraw(region);
@@ -5184,7 +5184,7 @@ static void region_blend_end(bContext *C, ARegion *region, const bool is_running
else {
if (rgi->hidden) {
rgi->region->flag |= rgi->hidden;
- ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), rgi->area);
+ ED_area_init(CTX_wm_manager(C), CTX_wm_window(C), rgi->area);
}
/* area decoration needs redraw in end */
ED_area_tag_redraw(rgi->area);
@@ -5215,7 +5215,7 @@ void ED_region_visibility_change_update_animated(bContext *C, ScrArea *area, ARe
/* blend in, reinitialize regions because it got unhidden */
if (rgi->hidden == 0) {
- ED_area_initialize(wm, win, area);
+ ED_area_init(wm, win, area);
}
else {
WM_event_remove_handlers(C, &region->handlers);
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index 478a0adfd9a..b20dc80d158 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -88,22 +88,15 @@ static void workspace_change_update(WorkSpace *workspace_new,
#endif
}
-static bool workspace_change_find_new_layout_cb(const WorkSpaceLayout *layout, void *UNUSED(arg))
-{
- /* return false to stop the iterator if we've found a layout that can be activated */
- return workspace_layout_set_poll(layout) ? false : true;
-}
-
static WorkSpaceLayout *workspace_change_get_new_layout(Main *bmain,
WorkSpace *workspace_new,
wmWindow *win)
{
- /* ED_workspace_duplicate may have stored a layout to activate
- * once the workspace gets activated. */
WorkSpaceLayout *layout_old = WM_window_get_active_layout(win);
WorkSpaceLayout *layout_new;
- bScreen *screen_new;
+ /* ED_workspace_duplicate may have stored a layout to activate
+ * once the workspace gets activated. */
if (win->workspace_hook->temp_workspace_store) {
layout_new = win->workspace_hook->temp_layout_store;
}
@@ -113,20 +106,9 @@ static WorkSpaceLayout *workspace_change_get_new_layout(Main *bmain,
layout_new = workspace_new->layouts.first;
}
}
- screen_new = BKE_workspace_layout_screen_get(layout_new);
-
- if (screen_new->winid) {
- /* screen is already used, try to find a free one */
- WorkSpaceLayout *layout_temp = BKE_workspace_layout_iter_circular(
- workspace_new, layout_new, workspace_change_find_new_layout_cb, NULL, false);
- if (!layout_temp) {
- /* fallback solution: duplicate layout from old workspace */
- layout_temp = ED_workspace_layout_duplicate(bmain, workspace_new, layout_old, win);
- }
- layout_new = layout_temp;
- }
- return layout_new;
+ return ED_workspace_screen_change_ensure_unused_layout(
+ bmain, workspace_new, layout_new, layout_old, win);
}
/**
@@ -153,10 +135,7 @@ bool ED_workspace_change(WorkSpace *workspace_new, bContext *C, wmWindowManager
return false;
}
- screen_new = screen_change_prepare(screen_old, screen_new, bmain, C, win);
- if (BKE_workspace_layout_screen_get(layout_new) != screen_new) {
- layout_new = BKE_workspace_layout_find(workspace_new, screen_new);
- }
+ screen_change_prepare(screen_old, screen_new, bmain, C, win);
if (screen_new == NULL) {
return false;
diff --git a/source/blender/editors/screen/workspace_layout_edit.c b/source/blender/editors/screen/workspace_layout_edit.c
index 0af81e0db21..8a36cffa1f1 100644
--- a/source/blender/editors/screen/workspace_layout_edit.c
+++ b/source/blender/editors/screen/workspace_layout_edit.c
@@ -160,6 +160,66 @@ bool ED_workspace_layout_delete(WorkSpace *workspace, WorkSpaceLayout *layout_ol
return false;
}
+static bool workspace_change_find_new_layout_cb(const WorkSpaceLayout *layout, void *UNUSED(arg))
+{
+ /* return false to stop the iterator if we've found a layout that can be activated */
+ return workspace_layout_set_poll(layout) ? false : true;
+}
+
+static bScreen *screen_fullscreen_find_associated_normal_screen(const Main *bmain, bScreen *screen)
+{
+ for (bScreen *screen_iter = bmain->screens.first; screen_iter;
+ screen_iter = screen_iter->id.next) {
+ if ((screen_iter != screen) && ELEM(screen_iter->state, SCREENMAXIMIZED, SCREENFULL)) {
+ ScrArea *area = screen_iter->areabase.first;
+ if (area && area->full == screen) {
+ return screen_iter;
+ }
+ }
+ }
+
+ return screen;
+}
+
+static bool screen_is_used_by_other_window(const wmWindow *win, const bScreen *screen)
+{
+ return BKE_screen_is_used(screen) && (screen->winid != win->winid);
+}
+
+/**
+ * Make sure there is a non-fullscreen layout to switch to that is not used yet by an other window.
+ * Needed for workspace or screen switching to ensure valid screens.
+ *
+ * \param layout_fallback_base: As last resort, this layout is duplicated and returned.
+ */
+WorkSpaceLayout *ED_workspace_screen_change_ensure_unused_layout(
+ Main *bmain,
+ WorkSpace *workspace,
+ WorkSpaceLayout *layout_new,
+ const WorkSpaceLayout *layout_fallback_base,
+ wmWindow *win)
+{
+ WorkSpaceLayout *layout_temp = layout_new;
+ bScreen *screen_temp = BKE_workspace_layout_screen_get(layout_new);
+
+ screen_temp = screen_fullscreen_find_associated_normal_screen(bmain, screen_temp);
+ layout_temp = BKE_workspace_layout_find(workspace, screen_temp);
+
+ if (screen_is_used_by_other_window(win, screen_temp)) {
+ /* Screen is already used, try to find a free one. */
+ layout_temp = BKE_workspace_layout_iter_circular(
+ workspace, layout_new, workspace_change_find_new_layout_cb, NULL, false);
+ screen_temp = layout_temp ? BKE_workspace_layout_screen_get(layout_temp) : NULL;
+
+ if (!layout_temp || screen_is_used_by_other_window(win, screen_temp)) {
+ /* Fallback solution: duplicate layout. */
+ layout_temp = ED_workspace_layout_duplicate(bmain, workspace, layout_fallback_base, win);
+ }
+ }
+
+ return layout_temp;
+}
+
static bool workspace_layout_cycle_iter_cb(const WorkSpaceLayout *layout, void *UNUSED(arg))
{
/* return false to stop iterator when we have found a layout to activate */