Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2018-03-23 13:56:14 +0300
committerCampbell Barton <ideasman42@gmail.com>2018-03-23 13:56:14 +0300
commitda00a50f7f48bfd95924705e69babea41f9d7b2b (patch)
tree099dd2761a77af893904098626119da0ae7bf18a /source/blender/windowmanager
parent2ee4e9761f6ab2c32e8e90c7317f5e7310a8e532 (diff)
parent529c21acc2e6e0830844a610d4f8d6a9b72a9902 (diff)
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r--source/blender/windowmanager/WM_api.h2
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c2
-rw-r--r--source/blender/windowmanager/intern/wm_files.c2
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c27
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c13
-rw-r--r--source/blender/windowmanager/intern/wm_window.c62
-rw-r--r--source/blender/windowmanager/wm.h3
-rw-r--r--source/blender/windowmanager/wm_window.h2
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);