Merge branch 'master' into blender2.8
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user