[Bf-blender-cvs] [e56bfc2] workspaces: Fix crash when deleting layouts

Julian Eisel noreply at git.blender.org
Tue Dec 6 15:40:10 CET 2016


Commit: e56bfc27bd463687dd2a3230b624fad05872e0a7
Author: Julian Eisel
Date:   Tue Dec 6 15:36:40 2016 +0100
Branches: workspaces
https://developer.blender.org/rBe56bfc27bd463687dd2a3230b624fad05872e0a7

Fix crash when deleting layouts

Behavior change: The layout we switch to when deleting another one now has to meet similar requirements as the one we choose for cycling layouts (Ctrl+Arrow left/right). E.g. no hidden screen will be activated.

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

M	source/blender/blenkernel/BKE_screen.h
M	source/blender/blenkernel/BKE_workspace.h
M	source/blender/blenkernel/intern/screen.c
M	source/blender/blenkernel/intern/workspace.c
M	source/blender/editors/include/ED_screen.h
M	source/blender/editors/screen/screen_edit.c
M	source/blender/editors/screen/screen_ops.c
M	source/blender/editors/screen/workspace_edit.c
M	source/blender/editors/space_view3d/space_view3d.c
M	source/blender/windowmanager/intern/wm_event_system.c

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

diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 010810a..80e6d15 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -311,6 +311,8 @@ void BKE_screen_view3d_main_sync(ListBase *screen_lb, struct Scene *scene);
 void BKE_screen_view3d_twmode_remove(struct View3D *v3d, const int i);
 void BKE_screen_view3d_main_twmode_remove(ListBase *screen_lb, struct Scene *scene, const int i);
 void BKE_screen_gpu_fx_validate(struct GPUFXSettings *fx_settings);
+bool BKE_screen_is_fullscreen_area(const struct bScreen *screen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BKE_screen_is_used(const struct bScreen *screen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 
 /* zoom factor conversion */
 float BKE_screen_view3d_zoom_to_fac(float camzoom);
diff --git a/source/blender/blenkernel/BKE_workspace.h b/source/blender/blenkernel/BKE_workspace.h
index 0529297..5be2399 100644
--- a/source/blender/blenkernel/BKE_workspace.h
+++ b/source/blender/blenkernel/BKE_workspace.h
@@ -39,7 +39,7 @@ struct WorkSpace *BKE_workspace_duplicate(Main *bmain, const struct WorkSpace *f
 void BKE_workspace_free(struct WorkSpace *ws);
 
 struct WorkSpaceLayout *BKE_workspace_layout_add(struct WorkSpace *workspace, struct bScreen *screen) ATTR_NONNULL();
-void BKE_workspace_layout_remove(struct WorkSpace *workspace, struct WorkSpaceLayout *layout) ATTR_NONNULL();
+void BKE_workspace_layout_remove(struct WorkSpace *workspace, struct WorkSpaceLayout *layout, Main *bmain) ATTR_NONNULL();
 
 
 /* -------------------------------------------------------------------- */
@@ -61,7 +61,6 @@ void            BKE_workspace_active_screen_set(struct WorkSpace *ws, struct bSc
 struct Scene   *BKE_workspace_active_scene_get(const struct WorkSpace *ws) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
 void            BKE_workspace_active_scene_set(struct WorkSpace *ws, struct Scene *scene);
 
-struct bScreen *BKE_workspace_layout_screen_get(
-        struct WorkSpaceLayout *layout) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+struct bScreen *BKE_workspace_layout_screen_get(const struct WorkSpaceLayout *layout) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
 
 #endif /* __BKE_WORKSPACE_H__ */
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index c5d00d6..3a39b33 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -700,3 +700,13 @@ void BKE_screen_gpu_fx_validate(GPUFXSettings *fx_settings)
 		GPU_fx_compositor_init_ssao_settings(fx_ssao);
 	}
 }
+
+bool BKE_screen_is_fullscreen_area(const bScreen *screen)
+{
+	return ELEM(screen->state, SCREENMAXIMIZED, SCREENFULL);
+}
+
+bool BKE_screen_is_used(const bScreen *screen)
+{
+	return (screen->winid != 0);
+}
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
index 933b77a..1ea24f3 100644
--- a/source/blender/blenkernel/intern/workspace.c
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -82,8 +82,9 @@ WorkSpaceLayout *BKE_workspace_layout_add(WorkSpace *workspace, bScreen *screen)
 	return layout;
 }
 
-void BKE_workspace_layout_remove(WorkSpace *workspace, WorkSpaceLayout *layout)
+void BKE_workspace_layout_remove(WorkSpace *workspace, WorkSpaceLayout *layout, Main *bmain)
 {
+	BKE_libblock_free(bmain, BKE_workspace_layout_screen_get(layout));
 	BLI_remlink(&workspace->layouts, layout);
 	MEM_freeN(layout);
 }
@@ -168,7 +169,7 @@ void BKE_workspace_active_scene_set(WorkSpace *ws, Scene *scene)
 }
 
 
-bScreen *BKE_workspace_layout_screen_get(WorkSpaceLayout *layout)
+bScreen *BKE_workspace_layout_screen_get(const WorkSpaceLayout *layout)
 {
 	return layout->screen;
 }
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index a2c1ef7..207a8bd 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -107,7 +107,6 @@ void    ED_screen_do_listen(struct bContext *C, struct wmNotifier *note);
 bScreen *ED_screen_duplicate(struct wmWindow *win, struct bScreen *sc, WorkSpaceLayout **r_layout);
 bScreen *ED_screen_add(struct wmWindow *win, struct Scene *scene, const char *name, WorkSpaceLayout **r_layout);
 bool    ED_screen_set(struct bContext *C, struct bScreen *sc);
-bool    ED_screen_delete(struct bContext *C, struct bScreen *sc);
 void    ED_screen_set_scene(struct bContext *C, struct bScreen *screen, struct Scene *scene);
 bool    ED_screen_delete_scene(struct bContext *C, struct Scene *scene);
 void    ED_screen_set_subwinactive(struct bContext *C, struct wmEvent *event);
@@ -127,6 +126,7 @@ void    ED_screen_preview_render(const struct bScreen *screen, int size_x, int s
 bool ED_workspace_change(struct bContext *C, struct wmWindow *win, WorkSpace *ws_new) ATTR_NONNULL();
 WorkSpace *ED_workspace_duplicate(struct Main *bmain, struct wmWindow *win);
 bool ED_workspace_delete(struct Main *bmain, struct bContext *C, struct wmWindow *win, WorkSpace *ws);
+bool ED_workspace_layout_delete(struct bContext *C, WorkSpace *workspace, WorkSpaceLayout *layout_old) ATTR_NONNULL();
 bool ED_workspace_layout_cycle(struct bContext *C, struct wmWindow *win, const short direction) ATTR_NONNULL();
 
 /* anim */
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 34df34d..35b9854 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -1673,48 +1673,6 @@ static bool ed_screen_used(wmWindowManager *wm, bScreen *sc)
 	return false;
 }
 
-/* only call outside of area/region loops */
-bool ED_screen_delete(bContext *C, bScreen *sc)
-{
-	Main *bmain = CTX_data_main(C);
-	wmWindowManager *wm = CTX_wm_manager(C);
-	wmWindow *win = CTX_wm_window(C);
-	bScreen *newsc;
-	
-	/* don't allow deleting temp fullscreens for now */
-	if (ELEM(sc->state, SCREENMAXIMIZED, SCREENFULL)) {
-		return false;
-	}
-
-	/* screen can only be in use by one window at a time, so as
-	 * long as we are able to find a screen that is unused, we
-	 * can safely assume ours is not in use anywhere an delete it */
-
-	for (newsc = sc->id.prev; newsc; newsc = newsc->id.prev)
-		if (!ed_screen_used(wm, newsc) && !newsc->temp)
-			break;
-	
-	if (!newsc) {
-		for (newsc = sc->id.next; newsc; newsc = newsc->id.next)
-			if (!ed_screen_used(wm, newsc) && !newsc->temp)
-				break;
-	}
-
-	if (!newsc) {
-		return false;
-	}
-
-	ED_screen_set(C, newsc);
-
-	if (WM_window_get_active_screen(win) != sc) {
-		BKE_libblock_free(bmain, sc);
-		return true;
-	}
-	else {
-		return false;
-	}
-}
-
 static void ed_screen_set_3dview_camera(Scene *scene, bScreen *sc, ScrArea *sa, View3D *v3d)
 {
 	/* fix any cameras that are used in the 3d view but not in the scene */
@@ -1991,9 +1949,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
 
 		ED_screen_set(C, sc);
 
-		BKE_workspace_layout_remove(win->workspace, layout_old);
-		BKE_screen_free(oldscreen);
-		BKE_libblock_free(CTX_data_main(C), oldscreen);
+		BKE_workspace_layout_remove(win->workspace, layout_old, CTX_data_main(C));
 
 		/* After we've restored back to SCREENNORMAL, we have to wait with
 		 * screen handling as it uses the area coords which aren't updated yet.
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 343557e..0ae582f 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -3903,9 +3903,11 @@ static void SCREEN_OT_new(wmOperatorType *ot)
 static int screen_delete_exec(bContext *C, wmOperator *UNUSED(op))
 {
 	bScreen *sc = CTX_wm_screen(C);
-	
-	WM_event_add_notifier(C, NC_SCREEN | ND_SCREENDELETE, sc);
-	
+	WorkSpace *workspace = CTX_wm_workspace(C);
+	WorkSpaceLayout *layout = BKE_workspace_layout_find(workspace, sc);
+
+	WM_event_add_notifier(C, NC_SCREEN | ND_SCREENDELETE, layout);
+
 	return OPERATOR_FINISHED;
 }
 
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index cf9e48a..d4097f6 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -25,6 +25,7 @@
 #include "BKE_context.h"
 #include "BKE_main.h"
 #include "BKE_library.h"
+#include "BKE_screen.h"
 #include "BKE_workspace.h"
 
 #include "BLI_listbase.h"
@@ -109,18 +110,81 @@ bool ED_workspace_delete(Main *bmain, bContext *C, wmWindow *win, WorkSpace *ws)
 	return true;
 }
 
+static bool workspace_layout_delete_doit(bContext *C, WorkSpace *workspace,
+                                         WorkSpaceLayout *layout_old, WorkSpaceLayout *layout_new)
+{
+	Main *bmain = CTX_data_main(C);
+	bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new);
+
+	ED_screen_set(C, screen_new);
+
+	if (BKE_workspace_active_layout_get(workspace) != layout_old) {
+		BKE_workspace_layout_remove(workspace, layout_old, bmain);
+		return true;
+	}
+
+	return false;
+}
+
 static bool workspace_layout_set_poll(const WorkSpaceLayout *layout)
 {
-	const bScreen *screen = layout->screen;
+	const bScreen *screen = BKE_workspace_layout_screen_get(layout);
 
-	return ((screen->winid == 0) &&
-	        /* in typical usage these should have a nonzero winid
+	return ((BKE_screen_is_used(screen) == false) &&
+	        /* in typical usage temp screens should have a nonzero winid
 	         * (all temp screens should be used, or closed & freed). */
-	        (screen->temp == false) &&
-	        (screen->state == SCREENNORMAL) &&
+	        (screen->temp == false) &
+	        (BKE_screen_is_fullscreen_area(screen) == false) &&
 	        (screen->id.name[2] != '.' || !(U.uiflag & USER_HIDE_DOT)));
 }
 
+static WorkSpaceLayout *workspace_layout_delete_find_new(const WorkSpaceLayout *layout_old)
+{
+	WorkSpaceLayout *layout_new;
+
+	for (layout_new = layout_old->prev; layout_new; layout_new = layout_new->prev) {
+		if (workspace_layout_set_poll(layout_new)) {
+			return layout_new;
+		}
+	}
+	for (layout_new = layout_old->next; layout_new; layout_new = layout_new->next) {
+		if (workspace_layout_set_poll(layout_new)) {
+			return layout_ne

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list