[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