[Bf-blender-cvs] [3c1b955b4d] workspaces: Store active layout of each workspace per window

Julian Eisel noreply at git.blender.org
Thu Mar 16 18:51:00 CET 2017


Commit: 3c1b955b4d06e735dd7dd247d887e613c4b03bb4
Author: Julian Eisel
Date:   Thu Mar 16 18:43:51 2017 +0100
Branches: workspaces
https://developer.blender.org/rB3c1b955b4d06e735dd7dd247d887e613c4b03bb4

Store active layout of each workspace per window

Allows users having a different active window stored even in inactive
workspaces per window. So that when activating a workspace the layout
is activated that was active the last time the workspace was active in
this window.
This is basically a per window, per workspace storage, but it's probably
how users would expect things to work.

Also, getting file read/write to work correctly was a challenge once
again, had to use global oldnew-map for pointer lookup on file read.

And another 'also': had to change order in which IDs are freed, so that
workspaces are freed after window-manager. Needed so that we can free
assignments/relations correctly when closing windows.

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

M	source/blender/blenkernel/BKE_workspace.h
M	source/blender/blenkernel/intern/library.c
M	source/blender/blenkernel/intern/workspace.c
M	source/blender/blenloader/intern/readfile.c
M	source/blender/blenloader/intern/versioning_280.c
M	source/blender/blenloader/intern/writefile.c
M	source/blender/editors/workspace/screen_edit.c
M	source/blender/editors/workspace/screen_ops.c
M	source/blender/editors/workspace/workspace_edit.c
M	source/blender/makesdna/DNA_ID.h
M	source/blender/makesdna/dna_workspace_types.h
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/intern/wm.c
M	source/blender/windowmanager/intern/wm_files.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 6b59b4a31e..e26dc524d6 100644
--- a/source/blender/blenkernel/BKE_workspace.h
+++ b/source/blender/blenkernel/BKE_workspace.h
@@ -56,8 +56,8 @@ WorkSpace *BKE_workspace_add(struct Main *bmain, const char *name);
 void BKE_workspace_free(WorkSpace *ws);
 void BKE_workspace_remove(WorkSpace *workspace, struct Main *bmain);
 
-WorkSpaceInstanceHook *BKE_workspace_instance_hook_create(void);
-void BKE_workspace_instance_hook_free(WorkSpaceInstanceHook *hook);
+WorkSpaceInstanceHook *BKE_workspace_instance_hook_create(const struct Main *bmain);
+void BKE_workspace_instance_hook_free(WorkSpaceInstanceHook *hook, const struct Main *bmain);
 
 struct WorkSpaceLayout *BKE_workspace_layout_add(WorkSpace *workspace, struct bScreen *screen, const char *name) ATTR_NONNULL();
 void BKE_workspace_layout_remove(WorkSpace *workspace, WorkSpaceLayout *layout, struct Main *bmain) ATTR_NONNULL();
@@ -99,10 +99,16 @@ WorkSpace *BKE_workspace_active_get(WorkSpaceInstanceHook *hook) ATTR_NONNULL()
 void       BKE_workspace_active_set(WorkSpaceInstanceHook *hook, WorkSpace *workspace) ATTR_NONNULL(1);
 struct ID *BKE_workspace_id_get(WorkSpace *workspace);
 const char *BKE_workspace_name_get(const WorkSpace *workspace);
+WorkSpaceLayout *BKE_workspace_active_layout_get_from_workspace(
+        const WorkSpaceInstanceHook *hook, const WorkSpace *workspace) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
 WorkSpaceLayout *BKE_workspace_active_layout_get(const WorkSpaceInstanceHook *hook) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
-void             BKE_workspace_active_layout_set(WorkSpaceInstanceHook *hook, WorkSpaceLayout *layout) ATTR_NONNULL(1);
+void             BKE_workspace_active_layout_set(
+        WorkSpaceInstanceHook *hook, WorkSpaceLayout *layout) ATTR_NONNULL(1);
+void BKE_workspace_active_layout_set_for_workspace(
+        WorkSpaceInstanceHook *hook, WorkSpace *workspace, WorkSpaceLayout *layout) ATTR_NONNULL(1);
 struct bScreen *BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
-void            BKE_workspace_active_screen_set(WorkSpaceInstanceHook *hook, struct bScreen *screen) ATTR_NONNULL(1);
+void            BKE_workspace_active_screen_set(
+        WorkSpaceInstanceHook *hook, struct WorkSpace *workspace, struct bScreen *screen) ATTR_NONNULL(1);
 enum ObjectMode BKE_workspace_object_mode_get(const WorkSpace *workspace) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
 #ifdef USE_WORKSPACE_MODE
 void            BKE_workspace_object_mode_set(WorkSpace *workspace, const enum ObjectMode mode) ATTR_NONNULL();
@@ -123,6 +129,11 @@ void            BKE_workspace_layout_screen_set(WorkSpaceLayout *layout, struct
 WorkSpaceLayout *BKE_workspace_layout_next_get(const WorkSpaceLayout *layout) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
 WorkSpaceLayout *BKE_workspace_layout_prev_get(const WorkSpaceLayout *layout) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
 
+struct ListBase *BKE_workspace_hook_layout_assignments_get(WorkSpace *workspace) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+struct WorkSpaceDataAssignment *BKE_workspace_assignment_next_get(const struct WorkSpaceDataAssignment *assignment) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+void BKE_workspace_assignment_data_get(const struct WorkSpaceDataAssignment *assignment, void **parent, void **data) ATTR_NONNULL();
+void BKE_workspace_assignment_data_set(struct WorkSpaceDataAssignment *assignment, void *parent, void *data) ATTR_NONNULL();
+
 /* -------------------------------------------------------------------- */
 /* Don't use outside of BKE! */
 
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 46dbc7f40b..4bec08bbc0 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -840,9 +840,9 @@ int set_listbasepointers(Main *main, ListBase **lb)
 	lb[INDEX_ID_OB]  = &(main->object);
 	lb[INDEX_ID_LS]  = &(main->linestyle); /* referenced by scenes */
 	lb[INDEX_ID_SCE] = &(main->scene);
+	lb[INDEX_ID_WS]  = &(main->workspaces); /* before wm, so it's freed after it! */
 	lb[INDEX_ID_WM]  = &(main->wm);
 	lb[INDEX_ID_MSK] = &(main->mask);
-	lb[INDEX_ID_WS]  = &(main->workspaces);
 
 	lb[INDEX_ID_NULL] = NULL;
 
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
index bb4dabc876..7da4aa701c 100644
--- a/source/blender/blenkernel/intern/workspace.c
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -56,6 +56,47 @@ static void workspace_name_set(WorkSpace *workspace, WorkSpaceLayout *layout, co
 	BLI_uniquename(&workspace->layouts, layout, "Layout", '.', offsetof(WorkSpaceLayout, name), sizeof(layout->name));
 }
 
+static void workspace_assignment_add(ListBase *assignment_list, void *parent, void *data)
+{
+	WorkSpaceDataAssignment *assignment = MEM_mallocN(sizeof(*assignment), __func__);
+	assignment->parent = parent;
+	assignment->value = data;
+	/* add to head, if we switch back to it soon we find it faster. */
+	BLI_addhead(assignment_list, assignment);
+}
+static void workspace_assignment_remove(ListBase *assignment_list, WorkSpaceDataAssignment *assignment)
+{
+	BLI_remlink(assignment_list, assignment);
+	MEM_freeN(assignment);
+}
+
+static void workspace_ensure_updated_assignment(ListBase *assignment_list, void *parent, void *data)
+{
+	for (WorkSpaceDataAssignment *assignment = assignment_list->first; assignment; assignment = assignment->next) {
+		if (assignment->parent == parent) {
+			assignment->value = data;
+			/* reinsert at the head of the list, so that more commonly used assignments are found faster. */
+			BLI_remlink(assignment_list, assignment);
+			BLI_addhead(assignment_list, assignment);
+			return;
+		}
+	}
+
+	/* no matching assignment found, add new one */
+	workspace_assignment_add(assignment_list, parent, data);
+}
+
+static void *workspace_assignment_get_data_matching_parent(const ListBase *assignment_list, const void *parent)
+{
+	for (WorkSpaceDataAssignment *assignment = assignment_list->first; assignment; assignment = assignment->next) {
+		if (assignment->parent == parent) {
+			return assignment->value;
+		}
+	}
+
+	return NULL;
+}
+
 
 /* -------------------------------------------------------------------- */
 /* Create, delete, init */
@@ -74,9 +115,16 @@ WorkSpace *BKE_workspace_add(Main *bmain, const char *name)
 	return new_ws;
 }
 
-void BKE_workspace_free(WorkSpace *ws)
+void BKE_workspace_free(WorkSpace *workspace)
 {
-	BLI_freelistN(&ws->layouts);
+	for (WorkSpaceDataAssignment *assignment = workspace->hook_layout_assignments.first, *assignment_next;
+	     assignment;
+	     assignment = assignment_next)
+	{
+		assignment_next = assignment->next;
+		workspace_assignment_remove(&workspace->hook_layout_assignments, assignment);
+	}
+	BLI_freelistN(&workspace->layouts);
 }
 
 void BKE_workspace_remove(WorkSpace *workspace, Main *bmain)
@@ -90,12 +138,40 @@ void BKE_workspace_remove(WorkSpace *workspace, Main *bmain)
 	BKE_libblock_free(bmain, workspace);
 }
 
-WorkSpaceInstanceHook *BKE_workspace_instance_hook_create(void)
+WorkSpaceInstanceHook *BKE_workspace_instance_hook_create(const Main *bmain)
 {
-	return MEM_callocN(sizeof(WorkSpaceInstanceHook), __func__);
+	WorkSpaceInstanceHook *hook = MEM_callocN(sizeof(WorkSpaceInstanceHook), __func__);
+
+	/* set an active screen-layout for each possible window/workspace combination */
+	BKE_workspace_iter_begin(workspace_iter, bmain->workspaces.first)
+	{
+		BLI_assert(BLI_listbase_count(&workspace_iter->layouts) == 1);
+		BKE_workspace_active_layout_set_for_workspace(hook, workspace_iter, workspace_iter->layouts.first);
+	}
+	BKE_workspace_iter_end;
+
+	return hook;
 }
-void BKE_workspace_instance_hook_free(WorkSpaceInstanceHook *hook)
+void BKE_workspace_instance_hook_free(WorkSpaceInstanceHook *hook, const Main *bmain)
 {
+	/* workspaces should never be freed before wm (during which we call this function) */
+	BLI_assert(!BLI_listbase_is_empty(&bmain->workspaces));
+
+	/* Free assignments for this hook */
+	BKE_workspace_iter_begin(workspace, bmain->workspaces.first)
+	{
+		for (WorkSpaceDataAssignment *assignment = workspace->hook_layout_assignments.first, *assignment_next;
+		     assignment;
+		     assignment = assignment_next)
+		{
+			assignment_next = assignment->next;
+			if (assignment->parent == hook) {
+				workspace_assignment_remove(&workspace->hook_layout_assignments, assignment);
+			}
+		}
+	}
+	BKE_workspace_iter_end;
+
 	MEM_freeN(hook);
 }
 
@@ -231,6 +307,12 @@ WorkSpace *BKE_workspace_active_get(WorkSpaceInstanceHook *hook)
 void BKE_workspace_active_set(WorkSpaceInstanceHook *hook, WorkSpace *workspace)
 {
 	hook->active = workspace;
+	if (workspace) {
+		WorkSpaceLayout *layout;
+		if ((layout = workspace_assignment_get_data_matching_parent(&workspace->hook_layout_assignments, hook))) {
+			hook->act_layout = layout;
+		}
+	}
 }
 
 ID *BKE_workspace_id_get(WorkSpace *workspace)
@@ -243,6 +325,11 @@ const char *BKE_workspace_name_get(const WorkSpace *workspace)
 	return workspace->id.name + 2;
 }
 
+WorkSpaceLayout *BKE_workspace_active_layout_get_from_workspace(
+        const WorkSpaceInstanceHook *hook, const WorkSpace *workspace)
+{
+	return workspace_assignment_get_data_matching_parent(&workspace->hook_layout_assignments, hook);
+}
 WorkSpaceLayout *BKE_workspace_active_layout_get(const WorkSpaceInstanceHook *hook)
 {
 	return hook->act_layout;
@@ -252,6 +339,13 @@ void BKE_workspace_active_layout_set(WorkSpaceInstanceHook *hook, WorkSpaceLayou
 	hook->act_layout = layout;
 }
 
+void BKE_workspace_active_layout_set_for_workspace(
+        WorkSpaceInstanceHook *hook, WorkSpace *workspace, WorkSpaceLayout *layout)
+{
+	hook->act_layout = layout;
+	workspace_ensure_updated_assignment(&workspace->hook_layout_assignments, hook, layout);
+}
+
 WorkSpaceLayout *BKE_workspace_temp_layout_store_get(const WorkSpaceInstanceHook *hook)
 {
 	return hook->temp_layout_store;
@@ -265,10 +359,11 @@ bScreen *BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook)
 {
 	return hook->act_layout->screen;
 }
-void BKE_w

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list