Merge branch 'master' into blender2.8

This commit is contained in:
2018-03-23 11:56:14 +01:00
8 changed files with 73 additions and 40 deletions

View File

@@ -220,7 +220,7 @@ enum {
struct wmEventHandler *WM_event_add_dropbox_handler(ListBase *handlers, ListBase *dropboxes);
/* mouse */
void WM_event_add_mousemove(struct bContext *C);
void WM_event_add_mousemove(const struct bContext *C);
bool WM_event_is_modal_tweak_exit(const struct wmEvent *event, int tweak_event);
bool WM_event_is_last_mousemove(const struct wmEvent *event);

View File

@@ -3226,7 +3226,7 @@ static void WM_event_remove_handler(ListBase *handlers, wmEventHandler *handler)
}
#endif
void WM_event_add_mousemove(bContext *C)
void WM_event_add_mousemove(const bContext *C)
{
wmWindow *window = CTX_wm_window(C);

View File

@@ -2128,7 +2128,7 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_WM | ND_FILESAVE, NULL);
if (RNA_boolean_get(op->ptr, "exit")) {
WM_exit(C);
wm_exit_schedule_delayed(C);
}
return OPERATOR_FINISHED;

View File

@@ -445,6 +445,29 @@ static void wait_for_console_key(void)
}
#endif
static int wm_exit_handler(bContext *C, const wmEvent *event, void *userdata)
{
WM_exit(C);
UNUSED_VARS(event, userdata);
return WM_UI_HANDLER_BREAK;
}
/**
* Cause a delayed WM_exit() call to avoid leaking memory when trying to exit from within operators.
*/
void wm_exit_schedule_delayed(const bContext *C)
{
/* What we do here is a little bit hacky, but quite simple and doesn't require bigger
* changes: Add a handler wrapping WM_exit() to cause a delayed call of it. */
wmWindow *win = CTX_wm_window(C);
/* Use modal UI handler for now. Could add separate WM handlers or so, but probably not worth it. */
WM_event_add_ui_handler(C, &win->modalhandlers, wm_exit_handler, NULL, NULL, 0);
WM_event_add_mousemove(C); /* ensure handler actually gets called */
}
/**
* \note doesn't run exit() call #WM_exit() for that.
*/
@@ -625,6 +648,10 @@ void WM_exit_ext(bContext *C, const bool do_python)
BKE_tempdir_session_purge();
}
/**
* \brief Main exit function to close Blender ordinarily.
* \note Use #wm_exit_schedule_delayed() to close Blender from an operator. Might leak memory otherwise.
*/
void WM_exit(bContext *C)
{
WM_exit_ext(C, 1);

View File

@@ -2315,18 +2315,9 @@ static void WM_OT_window_fullscreen_toggle(wmOperatorType *ot)
ot->poll = WM_operator_winactive;
}
static int wm_exit_blender_exec(bContext *C, wmOperator *op)
static int wm_exit_blender_exec(bContext *C, wmOperator *UNUSED(op))
{
wmWindowManager *wm = CTX_wm_manager(C);
if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved) {
wm_confirm_quit(C);
}
else {
WM_operator_free(op);
WM_exit(C);
}
wm_quit_with_optional_confirmation_prompt(C, CTX_wm_window(C));
return OPERATOR_FINISHED;
}

View File

@@ -438,18 +438,46 @@ static uiBlock *block_create_confirm_quit(struct bContext *C, struct ARegion *ar
}
/** Call the confirm dialog on quitting. */
void wm_confirm_quit(bContext *C)
/**
* Call the confirm dialog on quitting. It's displayed in the context window so
* caller should set it as desired.
*/
static void wm_confirm_quit(bContext *C)
{
wmWindow *win = CTX_wm_window(C);
if (GHOST_SupportsNativeDialogs() == 0) {
UI_popup_block_invoke(C, block_create_confirm_quit, NULL);
}
else if (GHOST_confirmQuit(win->ghostwin)) {
wm_exit_schedule_delayed(C);
}
}
/**
* Call the quit confirmation prompt or exit directly if needed. The use can
* still cancel via the confirmation popup. Also, this may not quit Blender
* immediately, but rather schedule the closing.
*
* \param win The window to show the confirmation popup/window in.
*/
void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win_ctx = CTX_wm_window(C);
/* The popup needs to have a window set in context to show up since
* it's being called outside the normal operator event handling loop */
if (wm->winactive) {
CTX_wm_window_set(C, wm->winactive);
/* The popup will be displayed in the context window which may not be set
* here (this function gets called outside of normal event handling loop). */
CTX_wm_window_set(C, win);
if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved && !G.background) {
wm_confirm_quit(C);
}
else {
wm_exit_schedule_delayed(C);
}
UI_popup_block_invoke(C, block_create_confirm_quit, NULL);
CTX_wm_window_set(C, win_ctx);
}
/** \} */
@@ -458,7 +486,6 @@ void wm_confirm_quit(bContext *C)
void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
{
wmWindow *tmpwin;
bool do_exit = false;
/* first check if we have to quit (there are non-temp remaining windows) */
for (tmpwin = wm->windows.first; tmpwin; tmpwin = tmpwin->next) {
@@ -468,23 +495,8 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
break;
}
if (tmpwin == NULL)
do_exit = 1;
if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved && !G.background && do_exit) {
/* We have unsaved changes and we're quitting */
if(GHOST_SupportsNativeDialogs() == 0) {
wm_confirm_quit(C);
}
else {
if (!GHOST_confirmQuit(win->ghostwin))
return;
}
}
else if (do_exit) {
/* No changes but we're quitting */
/* let WM_exit do all freeing, for correct quit.blend save */
WM_exit(C);
if (tmpwin == NULL) {
wm_quit_with_optional_confirmation_prompt(C, win);
}
else {
bScreen *screen = WM_window_get_active_screen(win);

View File

@@ -45,6 +45,9 @@ typedef struct wmPaintCursor {
void (*draw)(bContext *C, int, int, void *customdata);
} wmPaintCursor;
void wm_exit_schedule_delayed(const bContext *C);
extern void wm_close_and_free(bContext *C, wmWindowManager *);
extern void wm_close_and_free_all(bContext *C, ListBase *);

View File

@@ -82,7 +82,7 @@ void wm_window_IME_end (wmWindow *win);
/* *************** window operators ************** */
int wm_window_close_exec(bContext *C, struct wmOperator *op);
int wm_window_fullscreen_toggle_exec(bContext *C, struct wmOperator *op);
void wm_confirm_quit(bContext *C);
void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win) ATTR_NONNULL();
const struct EnumPropertyItem *wm_window_new_screen_itemf(
bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);