[Bf-blender-cvs] [436c1e0] workspaces: Make duplicating workspaces work

Julian Eisel noreply at git.blender.org
Sun Dec 4 23:10:13 CET 2016


Commit: 436c1e0221e8d1ab1d716c6f305d374239dcc110
Author: Julian Eisel
Date:   Sun Dec 4 23:08:41 2016 +0100
Branches: workspaces
https://developer.blender.org/rB436c1e0221e8d1ab1d716c6f305d374239dcc110

Make duplicating workspaces work

===================================================================

M	source/blender/blenkernel/BKE_workspace.h
M	source/blender/blenkernel/intern/workspace.c
M	source/blender/editors/include/ED_screen.h
M	source/blender/editors/screen/workspace_edit.c
M	source/blender/windowmanager/intern/wm_window.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_workspace.h b/source/blender/blenkernel/BKE_workspace.h
index fc80936..861fffd 100644
--- a/source/blender/blenkernel/BKE_workspace.h
+++ b/source/blender/blenkernel/BKE_workspace.h
@@ -35,7 +35,7 @@ struct WorkSpace;
 /* Create, delete, init */
 
 struct WorkSpace *BKE_workspace_add(Main *bmain, const char *name);
-struct WorkSpace *BKE_workspace_duplicate(Main *bmain, const struct WorkSpace *from);
+struct WorkSpace *BKE_workspace_duplicate(Main *bmain, const struct WorkSpace *from, struct bScreen *act_screen);
 void BKE_workspace_free(struct WorkSpace *ws);
 
 
@@ -44,6 +44,8 @@ void BKE_workspace_free(struct WorkSpace *ws);
 
 struct WorkSpaceLayout *BKE_workspace_layout_find(
         const struct WorkSpace *ws, const struct bScreen *screen) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+struct WorkSpaceLayout *BKE_workspace_layout_find_exec(
+        const struct WorkSpace *ws, const struct bScreen *screen) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
 
 
 /* -------------------------------------------------------------------- */
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
index c79c8dd..e592223 100644
--- a/source/blender/blenkernel/intern/workspace.c
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -35,6 +35,9 @@
 #include "MEM_guardedalloc.h"
 
 
+static bool workspaces_is_screen_used(const Main *bmain, bScreen *screen);
+
+
 /* -------------------------------------------------------------------- */
 /* Create, delete, init */
 
@@ -44,9 +47,21 @@ WorkSpace *BKE_workspace_add(Main *bmain, const char *name)
 	return new_ws;
 }
 
-WorkSpace *BKE_workspace_duplicate(Main *bmain, const WorkSpace *from)
+/**
+ * \param act_screen: Screen that will be assigned to the active layout. Note that it shouldn't be used by
+ *                    any other workspace and that the caller is responsible for actually setting it up.
+ */
+WorkSpace *BKE_workspace_duplicate(Main *bmain, const WorkSpace *from, bScreen *act_screen)
 {
 	WorkSpace *new_ws = BKE_libblock_alloc(bmain, ID_WS, from->id.name + 2);
+	WorkSpaceLayout *layout = MEM_mallocN(sizeof(*layout), __func__);
+
+	BLI_assert(!workspaces_is_screen_used(bmain, act_screen));
+
+	new_ws->act_layout = layout;
+	new_ws->act_layout->screen = act_screen;
+	BLI_addhead(&new_ws->layouts, layout);
+
 	return new_ws;
 }
 
@@ -59,7 +74,28 @@ void BKE_workspace_free(WorkSpace *ws)
 /* -------------------------------------------------------------------- */
 /* General Utils */
 
-WorkSpaceLayout *BKE_workspace_layout_find(const WorkSpace *ws, const bScreen *screen)
+/**
+ * Checks if \a screen is already used within any workspace. A screen should never be assigned to multiple
+ * WorkSpaceLayouts, but that should be ensured outside of the BKE_workspace module and without such checks.
+ * Hence, this should only be used as assert check before assigining a screen to a workflow.
+ */
+static bool workspaces_is_screen_used(const Main *bmain, bScreen *screen)
+{
+	for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
+		if (BKE_workspace_layout_find_exec(workspace, screen)) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/**
+ * This should only be used directly when it is to be expected that there isn't
+ * a layout within \a workspace that wraps \a screen. Usually - especially outside
+ * of BKE_workspace - #BKE_workspace_layout_find should be used!
+ */
+WorkSpaceLayout *BKE_workspace_layout_find_exec(const WorkSpace *ws, const bScreen *screen)
 {
 	for (WorkSpaceLayout *layout = ws->layouts.first; layout; layout = layout->next) {
 		if (layout->screen == screen) {
@@ -67,6 +103,16 @@ WorkSpaceLayout *BKE_workspace_layout_find(const WorkSpace *ws, const bScreen *s
 		}
 	}
 
+	return NULL;
+}
+
+WorkSpaceLayout *BKE_workspace_layout_find(const WorkSpace *ws, const bScreen *screen)
+{
+	WorkSpaceLayout *layout = BKE_workspace_layout_find_exec(ws, screen);
+	if (layout) {
+		return layout;
+	}
+
 	BLI_assert(!"Couldn't find layout in this workspace. This should not happen!");
 	return NULL;
 }
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index d9947d5..42b2399 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -125,6 +125,7 @@ void    ED_screen_preview_render(const struct bScreen *screen, int size_x, int s
 
 /* workspaces */
 bool ED_workspace_change(struct bContext *C, struct wmWindow *win, WorkSpace *ws_new) ATTR_NONNULL();
+WorkSpace *ED_workspace_duplicate(struct Main *bmain, struct wmWindow *win);
 bool ED_workspace_delete(struct Main *bmain, struct bContext *C, struct wmWindow *win, WorkSpace *ws);
 
 /* anim */
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index 91466d3..30fb5ea 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -76,6 +76,22 @@ bool ED_workspace_change(bContext *C, wmWindow *win, WorkSpace *ws_new)
 }
 
 /**
+ * Duplicate a workspace including its active screen (since two workspaces can't show the same screen).
+ */
+WorkSpace *ED_workspace_duplicate(Main *bmain, wmWindow *win)
+{
+	bScreen *old_screen = WM_window_get_active_screen(win);
+	bScreen *new_screen = ED_screen_duplicate(win, old_screen);
+	WorkSpace *old_ws = win->workspace;
+
+	new_screen->winid = win->winid;
+	new_screen->do_refresh = true;
+	new_screen->do_draw = true;
+
+	return BKE_workspace_duplicate(bmain, old_ws, new_screen);
+}
+
+/**
  * \return if succeeded.
  */
 bool ED_workspace_delete(Main *bmain, bContext *C, wmWindow *win, WorkSpace *ws)
@@ -104,10 +120,10 @@ static int workspace_new_exec(bContext *C, wmOperator *UNUSED(op))
 {
 	Main *bmain = CTX_data_main(C);
 	wmWindow *win = CTX_wm_window(C);
-	WorkSpace *old_ws = win->workspace;
-	WorkSpace *new_ws = BKE_workspace_duplicate(bmain, old_ws);
+	WorkSpace *workspace;
 
-	ED_workspace_change(C, win, new_ws);
+	workspace = ED_workspace_duplicate(bmain, win);
+	WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, workspace);
 
 	return OPERATOR_FINISHED;
 }
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 6ca7a8d..8d5ec7e 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -249,6 +249,7 @@ wmWindow *wm_window_new(bContext *C)
 /* part of wm_window.c api */
 wmWindow *wm_window_copy(bContext *C, wmWindow *win_src)
 {
+	Main *bmain = CTX_data_main(C);
 	wmWindow *win_dst = wm_window_new(C);
 	bScreen *new_screen;
 
@@ -257,15 +258,9 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *win_src)
 	win_dst->sizex = win_src->sizex;
 	win_dst->sizey = win_src->sizey;
 
-	/* duplicate assigns to window */
-	new_screen = ED_screen_duplicate(win_dst, WM_window_get_active_screen(win_src));
-	WM_window_set_active_screen(win_dst, new_screen);
+	win_dst->workspace = ED_workspace_duplicate(bmain, win_dst);
+	new_screen = WM_window_get_active_screen(win_dst);
 	BLI_strncpy(win_dst->screenname, new_screen->id.name + 2, sizeof(win_dst->screenname));
-	new_screen->winid = win_dst->winid;
-	win_dst->workspace = BKE_workspace_duplicate(CTX_data_main(C), win_src->workspace);
-
-	new_screen->do_refresh = true;
-	new_screen->do_draw = true;
 
 	win_dst->drawmethod = U.wmdrawmethod;




More information about the Bf-blender-cvs mailing list