diff options
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r-- | source/blender/windowmanager/WM_types.h | 10 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_cursors.c | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 15 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_files.c | 71 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_window.c | 25 | ||||
-rw-r--r-- | source/blender/windowmanager/wm_files.h | 3 |
6 files changed, 83 insertions, 43 deletions
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index d54925272de..1d99b605205 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -132,17 +132,21 @@ struct wmWindowManager; extern "C" { #endif +typedef void (*wmGenericUserDataFreeFn)(void *data); + typedef struct wmGenericUserData { void *data; /** When NULL, use #MEM_freeN. */ - void (*free_fn)(void *data); + wmGenericUserDataFreeFn free_fn; bool use_free; } wmGenericUserData; +typedef void (*wmGenericCallbackFn)(struct bContext *C, void *user_data); + typedef struct wmGenericCallback { - void (*exec)(struct bContext *C, void *user_data); + wmGenericCallbackFn exec; void *user_data; - void (*free_user_data)(void *user_data); + wmGenericUserDataFreeFn free_user_data; } wmGenericCallback; /* ************** wmOperatorType ************************ */ diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c index cdb7b591907..11783ae3517 100644 --- a/source/blender/windowmanager/intern/wm_cursors.c +++ b/source/blender/windowmanager/intern/wm_cursors.c @@ -264,7 +264,7 @@ void WM_cursor_grab_enable(wmWindow *win, int wrap, bool hide, int bounds[4]) if (wrap == WM_CURSOR_WRAP_X) { mode_axis = GHOST_kAxisX; } - if (wrap == WM_CURSOR_WRAP_Y) { + else if (wrap == WM_CURSOR_WRAP_Y) { mode_axis = GHOST_kGrabAxisY; } } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 0d1f4cc4830..a6588c40f0f 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1048,7 +1048,7 @@ static int wm_operator_exec(bContext *C, wmOperator *op, const bool repeat, cons wmWindowManager *wm = CTX_wm_manager(C); int retval = OPERATOR_CANCELLED; - CTX_wm_operator_poll_msg_set(C, NULL); + CTX_wm_operator_poll_msg_clear(C); if (op == NULL || op->type == NULL) { return retval; @@ -1469,7 +1469,7 @@ static int wm_operator_call_internal(bContext *C, { int retval; - CTX_wm_operator_poll_msg_set(C, NULL); + CTX_wm_operator_poll_msg_clear(C); /* Dummy test. */ if (ot) { @@ -4478,16 +4478,21 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void event.prevtype = event.type; event.prevval = event.val; - /* Ensure the event state is correct, any deviation from this may cause bugs. */ + /* Ensure the event state is correct, any deviation from this may cause bugs. + * + * NOTE: #EVENT_NONE is set when unknown keys are pressed, + * while not common, avoid a false alarm. */ #ifndef NDEBUG if ((event_state->type || event_state->val) && /* Ignore cleared event state. */ - !(ISMOUSE_BUTTON(event_state->type) || ISKEYBOARD(event_state->type))) { + !(ISMOUSE_BUTTON(event_state->type) || ISKEYBOARD(event_state->type) || + (event_state->type == EVENT_NONE))) { CLOG_WARN(WM_LOG_HANDLERS, "Non-keyboard/mouse button found in 'win->eventstate->type = %d'", event_state->type); } if ((event_state->prevtype || event_state->prevval) && /* Ignore cleared event state. */ - !(ISMOUSE_BUTTON(event_state->prevtype) || ISKEYBOARD(event_state->prevtype))) { + !(ISMOUSE_BUTTON(event_state->prevtype) || ISKEYBOARD(event_state->prevtype) || + (event_state->type == EVENT_NONE))) { CLOG_WARN(WM_LOG_HANDLERS, "Non-keyboard/mouse button found in 'win->eventstate->prevtype = %d'", event_state->prevtype); diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index bbcb0669cce..d0ee7075516 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -2157,21 +2157,9 @@ static void wm_homefile_read_after_dialog_callback(bContext *C, void *user_data) C, "WM_OT_read_homefile", WM_OP_EXEC_DEFAULT, (IDProperty *)user_data); } -static void wm_free_operator_properties_callback(void *user_data) -{ - IDProperty *properties = (IDProperty *)user_data; - IDP_FreeProperty(properties); -} - static int wm_homefile_read_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (U.uiflag & USER_SAVE_PROMPT && - wm_file_or_image_is_modified(CTX_data_main(C), CTX_wm_manager(C))) { - wmGenericCallback *callback = MEM_callocN(sizeof(*callback), __func__); - callback->exec = wm_homefile_read_after_dialog_callback; - callback->user_data = IDP_CopyProperty(op->properties); - callback->free_user_data = wm_free_operator_properties_callback; - wm_close_file_dialog(C, callback); + if (wm_operator_close_file_dialog_if_needed(C, op, wm_homefile_read_after_dialog_callback)) { return OPERATOR_INTERFACE; } return wm_homefile_read_exec(C, op); @@ -2331,13 +2319,7 @@ static int wm_open_mainfile__discard_changes(bContext *C, wmOperator *op) set_next_operator_state(op, OPEN_MAINFILE_STATE_OPEN); } - if (U.uiflag & USER_SAVE_PROMPT && - wm_file_or_image_is_modified(CTX_data_main(C), CTX_wm_manager(C))) { - wmGenericCallback *callback = MEM_callocN(sizeof(*callback), __func__); - callback->exec = wm_open_mainfile_after_dialog_callback; - callback->user_data = IDP_CopyProperty(op->properties); - callback->free_user_data = wm_free_operator_properties_callback; - wm_close_file_dialog(C, callback); + if (wm_operator_close_file_dialog_if_needed(C, op, wm_open_mainfile_after_dialog_callback)) { return OPERATOR_INTERFACE; } return wm_open_mainfile_dispatch(C, op); @@ -2637,12 +2619,25 @@ static int wm_recover_last_session_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int wm_recover_last_session_invoke(bContext *C, wmOperator *op, const wmEvent *event) +static void wm_recover_last_session_after_dialog_callback(bContext *C, void *user_data) +{ + WM_operator_name_call_with_properties( + C, "WM_OT_recover_last_session", WM_OP_EXEC_DEFAULT, (IDProperty *)user_data); +} + +static int wm_recover_last_session_invoke(bContext *C, + wmOperator *op, + const wmEvent *UNUSED(event)) { /* Keep the current setting instead of using the preferences since a file selector * doesn't give us the option to change the setting. */ wm_open_init_use_scripts(op, false); - return WM_operator_confirm(C, op, event); + + if (wm_operator_close_file_dialog_if_needed( + C, op, wm_recover_last_session_after_dialog_callback)) { + return OPERATOR_INTERFACE; + } + return wm_recover_last_session_exec(C, op); } void WM_OT_recover_last_session(wmOperatorType *ot) @@ -3270,7 +3265,10 @@ static void wm_block_file_close_save(bContext *C, void *arg_block, void *arg_dat bool file_has_been_saved_before = BKE_main_blendfile_path(bmain)[0] != '\0'; if (file_has_been_saved_before) { - WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_EXEC_DEFAULT, NULL); + if (WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_EXEC_DEFAULT, NULL) & + OPERATOR_CANCELLED) { + execute_callback = false; + } } else { WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_INVOKE_DEFAULT, NULL); @@ -3456,4 +3454,31 @@ void wm_close_file_dialog(bContext *C, wmGenericCallback *post_action) } } +static void wm_free_operator_properties_callback(void *user_data) +{ + IDProperty *properties = (IDProperty *)user_data; + IDP_FreeProperty(properties); +} + +/** + * \return True if the dialog was created, the calling operator should return #OPERATOR_INTERFACE + * then. + */ +bool wm_operator_close_file_dialog_if_needed(bContext *C, + wmOperator *op, + wmGenericCallbackFn post_action_fn) +{ + if (U.uiflag & USER_SAVE_PROMPT && + wm_file_or_image_is_modified(CTX_data_main(C), CTX_wm_manager(C))) { + wmGenericCallback *callback = MEM_callocN(sizeof(*callback), __func__); + callback->exec = post_action_fn; + callback->user_data = IDP_CopyProperty(op->properties); + callback->free_user_data = wm_free_operator_properties_callback; + wm_close_file_dialog(C, callback); + return true; + } + + return false; +} + /** \} */ diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 2e9fd1b1b16..cdd5ea12df8 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -133,7 +133,7 @@ static struct WMInitStruct { * \{ */ static void wm_window_set_drawable(wmWindowManager *wm, wmWindow *win, bool activate); -static int wm_window_timer(const bContext *C); +static bool wm_window_timer(const bContext *C); /* XXX this one should correctly check for apple top header... * done for Cocoa : returns window contents (and not frame) max size*/ @@ -1498,12 +1498,12 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr * Timer handlers should check for delta to decide if they just update, or follow real time. * Timer handlers can also set duration to match frames passed */ -static int wm_window_timer(const bContext *C) +static bool wm_window_timer(const bContext *C) { Main *bmain = CTX_data_main(C); wmWindowManager *wm = CTX_wm_manager(C); double time = PIL_check_seconds_timer(); - int retval = 0; + bool has_event = false; /* Mutable in case the timer gets removed. */ LISTBASE_FOREACH_MUTABLE (wmTimer *, wt, &wm->timers) { @@ -1540,31 +1540,34 @@ static int wm_window_timer(const bContext *C) event.customdata = wt; wm_event_add(win, &event); - retval = 1; + has_event = true; } } } - return retval; + return has_event; } void wm_window_process_events(const bContext *C) { BLI_assert(BLI_thread_is_main()); - int hasevent = GHOST_ProcessEvents(g_system, 0); /* 0 is no wait */ + bool has_event = GHOST_ProcessEvents(g_system, false); /* `false` is no wait. */ - if (hasevent) { + if (has_event) { GHOST_DispatchEvents(g_system); } - hasevent |= wm_window_timer(C); + has_event |= wm_window_timer(C); #ifdef WITH_XR_OPENXR /* XR events don't use the regular window queues. So here we don't only trigger * processing/dispatching but also handling. */ - hasevent |= wm_xr_events_handle(CTX_wm_manager(C)); + has_event |= wm_xr_events_handle(CTX_wm_manager(C)); #endif - /* no event, we sleep 5 milliseconds */ - if (hasevent == 0) { + /* When there is no event, sleep 5 milliseconds not to use too much CPU when idle. + * + * Skip sleeping when simulating events so tests don't idle unnecessarily as simulated + * events are typically generated from a timer that runs in the main loop. */ + if ((has_event == false) && !(G.f & G_FLAG_EVENT_SIMULATE)) { PIL_sleep_ms(5); } } diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h index d54090a6025..c7fe07cad7f 100644 --- a/source/blender/windowmanager/wm_files.h +++ b/source/blender/windowmanager/wm_files.h @@ -45,6 +45,9 @@ void wm_homefile_read(struct bContext *C, void wm_file_read_report(bContext *C, struct Main *bmain); void wm_close_file_dialog(bContext *C, struct wmGenericCallback *post_action); +bool wm_operator_close_file_dialog_if_needed(bContext *C, + wmOperator *op, + wmGenericCallbackFn exec_fn); bool wm_file_or_image_is_modified(const Main *bmain, const wmWindowManager *wm); void WM_OT_save_homefile(struct wmOperatorType *ot); |