diff options
Diffstat (limited to 'source/blender/editors/screen')
-rw-r--r-- | source/blender/editors/screen/area.c | 56 | ||||
-rw-r--r-- | source/blender/editors/screen/glutil.c | 133 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_context.c | 1 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_draw.c | 2 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_edit.c | 55 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_intern.h | 10 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_ops.c | 4 | ||||
-rw-r--r-- | source/blender/editors/screen/workspace_edit.c | 31 | ||||
-rw-r--r-- | source/blender/editors/screen/workspace_layout_edit.c | 60 |
9 files changed, 180 insertions, 172 deletions
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index f87f631c643..9616b8114ba 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -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 = ®ion->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, ®ion->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 5c3b1944164..07a122c7094 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -95,9 +95,8 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state, float y, int img_w, int img_h, - int format, - int type, - int zoomfilter, + eGPUTextureFormat gpu_format, + bool use_filter, void *rect, float scaleX, float scaleY, @@ -115,21 +114,30 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state, 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}; - if (type != GL_FLOAT) { - BLI_assert(type == GL_UNSIGNED_BYTE); - type = GL_UNSIGNED_BYTE; + if (ELEM(gpu_format, GPU_RGBA8, GPU_RGBA16F)) { + components = 4; + } + else if (ELEM(gpu_format, GPU_RGB16F)) { + components = 3; + } + else if (ELEM(gpu_format, GPU_R8, GPU_R16F)) { + components = 1; + } + else { + BLI_assert(!"Incompatible format passed to immDrawPixels"); + return; } - eGPUTextureFormat gpu_format = (type == GL_FLOAT) ? GPU_RGBA16F : GPU_RGBA8; - eGPUDataFormat gpu_data = (type == GL_FLOAT) ? GPU_DATA_FLOAT : GPU_DATA_UNSIGNED_BYTE; - GPUTexture *texture = GPU_texture_create_nD( - tex_w, tex_h, 0, 2, NULL, gpu_format, gpu_data, 0, false, NULL); + const bool use_float_data = ELEM(gpu_format, GPU_RGBA16F, GPU_RGB16F, GPU_R16F); + eGPUDataFormat gpu_data = (use_float_data) ? GPU_DATA_FLOAT : GPU_DATA_UNSIGNED_BYTE; + size_t stride = components * ((use_float_data) ? sizeof(float) : sizeof(uchar)); - /* TODO replace GL_NEAREST/LINEAR in callers. */ - GPU_texture_filter_mode(texture, (zoomfilter == GL_LINEAR)); - GPU_texture_wrap_mode(texture, false, true); + GPUTexture *tex = GPU_texture_create_2d(tex_w, tex_h, gpu_format, NULL, NULL); - GPU_texture_bind(texture, 0); + GPU_texture_filter_mode(tex, use_filter); + GPU_texture_wrap_mode(tex, false, true); + + GPU_texture_bind(tex, 0); /* setup seamless 2=on, 0=off */ seamless = ((tex_w < img_w || tex_h < img_h) && tex_w > 2 && tex_h > 2) ? 2 : 0; @@ -140,20 +148,6 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state, nsubparts_x = (img_w + (offset_x - 1)) / (offset_x); nsubparts_y = (img_h + (offset_y - 1)) / (offset_y); - if (format == GL_RGBA) { - components = 4; - } - else if (format == GL_RGB) { - components = 3; - } - else if (format == GL_RED) { - components = 1; - } - else { - BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled"); - return; - } - /* optional */ /* NOTE: Shader could be null for GLSL OCIO drawing, it is fine, since * it does not need color. @@ -199,26 +193,32 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state, { int src_y = subpart_y * offset_y; int src_x = subpart_x * offset_x; - size_t stride = components * ((type == GL_FLOAT) ? sizeof(float) : sizeof(uchar)); #define DATA(_y, _x) ((char *)rect + stride * ((size_t)(_y)*img_w + (_x))) { void *data = DATA(src_y, src_x); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, type, data); + GPU_texture_update_sub(tex, gpu_data, data, 0, 0, 0, subpart_w, subpart_h, 0); } /* Add an extra border of pixels so linear interpolation looks ok * at edges of full image. */ if (subpart_w < tex_w) { void *data = DATA(src_y, src_x + subpart_w - 1); - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, type, data); + int offset[2] = {subpart_w, 0}; + 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); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, type, data); + int offset[2] = {0, subpart_h}; + 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); - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, type, data); + int offset[2] = {subpart_w, subpart_h}; + int extent[2] = {1, 1}; + GPU_texture_update_sub(tex, gpu_data, data, UNPACK2(offset), 0, UNPACK2(extent), 0); } #undef DATA } @@ -253,8 +253,8 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state, immUnbindProgram(); } - GPU_texture_unbind(texture); - GPU_texture_free(texture); + GPU_texture_unbind(tex); + GPU_texture_free(tex); /* Restore default. */ GPU_unpack_row_length_set(0); @@ -265,9 +265,8 @@ void immDrawPixelsTexScaled(IMMDrawPixelsTexState *state, float y, int img_w, int img_h, - int format, - int type, - int zoomfilter, + eGPUTextureFormat gpu_format, + bool use_filter, void *rect, float scaleX, float scaleY, @@ -280,9 +279,8 @@ void immDrawPixelsTexScaled(IMMDrawPixelsTexState *state, y, img_w, img_h, - format, - type, - zoomfilter, + gpu_format, + use_filter, rect, scaleX, scaleY, @@ -300,9 +298,8 @@ void immDrawPixelsTex(IMMDrawPixelsTexState *state, float y, int img_w, int img_h, - int format, - int type, - int zoomfilter, + eGPUTextureFormat gpu_format, + bool use_filter, void *rect, float xzoom, float yzoom, @@ -313,9 +310,8 @@ void immDrawPixelsTex(IMMDrawPixelsTexState *state, y, img_w, img_h, - format, - type, - zoomfilter, + gpu_format, + use_filter, rect, 1.0f, 1.0f, @@ -333,9 +329,8 @@ void immDrawPixelsTex_clipping(IMMDrawPixelsTexState *state, float y, int img_w, int img_h, - int format, - int type, - int zoomfilter, + eGPUTextureFormat gpu_format, + bool use_filter, void *rect, float clip_min_x, float clip_min_y, @@ -350,9 +345,8 @@ void immDrawPixelsTex_clipping(IMMDrawPixelsTexState *state, y, img_w, img_h, - format, - type, - zoomfilter, + gpu_format, + use_filter, rect, 1.0f, 1.0f, @@ -371,7 +365,7 @@ void immDrawPixelsTex_clipping(IMMDrawPixelsTexState *state, void ED_draw_imbuf_clipping(ImBuf *ibuf, float x, float y, - int zoomfilter, + bool use_filter, ColorManagedViewSettings *view_settings, ColorManagedDisplaySettings *display_settings, float clip_min_x, @@ -421,13 +415,13 @@ void ED_draw_imbuf_clipping(ImBuf *ibuf, if (ok) { if (ibuf->rect_float) { - int format = 0; + eGPUTextureFormat format = 0; if (ibuf->channels == 3) { - format = GL_RGB; + format = GPU_RGB16F; } else if (ibuf->channels == 4) { - format = GL_RGBA; + format = GPU_RGBA16F; } else { BLI_assert(!"Incompatible number of channels for GLSL display"); @@ -440,8 +434,7 @@ void ED_draw_imbuf_clipping(ImBuf *ibuf, ibuf->x, ibuf->y, format, - GL_FLOAT, - zoomfilter, + use_filter, ibuf->rect_float, clip_min_x, clip_min_y, @@ -459,9 +452,8 @@ void ED_draw_imbuf_clipping(ImBuf *ibuf, y, ibuf->x, ibuf->y, - GL_RGBA, - GL_UNSIGNED_BYTE, - zoomfilter, + GPU_RGBA8, + use_filter, ibuf->rect, clip_min_x, clip_min_y, @@ -493,9 +485,8 @@ void ED_draw_imbuf_clipping(ImBuf *ibuf, y, ibuf->x, ibuf->y, - GL_RGBA, - GL_UNSIGNED_BYTE, - zoomfilter, + GPU_RGBA8, + use_filter, display_buffer, clip_min_x, clip_min_y, @@ -513,7 +504,7 @@ void ED_draw_imbuf_clipping(ImBuf *ibuf, void ED_draw_imbuf(ImBuf *ibuf, float x, float y, - int zoomfilter, + bool use_filter, ColorManagedViewSettings *view_settings, ColorManagedDisplaySettings *display_settings, float zoom_x, @@ -522,7 +513,7 @@ void ED_draw_imbuf(ImBuf *ibuf, ED_draw_imbuf_clipping(ibuf, x, y, - zoomfilter, + use_filter, view_settings, display_settings, 0.0f, @@ -537,7 +528,7 @@ void ED_draw_imbuf_ctx_clipping(const bContext *C, ImBuf *ibuf, float x, float y, - int zoomfilter, + bool use_filter, float clip_min_x, float clip_min_y, float clip_max_x, @@ -553,7 +544,7 @@ void ED_draw_imbuf_ctx_clipping(const bContext *C, ED_draw_imbuf_clipping(ibuf, x, y, - zoomfilter, + use_filter, view_settings, display_settings, clip_min_x, @@ -565,9 +556,9 @@ void ED_draw_imbuf_ctx_clipping(const bContext *C, } void ED_draw_imbuf_ctx( - const bContext *C, ImBuf *ibuf, float x, float y, int zoomfilter, float zoom_x, float zoom_y) + const bContext *C, ImBuf *ibuf, float x, float y, bool use_filter, float zoom_x, float zoom_y) { - ED_draw_imbuf_ctx_clipping(C, ibuf, x, y, zoomfilter, 0.0f, 0.0f, 0.0f, 0.0f, zoom_x, zoom_y); + ED_draw_imbuf_ctx_clipping(C, ibuf, x, y, use_filter, 0.0f, 0.0f, 0.0f, 0.0f, zoom_x, zoom_y); } int ED_draw_imbuf_method(ImBuf *ibuf) 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_draw.c b/source/blender/editors/screen/screen_draw.c index 1608e842376..40a452a5363 100644 --- a/source/blender/editors/screen/screen_draw.c +++ b/source/blender/editors/screen/screen_draw.c @@ -619,7 +619,7 @@ void ED_screen_preview_render(const bScreen *screen, int size_x, int size_y, uin screen_preview_draw(screen, size_x, size_y); - GPU_offscreen_read_pixels(offscreen, GL_UNSIGNED_BYTE, r_rect); + GPU_offscreen_read_pixels(offscreen, GPU_DATA_UNSIGNED_BYTE, r_rect); GPU_offscreen_unbind(offscreen, true); GPU_offscreen_free(offscreen); diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index b6f210d7f13..62720d8ca37 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,14 @@ 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; - } + BLI_assert(BLI_findindex(&bmain->screens, screen_new) != -1); if (screen_old != screen_new) { wmTimer *wt = screen_old->animtimer; @@ -1038,11 +1013,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 +1046,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..b96890c7db3 100644 --- a/source/blender/editors/screen/screen_intern.h +++ b/source/blender/editors/screen/screen_intern.h @@ -50,11 +50,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); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index fde1498bc5e..f4d36a15d30 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -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, ®ion->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 */ |