[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