diff options
21 files changed, 207 insertions, 135 deletions
diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py index beb59d2c512..5cf28578217 100644 --- a/release/scripts/startup/bl_ui/space_topbar.py +++ b/release/scripts/startup/bl_ui/space_topbar.py @@ -465,6 +465,10 @@ class INFO_MT_window(Menu): layout = self.layout layout.operator("wm.window_new") + layout.operator("wm.window_new_main") + + layout.separator() + layout.operator("wm.window_fullscreen_toggle", icon='FULLSCREEN_ENTER') layout.separator() diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index a38384f8f2b..1b309d76f61 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -906,7 +906,7 @@ Object *BKE_scene_object_find_by_name(Scene *scene, const char *name) /** * Sets the active scene, mainly used when running in background mode (``--scene`` command line argument). * This is also called to set the scene directly, bypassing windowing code. - * Otherwise #WM_window_change_active_scene is used when changing scenes by the user. + * Otherwise #WM_window_set_active_scene is used when changing scenes by the user. */ void BKE_scene_set_background(Main *bmain, Scene *scene) { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 2a48bf8fc5a..4fa897bb689 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6926,9 +6926,11 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm) link_list(fd, &wm->windows); for (win = wm->windows.first; win; win = win->next) { - WorkSpaceInstanceHook *hook = win->workspace_hook; + win->parent = newdataadr(fd, win->parent); + WorkSpaceInstanceHook *hook = win->workspace_hook; win->workspace_hook = newdataadr(fd, hook); + /* we need to restore a pointer to this later when reading workspaces, so store in global oldnew-map */ oldnewmap_insert(fd->globmap, hook, win->workspace_hook, 0); diff --git a/source/blender/editors/include/ED_scene.h b/source/blender/editors/include/ED_scene.h index 9b48187e541..116d9bd24fc 100644 --- a/source/blender/editors/include/ED_scene.h +++ b/source/blender/editors/include/ED_scene.h @@ -31,10 +31,7 @@ enum eSceneCopyMethod; struct Scene *ED_scene_add(struct Main *bmain, struct bContext *C, struct wmWindow *win, enum eSceneCopyMethod method) ATTR_NONNULL(); bool ED_scene_delete(struct bContext *C, struct Main *bmain, struct wmWindow *win, struct Scene *scene) ATTR_NONNULL(); -void ED_scene_change_update( - struct Main *bmain, struct bContext *C, - struct wmWindow *win, const struct bScreen *screen, - struct Scene *scene_old, struct Scene *scene_new) ATTR_NONNULL(); +void ED_scene_change_update(struct Main *bmain, struct Scene *scene, struct ViewLayer *layer) ATTR_NONNULL(); bool ED_scene_view_layer_delete( struct Main *bmain, struct Scene *scene, struct ViewLayer *layer, struct ReportList *reports) ATTR_NONNULL(1, 2, 3); diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 1fdbd46bacf..cc80108e20c 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -184,10 +184,7 @@ void ED_screen_refresh(struct wmWindowManager *wm, struct wmWindow *win); void ED_screen_ensure_updated(struct wmWindowManager *wm, struct wmWindow *win, struct bScreen *screen); void ED_screen_do_listen(struct bContext *C, struct wmNotifier *note); bool ED_screen_change(struct bContext *C, struct bScreen *sc); -void ED_screen_update_after_scene_change( - const struct bScreen *screen, - struct Scene *scene_new, - struct ViewLayer *view_layer); +void ED_screen_scene_change(struct bContext *C, struct wmWindow *win, struct Scene *scene); void ED_screen_set_active_region(struct bContext *C, struct wmWindow *win, const int xy[2]); void ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen); void ED_screen_animation_timer(struct bContext *C, int redraws, int refresh, int sync, int enable); diff --git a/source/blender/editors/scene/scene_edit.c b/source/blender/editors/scene/scene_edit.c index 677fc0a068e..0ebbd770c9f 100644 --- a/source/blender/editors/scene/scene_edit.c +++ b/source/blender/editors/scene/scene_edit.c @@ -80,7 +80,7 @@ Scene *ED_scene_add(Main *bmain, bContext *C, wmWindow *win, eSceneCopyMethod me } } - WM_window_change_active_scene(bmain, C, win, scene_new); + WM_window_set_active_scene(bmain, C, win, scene_new); WM_event_add_notifier(C, NC_SCENE | ND_SCENEBROWSE, scene_new); @@ -102,7 +102,7 @@ bool ED_scene_delete(bContext *C, Main *bmain, wmWindow *win, Scene *scene) else return false; - WM_window_change_active_scene(bmain, C, win, scene_new); + WM_window_set_active_scene(bmain, C, win, scene_new); BKE_libblock_remap(bmain, scene, scene_new, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE); @@ -114,43 +114,17 @@ bool ED_scene_delete(bContext *C, Main *bmain, wmWindow *win, Scene *scene) return true; } -static ViewLayer *scene_change_get_new_view_layer(const WorkSpace *workspace, const Scene *scene_new) +/* Depsgraph updates after scene becomes active in a window. */ +void ED_scene_change_update(Main *bmain, Scene *scene, ViewLayer *layer) { - ViewLayer *layer_new = BKE_workspace_view_layer_exists(workspace, scene_new); - return layer_new ? layer_new : BKE_view_layer_default_view(scene_new); -} + Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, layer, true); -void ED_scene_change_update( - Main *bmain, bContext *C, - wmWindow *win, const bScreen *screen, Scene *UNUSED(scene_old), Scene *scene_new) -{ - WorkSpace *workspace = CTX_wm_workspace(C); - ViewLayer *layer_new = scene_change_get_new_view_layer(workspace, scene_new); - Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene_new, layer_new, true); - Object *obact_new = OBACT(layer_new); - UNUSED_VARS(obact_new); - -#if 0 - /* mode syncing */ - eObjectMode object_mode_old = workspace->object_mode; - ViewLayer *layer_old = BKE_view_layer_from_workspace_get(scene_old, workspace); - Object *obact_old = OBACT(layer_old); - UNUSED_VARS(obact_old, object_mode_old); -#endif - - win->scene = scene_new; - CTX_data_scene_set(C, scene_new); - BKE_workspace_view_layer_set(workspace, layer_new, scene_new); - BKE_scene_set_background(bmain, scene_new); - DEG_graph_relations_update(depsgraph, bmain, scene_new, layer_new); + BKE_scene_set_background(bmain, scene); + DEG_graph_relations_update(depsgraph, bmain, scene, layer); DEG_on_visible_update(bmain, false); - ED_screen_update_after_scene_change(screen, scene_new, layer_new); ED_render_engine_changed(bmain); ED_update_for_newframe(bmain, depsgraph); - - /* complete redraw */ - WM_event_add_notifier(C, NC_WINDOW, NULL); } static bool view_layer_remove_poll( diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 6bc8a6c10cf..50609815168 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -477,8 +477,8 @@ void ED_screens_initialize(Main *bmain, wmWindowManager *wm) wmWindow *win; for (win = wm->windows.first; win; win = win->next) { - if (WM_window_get_active_workspace(win) == NULL) { - WM_window_set_active_workspace(win, bmain->workspaces.first); + if (BKE_workspace_active_get(win->workspace_hook) == NULL) { + BKE_workspace_active_set(win->workspace_hook, bmain->workspaces.first); } if (BLI_listbase_is_empty(&win->global_areas.areabase)) { @@ -792,11 +792,19 @@ static void screen_global_statusbar_area_create(wmWindow *win) void ED_screen_global_areas_create(wmWindow *win) { + /* Don't create global areas for child windows. */ + if (win->parent) { + return; + } + + /* Don't create global area for temporary windows. */ bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook); - if (screen->temp == 0) { - screen_global_topbar_area_create(win); - screen_global_statusbar_area_create(win); + if (screen->temp) { + return; } + + screen_global_topbar_area_create(win); + screen_global_statusbar_area_create(win); } @@ -936,13 +944,40 @@ static void screen_set_3dview_camera(Scene *scene, ViewLayer *view_layer, ScrAre } } -void ED_screen_update_after_scene_change(const bScreen *screen, Scene *scene_new, ViewLayer *view_layer) +static ViewLayer *scene_change_get_new_view_layer(const WorkSpace *workspace, const Scene *scene_new) +{ + ViewLayer *layer_new = BKE_workspace_view_layer_exists(workspace, scene_new); + return layer_new ? layer_new : BKE_view_layer_default_view(scene_new); +} + +void ED_screen_scene_change(bContext *C, wmWindow *win, Scene *scene) { + const bScreen *screen = WM_window_get_active_screen(win); + WorkSpace *workspace = CTX_wm_workspace(C); + ViewLayer *view_layer = scene_change_get_new_view_layer(workspace, scene); + +#if 0 + /* mode syncing */ + Object *obact_new = OBACT(view_layer); + UNUSED_VARS(obact_new); + eObjectMode object_mode_old = workspace->object_mode; + ViewLayer *layer_old = BKE_view_layer_from_workspace_get(scene_old, workspace); + Object *obact_old = OBACT(layer_old); + UNUSED_VARS(obact_old, object_mode_old); +#endif + + BKE_workspace_view_layer_set(workspace, view_layer, scene); + + win->scene = scene; + if (CTX_wm_window(C) == win) { + CTX_data_scene_set(C, scene); + } + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) { if (sl->spacetype == SPACE_VIEW3D) { View3D *v3d = (View3D *)sl; - screen_set_3dview_camera(scene_new, view_layer, sa, v3d); + screen_set_3dview_camera(scene, view_layer, sa, v3d); } } } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index a0e8357b8f3..ab0fbfacf93 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -1130,7 +1130,7 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event) newwin->scene = scene; - WM_window_set_active_workspace(newwin, workspace); + BKE_workspace_active_set(newwin->workspace_hook, workspace); /* allocs new screen and adds to newly created window, using window size */ layout_new = ED_workspace_layout_add(bmain, workspace, newwin, BKE_workspace_layout_name_get(layout_old)); newsc = BKE_workspace_layout_screen_get(layout_new); diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c index 9d329355500..9ba9b70a6e8 100644 --- a/source/blender/editors/screen/workspace_edit.c +++ b/source/blender/editors/screen/workspace_edit.c @@ -191,8 +191,8 @@ bool ED_workspace_change( BLI_assert(BKE_workspace_layout_screen_get(layout_new) == screen_new); if (screen_new) { - WM_window_set_active_layout(win, workspace_new, layout_new); - WM_window_set_active_workspace(win, workspace_new); + BKE_workspace_hook_layout_for_workspace_set(win->workspace_hook, workspace_new, layout_new); + BKE_workspace_active_set(win->workspace_hook, workspace_new); /* update screen *after* changing workspace - which also causes the * actual screen change and updates context (including CTX_wm_workspace) */ diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 6668ea1faeb..8a5df196c7b 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -262,7 +262,7 @@ static eOLDrawState tree_element_set_active_object( sce = (Scene *)outliner_search_back(soops, te, ID_SCE); if (sce && scene != sce) { - WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce); + WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce); scene = sce; } @@ -431,7 +431,7 @@ static eOLDrawState tree_element_active_world( if (set != OL_SETSEL_NONE) { /* make new scene active */ if (sce && scene != sce) { - WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce); + WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce); } } @@ -950,7 +950,7 @@ static void do_outliner_item_activate_tree_element( /* editmode? */ if (te->idcode == ID_SCE) { if (scene != (Scene *)tselem->id) { - WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), (Scene *)tselem->id); + WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), (Scene *)tselem->id); } } else if (te->idcode == ID_GR) { diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 9952db5e652..b23ea8e4dae 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -580,7 +580,7 @@ void outliner_do_object_operation_ex( // when objects selected in other scenes... dunno if that should be allowed Scene *scene_owner = (Scene *)outliner_search_back(soops, te, ID_SCE); if (scene_owner && scene_act != scene_owner) { - WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), scene_owner); + WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), scene_owner); } /* important to use 'scene_owner' not scene_act else deleting objects can crash. * only use 'scene_act' when 'scene_owner' is NULL, which can happen when the @@ -956,7 +956,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) Scene *sce = scene; // to be able to delete, scenes are set... outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_select_cb); if (scene != sce) { - WM_window_change_active_scene(bmain, C, win, sce); + WM_window_set_active_scene(bmain, C, win, sce); } str = "Select Objects"; @@ -967,7 +967,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) Scene *sce = scene; // to be able to delete, scenes are set... outliner_do_object_operation_ex(C, op->reports, scene, soops, &soops->tree, object_select_hierarchy_cb, false); if (scene != sce) { - WM_window_change_active_scene(bmain, C, win, sce); + WM_window_set_active_scene(bmain, C, win, sce); } str = "Select Object Hierarchy"; DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index c6ad1470561..0ef9e9b134a 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -186,8 +186,10 @@ typedef struct wmWindow { void *ghostwin; /* don't want to include ghost.h stuff */ void *gwnctx; /* don't want to include gawin stuff */ - struct Scene *scene; /* The scene displayed in this window. */ - struct Scene *new_scene; /* temporary when switching */ + struct wmWindow *parent; /* Parent window */ + + struct Scene *scene; /* The scene displayed in this window. */ + struct Scene *new_scene; /* temporary when switching */ struct WorkSpaceInstanceHook *workspace_hook; diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index fff53aafcc7..5fca91064b6 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -185,7 +185,7 @@ static void rna_Main_scenes_remove(Main *bmain, bContext *C, ReportList *reports BPy_BEGIN_ALLOW_THREADS; #endif - WM_window_change_active_scene(bmain, C, win, scene_new); + WM_window_set_active_scene(bmain, C, win, scene_new); #ifdef WITH_PYTHON BPy_END_ALLOW_THREADS; diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 1c94582c57e..569bc20d435 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -675,7 +675,7 @@ static void rna_Window_scene_update(bContext *C, PointerRNA *ptr) BPy_BEGIN_ALLOW_THREADS; #endif - WM_window_change_active_scene(bmain, C, win, win->new_scene); + WM_window_set_active_scene(bmain, C, win, win->new_scene); #ifdef WITH_PYTHON BPy_END_ALLOW_THREADS; @@ -2041,6 +2041,9 @@ static void rna_def_window(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Window", "Open window"); RNA_def_struct_sdna(srna, "wmWindow"); + prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE); + RNA_def_property_ui_text(prop, "Parent Window", "Active workspace and scene follow this window"); + rna_def_window_stereo3d(brna); prop = RNA_def_property(srna, "scene", PROP_POINTER, PROP_NONE); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 3d1ee273108..0ed23a8fb20 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -111,10 +111,10 @@ struct Scene *WM_windows_scene_get_from_screen(const struct wmWindowManager *wm, struct WorkSpace *WM_windows_workspace_get_from_screen(const wmWindowManager *wm, const struct bScreen *screen) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; struct Scene *WM_window_get_active_scene(const struct wmWindow *win) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; -void WM_window_change_active_scene(struct Main *bmain, struct bContext *C, struct wmWindow *win, +void WM_window_set_active_scene(struct Main *bmain, struct bContext *C, struct wmWindow *win, struct Scene *scene_new) ATTR_NONNULL(); struct WorkSpace *WM_window_get_active_workspace(const struct wmWindow *win) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; -void WM_window_set_active_workspace(struct wmWindow *win, struct WorkSpace *workspace) ATTR_NONNULL(1); +void WM_window_set_active_workspace(struct bContext *C, struct wmWindow *win, struct WorkSpace *workspace) ATTR_NONNULL(1); struct WorkSpaceLayout *WM_window_get_active_layout(const struct wmWindow *win) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; void WM_window_set_active_layout( struct wmWindow *win, struct WorkSpace *workspace, struct WorkSpaceLayout *layout) ATTR_NONNULL(1); diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 701ad49b520..9ef0883cbbf 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -461,10 +461,10 @@ void wm_add_default(Main *bmain, bContext *C) WorkSpaceLayout *layout = BKE_workspace_layout_find_global(bmain, screen, &workspace); CTX_wm_manager_set(C, wm); - win = wm_window_new(C); + win = wm_window_new(C, NULL); win->scene = CTX_data_scene(C); - WM_window_set_active_workspace(win, workspace); - WM_window_set_active_layout(win, workspace, layout); + BKE_workspace_active_set(win->workspace_hook, workspace); + BKE_workspace_hook_layout_for_workspace_set(win->workspace_hook, workspace, layout); screen->winid = win->winid; wm->winactive = win; @@ -484,7 +484,8 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm) wm_autosave_timer_ended(wm); while ((win = BLI_pophead(&wm->windows))) { - WM_window_set_active_workspace(win, NULL); /* prevent draw clear to use screen */ + /* prevent draw clear to use screen */ + BKE_workspace_active_set(win->workspace_hook, NULL); wm_window_free(C, wm, win); } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 6fd23dc6b08..3aee57d5801 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -384,7 +384,7 @@ void wm_event_do_notifiers(bContext *C) UI_popup_handlers_remove_all(C, &win->modalhandlers); - ED_workspace_change(ref_ws, C, wm, win); + WM_window_set_active_workspace(C, win, ref_ws); if (G.debug & G_DEBUG_EVENTS) printf("%s: Workspace set %p\n", __func__, note->reference); } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 5628d39e5f8..1983c0e6b84 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2298,7 +2298,7 @@ static void WM_OT_window_close(wmOperatorType *ot) { ot->name = "Close Window"; ot->idname = "WM_OT_window_close"; - ot->description = "Close the current Blender window"; + ot->description = "Close the current window"; ot->exec = wm_window_close_exec; ot->poll = WM_operator_winactive; @@ -2308,12 +2308,22 @@ static void WM_OT_window_new(wmOperatorType *ot) { ot->name = "New Window"; ot->idname = "WM_OT_window_new"; - ot->description = "Create a new Blender window"; + ot->description = "Create a new window"; ot->exec = wm_window_new_exec; ot->poll = wm_operator_winactive_normal; } +static void WM_OT_window_new_main(wmOperatorType *ot) +{ + ot->name = "New Main Window"; + ot->idname = "WM_OT_window_new_main"; + ot->description = "Create a new main window with its own workspace and scene selection"; + + ot->exec = wm_window_new_main_exec; + ot->poll = wm_operator_winactive_normal; +} + static void WM_OT_window_fullscreen_toggle(wmOperatorType *ot) { ot->name = "Toggle Window Fullscreen"; @@ -3703,6 +3713,7 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_window_close); WM_operatortype_append(WM_OT_window_new); + WM_operatortype_append(WM_OT_window_new_main); WM_operatortype_append(WM_OT_read_history); WM_operatortype_append(WM_OT_read_homefile); WM_operatortype_append(WM_OT_read_factory_settings); diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index 4450d18a5df..2c779ba9c7c 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -404,7 +404,7 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) prev_display_mode != win_src->stereo3d_format->display_mode) { /* in case the hardward supports pageflip but not the display */ - if ((win_dst = wm_window_copy_test(C, win_src, false))) { + if ((win_dst = wm_window_copy_test(C, win_src, false, false))) { /* pass */ } else { @@ -423,7 +423,7 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) ok = false; } /* pageflip requires a new window to be created with the proper OS flags */ - else if ((win_dst = wm_window_copy_test(C, win_src, false))) { + else if ((win_dst = wm_window_copy_test(C, win_src, false, false))) { if (wm_stereo3d_quadbuffer_supported()) { BKE_report(op->reports, RPT_INFO, "Quad-buffer window successfully created"); } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 43231855162..d28d2c6b001 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -256,7 +256,7 @@ static int find_free_winid(wmWindowManager *wm) } /* don't change context itself */ -wmWindow *wm_window_new(bContext *C) +wmWindow *wm_window_new(bContext *C, wmWindow *parent) { Main *bmain = CTX_data_main(C); wmWindowManager *wm = CTX_wm_manager(C); @@ -265,6 +265,7 @@ wmWindow *wm_window_new(bContext *C) BLI_addtail(&wm->windows, win); win->winid = find_free_winid(wm); + win->parent = (parent && parent->parent) ? parent->parent : parent; win->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo 3D Format (window)"); win->workspace_hook = BKE_workspace_instance_hook_create(bmain); @@ -272,10 +273,11 @@ wmWindow *wm_window_new(bContext *C) } /* part of wm_window.c api */ -wmWindow *wm_window_copy(bContext *C, wmWindow *win_src, const bool duplicate_layout) +wmWindow *wm_window_copy(bContext *C, wmWindow *win_src, const bool duplicate_layout, const bool child) { Main *bmain = CTX_data_main(C); - wmWindow *win_dst = wm_window_new(C); + wmWindow *win_parent = (child) ? win_src : win_src->parent; + wmWindow *win_dst = wm_window_new(C, win_parent); WorkSpace *workspace = WM_window_get_active_workspace(win_src); WorkSpaceLayout *layout_old = WM_window_get_active_layout(win_src); Scene *scene = WM_window_get_active_scene(win_src); @@ -287,9 +289,9 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *win_src, const bool duplicate_la win_dst->sizey = win_src->sizey; win_dst->scene = scene; - WM_window_set_active_workspace(win_dst, workspace); + BKE_workspace_active_set(win_dst->workspace_hook, workspace); layout_new = duplicate_layout ? ED_workspace_layout_duplicate(bmain, workspace, layout_old, win_dst) : layout_old; - WM_window_set_active_layout(win_dst, workspace, layout_new); + BKE_workspace_hook_layout_for_workspace_set(win_dst->workspace_hook, workspace, layout_new); *win_dst->stereo3d_format = *win_src->stereo3d_format; @@ -300,12 +302,12 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *win_src, const bool duplicate_la * A higher level version of copy that tests the new window can be added. * (called from the operator directly) */ -wmWindow *wm_window_copy_test(bContext *C, wmWindow *win_src, const bool duplicate_layout) +wmWindow *wm_window_copy_test(bContext *C, wmWindow *win_src, const bool duplicate_layout, const bool child) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win_dst; - win_dst = wm_window_copy(C, win_src, duplicate_layout); + win_dst = wm_window_copy(C, win_src, duplicate_layout, child); WM_check(C); @@ -473,56 +475,67 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) { wmWindow *tmpwin; - /* first check if we have to quit (there are non-temp remaining windows) */ - for (tmpwin = wm->windows.first; tmpwin; tmpwin = tmpwin->next) { - if (tmpwin == win) - continue; - if (WM_window_is_temp_screen(tmpwin) == false) - break; + /* first check if we have to quit (there are non-temp and non-child windows remaining) */ + if (win->parent == NULL) { + for (tmpwin = wm->windows.first; tmpwin; tmpwin = tmpwin->next) { + if (tmpwin == win) + continue; + if (tmpwin->parent == NULL) + break; + if (WM_window_is_temp_screen(tmpwin) == false) + break; + } + + if (tmpwin == NULL) { + wm_quit_with_optional_confirmation_prompt(C, win); + return; + } } - if (tmpwin == NULL) { - wm_quit_with_optional_confirmation_prompt(C, win); + /* close child windows */ + for (tmpwin = wm->windows.first; tmpwin; tmpwin = tmpwin->next) { + if (tmpwin->parent == win) { + wm_window_close(C, wm, tmpwin); + } } - else { - bScreen *screen = WM_window_get_active_screen(win); - WorkSpace *workspace = WM_window_get_active_workspace(win); - WorkSpaceLayout *layout = BKE_workspace_active_layout_get(win->workspace_hook); - BLI_remlink(&wm->windows, win); + bScreen *screen = WM_window_get_active_screen(win); + WorkSpace *workspace = WM_window_get_active_workspace(win); + WorkSpaceLayout *layout = BKE_workspace_active_layout_get(win->workspace_hook); - CTX_wm_window_set(C, win); /* needed by handlers */ - WM_event_remove_handlers(C, &win->handlers); - WM_event_remove_handlers(C, &win->modalhandlers); + BLI_remlink(&wm->windows, win); - /* for regular use this will _never_ be NULL, - * however we may be freeing an improperly initialized window. */ - if (screen) { - ED_screen_exit(C, win, screen); - } + CTX_wm_window_set(C, win); /* needed by handlers */ + WM_event_remove_handlers(C, &win->handlers); + WM_event_remove_handlers(C, &win->modalhandlers); - if (tmpwin) { - BLF_batch_reset(); - gpu_batch_presets_reset(); - immDeactivate(); - } + /* for regular use this will _never_ be NULL, + * however we may be freeing an improperly initialized window. */ + if (screen) { + ED_screen_exit(C, win, screen); + } - wm_window_free(C, wm, win); + if (tmpwin) { + BLF_batch_reset(); + gpu_batch_presets_reset(); + immDeactivate(); + } - /* keep imediatemode active before the next `wm_window_make_drawable` call */ - if (tmpwin) { - GHOST_ActivateWindowDrawingContext(tmpwin->ghostwin); - GWN_context_active_set(tmpwin->gwnctx); - immActivate(); - } + wm_window_free(C, wm, win); + + /* keep imediatemode active before the next `wm_window_make_drawable` call */ + if (tmpwin) { + GHOST_ActivateWindowDrawingContext(tmpwin->ghostwin); + GWN_context_active_set(tmpwin->gwnctx); + immActivate(); + } - /* if temp screen, delete it after window free (it stops jobs that can access it) */ - if (screen && screen->temp) { - Main *bmain = CTX_data_main(C); + /* if temp screen, delete it after window free (it stops jobs that can access it) */ + if (screen && screen->temp) { + Main *bmain = CTX_data_main(C); - BLI_assert(BKE_workspace_layout_screen_get(layout) == screen); - BKE_workspace_layout_remove(bmain, workspace, layout); - } + BLI_assert(BKE_workspace_layout_screen_get(layout) == screen); + BKE_workspace_layout_remove(bmain, workspace, layout); } } @@ -809,7 +822,7 @@ void wm_window_ghostwindows_remove_invalid(bContext *C, wmWindowManager *wm) wmWindow *WM_window_open(bContext *C, const rcti *rect) { wmWindow *win_prev = CTX_wm_window(C); - wmWindow *win = wm_window_new(C); + wmWindow *win = wm_window_new(C, win_prev); win->posx = rect->xmin; win->posy = rect->ymin; @@ -869,7 +882,7 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i /* add new window? */ if (win == NULL) { - win = wm_window_new(C); + win = wm_window_new(C, win_prev); win->posx = rect.xmin; win->posy = rect.ymin; @@ -887,7 +900,7 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i if (WM_window_get_active_workspace(win) == NULL) { WorkSpace *workspace = WM_window_get_active_workspace(win_prev); - WM_window_set_active_workspace(win, workspace); + BKE_workspace_active_set(win->workspace_hook, workspace); } if (screen == NULL) { @@ -904,7 +917,7 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i } /* In case we reuse an already existing temp window (see win lookup above). */ else if (WM_window_get_active_scene(win) != scene) { - WM_window_change_active_scene(bmain, C, win, scene); + WM_window_set_active_scene(bmain, C, win, scene); } screen->temp = 1; @@ -976,17 +989,25 @@ int wm_window_close_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -/* operator callback */ int wm_window_new_exec(bContext *C, wmOperator *UNUSED(op)) { wmWindow *win_src = CTX_wm_window(C); bool ok; - ok = (wm_window_copy_test(C, win_src, true) != NULL); + ok = (wm_window_copy_test(C, win_src, true, true) != NULL); return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } +int wm_window_new_main_exec(bContext *C, wmOperator *UNUSED(op)) +{ + wmWindow *win_src = CTX_wm_window(C); + bool ok; + + ok = (wm_window_copy_test(C, win_src, true, false) != NULL); + + return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; +} /* fullscreen operator callback */ int wm_window_fullscreen_toggle_exec(bContext *C, wmOperator *UNUSED(op)) @@ -2103,21 +2124,45 @@ Scene *WM_window_get_active_scene(const wmWindow *win) /** * \warning Only call outside of area/region loops */ -void WM_window_change_active_scene(Main *bmain, bContext *C, wmWindow *win, Scene *scene_new) +void WM_window_set_active_scene(Main *bmain, bContext *C, wmWindow *win, Scene *scene) { - const bScreen *screen = WM_window_get_active_screen(win); - Scene *scene_old = win->scene; + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win_parent = (win->parent) ? win->parent : win; - ED_scene_change_update(bmain, C, win, screen, scene_old, scene_new); + /* Set scene in parent and its child windows. */ + ED_screen_scene_change(C, win_parent, scene); + + for (wmWindow *win_child = wm->windows.first; win_child; win_child = win_child->next) { + if (win_child->parent == win_parent) { + ED_screen_scene_change(C, win_child, scene); + } + } + + /* Update depsgraph and renderers for scene change. */ + ViewLayer *view_layer = WM_window_get_active_view_layer(win_parent); + ED_scene_change_update(bmain, scene, view_layer); + + /* Complete redraw. */ + WM_event_add_notifier(C, NC_WINDOW, NULL); } WorkSpace *WM_window_get_active_workspace(const wmWindow *win) { return BKE_workspace_active_get(win->workspace_hook); } -void WM_window_set_active_workspace(wmWindow *win, WorkSpace *workspace) + +void WM_window_set_active_workspace(bContext *C, wmWindow *win, WorkSpace *workspace) { - BKE_workspace_active_set(win->workspace_hook, workspace); + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win_parent = (win->parent) ? win->parent : win; + + ED_workspace_change(workspace, C, wm, win); + + for (wmWindow *win_child = wm->windows.first; win_child; win_child = win_child->next) { + if (win_child->parent == win_parent) { + ED_workspace_change(workspace, C, wm, win_child); + } + } } WorkSpaceLayout *WM_window_get_active_layout(const wmWindow *win) diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index 952ffe5c117..385d61217ad 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -45,9 +45,9 @@ void wm_ghost_exit(void); void wm_get_screensize(int *r_width, int *r_height); void wm_get_desktopsize(int *r_width, int *r_height); -wmWindow *wm_window_new (bContext *C); -wmWindow *wm_window_copy (bContext *C, wmWindow *win_src, const bool duplicate_layout); -wmWindow *wm_window_copy_test (bContext *C, wmWindow *win_src, const bool duplicate_layout); +wmWindow *wm_window_new (bContext *C, wmWindow *parent); +wmWindow *wm_window_copy (bContext *C, wmWindow *win_src, const bool duplicate_layout, const bool child); +wmWindow *wm_window_copy_test (bContext *C, wmWindow *win_src, const bool duplicate_layout, const bool child); void wm_window_free (bContext *C, wmWindowManager *wm, wmWindow *win); void wm_window_close (bContext *C, wmWindowManager *wm, wmWindow *win); @@ -85,6 +85,7 @@ int wm_window_fullscreen_toggle_exec(bContext *C, struct wmOperator *op); void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win) ATTR_NONNULL(); int wm_window_new_exec(bContext *C, struct wmOperator *op); +int wm_window_new_main_exec(bContext *C, struct wmOperator *op); /* Initial (unmaximized) size to start with for * systems that can't find it for themselves (X11). |