diff options
author | Campbell Barton <ideasman42@gmail.com> | 2018-03-23 13:56:14 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2018-03-23 13:56:14 +0300 |
commit | da00a50f7f48bfd95924705e69babea41f9d7b2b (patch) | |
tree | 099dd2761a77af893904098626119da0ae7bf18a /source/blender/windowmanager | |
parent | 2ee4e9761f6ab2c32e8e90c7317f5e7310a8e532 (diff) | |
parent | 529c21acc2e6e0830844a610d4f8d6a9b72a9902 (diff) |
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_files.c | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_init_exit.c | 27 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 13 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_window.c | 62 | ||||
-rw-r--r-- | source/blender/windowmanager/wm.h | 3 | ||||
-rw-r--r-- | source/blender/windowmanager/wm_window.h | 2 |
8 files changed, 73 insertions, 40 deletions
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 742adda2644..294134767c7 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -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); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index b6a9115cca4..630f858099f 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -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); diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index e7ad8127f39..c8af0fc3889 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.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; diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 98ac3eebb57..03bc1ae0a02 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -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); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index ae96c9646be..53098ea58b2 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -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; } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index a173281b7d0..4c3a89f76fa 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -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 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); - /* 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); + 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); diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h index 7fe6db4e470..b2e8c914fa8 100644 --- a/source/blender/windowmanager/wm.h +++ b/source/blender/windowmanager/wm.h @@ -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 *); diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index 75595eb8817..b0c7021c496 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -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); |