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-21 18:00:18 +0300
committerCampbell Barton <ideasman42@gmail.com>2018-03-21 18:04:01 +0300
commit5ba5254ec1ebba6c1e89b663592d716b92e13165 (patch)
treeb8f74acaf2ec5ba374235bbf811f412ad8b1f7e3
parent23ffd4ec394011cec26879cba946501b245020fd (diff)
UI: Optional prompt to quit for non win32 systems
D566 by @januz Use Blender native dialog when OS dialog's aren't supported.
-rw-r--r--intern/ghost/GHOST_C-api.h5
-rw-r--r--intern/ghost/GHOST_ISystem.h6
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp5
-rw-r--r--intern/ghost/intern/GHOST_System.cpp5
-rw-r--r--intern/ghost/intern/GHOST_System.h4
-rw-r--r--intern/ghost/intern/GHOST_SystemNULL.h1
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.cpp5
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.h4
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp5
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h4
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py6
-rw-r--r--source/blender/windowmanager/intern/wm_files.c8
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c15
-rw-r--r--source/blender/windowmanager/intern/wm_window.c136
-rw-r--r--source/blender/windowmanager/wm_window.h1
15 files changed, 195 insertions, 15 deletions
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 967d3f58143..55a56b1b09f 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -898,6 +898,11 @@ extern int GHOST_toggleConsole(int action);
extern int GHOST_confirmQuit(GHOST_WindowHandle windowhandle);
/**
+ * Informs if the system provides native dialogs (eg. confirm quit)
+ */
+extern int GHOST_SupportsNativeDialogs(void);
+
+/**
* Use native pixel size (MacBook pro 'retina'), if supported.
*/
extern int GHOST_UseNativePixels(void);
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index 03193d6e1da..6f719572b73 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -418,6 +418,12 @@ public:
* in the application
*/
virtual int confirmQuit(GHOST_IWindow *window) const = 0;
+
+ /**
+ * Informs if the system provides native dialogs (eg. confirm quit)
+ */
+ virtual bool supportsNativeDialogs(void) = 0;
+
protected:
/**
* Initialize the system.
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index ce653188760..daafe3640e0 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -893,6 +893,11 @@ int GHOST_toggleConsole(int action)
return system->toggleConsole(action);
}
+int GHOST_SupportsNativeDialogs(void)
+{
+ GHOST_ISystem *system = GHOST_ISystem::getSystem();
+ return system->supportsNativeDialogs();
+}
int GHOST_confirmQuit(GHOST_WindowHandle windowhandle)
{
diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp
index 56d68b98ce0..4db2f0616d7 100644
--- a/intern/ghost/intern/GHOST_System.cpp
+++ b/intern/ghost/intern/GHOST_System.cpp
@@ -380,6 +380,11 @@ int GHOST_System::confirmQuit(GHOST_IWindow * /*window*/) const
return 1;
}
+bool GHOST_System::supportsNativeDialogs(void)
+{
+ return 1;
+}
+
bool GHOST_System::useNativePixel(void)
{
m_nativePixel = true;
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index af083996d91..50c893b1113 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -319,6 +319,10 @@ public:
*/
virtual int confirmQuit(GHOST_IWindow *window) const;
+ /**
+ * Informs if the system provides native dialogs (eg. confirm quit)
+ */
+ virtual bool supportsNativeDialogs(void);
protected:
diff --git a/intern/ghost/intern/GHOST_SystemNULL.h b/intern/ghost/intern/GHOST_SystemNULL.h
index 868416cd227..7c8d26d7486 100644
--- a/intern/ghost/intern/GHOST_SystemNULL.h
+++ b/intern/ghost/intern/GHOST_SystemNULL.h
@@ -52,6 +52,7 @@ public:
GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) { return GHOST_kFailure; }
void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const { /* nop */ }
void getAllDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const { /* nop */ }
+ bool supportsNativeDialogs(void) { return false;}
GHOST_TSuccess init() {
GHOST_TSuccess success = GHOST_System::init();
diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp
index e9768e4b845..db555910f4b 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.cpp
+++ b/intern/ghost/intern/GHOST_SystemSDL.cpp
@@ -635,6 +635,11 @@ GHOST_SystemSDL::addDirtyWindow(GHOST_WindowSDL *bad_wind)
m_dirty_windows.push_back(bad_wind);
}
+bool
+GHOST_SystemSDL::supportsNativeDialogs(void)
+{
+ return false
+}
GHOST_TSuccess GHOST_SystemSDL::getButtons(GHOST_Buttons& buttons) const
{
diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h
index 6f4ecec586b..41f110ed15d 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.h
+++ b/intern/ghost/intern/GHOST_SystemSDL.h
@@ -95,6 +95,10 @@ public:
getMainDisplayDimensions(GHOST_TUns32& width,
GHOST_TUns32& height) const;
+ /**
+ * Informs if the system provides native dialogs (eg. confirm quit)
+ */
+ virtual bool supportsNativeDialogs(void);
private:
GHOST_TSuccess
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index 9b617a34e1a..7fde6791d78 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -379,6 +379,11 @@ createWindow(const STR_String& title,
return window;
}
+bool GHOST_SystemX11::supportsNativeDialogs(void)
+{
+ return false;
+}
+
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
static void destroyIMCallback(XIM /*xim*/, XPointer ptr, XPointer /*data*/)
{
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index e60cab6a194..9973f6e133f 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -97,6 +97,10 @@ public:
init(
);
+ /**
+ * Informs if the system provides native dialogs (eg. confirm quit)
+ */
+ virtual bool supportsNativeDialogs(void);
/**
* \section Interface Inherited from GHOST_ISystem
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index e61a6abbbca..7e7e6ccca2d 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -211,7 +211,6 @@ class USERPREF_PT_interface(Panel):
return (userpref.active_section == 'INTERFACE')
def draw(self, context):
- import sys
layout = self.layout
userpref = context.user_preferences
@@ -244,9 +243,8 @@ class USERPREF_PT_interface(Panel):
col.separator()
- if sys.platform[:3] == "win":
- col.label("Warnings")
- col.prop(view, "use_quit_dialog")
+ col.label("Warnings")
+ col.prop(view, "use_quit_dialog")
row.separator()
row.separator()
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 16cc1d44923..551b17302fe 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -2075,6 +2075,10 @@ 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);
+ }
+
return OPERATOR_FINISHED;
}
@@ -2174,12 +2178,16 @@ void WM_OT_save_mainfile(wmOperatorType *ot)
ot->check = blend_save_check;
/* omit window poll so this can work in background mode */
+ PropertyRNA *prop;
WM_operator_properties_filesel(
ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_SAVE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
RNA_def_boolean(ot->srna, "compress", false, "Compress", "Write compressed .blend file");
RNA_def_boolean(ot->srna, "relative_remap", false, "Remap Relative",
"Remap relative paths when saving in a different directory");
+
+ prop = RNA_def_boolean(ot->srna, "exit", false, "Exit", "Exit Blender after saving");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 2a50de62dda..363b8e61763 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -2162,10 +2162,16 @@ static void WM_OT_window_fullscreen_toggle(wmOperatorType *ot)
static int wm_exit_blender_exec(bContext *C, wmOperator *op)
{
- WM_operator_free(op);
-
- WM_exit(C);
-
+ 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);
+ }
+
return OPERATOR_FINISHED;
}
@@ -2175,7 +2181,6 @@ static void WM_OT_quit_blender(wmOperatorType *ot)
ot->idname = "WM_OT_quit_blender";
ot->description = "Quit Blender";
- ot->invoke = WM_operator_confirm;
ot->exec = wm_exit_blender_exec;
}
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index cbf06e8c6e9..2e12ceab5b3 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -70,6 +70,7 @@
#include "ED_fileselect.h"
#include "UI_interface.h"
+#include "UI_resources.h"
#include "PIL_time.h"
@@ -295,6 +296,124 @@ wmWindow *wm_window_copy_test(bContext *C, wmWindow *win_src)
}
}
+
+/* -------------------------------------------------------------------- */
+/** \name Quit Confirmation Dialog
+ * \{ */
+
+/** Cancel quitting and close the dialog */
+static void wm_block_confirm_quit_cancel(bContext *C, void *arg_block, void *UNUSED(arg))
+{
+ wmWindow *win = CTX_wm_window(C);
+ UI_popup_block_close(C, win, arg_block);
+}
+
+/** Discard the file changes and quit */
+static void wm_block_confirm_quit_discard(bContext *C, void *arg_block, void *UNUSED(arg))
+{
+ wmWindow *win = CTX_wm_window(C);
+ UI_popup_block_close(C, win, arg_block);
+ WM_exit(C);
+}
+
+/* Save changes and quit */
+static void wm_block_confirm_quit_save(bContext *C, void *arg_block, void *UNUSED(arg))
+{
+ PointerRNA props_ptr;
+ wmWindow *win = CTX_wm_window(C);
+
+ UI_popup_block_close(C, win, arg_block);
+
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_save_mainfile", false);
+
+ WM_operator_properties_create_ptr(&props_ptr, ot);
+ RNA_boolean_set(&props_ptr, "exit", true);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ WM_operator_properties_free(&props_ptr);
+}
+
+
+/* Build the confirm dialog UI */
+static uiBlock *block_create_confirm_quit(struct bContext *C, struct ARegion *ar, void *UNUSED(arg1))
+{
+
+ uiStyle *style = UI_style_get();
+ uiBlock *block = UI_block_begin(C, ar, "confirm_quit_popup", UI_EMBOSS);
+
+ UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP );
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ uiLayout *layout = UI_block_layout(
+ block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 10, 2, U.pixelsize * 480, U.pixelsize * 110, 0, style);
+
+ /* Text and some vertical space */
+ {
+ char *message;
+ if (G.main->name[0] == '\0') {
+ message = BLI_strdup(IFACE_("This file has not been saved yet. Save before closing?"));
+ }
+ else {
+ const char *basename = BLI_path_basename(G.main->name);
+ message = BLI_sprintfN(IFACE_("Save changes to \"%s\" before closing?"), basename);
+ }
+ uiItemL(layout, message, ICON_ERROR);
+ MEM_freeN(message);
+ }
+
+ uiItemS(layout);
+ uiItemS(layout);
+
+
+ /* Buttons */
+ uiBut *but;
+
+ uiLayout *split = uiLayoutSplit(layout, 0.0f, true);
+
+ uiLayout *col = uiLayoutColumn(split, false);
+
+ but = uiDefIconTextBut(
+ block, UI_BTYPE_BUT, 0, ICON_SCREEN_BACK, IFACE_("Cancel"), 0, 0, 0, UI_UNIT_Y,
+ NULL, 0, 0, 0, 0, TIP_("Do not quit"));
+ UI_but_func_set(but, wm_block_confirm_quit_cancel, block, NULL);
+
+ /* empty space between buttons */
+ col = uiLayoutColumn(split, false);
+ uiItemS(col);
+
+ col = uiLayoutColumn(split, 1);
+ but = uiDefIconTextBut(
+ block, UI_BTYPE_BUT, 0, ICON_CANCEL, IFACE_("Discard Changes"), 0, 0, 50, UI_UNIT_Y,
+ NULL, 0, 0, 0, 0, TIP_("Discard changes and quit"));
+ UI_but_func_set(but, wm_block_confirm_quit_discard, block, NULL);
+
+ col = uiLayoutColumn(split, 1);
+ but = uiDefIconTextBut(
+ block, UI_BTYPE_BUT, 0, ICON_FILE_TICK, IFACE_("Save & Quit"), 0, 0, 50, UI_UNIT_Y,
+ NULL, 0, 0, 0, 0, TIP_("Save and quit"));
+ UI_but_func_set(but, wm_block_confirm_quit_save, block, NULL);
+
+ UI_block_bounds_set_centered(block, 10);
+
+ return block;
+}
+
+
+/** Call the confirm dialog on quitting. */
+void wm_confirm_quit(bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(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);
+ }
+
+ UI_popup_block_invoke(C, block_create_confirm_quit, NULL);
+}
+
+/** \} */
+
/* this is event from ghost, or exit-blender op */
void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
{
@@ -311,19 +430,24 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
if (tmpwin == NULL)
do_exit = 1;
-
- if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved && !G.background) {
- if (do_exit) {
+
+ 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;
}
}
-
- /* let WM_exit do all freeing, for correct quit.blend save */
- if (do_exit) {
+ else if (do_exit) {
+ /* No changes but we're quitting */
+ /* let WM_exit do all freeing, for correct quit.blend save */
WM_exit(C);
}
else {
+ /* We're just closing a window */
bScreen *screen = win->screen;
BLI_remlink(&wm->windows, win);
diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h
index f70ec6b47f6..4313c978ef4 100644
--- a/source/blender/windowmanager/wm_window.h
+++ b/source/blender/windowmanager/wm_window.h
@@ -78,6 +78,7 @@ void wm_window_IME_end (wmWindow *win);
int wm_window_close_exec(bContext *C, struct wmOperator *op);
int wm_window_duplicate_exec(bContext *C, struct wmOperator *op);
int wm_window_fullscreen_toggle_exec(bContext *C, struct wmOperator *op);
+void wm_confirm_quit(bContext *C);
/* Initial (unmaximized) size to start with for
* systems that can't find it for themselves (X11).