Merge branch 'master' into blender2.8

This commit is contained in:
Campbell Barton 2018-03-21 16:27:48 +01:00
commit 69eb452622
15 changed files with 192 additions and 15 deletions

@ -929,6 +929,11 @@ extern int GHOST_toggleConsole(int action);
*/ */
extern int GHOST_confirmQuit(GHOST_WindowHandle windowhandle); 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. * Use native pixel size (MacBook pro 'retina'), if supported.
*/ */

@ -433,6 +433,12 @@ public:
* in the application * in the application
*/ */
virtual int confirmQuit(GHOST_IWindow *window) const = 0; virtual int confirmQuit(GHOST_IWindow *window) const = 0;
/**
* Informs if the system provides native dialogs (eg. confirm quit)
*/
virtual bool supportsNativeDialogs(void) = 0;
protected: protected:
/** /**
* Initialize the system. * Initialize the system.

@ -921,6 +921,11 @@ int GHOST_toggleConsole(int action)
return system->toggleConsole(action); return system->toggleConsole(action);
} }
int GHOST_SupportsNativeDialogs(void)
{
GHOST_ISystem *system = GHOST_ISystem::getSystem();
return system->supportsNativeDialogs();
}
int GHOST_confirmQuit(GHOST_WindowHandle windowhandle) int GHOST_confirmQuit(GHOST_WindowHandle windowhandle)
{ {

@ -380,6 +380,11 @@ int GHOST_System::confirmQuit(GHOST_IWindow * /*window*/) const
return 1; return 1;
} }
bool GHOST_System::supportsNativeDialogs(void)
{
return 1;
}
bool GHOST_System::useNativePixel(void) bool GHOST_System::useNativePixel(void)
{ {
m_nativePixel = true; m_nativePixel = true;

@ -319,6 +319,10 @@ public:
*/ */
virtual int confirmQuit(GHOST_IWindow *window) const; virtual int confirmQuit(GHOST_IWindow *window) const;
/**
* Informs if the system provides native dialogs (eg. confirm quit)
*/
virtual bool supportsNativeDialogs(void);
protected: protected:

@ -52,6 +52,7 @@ public:
GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) { return GHOST_kFailure; } GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) { return GHOST_kFailure; }
void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const { /* nop */ } void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const { /* nop */ }
void getAllDisplayDimensions(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 init() {
GHOST_TSuccess success = GHOST_System::init(); GHOST_TSuccess success = GHOST_System::init();

@ -635,6 +635,11 @@ GHOST_SystemSDL::addDirtyWindow(GHOST_WindowSDL *bad_wind)
m_dirty_windows.push_back(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 GHOST_TSuccess GHOST_SystemSDL::getButtons(GHOST_Buttons& buttons) const
{ {

@ -95,6 +95,10 @@ public:
getMainDisplayDimensions(GHOST_TUns32& width, getMainDisplayDimensions(GHOST_TUns32& width,
GHOST_TUns32& height) const; GHOST_TUns32& height) const;
/**
* Informs if the system provides native dialogs (eg. confirm quit)
*/
virtual bool supportsNativeDialogs(void);
private: private:
GHOST_TSuccess GHOST_TSuccess

@ -386,6 +386,10 @@ createWindow(const STR_String& title,
return window; return window;
} }
bool GHOST_SystemX11::supportsNativeDialogs(void)
{
return false;
}
/** /**
* Create a new offscreen context. * Create a new offscreen context.

@ -97,6 +97,10 @@ public:
init( init(
); );
/**
* Informs if the system provides native dialogs (eg. confirm quit)
*/
virtual bool supportsNativeDialogs(void);
/** /**
* \section Interface Inherited from GHOST_ISystem * \section Interface Inherited from GHOST_ISystem

@ -213,7 +213,6 @@ class USERPREF_PT_interface(Panel):
return (userpref.active_section == 'INTERFACE') return (userpref.active_section == 'INTERFACE')
def draw(self, context): def draw(self, context):
import sys
layout = self.layout layout = self.layout
userpref = context.user_preferences userpref = context.user_preferences
@ -245,9 +244,8 @@ class USERPREF_PT_interface(Panel):
col.separator() col.separator()
if sys.platform[:3] == "win": col.label("Warnings")
col.label("Warnings") col.prop(view, "use_quit_dialog")
col.prop(view, "use_quit_dialog")
row.separator() row.separator()
row.separator() row.separator()

@ -2127,6 +2127,10 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_WM | ND_FILESAVE, NULL); WM_event_add_notifier(C, NC_WM | ND_FILESAVE, NULL);
if (RNA_boolean_get(op->ptr, "exit")) {
WM_exit(C);
}
return OPERATOR_FINISHED; return OPERATOR_FINISHED;
} }
@ -2226,12 +2230,16 @@ void WM_OT_save_mainfile(wmOperatorType *ot)
ot->check = blend_save_check; ot->check = blend_save_check;
/* omit window poll so this can work in background mode */ /* omit window poll so this can work in background mode */
PropertyRNA *prop;
WM_operator_properties_filesel( WM_operator_properties_filesel(
ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_SAVE, ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_SAVE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); 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, "compress", false, "Compress", "Write compressed .blend file");
RNA_def_boolean(ot->srna, "relative_remap", false, "Remap Relative", RNA_def_boolean(ot->srna, "relative_remap", false, "Remap Relative",
"Remap relative paths when saving in a different directory"); "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);
} }
/** \} */ /** \} */

@ -2317,10 +2317,16 @@ static void WM_OT_window_fullscreen_toggle(wmOperatorType *ot)
static int wm_exit_blender_exec(bContext *C, wmOperator *op) static int wm_exit_blender_exec(bContext *C, wmOperator *op)
{ {
WM_operator_free(op); wmWindowManager *wm = CTX_wm_manager(C);
WM_exit(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; return OPERATOR_FINISHED;
} }
@ -2330,7 +2336,6 @@ static void WM_OT_quit_blender(wmOperatorType *ot)
ot->idname = "WM_OT_quit_blender"; ot->idname = "WM_OT_quit_blender";
ot->description = "Quit Blender"; ot->description = "Quit Blender";
ot->invoke = WM_operator_confirm;
ot->exec = wm_exit_blender_exec; ot->exec = wm_exit_blender_exec;
} }

@ -334,6 +334,124 @@ wmWindow *wm_window_copy_test(bContext *C, wmWindow *win_src, const bool duplica
} }
} }
/* -------------------------------------------------------------------- */
/** \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 */ /* this is event from ghost, or exit-blender op */
void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
{ {
@ -350,16 +468,20 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
if (tmpwin == NULL) if (tmpwin == NULL)
do_exit = 1; do_exit = 1;
if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved && !G.background) { if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved && !G.background && do_exit) {
if (do_exit) { /* We have unsaved changes and we're quitting */
if(GHOST_SupportsNativeDialogs() == 0) {
wm_confirm_quit(C);
}
else {
if (!GHOST_confirmQuit(win->ghostwin)) if (!GHOST_confirmQuit(win->ghostwin))
return; return;
} }
} }
else if (do_exit) {
/* let WM_exit do all freeing, for correct quit.blend save */ /* No changes but we're quitting */
if (do_exit) { /* let WM_exit do all freeing, for correct quit.blend save */
WM_exit(C); WM_exit(C);
} }
else { else {

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