Blender  V3.3
workspace.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include "BLI_listbase.h"
12 #include "BLI_string.h"
13 #include "BLI_string_utils.h"
14 #include "BLI_utildefines.h"
15 
16 #include "BLT_translation.h"
17 
18 #include "BKE_asset.h"
19 #include "BKE_global.h"
20 #include "BKE_idprop.h"
21 #include "BKE_idtype.h"
22 #include "BKE_lib_id.h"
23 #include "BKE_lib_query.h"
24 #include "BKE_main.h"
25 #include "BKE_object.h"
26 #include "BKE_scene.h"
27 #include "BKE_workspace.h"
28 
29 #include "DNA_object_types.h"
30 #include "DNA_scene_types.h"
31 #include "DNA_screen_types.h"
33 #include "DNA_workspace_types.h"
34 
35 #include "DEG_depsgraph.h"
36 
37 #include "MEM_guardedalloc.h"
38 
39 #include "BLO_read_write.h"
40 
41 /* -------------------------------------------------------------------- */
42 
43 static void workspace_init_data(ID *id)
44 {
45  WorkSpace *workspace = (WorkSpace *)id;
46 
48 }
49 
50 static void workspace_free_data(ID *id)
51 {
52  WorkSpace *workspace = (WorkSpace *)id;
53 
55 
56  BLI_freelistN(&workspace->owner_ids);
57  BLI_freelistN(&workspace->layouts);
58 
59  while (!BLI_listbase_is_empty(&workspace->tools)) {
60  BKE_workspace_tool_remove(workspace, workspace->tools.first);
61  }
62 
63  MEM_SAFE_FREE(workspace->status_text);
64 }
65 
67 {
68  WorkSpace *workspace = (WorkSpace *)id;
69 
71 
72  LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) {
74  }
75 }
76 
77 static void workspace_blend_write(BlendWriter *writer, ID *id, const void *id_address)
78 {
79  WorkSpace *workspace = (WorkSpace *)id;
80 
81  BLO_write_id_struct(writer, WorkSpace, id_address, &workspace->id);
82  BKE_id_blend_write(writer, &workspace->id);
83  BLO_write_struct_list(writer, WorkSpaceLayout, &workspace->layouts);
85  BLO_write_struct_list(writer, wmOwnerID, &workspace->owner_ids);
86  BLO_write_struct_list(writer, bToolRef, &workspace->tools);
87  LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
88  if (tref->properties) {
89  IDP_BlendWrite(writer, tref->properties);
90  }
91  }
92 }
93 
94 static void workspace_blend_read_data(BlendDataReader *reader, ID *id)
95 {
96  WorkSpace *workspace = (WorkSpace *)id;
97 
98  BLO_read_list(reader, &workspace->layouts);
99  BLO_read_list(reader, &workspace->hook_layout_relations);
100  BLO_read_list(reader, &workspace->owner_ids);
101  BLO_read_list(reader, &workspace->tools);
102 
104  /* Parent pointer does not belong to workspace data and is therefore restored in lib_link step
105  * of window manager. */
106  BLO_read_data_address(reader, &relation->value);
107  }
108 
109  LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
110  tref->runtime = NULL;
111  BLO_read_data_address(reader, &tref->properties);
112  IDP_BlendDataRead(reader, &tref->properties);
113  }
114 
115  workspace->status_text = NULL;
116 
117  id_us_ensure_real(&workspace->id);
118 }
119 
120 static void workspace_blend_read_lib(BlendLibReader *reader, ID *id)
121 {
122  WorkSpace *workspace = (WorkSpace *)id;
123  Main *bmain = BLO_read_lib_get_main(reader);
124 
125  /* Do not keep the scene reference when appending a workspace. Setting a scene for a workspace is
126  * a convenience feature, but the workspace should never truly depend on scene data. */
127  if (ID_IS_LINKED(id)) {
128  workspace->pin_scene = NULL;
129  }
130  else {
131  BLO_read_id_address(reader, NULL, &workspace->pin_scene);
132  }
133 
134  /* Restore proper 'parent' pointers to relevant data, and clean up unused/invalid entries. */
136  relation->parent = NULL;
137  LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) {
138  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
139  if (win->winid == relation->parentid) {
140  relation->parent = win->workspace_hook;
141  }
142  }
143  }
144  if (relation->parent == NULL) {
145  BLI_freelinkN(&workspace->hook_layout_relations, relation);
146  }
147  }
148 
149  LISTBASE_FOREACH_MUTABLE (WorkSpaceLayout *, layout, &workspace->layouts) {
150  BLO_read_id_address(reader, id->lib, &layout->screen);
151 
152  if (layout->screen) {
153  if (ID_IS_LINKED(id)) {
154  layout->screen->winid = 0;
155  if (layout->screen->temp) {
156  /* delete temp layouts when appending */
157  BKE_workspace_layout_remove(bmain, workspace, layout);
158  }
159  }
160  }
161  else {
162  /* If we're reading a layout without screen stored, it's useless and we shouldn't keep it
163  * around. */
164  BKE_workspace_layout_remove(bmain, workspace, layout);
165  }
166  }
167 }
168 
169 static void workspace_blend_read_expand(BlendExpander *expander, ID *id)
170 {
171  WorkSpace *workspace = (WorkSpace *)id;
172 
173  LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) {
174  BLO_expand(expander, BKE_workspace_layout_screen_get(layout));
175  }
176 }
177 
179  .id_code = ID_WS,
180  .id_filter = FILTER_ID_WS,
181  .main_listbase_index = INDEX_ID_WS,
182  .struct_size = sizeof(WorkSpace),
183  .name = "WorkSpace",
184  .name_plural = "workspaces",
185  .translation_context = BLT_I18NCONTEXT_ID_WORKSPACE,
187  .asset_type_info = NULL,
188 
190  .copy_data = NULL,
191  .free_data = workspace_free_data,
192  .make_local = NULL,
193  .foreach_id = workspace_foreach_id,
194  .foreach_cache = NULL,
195  .foreach_path = NULL,
196  .owner_get = NULL,
197 
198  .blend_write = workspace_blend_write,
199  .blend_read_data = workspace_blend_read_data,
200  .blend_read_lib = workspace_blend_read_lib,
201  .blend_read_expand = workspace_blend_read_expand,
202 
203  .blend_read_undo_preserve = NULL,
204 
205  .lib_override_apply_post = NULL,
206 };
207 
208 /* -------------------------------------------------------------------- */
212 static void workspace_layout_name_set(WorkSpace *workspace,
213  WorkSpaceLayout *layout,
214  const char *new_name)
215 {
216  BLI_strncpy(layout->name, new_name, sizeof(layout->name));
217  BLI_uniquename(&workspace->layouts,
218  layout,
219  "Layout",
220  '.',
221  offsetof(WorkSpaceLayout, name),
222  sizeof(layout->name));
223 }
224 
231  const bScreen *screen)
232 {
233  return BLI_findptr(&workspace->layouts, screen, offsetof(WorkSpaceLayout, screen));
234 }
235 
236 static void workspace_relation_add(ListBase *relation_list,
237  void *parent,
238  const int parentid,
239  void *data)
240 {
241  WorkSpaceDataRelation *relation = MEM_callocN(sizeof(*relation), __func__);
242  relation->parent = parent;
243  relation->parentid = parentid;
244  relation->value = data;
245  /* add to head, if we switch back to it soon we find it faster. */
246  BLI_addhead(relation_list, relation);
247 }
248 static void workspace_relation_remove(ListBase *relation_list, WorkSpaceDataRelation *relation)
249 {
250  BLI_remlink(relation_list, relation);
251  MEM_freeN(relation);
252 }
253 
254 static void workspace_relation_ensure_updated(ListBase *relation_list,
255  void *parent,
256  const int parentid,
257  void *data)
258 {
260  relation_list, &parentid, sizeof(parentid), offsetof(WorkSpaceDataRelation, parentid));
261  if (relation != NULL) {
262  relation->parent = parent;
263  relation->value = data;
264  /* reinsert at the head of the list, so that more commonly used relations are found faster. */
265  BLI_remlink(relation_list, relation);
266  BLI_addhead(relation_list, relation);
267  }
268  else {
269  /* no matching relation found, add new one */
270  workspace_relation_add(relation_list, parent, parentid, data);
271  }
272 }
273 
274 static void *workspace_relation_get_data_matching_parent(const ListBase *relation_list,
275  const void *parent)
276 {
278  relation_list, parent, offsetof(WorkSpaceDataRelation, parent));
279  if (relation != NULL) {
280  return relation->value;
281  }
282 
283  return NULL;
284 }
285 
292 #ifndef NDEBUG
294 #else
296 #endif
297  (const Main *bmain, bScreen *screen)
298 {
299  for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
300  if (workspace_layout_find_exec(workspace, screen)) {
301  return true;
302  }
303  }
304 
305  return false;
306 }
307 
310 /* -------------------------------------------------------------------- */
314 WorkSpace *BKE_workspace_add(Main *bmain, const char *name)
315 {
316  WorkSpace *new_workspace = BKE_id_new(bmain, ID_WS, name);
317  id_us_ensure_real(&new_workspace->id);
318  return new_workspace;
319 }
320 
321 void BKE_workspace_remove(Main *bmain, WorkSpace *workspace)
322 {
323  for (WorkSpaceLayout *layout = workspace->layouts.first, *layout_next; layout;
324  layout = layout_next) {
325  layout_next = layout->next;
326  BKE_workspace_layout_remove(bmain, workspace, layout);
327  }
328  BKE_id_free(bmain, workspace);
329 }
330 
332 {
333  WorkSpaceInstanceHook *hook = MEM_callocN(sizeof(WorkSpaceInstanceHook), __func__);
334 
335  /* set an active screen-layout for each possible window/workspace combination */
336  for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
337  BKE_workspace_active_layout_set(hook, winid, workspace, workspace->layouts.first);
338  }
339 
340  return hook;
341 }
343 {
344  /* workspaces should never be freed before wm (during which we call this function).
345  * However, when running in background mode, loading a blend file may allocate windows (that need
346  * to be freed) without creating workspaces. This happens in BlendfileLoadingBaseTest. */
347  BLI_assert(!BLI_listbase_is_empty(&bmain->workspaces) || G.background);
348 
349  /* Free relations for this hook */
350  for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
351  for (WorkSpaceDataRelation *relation = workspace->hook_layout_relations.first, *relation_next;
352  relation;
353  relation = relation_next) {
354  relation_next = relation->next;
355  if (relation->parent == hook) {
356  workspace_relation_remove(&workspace->hook_layout_relations, relation);
357  }
358  }
359  }
360 
361  MEM_freeN(hook);
362 }
363 
365  WorkSpace *workspace,
366  bScreen *screen,
367  const char *name)
368 {
369  WorkSpaceLayout *layout = MEM_callocN(sizeof(*layout), __func__);
370 
371  BLI_assert(!workspaces_is_screen_used(bmain, screen));
372 #ifndef DEBUG
373  UNUSED_VARS(bmain);
374 #endif
375  layout->screen = screen;
376  id_us_plus(&layout->screen->id);
377  workspace_layout_name_set(workspace, layout, name);
378  BLI_addtail(&workspace->layouts, layout);
379 
380  return layout;
381 }
382 
384 {
385  /* Screen should usually be set, but we call this from file reading to get rid of invalid
386  * layouts. */
387  if (layout->screen) {
388  id_us_min(&layout->screen->id);
389  BKE_id_free(bmain, layout->screen);
390  }
391  BLI_freelinkN(&workspace->layouts, layout);
392 }
393 
395 {
396  for (WorkSpaceDataRelation *relation = relation_list->first, *relation_next; relation;
397  relation = relation_next) {
398  relation_next = relation->next;
399  workspace_relation_remove(relation_list, relation);
400  }
401 }
402 
405 /* -------------------------------------------------------------------- */
410 {
411  WorkSpaceLayout *layout = workspace_layout_find_exec(workspace, screen);
412  if (layout) {
413  return layout;
414  }
415 
416  printf(
417  "%s: Couldn't find layout in this workspace: '%s' screen: '%s'. "
418  "This should not happen!\n",
419  __func__,
420  workspace->id.name + 2,
421  screen->id.name + 2);
422 
423  return NULL;
424 }
425 
427  const bScreen *screen,
428  WorkSpace **r_workspace)
429 {
430  WorkSpaceLayout *layout;
431 
432  if (r_workspace) {
433  *r_workspace = NULL;
434  }
435 
436  for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
437  if ((layout = workspace_layout_find_exec(workspace, screen))) {
438  if (r_workspace) {
439  *r_workspace = workspace;
440  }
441 
442  return layout;
443  }
444  }
445 
446  return NULL;
447 }
448 
450  WorkSpaceLayout *start,
451  bool (*callback)(const WorkSpaceLayout *layout,
452  void *arg),
453  void *arg,
454  const bool iter_backward)
455 {
456  WorkSpaceLayout *iter_layout;
457 
458  if (iter_backward) {
459  LISTBASE_CIRCULAR_BACKWARD_BEGIN (&workspace->layouts, iter_layout, start) {
460  if (!callback(iter_layout, arg)) {
461  return iter_layout;
462  }
463  }
464  LISTBASE_CIRCULAR_BACKWARD_END(&workspace->layouts, iter_layout, start);
465  }
466  else {
467  LISTBASE_CIRCULAR_FORWARD_BEGIN (&workspace->layouts, iter_layout, start) {
468  if (!callback(iter_layout, arg)) {
469  return iter_layout;
470  }
471  }
472  LISTBASE_CIRCULAR_FORWARD_END(&workspace->layouts, iter_layout, start);
473  }
474 
475  return NULL;
476 }
477 
478 void BKE_workspace_tool_remove(struct WorkSpace *workspace, struct bToolRef *tref)
479 {
480  if (tref->runtime) {
481  MEM_freeN(tref->runtime);
482  }
483  if (tref->properties) {
485  }
486  BLI_remlink(&workspace->tools, tref);
487  MEM_freeN(tref);
488 }
489 
490 bool BKE_workspace_owner_id_check(const WorkSpace *workspace, const char *owner_id)
491 {
492  if ((*owner_id == '\0') || ((workspace->flags & WORKSPACE_USE_FILTER_BY_ORIGIN) == 0)) {
493  return true;
494  }
495 
496  /* We could use hash lookup, for now this list is highly likely under < ~16 items. */
497  return BLI_findstring(&workspace->owner_ids, owner_id, offsetof(wmOwnerID, name)) != NULL;
498 }
499 
501 {
502  BKE_main_id_tag_listbase(&bmain->workspaces, tag, false);
503  wmWindowManager *wm = bmain->wm.first;
504  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
505  WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
506  workspace->id.tag |= tag;
507  }
508 }
509 
512 /* -------------------------------------------------------------------- */
517 {
518  return hook->active;
519 }
521 {
522  /* DO NOT check for `hook->active == workspace` here. Caller code is supposed to do it if
523  * that optimization is possible and needed.
524  * This code can be called from places where we might have this equality, but still want to
525  * ensure/update the active layout below.
526  * Known case where this is buggy and will crash later due to NULL active layout: reading
527  * a blend file, when the new read workspace ID happens to have the exact same memory address
528  * as when it was saved in the blend file (extremely unlikely, but possible). */
529 
530  hook->active = workspace;
531  if (workspace) {
533  &workspace->hook_layout_relations, hook);
534  if (layout) {
535  hook->act_layout = layout;
536  }
537  }
538 }
539 
541 {
542  return hook->act_layout;
543 }
544 
546  const WorkSpace *workspace)
547 {
548  /* If the workspace is active, the active layout can be returned, no need for a lookup. */
549  if (hook->active == workspace) {
550  return hook->act_layout;
551  }
552 
553  /* Inactive workspace */
555 }
556 
558  const int winid,
559  WorkSpace *workspace,
560  WorkSpaceLayout *layout)
561 {
562  hook->act_layout = layout;
564 }
565 
567 {
568  return hook->act_layout->screen;
569 }
571  const int winid,
572  WorkSpace *workspace,
573  bScreen *screen)
574 {
575  /* we need to find the WorkspaceLayout that wraps this screen */
576  WorkSpaceLayout *layout = BKE_workspace_layout_find(hook->active, screen);
577  BKE_workspace_active_layout_set(hook, winid, workspace, layout);
578 }
579 
581 {
582  return layout->name;
583 }
585  WorkSpaceLayout *layout,
586  const char *new_name)
587 {
588  workspace_layout_name_set(workspace, layout, new_name);
589 }
590 
592 {
593  return layout->screen;
594 }
595 
void BKE_asset_library_reference_init_default(struct AssetLibraryReference *library_ref)
Definition: asset.cc:99
void IDP_BlendWrite(struct BlendWriter *writer, const struct IDProperty *prop)
#define IDP_BlendDataRead(reader, prop)
Definition: BKE_idprop.h:321
void IDP_FreeProperty(struct IDProperty *prop)
Definition: idprop.c:1093
@ IDTYPE_FLAGS_NO_ANIMDATA
Definition: BKE_idtype.h:41
@ IDTYPE_FLAGS_ONLY_APPEND
Definition: BKE_idtype.h:36
@ IDTYPE_FLAGS_NO_COPY
Definition: BKE_idtype.h:30
void id_us_min(struct ID *id)
Definition: lib_id.c:313
void BKE_id_free(struct Main *bmain, void *idv)
void id_us_ensure_real(struct ID *id)
Definition: lib_id.c:260
void id_us_plus(struct ID *id)
Definition: lib_id.c:305
void BKE_id_blend_write(struct BlendWriter *writer, struct ID *id)
Definition: lib_id.c:2008
void * BKE_id_new(struct Main *bmain, short type, const char *name)
Definition: lib_id.c:1159
void BKE_main_id_tag_listbase(struct ListBase *lb, int tag, bool value)
Definition: lib_id.c:904
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(_data, _id_super, _cb_flag)
@ IDWALK_CB_USER
Definition: BKE_lib_query.h:73
@ IDWALK_CB_NOP
Definition: BKE_lib_query.h:33
General operations, lookup, etc. for blender objects.
#define BLI_assert(a)
Definition: BLI_assert.h:46
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:60
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:239
#define LISTBASE_CIRCULAR_FORWARD_BEGIN(lb, lb_iter, lb_init)
Definition: BLI_listbase.h:314
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:354
#define LISTBASE_CIRCULAR_FORWARD_END(lb, lb_iter, lb_init)
Definition: BLI_listbase.h:318
void * BLI_listbase_bytes_find(const ListBase *listbase, const void *bytes, size_t bytes_size, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
#define LISTBASE_CIRCULAR_BACKWARD_BEGIN(lb, lb_iter, lb_init)
Definition: BLI_listbase.h:325
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
#define LISTBASE_CIRCULAR_BACKWARD_END(lb, lb_iter, lb_init)
Definition: BLI_listbase.h:329
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findptr(const struct ListBase *listbase, const void *ptr, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
bool BLI_uniquename(struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_len)
Definition: string_utils.c:309
#define UNUSED_FUNCTION(x)
#define UNUSED_VARS(...)
#define BLO_read_data_address(reader, ptr_p)
struct Main * BLO_read_lib_get_main(BlendLibReader *reader)
Definition: readfile.c:5313
#define BLO_write_id_struct(writer, struct_name, id_address, id)
void BLO_read_list(BlendDataReader *reader, struct ListBase *list)
Definition: readfile.c:5172
#define BLO_read_id_address(reader, lib, id_ptr_p)
#define BLO_expand(expander, id)
#define BLO_write_struct_list(writer, struct_name, list_ptr)
#define BLT_I18NCONTEXT_ID_WORKSPACE
@ INDEX_ID_WS
Definition: DNA_ID.h:1053
#define FILTER_ID_WS
Definition: DNA_ID.h:928
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
@ ID_WS
Definition: DNA_ID_enums.h:79
Object is a sort of wrapper for general info.
@ WORKSPACE_USE_FILTER_BY_ORIGIN
struct WorkSpace WorkSpace
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
static void init_data(ModifierData *md)
DEGForeachIDComponentCallback callback
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define G(x, y, z)
short id_code
Definition: BKE_idtype.h:114
Definition: DNA_ID.h:368
int tag
Definition: DNA_ID.h:387
struct Library * lib
Definition: DNA_ID.h:372
void * next
Definition: DNA_ID.h:369
char name[66]
Definition: DNA_ID.h:378
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase wm
Definition: BKE_main.h:197
ListBase workspaces
Definition: BKE_main.h:203
struct WorkSpaceLayout * act_layout
Wrapper for bScreen.
struct bScreen * screen
AssetLibraryReference asset_library_ref
ListBase owner_ids
ListBase hook_layout_relations
struct Scene * pin_scene
IDProperty * properties
bToolRef_Runtime * runtime
int winid
Definition: wm_draw.c:134
bScreen * BKE_workspace_layout_screen_get(const WorkSpaceLayout *layout)
Definition: workspace.c:591
bScreen * BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook)
Definition: workspace.c:566
static void workspace_relation_ensure_updated(ListBase *relation_list, void *parent, const int parentid, void *data)
Definition: workspace.c:254
void BKE_workspace_tool_remove(struct WorkSpace *workspace, struct bToolRef *tref)
Definition: workspace.c:478
IDTypeInfo IDType_ID_WS
Definition: workspace.c:178
static void workspace_relation_remove(ListBase *relation_list, WorkSpaceDataRelation *relation)
Definition: workspace.c:248
static void workspace_blend_read_expand(BlendExpander *expander, ID *id)
Definition: workspace.c:169
static void workspace_free_data(ID *id)
Definition: workspace.c:50
static void workspace_layout_name_set(WorkSpace *workspace, WorkSpaceLayout *layout, const char *new_name)
Definition: workspace.c:212
static void workspace_blend_write(BlendWriter *writer, ID *id, const void *id_address)
Definition: workspace.c:77
static bool workspaces_is_screen_used(const Main *bmain, bScreen *screen)
Definition: workspace.c:297
WorkSpaceLayout * BKE_workspace_layout_add(Main *bmain, WorkSpace *workspace, bScreen *screen, const char *name)
Definition: workspace.c:364
void BKE_workspace_layout_remove(Main *bmain, WorkSpace *workspace, WorkSpaceLayout *layout)
Definition: workspace.c:383
static void workspace_foreach_id(ID *id, LibraryForeachIDData *data)
Definition: workspace.c:66
WorkSpace * BKE_workspace_active_get(WorkSpaceInstanceHook *hook)
Definition: workspace.c:516
bool BKE_workspace_owner_id_check(const WorkSpace *workspace, const char *owner_id)
Definition: workspace.c:490
WorkSpaceLayout * BKE_workspace_layout_iter_circular(const WorkSpace *workspace, WorkSpaceLayout *start, bool(*callback)(const WorkSpaceLayout *layout, void *arg), void *arg, const bool iter_backward)
Definition: workspace.c:449
void BKE_workspace_active_screen_set(WorkSpaceInstanceHook *hook, const int winid, WorkSpace *workspace, bScreen *screen)
Definition: workspace.c:570
static void * workspace_relation_get_data_matching_parent(const ListBase *relation_list, const void *parent)
Definition: workspace.c:274
WorkSpaceLayout * BKE_workspace_layout_find(const WorkSpace *workspace, const bScreen *screen)
Definition: workspace.c:409
WorkSpaceLayout * BKE_workspace_active_layout_for_workspace_get(const WorkSpaceInstanceHook *hook, const WorkSpace *workspace)
Definition: workspace.c:545
static void workspace_relation_add(ListBase *relation_list, void *parent, const int parentid, void *data)
Definition: workspace.c:236
void BKE_workspace_instance_hook_free(const Main *bmain, WorkSpaceInstanceHook *hook)
Definition: workspace.c:342
static WorkSpaceLayout * workspace_layout_find_exec(const WorkSpace *workspace, const bScreen *screen)
Definition: workspace.c:230
static void workspace_init_data(ID *id)
Definition: workspace.c:43
void BKE_workspace_active_set(WorkSpaceInstanceHook *hook, WorkSpace *workspace)
Definition: workspace.c:520
WorkSpaceLayout * BKE_workspace_active_layout_get(const WorkSpaceInstanceHook *hook)
Definition: workspace.c:540
void BKE_workspace_id_tag_all_visible(Main *bmain, int tag)
Definition: workspace.c:500
WorkSpaceInstanceHook * BKE_workspace_instance_hook_create(const Main *bmain, const int winid)
Definition: workspace.c:331
void BKE_workspace_relations_free(ListBase *relation_list)
Definition: workspace.c:394
void BKE_workspace_remove(Main *bmain, WorkSpace *workspace)
Definition: workspace.c:321
void BKE_workspace_active_layout_set(WorkSpaceInstanceHook *hook, const int winid, WorkSpace *workspace, WorkSpaceLayout *layout)
Activate a layout.
Definition: workspace.c:557
const char * BKE_workspace_layout_name_get(const WorkSpaceLayout *layout)
Definition: workspace.c:580
static void workspace_blend_read_data(BlendDataReader *reader, ID *id)
Definition: workspace.c:94
WorkSpaceLayout * BKE_workspace_layout_find_global(const Main *bmain, const bScreen *screen, WorkSpace **r_workspace)
Definition: workspace.c:426
static void workspace_blend_read_lib(BlendLibReader *reader, ID *id)
Definition: workspace.c:120
void BKE_workspace_layout_name_set(WorkSpace *workspace, WorkSpaceLayout *layout, const char *new_name)
Definition: workspace.c:584
WorkSpace * BKE_workspace_add(Main *bmain, const char *name)
Definition: workspace.c:314