[Bf-blender-cvs] [8471362] master: WM: Fix crash when a new window can't be created

Campbell Barton noreply at git.blender.org
Tue Oct 6 15:42:45 CEST 2015


Commit: 84713629877d84d8c973d55e7e7cb0eca0f2ba49
Author: Campbell Barton
Date:   Wed Oct 7 00:27:27 2015 +1100
Branches: master
https://developer.blender.org/rB84713629877d84d8c973d55e7e7cb0eca0f2ba49

WM: Fix crash when a new window can't be created

Report an error instead of crashing if a new window can't be created
(typically caused by bad drivers).

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

M	source/blender/editors/render/render_intern.h
M	source/blender/editors/render/render_internal.c
M	source/blender/editors/render/render_opengl.c
M	source/blender/editors/render/render_view.c
M	source/blender/editors/screen/screen_ops.c
M	source/blender/gpu/intern/gpu_init_exit.c
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
M	source/blender/windowmanager/wm_window.h

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

diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h
index 54429f9..26f313c 100644
--- a/source/blender/editors/render/render_intern.h
+++ b/source/blender/editors/render/render_intern.h
@@ -93,7 +93,7 @@ void render_view3d_update(struct RenderEngine *engine, const struct bContext *C)
 void render_view3d_draw(struct RenderEngine *engine, const struct bContext *C);
 
 /* render_view.c */
-struct ScrArea *render_view_open(struct bContext *C, int mx, int my);
+struct ScrArea *render_view_open(struct bContext *C, int mx, int my, struct ReportList *reports);
 
 void RENDER_OT_view_show(struct wmOperatorType *ot);
 void RENDER_OT_view_cancel(struct wmOperatorType *ot);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 10de2d6..4c10c07 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -877,7 +877,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
 	// store spare
 
 	/* ensure at least 1 area shows result */
-	sa = render_view_open(C, event->x, event->y);
+	sa = render_view_open(C, event->x, event->y, op->reports);
 
 	jobflag = WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS;
 	
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index fe40227..954fcde 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -911,7 +911,7 @@ static int screen_opengl_render_invoke(bContext *C, wmOperator *op, const wmEven
 	}
 	
 	oglrender = op->customdata;
-	render_view_open(C, event->x, event->y);
+	render_view_open(C, event->x, event->y, op->reports);
 	
 	/* view may be changed above (R_OUTPUT_WINDOW) */
 	oglrender->win = CTX_wm_window(C);
diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c
index f669029..4e36303 100644
--- a/source/blender/editors/render/render_view.c
+++ b/source/blender/editors/render/render_view.c
@@ -38,6 +38,7 @@
 #include "BKE_image.h"
 #include "BKE_global.h"
 #include "BKE_screen.h"
+#include "BKE_report.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
@@ -125,7 +126,7 @@ static ScrArea *find_area_image_empty(bContext *C)
 /********************** open image editor for render *************************/
 
 /* new window uses x,y to set position */
-ScrArea *render_view_open(bContext *C, int mx, int my)
+ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
 {
 	wmWindow *win = CTX_wm_window(C);
 	Scene *scene = CTX_data_scene(C);
@@ -155,7 +156,10 @@ ScrArea *render_view_open(bContext *C, int mx, int my)
 		rect.ymax = rect.ymin + sizey;
 
 		/* changes context! */
-		WM_window_open_temp(C, &rect, WM_WINDOW_RENDER);
+		if (WM_window_open_temp(C, &rect, WM_WINDOW_RENDER) == NULL) {
+			BKE_report(reports, RPT_ERROR, "Failed to open window!");
+			return NULL;
+		}
 
 		sa = CTX_wm_area(C);
 	}
@@ -292,7 +296,7 @@ void RENDER_OT_view_cancel(struct wmOperatorType *ot)
 
 /************************* show render viewer *****************/
 
-static int render_view_show_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+static int render_view_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
 {
 	wmWindow *wincur = CTX_wm_window(C);
 	
@@ -341,7 +345,7 @@ static int render_view_show_invoke(bContext *C, wmOperator *UNUSED(op), const wm
 			}
 		}
 		else {
-			render_view_open(C, event->x, event->y);
+			render_view_open(C, event->x, event->y, op->reports);
 		}
 	}
 
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 4a1c1e3..24653dc 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -992,6 +992,11 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
 	rect.ymax = rect.ymin + BLI_rcti_size_y(&rect) / U.pixelsize;
 
 	newwin = WM_window_open(C, &rect);
+	if (newwin == NULL) {
+		BKE_report(op->reports, RPT_ERROR, "Failed to open window!");
+		goto finally;
+	}
+
 	*newwin->stereo3d_format = *win->stereo3d_format;
 	
 	/* allocs new screen and adds to newly created window, using window size */
@@ -1005,11 +1010,18 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
 
 	/* screen, areas init */
 	WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
-	
+
+
+finally:
 	if (event->type == EVT_ACTIONZONE_AREA)
 		actionzone_exit(op);
 	
-	return OPERATOR_FINISHED;
+	if (newwin) {
+		return OPERATOR_FINISHED;
+	}
+	else {
+		return OPERATOR_CANCELLED;
+	}
 }
 
 static void SCREEN_OT_area_dupli(wmOperatorType *ot)
@@ -3845,7 +3857,7 @@ static void SCREEN_OT_back_to_previous(struct wmOperatorType *ot)
 
 /* *********** show user pref window ****** */
 
-static int userpref_show_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+static int userpref_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
 {
 	wmWindow *win = CTX_wm_window(C);
 	rcti rect;
@@ -3862,9 +3874,13 @@ static int userpref_show_invoke(bContext *C, wmOperator *UNUSED(op), const wmEve
 	rect.ymax = rect.ymin + sizey;
 	
 	/* changes context! */
-	WM_window_open_temp(C, &rect, WM_WINDOW_USERPREFS);
-	
-	return OPERATOR_FINISHED;
+	if (WM_window_open_temp(C, &rect, WM_WINDOW_USERPREFS) != NULL) {
+		return OPERATOR_FINISHED;
+	}
+	else {
+		BKE_report(op->reports, RPT_ERROR, "Failed to open window!");
+		return OPERATOR_CANCELLED;
+	}
 }
 
 
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
index 3a8a6fc..da4dd65 100644
--- a/source/blender/gpu/intern/gpu_init_exit.c
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -49,7 +49,7 @@ static bool initialized = false;
 
 void GPU_init(void)
 {
-	/* can't avoid calling this multiple times, see wm_window_add_ghostwindow */
+	/* can't avoid calling this multiple times, see wm_window_ghostwindow_add */
 	if (initialized)
 		return;
 
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index abbbe75..8aea581 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -87,18 +87,19 @@ void		WM_init_splash		(struct bContext *C);
 
 void		WM_check			(struct bContext *C);
 
-struct wmWindow	*WM_window_open	(struct bContext *C, const struct rcti *rect);
-
 int			WM_window_pixels_x		(struct wmWindow *win);
 int			WM_window_pixels_y		(struct wmWindow *win);
 bool		WM_window_is_fullscreen	(struct wmWindow *win);
 
 /* defines for 'type' WM_window_open_temp */
-#define WM_WINDOW_RENDER		0
-#define WM_WINDOW_USERPREFS		1
-// #define WM_WINDOW_FILESEL		2  // UNUSED
+enum {
+	WM_WINDOW_RENDER = 1,
+	WM_WINDOW_USERPREFS,
+	// WM_WINDOW_FILESEL // UNUSED
+};
 
-void		WM_window_open_temp	(struct bContext *C, struct rcti *position, int type);
+struct wmWindow	*WM_window_open(struct bContext *C, const struct rcti *rect);
+struct wmWindow *WM_window_open_temp(struct bContext *C, const struct rcti *rect_init, int type);
 			
 			/* returns true if draw method is triple buffer */
 bool		WM_is_draw_triple(struct wmWindow *win);
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index fe92d80..b76a1f1 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -376,7 +376,7 @@ void WM_check(bContext *C)
 		}
 
 		/* case: no open windows at all, for old file reads */
-		wm_window_add_ghostwindows(wm);
+		wm_window_ghostwindows_ensure(wm);
 	}
 
 	/* case: fileread */
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index d08c6c5..fc5cad6 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -438,7 +438,14 @@ void wm_file_read_report(bContext *C)
 static void wm_file_read_post(bContext *C, bool is_startup_file)
 {
 	bool addons_loaded = false;
-	CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first);
+	wmWindowManager *wm = CTX_wm_manager(C);
+
+	if (!G.background) {
+		/* remove windows which failed to be added via WM_check */
+		wm_window_ghostwindows_remove_invalid(C, wm);
+	}
+
+	CTX_wm_window_set(C, wm->windows.first);
 
 	ED_editors_init(C);
 	DAG_on_visible_update(CTX_data_main(C), true);
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 030399a..51feea5 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -329,12 +329,17 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
 		CTX_wm_window_set(C, win);  /* needed by handlers */
 		WM_event_remove_handlers(C, &win->handlers);
 		WM_event_remove_handlers(C, &win->modalhandlers);
-		ED_screen_exit(C, win, win->screen); 
+
+		/* 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);
+		}
 		
 		wm_window_free(C, wm, win);
 	
 		/* if temp screen, delete it after window free (it stops jobs that can access it) */
-		if (screen->temp) {
+		if (screen && screen->temp) {
 			Main *bmain = CTX_data_main(C);
 			BKE_libblock_free(bmain, screen);
 		}
@@ -380,7 +385,7 @@ float wm_window_pixelsize(wmWindow *win)
 }
 
 /* belongs to below */
-static void wm_window_add_ghostwindow(wmWindowManager *wm, const char *title, wmWindow *win)
+static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wmWindow *win)
 {
 	GHOST_WindowHandle ghostwin;
 	GHOST_GLSettings glSettings = {0};
@@ -466,14 +471,26 @@ static void wm_window_add_ghostwindow(wmWindowManager *wm, const char *title, wm
 	}
 }
 
-/* for wmWindows without ghostwin, open these and clear */
-/* window size is read from window, if 0 it uses prefsize */
-/* called in WM_check, also inits stuff after file read */
-void wm_window_add_ghostwindows(wmWindowManager *wm)
+/**
+ * Initialize #wmWindows without ghostwin, open these

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list