diff options
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 15 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_types.h | 11 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm.c | 8 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_draw.c | 69 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 105 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_files.c | 72 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_files_link.c | 60 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_init_exit.c | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 9 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_stereo.c | 15 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_subwindow.c | 4 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_window.c | 244 | ||||
-rw-r--r-- | source/blender/windowmanager/wm_files.h | 1 | ||||
-rw-r--r-- | source/blender/windowmanager/wm_window.h | 4 |
14 files changed, 461 insertions, 158 deletions
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 80170d70dbd..6fa9429d04f 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -102,6 +102,21 @@ int WM_window_pixels_x (struct wmWindow *win); int WM_window_pixels_y (struct wmWindow *win); bool WM_window_is_fullscreen (struct wmWindow *win); +void WM_windows_scene_data_sync(const ListBase *win_lb, struct Scene *scene) ATTR_NONNULL(); +struct Scene *WM_windows_scene_get_from_screen(const struct wmWindowManager *wm, const struct bScreen *screen) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; + +struct Scene *WM_window_get_active_scene(const struct wmWindow *win) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; +void WM_window_change_active_scene(struct Main *bmain, struct bContext *C, struct wmWindow *win, + struct Scene *scene_new) ATTR_NONNULL(); +struct WorkSpace *WM_window_get_active_workspace(const struct wmWindow *win) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; +void WM_window_set_active_workspace(struct wmWindow *win, struct WorkSpace *workspace) ATTR_NONNULL(1); +struct WorkSpaceLayout *WM_window_get_active_layout(const struct wmWindow *win) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; +void WM_window_set_active_layout( + struct wmWindow *win, struct WorkSpace *workspace, struct WorkSpaceLayout *layout) ATTR_NONNULL(1); +struct bScreen *WM_window_get_active_screen(const struct wmWindow *win) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; +void WM_window_set_active_screen(struct wmWindow *win, struct WorkSpace *workspace, struct bScreen *screen) ATTR_NONNULL(1); +bool WM_window_is_temp_screen(const struct wmWindow *win) ATTR_WARN_UNUSED_RESULT; + /* defines for 'type' WM_window_open_temp */ enum { WM_WINDOW_RENDER = 1, diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 84209a0e3c8..756a9d6a1d1 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -224,7 +224,7 @@ typedef struct wmNotifier { #define NOTE_CATEGORY 0xFF000000 #define NC_WM (1<<24) #define NC_WINDOW (2<<24) -#define NC_SCREEN (3<<24) +#define NC_SCREEN (3<<24) #define NC_SCENE (4<<24) #define NC_OBJECT (5<<24) #define NC_MATERIAL (6<<24) @@ -258,15 +258,16 @@ typedef struct wmNotifier { #define ND_JOB (5<<16) #define ND_UNDO (6<<16) - /* NC_SCREEN screen */ -#define ND_SCREENBROWSE (1<<16) -#define ND_SCREENDELETE (2<<16) + /* NC_SCREEN */ +#define ND_LAYOUTBROWSE (1<<16) +#define ND_LAYOUTDELETE (2<<16) #define ND_SCREENCAST (3<<16) #define ND_ANIMPLAY (4<<16) #define ND_GPENCIL (5<<16) #define ND_EDITOR_CHANGED (6<<16) /*sent to new editors after switching to them*/ -#define ND_SCREENSET (7<<16) +#define ND_LAYOUTSET (7<<16) #define ND_SKETCH (8<<16) +#define ND_WORKSPACE_SET (9<<16) /* NC_SCENE Scene */ #define ND_SCENEBROWSE (1<<16) diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index d0522fdd7d4..af275394fcb 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -433,10 +433,12 @@ void wm_add_default(bContext *C) wmWindowManager *wm = BKE_libblock_alloc(CTX_data_main(C), ID_WM, "WinMan"); wmWindow *win; bScreen *screen = CTX_wm_screen(C); /* XXX from file read hrmf */ - + struct WorkSpace *workspace = G.main->workspaces.last; + CTX_wm_manager_set(C, wm); win = wm_window_new(C); - win->screen = screen; + WM_window_set_active_workspace(win, workspace); + WM_window_set_active_screen(win, workspace, screen); screen->winid = win->winid; BLI_strncpy(win->screenname, screen->id.name + 2, sizeof(win->screenname)); @@ -457,7 +459,7 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm) wm_autosave_timer_ended(wm); while ((win = BLI_pophead(&wm->windows))) { - win->screen = NULL; /* prevent draw clear to use screen */ + WM_window_set_active_workspace(win, NULL); /* prevent draw clear to use screen */ wm_draw_window_clear(win); wm_window_free(C, wm, win); } diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 3c176912409..5be3429f2de 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -87,7 +87,7 @@ static void wm_paintcursor_draw(bContext *C, ARegion *ar) if (wm->paintcursors.first) { wmWindow *win = CTX_wm_window(C); - bScreen *screen = win->screen; + bScreen *screen = WM_window_get_active_screen(win); wmPaintCursor *pc; if (ar->swinid && screen->subwinactive == ar->swinid) { @@ -130,7 +130,7 @@ static bool wm_area_test_invalid_backbuf(ScrArea *sa) return true; } -static void wm_region_test_render_do_draw(bScreen *screen, ScrArea *sa, ARegion *ar) +static void wm_region_test_render_do_draw(const Scene *scene, ScrArea *sa, ARegion *ar) { /* tag region for redraw from render engine preview running inside of it */ if (sa->spacetype == SPACE_VIEW3D) { @@ -138,7 +138,6 @@ static void wm_region_test_render_do_draw(bScreen *screen, ScrArea *sa, ARegion RenderEngine *engine = (rv3d) ? rv3d->render_engine : NULL; if (engine && (engine->flag & RE_ENGINE_DO_DRAW)) { - Scene *scene = screen->scene; View3D *v3d = sa->spacedata.first; rcti border_rect; @@ -158,7 +157,7 @@ static void wm_region_test_render_do_draw(bScreen *screen, ScrArea *sa, ARegion static void wm_method_draw_full(bContext *C, wmWindow *win) { - bScreen *screen = win->screen; + bScreen *screen = WM_window_get_active_screen(win); ScrArea *sa; ARegion *ar; @@ -181,7 +180,7 @@ static void wm_method_draw_full(bContext *C, wmWindow *win) } ED_screen_draw(win); - win->screen->do_draw = false; + screen->do_draw = false; /* draw overlapping regions */ for (ar = screen->regionbase.first; ar; ar = ar->next) { @@ -237,7 +236,7 @@ static void wm_flush_regions_up(bScreen *screen, rcti *dirty) static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange) { wmWindowManager *wm = CTX_wm_manager(C); - bScreen *screen = win->screen; + bScreen *screen = WM_window_get_active_screen(win); ScrArea *sa; ARegion *ar; static rcti rect = {0, 0, 0, 0}; @@ -318,7 +317,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange) /* after area regions so we can do area 'overlay' drawing */ if (screen->do_draw) { ED_screen_draw(win); - win->screen->do_draw = false; + screen->do_draw = false; if (exchange) screen->swap = WIN_FRONT_OK; @@ -326,7 +325,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange) else if (exchange) { if (screen->swap == WIN_FRONT_OK) { ED_screen_draw(win); - win->screen->do_draw = false; + screen->do_draw = false; screen->swap = WIN_BOTH_OK; } else if (screen->swap == WIN_BACK_OK) @@ -500,7 +499,9 @@ static void wm_draw_region_blend(wmWindow *win, ARegion *ar, wmDrawTriple *tripl /* region blend always is 1, except when blend timer is running */ if (fac < 1.0f) { - wmSubWindowScissorSet(win, win->screen->mainwin, &ar->winrct, true); + bScreen *screen = WM_window_get_active_screen(win); + + wmSubWindowScissorSet(win, screen->mainwin, &ar->winrct, true); glEnable(GL_BLEND); wm_triple_draw_textures(win, triple, 1.0f - fac); @@ -512,7 +513,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win) { wmWindowManager *wm = CTX_wm_manager(C); wmDrawData *dd, *dd_next, *drawdata = win->drawdata.first; - bScreen *screen = win->screen; + bScreen *screen = WM_window_get_active_screen(win); ScrArea *sa; ARegion *ar; bool copytex = false; @@ -620,7 +621,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win) /* after area regions so we can do area 'overlay' drawing */ ED_screen_draw(win); - win->screen->do_draw = false; + WM_window_get_active_screen(win)->do_draw = false; /* draw floating regions (menus) */ for (ar = screen->regionbase.first; ar; ar = ar->next) { @@ -647,7 +648,7 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, StereoVi wmWindowManager *wm = CTX_wm_manager(C); wmDrawData *drawdata; wmDrawTriple *triple_data, *triple_all; - bScreen *screen = win->screen; + bScreen *screen = WM_window_get_active_screen(win); ScrArea *sa; ARegion *ar; int copytex = false; @@ -793,7 +794,7 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, StereoVi /* after area regions so we can do area 'overlay' drawing */ ED_screen_draw(win); if (sview == STEREO_RIGHT_ID) - win->screen->do_draw = false; + screen->do_draw = false; /* draw floating regions (menus) */ for (ar = screen->regionbase.first; ar; ar = ar->next) { @@ -825,11 +826,13 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, StereoVi /* quick test to prevent changing window drawable */ static bool wm_draw_update_test_window(wmWindow *win) { + const Scene *scene = WM_window_get_active_scene(win); + const bScreen *screen = WM_window_get_active_screen(win); ScrArea *sa; ARegion *ar; bool do_draw = false; - for (ar = win->screen->regionbase.first; ar; ar = ar->next) { + for (ar = screen->regionbase.first; ar; ar = ar->next) { if (ar->do_draw_overlay) { wm_tag_redraw_overlay(win, ar); ar->do_draw_overlay = false; @@ -838,9 +841,9 @@ static bool wm_draw_update_test_window(wmWindow *win) do_draw = true; } - for (sa = win->screen->areabase.first; sa; sa = sa->next) { + for (sa = screen->areabase.first; sa; sa = sa->next) { for (ar = sa->regionbase.first; ar; ar = ar->next) { - wm_region_test_render_do_draw(win->screen, sa, ar); + wm_region_test_render_do_draw(scene, sa, ar); if (ar->swinid && ar->do_draw) do_draw = true; @@ -850,15 +853,15 @@ static bool wm_draw_update_test_window(wmWindow *win) if (do_draw) return true; - if (win->screen->do_refresh) + if (screen->do_refresh) return true; - if (win->screen->do_draw) + if (screen->do_draw) return true; - if (win->screen->do_draw_gesture) + if (screen->do_draw_gesture) return true; - if (win->screen->do_draw_paintcursor) + if (screen->do_draw_paintcursor) return true; - if (win->screen->do_draw_drag) + if (screen->do_draw_drag) return true; return false; @@ -899,15 +902,18 @@ void wm_tag_redraw_overlay(wmWindow *win, ARegion *ar) { /* for draw triple gestures, paint cursors don't need region redraw */ if (ar && win) { + bScreen *screen = WM_window_get_active_screen(win); + if (wm_automatic_draw_method(win) != USER_DRAW_TRIPLE) ED_region_tag_redraw(ar); - win->screen->do_draw_paintcursor = true; + screen->do_draw_paintcursor = true; } } void WM_paint_cursor_tag_redraw(wmWindow *win, ARegion *ar) { - win->screen->do_draw_paintcursor = true; + bScreen *screen = WM_window_get_active_screen(win); + screen->do_draw_paintcursor = true; wm_tag_redraw_overlay(win, ar); } @@ -941,13 +947,15 @@ void wm_draw_update(bContext *C) } if (wm_draw_update_test_window(win)) { + bScreen *screen = WM_window_get_active_screen(win); + CTX_wm_window_set(C, win); /* sets context window+screen */ wm_window_make_drawable(wm, win); /* notifiers for screen redraw */ - if (win->screen->do_refresh) + if (screen->do_refresh) ED_screen_refresh(wm, win); int drawmethod = wm_automatic_draw_method(win); @@ -971,9 +979,9 @@ void wm_draw_update(bContext *C) } } - win->screen->do_draw_gesture = false; - win->screen->do_draw_paintcursor = false; - win->screen->do_draw_drag = false; + screen->do_draw_gesture = false; + screen->do_draw_paintcursor = false; + screen->do_draw_drag = false; wm_window_swap_buffers(win); @@ -994,7 +1002,7 @@ void wm_draw_data_free(wmWindow *win) void wm_draw_window_clear(wmWindow *win) { - bScreen *screen = win->screen; + bScreen *screen = WM_window_get_active_screen(win); ScrArea *sa; ARegion *ar; @@ -1012,12 +1020,13 @@ void wm_draw_window_clear(wmWindow *win) void wm_draw_region_clear(wmWindow *win, ARegion *ar) { + bScreen *screen = WM_window_get_active_screen(win); int drawmethod = wm_automatic_draw_method(win); if (ELEM(drawmethod, USER_DRAW_OVERLAP, USER_DRAW_OVERLAP_FLIP)) - wm_flush_regions_down(win->screen, &ar->winrct); + wm_flush_regions_down(screen, &ar->winrct); - win->screen->do_draw = true; + screen->do_draw = true; } void WM_redraw_windows(bContext *C) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 5d4b7a68d42..c4776f53f42 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -59,6 +59,7 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" +#include "BKE_workspace.h" #include "BKE_sound.h" @@ -276,6 +277,7 @@ void wm_event_do_notifiers(bContext *C) /* cache & catch WM level notifiers, such as frame change, scene/screen set */ for (win = wm->windows.first; win; win = win->next) { + Scene *scene = WM_window_get_active_scene(win); bool do_anim = false; CTX_wm_window_set(C, win); @@ -293,17 +295,31 @@ void wm_event_do_notifiers(bContext *C) } if (note->window == win) { if (note->category == NC_SCREEN) { - if (note->data == ND_SCREENBROWSE) { + if (note->data == ND_WORKSPACE_SET) { + WorkSpace *ref_ws = note->reference; + + UI_popup_handlers_remove_all(C, &win->modalhandlers); + + ED_workspace_change(ref_ws, C, wm, win); + if (G.debug & G_DEBUG_EVENTS) + printf("%s: Workspace set %p\n", __func__, note->reference); + } + else if (note->data == ND_LAYOUTBROWSE) { + bScreen *ref_screen = BKE_workspace_layout_screen_get(note->reference); + /* free popup handlers only [#35434] */ UI_popup_handlers_remove_all(C, &win->modalhandlers); - ED_screen_set(C, note->reference); // XXX hrms, think this over! + ED_screen_change(C, ref_screen); /* XXX hrms, think this over! */ if (G.debug & G_DEBUG_EVENTS) printf("%s: screen set %p\n", __func__, note->reference); } - else if (note->data == ND_SCREENDELETE) { - ED_screen_delete(C, note->reference); // XXX hrms, think this over! + else if (note->data == ND_LAYOUTDELETE) { + WorkSpace *workspace = WM_window_get_active_workspace(win); + WorkSpaceLayout *layout = note->reference; + + ED_workspace_layout_delete(workspace, layout, C); // XXX hrms, think this over! if (G.debug & G_DEBUG_EVENTS) printf("%s: screen delete %p\n", __func__, note->reference); } @@ -311,7 +327,7 @@ void wm_event_do_notifiers(bContext *C) } if (note->window == win || - (note->window == NULL && (note->reference == NULL || note->reference == win->screen->scene))) + (note->window == NULL && (note->reference == NULL || note->reference == scene))) { if (note->category == NC_SCENE) { if (note->data == ND_FRAME) @@ -319,7 +335,7 @@ void wm_event_do_notifiers(bContext *C) } } if (ELEM(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_WM)) { - SceneLayer *sl = BKE_scene_layer_context_active(win->screen->scene); + SceneLayer *sl = BKE_scene_layer_context_active(scene); ED_info_stats_clear(sl); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL); } @@ -332,7 +348,7 @@ void wm_event_do_notifiers(bContext *C) if (G.is_rendering == false) { /* depsgraph gets called, might send more notifiers */ - ED_update_for_newframe(CTX_data_main(C), win->screen->scene, 1); + ED_update_for_newframe(CTX_data_main(C), scene, 1); } } } @@ -340,10 +356,16 @@ void wm_event_do_notifiers(bContext *C) /* the notifiers are sent without context, to keep it clean */ while ((note = BLI_pophead(&wm->queue))) { for (win = wm->windows.first; win; win = win->next) { - Scene *scene = win->screen->scene; - + Scene *scene = WM_window_get_active_scene(win); + bScreen *screen = WM_window_get_active_screen(win); + /* filter out notifiers */ - if (note->category == NC_SCREEN && note->reference && note->reference != win->screen) { + if (note->category == NC_SCREEN && + note->reference && + note->reference != screen && + note->reference != WM_window_get_active_workspace(win) && + note->reference != WM_window_get_active_layout(win)) + { /* pass */ } else if (note->category == NC_SCENE && note->reference && note->reference != scene) { @@ -359,14 +381,14 @@ void wm_event_do_notifiers(bContext *C) /* printf("notifier win %d screen %s cat %x\n", win->winid, win->screen->id.name + 2, note->category); */ ED_screen_do_listen(C, note); - for (ar = win->screen->regionbase.first; ar; ar = ar->next) { - ED_region_do_listen(win->screen, NULL, ar, note, scene); + for (ar = screen->regionbase.first; ar; ar = ar->next) { + ED_region_do_listen(screen, NULL, ar, note, scene); } - for (sa = win->screen->areabase.first; sa; sa = sa->next) { - ED_area_do_listen(win->screen, sa, note, scene); + for (sa = screen->areabase.first; sa; sa = sa->next) { + ED_area_do_listen(screen, sa, note, scene); for (ar = sa->regionbase.first; ar; ar = ar->next) { - ED_region_do_listen(win->screen, sa, ar, note, scene); + ED_region_do_listen(screen, sa, ar, note, scene); } } } @@ -374,18 +396,23 @@ void wm_event_do_notifiers(bContext *C) MEM_freeN(note); } - + /* combine datamasks so 1 win doesn't disable UV's in another [#26448] */ for (win = wm->windows.first; win; win = win->next) { - win_combine_v3d_datamask |= ED_view3d_screen_datamask(win->screen); + const Scene *scene = WM_window_get_active_scene(win); + const bScreen *screen = WM_window_get_active_screen(win); + + win_combine_v3d_datamask |= ED_view3d_screen_datamask(scene, screen); } /* cached: editor refresh callbacks now, they get context */ for (win = wm->windows.first; win; win = win->next) { + const bScreen *screen = WM_window_get_active_screen(win); + Scene *scene = WM_window_get_active_scene(win); ScrArea *sa; CTX_wm_window_set(C, win); - for (sa = win->screen->areabase.first; sa; sa = sa->next) { + for (sa = screen->areabase.first; sa; sa = sa->next) { if (sa->do_refresh) { CTX_wm_area_set(C, sa); ED_area_do_refresh(C, sa); @@ -398,12 +425,12 @@ void wm_event_do_notifiers(bContext *C) Main *bmain = CTX_data_main(C); /* copied to set's in scene_update_tagged_recursive() */ - win->screen->scene->customdata_mask = win_combine_v3d_datamask; + scene->customdata_mask = win_combine_v3d_datamask; /* XXX, hack so operators can enforce datamasks [#26482], gl render */ - win->screen->scene->customdata_mask |= win->screen->scene->customdata_mask_modal; + scene->customdata_mask |= scene->customdata_mask_modal; - BKE_scene_update_tagged(bmain->eval_ctx, bmain, win->screen->scene); + BKE_scene_update_tagged(bmain->eval_ctx, bmain, scene); } } @@ -2362,17 +2389,19 @@ static void wm_paintcursor_test(bContext *C, const wmEvent *event) static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *event) { + bScreen *screen = WM_window_get_active_screen(win); + if (BLI_listbase_is_empty(&wm->drags)) { return; } if (event->type == MOUSEMOVE || ISKEYMODIFIER(event->type)) { - win->screen->do_draw_drag = true; + screen->do_draw_drag = true; } else if (event->type == ESCKEY) { WM_drag_free_list(&wm->drags); - win->screen->do_draw_drag = true; + screen->do_draw_drag = true; } else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { event->type = EVT_DROP; @@ -2388,16 +2417,16 @@ static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *even event->customdatafree = 1; /* clear drop icon */ - win->screen->do_draw_drag = true; + screen->do_draw_drag = true; /* restore cursor (disabled, see wm_dragdrop.c) */ // WM_cursor_modal_restore(win); } /* overlap fails otherwise */ - if (win->screen->do_draw_drag) + if (screen->do_draw_drag) if (win->drawmethod == USER_DRAW_OVERLAP) - win->screen->do_draw = true; + screen->do_draw = true; } @@ -2429,20 +2458,25 @@ void wm_event_do_handlers(bContext *C) WM_keyconfig_update(wm); for (win = wm->windows.first; win; win = win->next) { + bScreen *screen = WM_window_get_active_screen(win); wmEvent *event; - - if (win->screen == NULL) + + /* some safty checks - these should always be set! */ + BLI_assert(WM_window_get_active_scene(win)); + BLI_assert(WM_window_get_active_screen(win)); + BLI_assert(WM_window_get_active_workspace(win)); + + if (screen == NULL) wm_event_free_all(win); else { - Scene *scene = win->screen->scene; + Scene *scene = WM_window_get_active_scene(win); if (scene) { - int is_playing_sound = BKE_sound_scene_playing(win->screen->scene); + int is_playing_sound = BKE_sound_scene_playing(scene); if (is_playing_sound != -1) { bool is_playing_screen; CTX_wm_window_set(C, win); - CTX_wm_screen_set(C, win->screen); CTX_data_scene_set(C, scene); is_playing_screen = (ED_screen_animation_playing(wm) != NULL); @@ -2475,6 +2509,9 @@ void wm_event_do_handlers(bContext *C) while ( (event = win->queue.first) ) { int action = WM_HANDLER_CONTINUE; + /* active screen might change during handlers, update pointer */ + screen = WM_window_get_active_screen(win); + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { printf("\n%s: Handling event\n", __func__); WM_event_print(event); @@ -2532,12 +2569,12 @@ void wm_event_do_handlers(bContext *C) } #endif - for (sa = win->screen->areabase.first; sa; sa = sa->next) { + for (sa = screen->areabase.first; sa; sa = sa->next) { /* after restoring a screen from SCREENMAXIMIZED we have to wait * with the screen handling till the region coordinates are updated */ - if (win->screen->skip_handling == true) { + if (screen->skip_handling == true) { /* restore for the next iteration of wm_event_do_handlers */ - win->screen->skip_handling = false; + screen->skip_handling = false; break; } diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 99e0e28ab1b..8d442a2ed25 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -85,6 +85,7 @@ #include "BKE_sound.h" #include "BKE_scene.h" #include "BKE_screen.h" +#include "BKE_workspace.h" #include "BLO_readfile.h" #include "BLO_writefile.h" @@ -160,7 +161,7 @@ static void wm_window_match_init(bContext *C, ListBase *wmlist) CTX_wm_window_set(C, win); /* needed by operator close callbacks */ WM_event_remove_handlers(C, &win->handlers); WM_event_remove_handlers(C, &win->modalhandlers); - ED_screen_exit(C, win, win->screen); + ED_screen_exit(C, win, WM_window_get_active_screen(win)); } } @@ -249,16 +250,23 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist) /* match oldwm to new dbase, only old files */ for (wm = oldwmlist->first; wm; wm = wm->id.next) { - for (win = wm->windows.first; win; win = win->next) { + WorkSpace *workspace = WM_window_get_active_workspace(win); + /* all windows get active screen from file */ - if (screen->winid == 0) - win->screen = screen; - else - win->screen = ED_screen_duplicate(win, screen); - - BLI_strncpy(win->screenname, win->screen->id.name + 2, sizeof(win->screenname)); - win->screen->winid = win->winid; + if (screen->winid == 0) { + WM_window_set_active_screen(win, workspace, screen); + } + else { + WorkSpaceLayout *layout_old = WM_window_get_active_layout(win); + WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate(workspace, layout_old, win); + + WM_window_set_active_layout(win, workspace, layout_new); + } + + bScreen *win_screen = WM_window_get_active_screen(win); + BLI_strncpy(win->screenname, win_screen->id.name + 2, sizeof(win->screenname)); + win_screen->winid = win->winid; } } } @@ -317,10 +325,8 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist) } /* in case UserDef was read, we re-initialize all, and do versioning */ -static void wm_init_userdef(bContext *C, const bool use_factory_settings) +static void wm_init_userdef(Main *bmain, const bool use_factory_settings) { - Main *bmain = CTX_data_main(C); - /* versioning is here */ UI_init_userdef(); @@ -582,7 +588,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) if (retval == BKE_BLENDFILE_READ_OK_USERPREFS) { /* in case a userdef is read from regular .blend */ - wm_init_userdef(C, false); + wm_init_userdef(G.main, false); } if (retval != BKE_BLENDFILE_READ_FAIL) { @@ -828,7 +834,7 @@ int wm_homefile_read( G.fileflags &= ~G_FILE_RELATIVE_REMAP; /* check userdef before open window, keymaps etc */ - wm_init_userdef(C, read_userdef_from_memory); + wm_init_userdef(CTX_data_main(C), read_userdef_from_memory); /* match the read WM with current WM */ wm_window_match_do(C, &wmbase); @@ -1370,7 +1376,7 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op) BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_PRE); /* check current window and close it if temp */ - if (win && win->screen->temp) + if (win && WM_window_is_temp_screen(win)) wm_window_close(C, wm, win); /* update keymaps in user preferences */ @@ -1505,6 +1511,42 @@ void WM_OT_save_userpref(wmOperatorType *ot) ot->exec = wm_userpref_write_exec; } +static int wm_workspace_configuration_file_write_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + char filepath[FILE_MAX]; + + const char *app_template = U.app_template[0] ? U.app_template : NULL; + const char * const cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, app_template); + if (cfgdir == NULL) { + BKE_report(op->reports, RPT_ERROR, "Unable to create workspace configuration file path"); + return OPERATOR_CANCELLED; + } + + BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_WORKSPACES_FILE, NULL); + printf("trying to save workspace configuration file at %s ", filepath); + + if (BKE_blendfile_workspace_config_write(bmain, filepath, op->reports) != 0) { + printf("ok\n"); + return OPERATOR_FINISHED; + } + else { + printf("fail\n"); + } + + return OPERATOR_CANCELLED; +} + +void WM_OT_save_workspace_file(wmOperatorType *ot) +{ + ot->name = "Save Workspace Configuration"; + ot->idname = "WM_OT_save_workspace_file"; + ot->description = "Save workspaces of the current file as part of the user configuration"; + + ot->invoke = WM_operator_confirm; + ot->exec = wm_workspace_configuration_file_write_exec; +} + static int wm_history_file_read_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) { ED_file_read_bookmarks(); diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c index 82e9be3970f..3c7a48662f8 100644 --- a/source/blender/windowmanager/intern/wm_files_link.c +++ b/source/blender/windowmanager/intern/wm_files_link.c @@ -278,6 +278,40 @@ static void wm_link_do( } } +/** + * Check if an item defined by \a name and \a group can be appended/linked. + * + * \param reports: Optionally report an error when an item can't be appended/linked. + */ +static bool wm_link_append_item_poll( + ReportList *reports, const char *path, const char *group, const char *name, const bool do_append) +{ + short idcode; + + if (!group || !name) { + printf("skipping %s\n", path); + return false; + } + + idcode = BKE_idcode_from_name(group); + + /* XXX For now, we do a nasty exception for workspace, forbid linking them. + * Not nice, ultimately should be solved! */ + if (!BKE_idcode_is_linkable(idcode) && (do_append || idcode != ID_WS)) { + if (reports) { + if (do_append) { + BKE_reportf(reports, RPT_ERROR_INVALID_INPUT, "Can't append data-block '%s' of type '%s'", name, group); + } + else { + BKE_reportf(reports, RPT_ERROR_INVALID_INPUT, "Can't link data-block '%s' of type '%s'", name, group); + } + } + return false; + } + + return true; +} + static int wm_link_append_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -289,6 +323,8 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) char *group, *name; int totfiles = 0; short flag; + bool has_item = false; + bool do_append; RNA_string_get(op->ptr, "filename", relname); RNA_string_get(op->ptr, "directory", root); @@ -326,6 +362,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) } flag = wm_link_append_flag(op); + do_append = (flag & FILE_LINK) == 0; /* sanity checks for flag */ if (scene && scene->id.lib) { @@ -361,7 +398,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) BLI_join_dirfile(path, sizeof(path), root, relname); if (BLO_library_path_explode(path, libname, &group, &name)) { - if (!group || !name) { + if (!wm_link_append_item_poll(NULL, path, group, name, do_append)) { continue; } @@ -369,6 +406,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) BLI_ghash_insert(libraries, BLI_strdup(libname), SET_INT_IN_POINTER(lib_idx)); lib_idx++; wm_link_append_data_library_add(lapp_data, libname); + has_item = true; } } } @@ -382,8 +420,8 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) if (BLO_library_path_explode(path, libname, &group, &name)) { WMLinkAppendDataItem *item; - if (!group || !name) { - printf("skipping %s\n", path); + + if (!wm_link_append_item_poll(op->reports, path, group, name, do_append)) { continue; } @@ -391,6 +429,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) item = wm_link_append_data_item_add(lapp_data, name, BKE_idcode_from_name(group), NULL); BLI_BITMAP_ENABLE(item->libraries, lib_idx); + has_item = true; } } RNA_END; @@ -403,6 +442,12 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) wm_link_append_data_library_add(lapp_data, libname); item = wm_link_append_data_item_add(lapp_data, name, BKE_idcode_from_name(group), NULL); BLI_BITMAP_ENABLE(item->libraries, 0); + has_item = true; + } + + if (!has_item) { + wm_link_append_data_free(lapp_data); + return OPERATOR_CANCELLED; } /* XXX We'd need re-entrant locking on Main for this to work... */ @@ -417,7 +462,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) IMB_colormanagement_check_file_config(bmain); /* append, rather than linking */ - if ((flag & FILE_LINK) == 0) { + if (do_append) { const bool set_fake = RNA_boolean_get(op->ptr, "set_fake"); const bool use_recursive = RNA_boolean_get(op->ptr, "use_recursive"); @@ -572,6 +617,7 @@ static void lib_relocate_do( LinkNode *itemlink; int item_idx; + bool has_item = false; /* Remove all IDs to be reloaded from Main. */ lba_idx = set_listbasepointers(bmain, lbarray); @@ -593,6 +639,7 @@ static void lib_relocate_do( BLI_remlink(lbarray[lba_idx], id); item = wm_link_append_data_item_add(lapp_data, id->name + 2, idcode, id); BLI_BITMAP_SET_ALL(item->libraries, true, lapp_data->num_libraries); + has_item = true; #ifdef PRINT_DEBUG printf("\tdatablock to seek for: %s\n", id->name); @@ -601,6 +648,11 @@ static void lib_relocate_do( } } + if (!has_item) { + /* nothing to relocate */ + return; + } + BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true); /* We do not want any instanciation here! */ diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index ce4a65b854a..022502c9935 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -478,7 +478,7 @@ void WM_exit_ext(bContext *C, const bool do_python) CTX_wm_window_set(C, win); /* needed by operator close callbacks */ WM_event_remove_handlers(C, &win->handlers); WM_event_remove_handlers(C, &win->modalhandlers); - ED_screen_exit(C, win, win->screen); + ED_screen_exit(C, win, WM_window_get_active_screen(win)); } } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 00fc75eb282..3665b6f2c12 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2101,8 +2101,11 @@ static void WM_OT_call_menu_pie(wmOperatorType *ot) static int wm_operator_winactive_normal(bContext *C) { wmWindow *win = CTX_wm_window(C); + bScreen *screen; - if (win == NULL || win->screen == NULL || win->screen->state != SCREENNORMAL) + if (win == NULL) + return 0; + if (!((screen = WM_window_get_active_screen(win)) && (screen->state == SCREENNORMAL))) return 0; return 1; @@ -3830,11 +3833,12 @@ static void redraw_timer_step( CTX_wm_window_set(C, win); /* XXX context manipulation warning! */ } else if (type == eRTDrawWindow) { + bScreen *screen = WM_window_get_active_screen(win); ScrArea *sa_iter; CTX_wm_menu_set(C, NULL); - for (sa_iter = win->screen->areabase.first; sa_iter; sa_iter = sa_iter->next) { + for (sa_iter = screen->areabase.first; sa_iter; sa_iter = sa_iter->next) { ARegion *ar_iter; CTX_wm_area_set(C, sa_iter); @@ -4209,6 +4213,7 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_read_factory_settings); WM_operatortype_append(WM_OT_save_homefile); WM_operatortype_append(WM_OT_save_userpref); + WM_operatortype_append(WM_OT_save_workspace_file); WM_operatortype_append(WM_OT_userpref_autoexec_path_add); WM_operatortype_append(WM_OT_userpref_autoexec_path_remove); WM_operatortype_append(WM_OT_window_fullscreen_toggle); diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index 94e4e85026f..f8c4639c1b1 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -373,7 +373,8 @@ static bool wm_stereo3d_is_fullscreen_required(eStereoDisplayMode stereo_display bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check) { - bScreen *screen = win->screen; + const bScreen *screen = WM_window_get_active_screen(win); + const Scene *scene = WM_window_get_active_scene(win); /* some 3d methods change the window arrangement, thus they shouldn't * toggle on/off just because there is no 3d elements being drawn */ @@ -381,7 +382,7 @@ bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check) return GHOST_GetWindowState(win->ghostwin) == GHOST_kWindowStateFullScreen; } - if ((skip_stereo3d_check == false) && (ED_screen_stereo3d_required(screen) == false)) { + if ((skip_stereo3d_check == false) && (ED_screen_stereo3d_required(screen, scene) == false)) { return false; } @@ -508,7 +509,7 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) prev_display_mode != win_src->stereo3d_format->display_mode) { /* in case the hardward supports pageflip but not the display */ - if ((win_dst = wm_window_copy_test(C, win_src))) { + if ((win_dst = wm_window_copy_test(C, win_src, false))) { /* pass */ } else { @@ -518,14 +519,16 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) } } else if (win_src->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { - /* ED_screen_duplicate() can't handle other cases yet T44688 */ - if (win_src->screen->state != SCREENNORMAL) { + const bScreen *screen = WM_window_get_active_screen(win_src); + + /* ED_workspace_layout_duplicate() can't handle other cases yet T44688 */ + if (screen->state != SCREENNORMAL) { BKE_report(op->reports, RPT_ERROR, "Failed to switch to Time Sequential mode when in fullscreen"); ok = false; } /* pageflip requires a new window to be created with the proper OS flags */ - else if ((win_dst = wm_window_copy_test(C, win_src))) { + else if ((win_dst = wm_window_copy_test(C, win_src, false))) { if (wm_stereo3d_quadbuffer_supported()) { BKE_report(op->reports, RPT_INFO, "Quad-buffer window successfully created"); } diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c index 7613479aacd..1a8f71891c0 100644 --- a/source/blender/windowmanager/intern/wm_subwindow.c +++ b/source/blender/windowmanager/intern/wm_subwindow.c @@ -141,8 +141,10 @@ void wm_subwindow_origin_get(wmWindow *win, int swinid, int *x, int *y) static void wm_swin_matrix_get(wmWindow *win, wmSubWindow *swin, float mat[4][4]) { + const bScreen *screen = WM_window_get_active_screen(win); + /* used by UI, should find a better way to get the matrix there */ - if (swin->swinid == win->screen->mainwin) { + if (swin->swinid == screen->mainwin) { int width, height; wm_swin_size_get(swin, &width, &height); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 3ff323862b3..66df41e5b84 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -38,6 +38,7 @@ #include "DNA_listBase.h" #include "DNA_screen_types.h" #include "DNA_windowmanager_types.h" +#include "DNA_workspace_types.h" #include "MEM_guardedalloc.h" @@ -55,6 +56,8 @@ #include "BKE_library.h" #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_screen.h" +#include "BKE_workspace.h" #include "RNA_access.h" @@ -68,6 +71,7 @@ #include "wm_subwindow.h" #include "wm_event_system.h" +#include "ED_scene.h" #include "ED_screen.h" #include "ED_fileselect.h" @@ -218,6 +222,7 @@ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win) wm_ghostwindow_destroy(win); + BKE_workspace_instance_hook_free(G.main, win->workspace_hook); MEM_freeN(win->stereo3d_format); MEM_freeN(win); @@ -238,13 +243,15 @@ static int find_free_winid(wmWindowManager *wm) /* don't change context itself */ wmWindow *wm_window_new(bContext *C) { + Main *bmain = CTX_data_main(C); wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = MEM_callocN(sizeof(wmWindow), "window"); - + BLI_addtail(&wm->windows, win); win->winid = find_free_winid(wm); win->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo 3D Format (window)"); + win->workspace_hook = BKE_workspace_instance_hook_create(bmain); return win; } @@ -270,22 +277,26 @@ static wmWindow *wm_window_new_test(bContext *C) } /* part of wm_window.c api */ -wmWindow *wm_window_copy(bContext *C, wmWindow *win_src) +wmWindow *wm_window_copy(bContext *C, wmWindow *win_src, const bool duplicate_layout) { wmWindow *win_dst = wm_window_new(C); - + WorkSpace *workspace = WM_window_get_active_workspace(win_src); + WorkSpaceLayout *layout_old = WM_window_get_active_layout(win_src); + Scene *scene = WM_window_get_active_scene(win_src); + WorkSpaceLayout *layout_new; + bScreen *new_screen; + win_dst->posx = win_src->posx + 10; win_dst->posy = win_src->posy; win_dst->sizex = win_src->sizex; win_dst->sizey = win_src->sizey; - - /* duplicate assigns to window */ - win_dst->screen = ED_screen_duplicate(win_dst, win_src->screen); - BLI_strncpy(win_dst->screenname, win_dst->screen->id.name + 2, sizeof(win_dst->screenname)); - win_dst->screen->winid = win_dst->winid; - win_dst->screen->do_refresh = true; - win_dst->screen->do_draw = true; + win_dst->scene = scene; + WM_window_set_active_workspace(win_dst, workspace); + layout_new = duplicate_layout ? ED_workspace_layout_duplicate(workspace, layout_old, win_dst) : layout_old; + WM_window_set_active_layout(win_dst, workspace, layout_new); + new_screen = WM_window_get_active_screen(win_dst); + BLI_strncpy(win_dst->screenname, new_screen->id.name + 2, sizeof(win_dst->screenname)); win_dst->drawmethod = U.wmdrawmethod; @@ -300,12 +311,12 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *win_src) * A higher level version of copy that tests the new window can be added. * (called from the operator directly) */ -wmWindow *wm_window_copy_test(bContext *C, wmWindow *win_src) +wmWindow *wm_window_copy_test(bContext *C, wmWindow *win_src, const bool duplicate_layout) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win_dst; - win_dst = wm_window_copy(C, win_src); + win_dst = wm_window_copy(C, win_src, duplicate_layout); WM_check(C); @@ -329,7 +340,7 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) for (tmpwin = wm->windows.first; tmpwin; tmpwin = tmpwin->next) { if (tmpwin == win) continue; - if (tmpwin->screen->temp == 0) + if (WM_window_is_temp_screen(tmpwin) == false) break; } @@ -348,8 +359,10 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) WM_exit(C); } else { - bScreen *screen = win->screen; - + bScreen *screen = WM_window_get_active_screen(win); + WorkSpace *workspace = WM_window_get_active_workspace(win); + WorkSpaceLayout *layout = BKE_workspace_active_layout_get(win->workspace_hook); + BLI_remlink(&wm->windows, win); wm_draw_window_clear(win); @@ -360,8 +373,8 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) /* for regular use this will _never_ be NULL, * however we may be freeing an improperly initialized window. */ - if (win->screen) { - ED_screen_exit(C, win, win->screen); + if (screen) { + ED_screen_exit(C, win, screen); } wm_window_free(C, wm, win); @@ -369,14 +382,16 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) /* if temp screen, delete it after window free (it stops jobs that can access it) */ if (screen && screen->temp) { Main *bmain = CTX_data_main(C); - BKE_libblock_free(bmain, screen); + + BLI_assert(BKE_workspace_layout_screen_get(layout) == screen); + BKE_workspace_layout_remove(bmain, workspace, layout); } - } + } } void wm_window_title(wmWindowManager *wm, wmWindow *win) { - if (win->screen && win->screen->temp) { + if (WM_window_is_temp_screen(win)) { /* nothing to do for 'temp' windows, * because WM_window_open_temp always sets window title */ } @@ -668,8 +683,10 @@ wmWindow *WM_window_open(bContext *C, const rcti *rect) */ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, int type) { + Main *bmain = CTX_data_main(C); wmWindow *win_prev = CTX_wm_window(C); wmWindow *win; + bScreen *screen; ScrArea *sa; Scene *scene = CTX_data_scene(C); const char *title; @@ -693,7 +710,7 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i /* test if we have a temp screen already */ for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) - if (win->screen->temp) + if (WM_window_is_temp_screen(win)) break; /* add new window? */ @@ -704,6 +721,8 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i win->posy = rect.ymin; } + screen = WM_window_get_active_screen(win); + win->sizex = BLI_rcti_size_x(&rect); win->sizey = BLI_rcti_size_y(&rect); @@ -711,19 +730,27 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i wm_window_set_size(win, win->sizex, win->sizey); wm_window_raise(win); } - - if (win->screen == NULL) { - /* add new screen */ - win->screen = ED_screen_add(win, scene, "temp"); + + if (WM_window_get_active_workspace(win) == NULL) { + WorkSpace *workspace = WM_window_get_active_workspace(win_prev); + WM_window_set_active_workspace(win, workspace); } - else { - /* switch scene for rendering */ - if (win->screen->scene != scene) - ED_screen_set_scene(C, win->screen, scene); + + if (screen == NULL) { + /* add new screen layout */ + WorkSpace *workspace = WM_window_get_active_workspace(win); + WorkSpaceLayout *layout = ED_workspace_layout_add(workspace, win, "temp"); + + screen = BKE_workspace_layout_screen_get(layout); + WM_window_set_active_layout(win, workspace, layout); } - win->screen->temp = 1; - + if (WM_window_get_active_scene(win) != scene) { + WM_window_change_active_scene(bmain, C, win, scene); + } + + screen->temp = 1; + /* make window active, and validate/resize */ CTX_wm_window_set(C, win); WM_check(C); @@ -735,7 +762,7 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i */ /* ensure it shows the right spacetype editor */ - sa = win->screen->areabase.first; + sa = screen->areabase.first; CTX_wm_area_set(C, sa); if (type == WM_WINDOW_RENDER) { @@ -745,7 +772,7 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i ED_area_newspace(C, sa, SPACE_USERPREF, false); } - ED_screen_set(C, win->screen); + ED_screen_change(C, screen); ED_screen_refresh(CTX_wm_manager(C), win); /* test scale */ if (sa->spacetype == SPACE_IMAGE) @@ -781,23 +808,42 @@ int wm_window_close_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } +static WorkSpaceLayout *wm_window_new_find_layout(wmOperator *op, WorkSpace *workspace) +{ + ListBase *listbase = BKE_workspace_layouts_get(workspace); + const int layout_id = RNA_enum_get(op->ptr, "screen"); + int i = 0; + + for (WorkSpaceLayout *layout = listbase->first; layout; layout = layout->next) { + if (i++ == layout_id) { + return layout; + } + } + + BLI_assert(0); + return NULL; +} + /* new window operator callback */ int wm_window_new_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); wmWindow *win_src = CTX_wm_window(C); - const int screen_id = RNA_enum_get(op->ptr, "screen"); - bScreen *screen = BLI_findlink(&bmain->screen, screen_id); + WorkSpace *workspace = WM_window_get_active_workspace(win_src); + WorkSpaceLayout *layout_new = wm_window_new_find_layout(op, workspace); + bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new); wmWindow *win_dst; - if (screen->winid) { - /* Screen is already used, duplicate window and screen */ - win_dst = wm_window_copy_test(C, win_src); - } - else if ((win_dst = wm_window_new_test(C))) { - /* New window with a different screen */ - win_dst->screen = screen; - screen->winid = win_dst->winid; + if ((win_dst = wm_window_new_test(C))) { + if (screen_new->winid) { + /* layout/screen is already used, duplicate it */ + layout_new = ED_workspace_layout_duplicate(workspace, layout_new, win_dst); + screen_new = BKE_workspace_layout_screen_get(layout_new); + } + /* New window with a different screen but same workspace */ + WM_window_set_active_workspace(win_dst, workspace); + WM_window_set_active_screen(win_dst, workspace, screen_new); + win_dst->scene = win_src->scene; + screen_new->winid = win_dst->winid; CTX_wm_window_set(C, win_dst); ED_screen_refresh(CTX_wm_manager(C), win_dst); } @@ -807,9 +853,11 @@ int wm_window_new_exec(bContext *C, wmOperator *op) int wm_window_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - Main *bmain = CTX_data_main(C); + wmWindow *win = CTX_wm_window(C); + WorkSpace *workspace = WM_window_get_active_workspace(win); + ListBase *listbase = BKE_workspace_layouts_get(workspace); - if (BLI_listbase_count_ex(&bmain->screen, 2) == 1) { + if (BLI_listbase_count_ex(listbase, 2) == 1) { RNA_enum_set(op->ptr, "screen", 0); return wm_window_new_exec(C, op); } @@ -821,7 +869,9 @@ int wm_window_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(even struct EnumPropertyItem *wm_window_new_screen_itemf( bContext *C, struct PointerRNA *UNUSED(ptr), struct PropertyRNA *UNUSED(prop), bool *r_free) { - Main *bmain = CTX_data_main(C); + wmWindow *win = CTX_wm_window(C); + WorkSpace *workspace = WM_window_get_active_workspace(win); + ListBase *listbase = BKE_workspace_layouts_get(workspace); EnumPropertyItem *item = NULL; EnumPropertyItem tmp = {0, "", 0, "", ""}; int value = 0, totitem = 0; @@ -830,18 +880,20 @@ struct EnumPropertyItem *wm_window_new_screen_itemf( * for dynamic strings in EnumPropertyItem.name to avoid this. */ static char active_screens[20][MAX_NAME + 12]; - for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) { + for (WorkSpaceLayout *layout = listbase->first; layout; layout = layout->next) { + bScreen *screen = BKE_workspace_layout_screen_get(layout); + const char *layout_name = BKE_workspace_layout_name_get(layout); + if (screen->winid) { - BLI_snprintf(active_screens[count_act_screens], sizeof(*active_screens), "%s (Duplicate)", - screen->id.name + 2); + BLI_snprintf(active_screens[count_act_screens], sizeof(*active_screens), "%s (Duplicate)", layout_name); tmp.name = active_screens[count_act_screens++]; } else { - tmp.name = screen->id.name + 2; + tmp.name = layout_name; } tmp.value = value; - tmp.identifier = screen->id.name; + tmp.identifier = layout_name; UI_id_icon_render(C, CTX_data_scene(C), &screen->id, true, false); tmp.icon = BKE_icon_id_ensure(&screen->id); @@ -1156,7 +1208,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr /* stop screencast if resize */ if (type == GHOST_kEventWindowSize) { - WM_jobs_stop(wm, win->screen, NULL); + WM_jobs_stop(wm, WM_window_get_active_screen(win), NULL); } wm_window_set_dpi(win); @@ -1191,6 +1243,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr win->posx != posx || win->posy != posy) { + const bScreen *screen = WM_window_get_active_screen(win); + win->sizex = sizex; win->sizey = sizey; win->posx = posx; @@ -1227,7 +1281,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr wm_window_make_drawable(wm, win); wm_draw_window_clear(win); - BKE_icon_changed(win->screen->id.icon_id); + BKE_icon_changed(screen->id.icon_id); WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); @@ -1340,7 +1394,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr wm_window_set_dpi(win); if (U.pixelsize != prev_pixelsize) { - BKE_icon_changed(win->screen->id.icon_id); + BKE_icon_changed(WM_window_get_active_screen(win)->id.icon_id); // close all popups since they are positioned with the pixel // size baked in and it's difficult to correct them @@ -1847,6 +1901,86 @@ bool WM_window_is_fullscreen(wmWindow *win) return win->windowstate == GHOST_kWindowStateFullScreen; } +/** + * Some editor data may need to be synced with scene data (3D View camera and layers). + * This function ensures data is synced for editors in visible workspaces and their visible layouts. + */ +void WM_windows_scene_data_sync(const ListBase *win_lb, Scene *scene) +{ + for (wmWindow *win = win_lb->first; win; win = win->next) { + if (WM_window_get_active_scene(win) == scene) { + ED_workspace_scene_data_sync(win->workspace_hook, scene); + } + } +} + +Scene *WM_windows_scene_get_from_screen(const wmWindowManager *wm, const bScreen *screen) +{ + for (wmWindow *win = wm->windows.first; win; win = win->next) { + if (WM_window_get_active_screen(win) == screen) { + return WM_window_get_active_scene(win); + } + } + + return NULL; +} + +Scene *WM_window_get_active_scene(const wmWindow *win) +{ + return win->scene; +} + +/** + * \warning Only call outside of area/region loops + */ +void WM_window_change_active_scene(Main *bmain, bContext *C, wmWindow *win, Scene *scene_new) +{ + const bScreen *screen = WM_window_get_active_screen(win); + + ED_scene_exit(C); + win->scene = scene_new; + ED_scene_changed_update(bmain, C, scene_new, screen); +} + +WorkSpace *WM_window_get_active_workspace(const wmWindow *win) +{ + return BKE_workspace_active_get(win->workspace_hook); +} +void WM_window_set_active_workspace(wmWindow *win, WorkSpace *workspace) +{ + BKE_workspace_active_set(win->workspace_hook, workspace); +} + +WorkSpaceLayout *WM_window_get_active_layout(const wmWindow *win) +{ + const WorkSpace *workspace = WM_window_get_active_workspace(win); + return (LIKELY(workspace != NULL) ? BKE_workspace_active_layout_get(win->workspace_hook): NULL); +} +void WM_window_set_active_layout(wmWindow *win, WorkSpace *workspace, WorkSpaceLayout *layout) +{ + BKE_workspace_hook_layout_for_workspace_set(win->workspace_hook, workspace, layout); +} + +/** + * Get the active screen of the active workspace in \a win. + */ +bScreen *WM_window_get_active_screen(const wmWindow *win) +{ + const WorkSpace *workspace = WM_window_get_active_workspace(win); + /* May be NULL in rare cases like closing Blender */ + return (LIKELY(workspace != NULL) ? BKE_workspace_active_screen_get(win->workspace_hook) : NULL); +} +void WM_window_set_active_screen(wmWindow *win, WorkSpace *workspace, bScreen *screen) +{ + BKE_workspace_active_screen_set(win->workspace_hook, workspace, screen); +} + +bool WM_window_is_temp_screen(const wmWindow *win) +{ + const bScreen *screen = WM_window_get_active_screen(win); + return (screen && screen->temp != 0); +} + #ifdef WITH_INPUT_IME /* note: keep in mind wm_window_IME_begin is also used to reposition the IME window */ diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h index 9a1518e15b0..4fbbe3d2879 100644 --- a/source/blender/windowmanager/wm_files.h +++ b/source/blender/windowmanager/wm_files.h @@ -45,6 +45,7 @@ void WM_OT_save_homefile(struct wmOperatorType *ot); void WM_OT_userpref_autoexec_path_add(struct wmOperatorType *ot); void WM_OT_userpref_autoexec_path_remove(struct wmOperatorType *ot); void WM_OT_save_userpref(struct wmOperatorType *ot); +void WM_OT_save_workspace_file(struct wmOperatorType *ot); void WM_OT_read_history(struct wmOperatorType *ot); void WM_OT_read_homefile(struct wmOperatorType *ot); void WM_OT_read_factory_settings(struct wmOperatorType *ot); diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index 089e2994d3d..c8f89a5bf62 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -46,8 +46,8 @@ void wm_get_screensize(int *r_width, int *r_height); void wm_get_desktopsize(int *r_width, int *r_height); wmWindow *wm_window_new (bContext *C); -wmWindow *wm_window_copy (bContext *C, wmWindow *win_src); -wmWindow *wm_window_copy_test (bContext *C, wmWindow *win_src); +wmWindow *wm_window_copy (bContext *C, wmWindow *win_src, const bool duplicate_layout); +wmWindow *wm_window_copy_test (bContext *C, wmWindow *win_src, const bool duplicate_layout); void wm_window_free (bContext *C, wmWindowManager *wm, wmWindow *win); void wm_window_close (bContext *C, wmWindowManager *wm, wmWindow *win); |