Merge remote-tracking branch 'upstream/blender-v3.5-release'

This commit is contained in:
Bastien Montagne
2023-03-03 15:27:07 +01:00
4 changed files with 56 additions and 18 deletions

View File

@@ -544,6 +544,8 @@ struct wmTimer *WM_event_add_timer_notifier(struct wmWindowManager *wm,
struct wmWindow *win,
unsigned int type,
double timestep);
/** Mark the given `timer` to be removed, actual removal and deletion is deferred and handled
* internally by the window manager code. */
void WM_event_remove_timer(struct wmWindowManager *wm,
struct wmWindow *win,
struct wmTimer *timer);

View File

@@ -848,6 +848,11 @@ typedef struct wmXrActionData {
typedef enum {
/** Do not attempt to free custom-data pointer even if non-NULL. */
WM_TIMER_NO_FREE_CUSTOM_DATA = 1 << 0,
/* Internal falgs, should not be used outside of WM code. */
/** This timer has been tagged for removal and deletion, handled by WM code to ensure timers are
* deleted in a safe context. */
WM_TIMER_TAGGED_FOR_REMOVAL = 1 << 16,
} wmTimerFlags;
typedef struct wmTimer {

View File

@@ -231,6 +231,9 @@ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win)
/* end running jobs, a job end also removes its timer */
LISTBASE_FOREACH_MUTABLE (wmTimer *, wt, &wm->timers) {
if (wt->flags & WM_TIMER_TAGGED_FOR_REMOVAL) {
continue;
}
if (wt->win == win && wt->event_type == TIMERJOBS) {
wm_jobs_timer_end(wm, wt);
}
@@ -238,10 +241,14 @@ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win)
/* timer removing, need to call this api function */
LISTBASE_FOREACH_MUTABLE (wmTimer *, wt, &wm->timers) {
if (wt->flags & WM_TIMER_TAGGED_FOR_REMOVAL) {
continue;
}
if (wt->win == win) {
WM_event_remove_timer(wm, win, wt);
}
}
wm_window_delete_removed_timers(wm);
if (win->eventstate) {
MEM_freeN(win->eventstate);
@@ -1547,6 +1554,9 @@ static bool wm_window_timer(const bContext *C)
/* Mutable in case the timer gets removed. */
LISTBASE_FOREACH_MUTABLE (wmTimer *, wt, &wm->timers) {
if (wt->flags & WM_TIMER_TAGGED_FOR_REMOVAL) {
continue;
}
wmWindow *win = wt->win;
if (wt->sleep != 0) {
@@ -1588,6 +1598,10 @@ static bool wm_window_timer(const bContext *C)
}
}
}
/* Effectively delete all timers marked for removal. */
wm_window_delete_removed_timers(wm);
return has_event;
}
@@ -1832,6 +1846,9 @@ void WM_event_timer_sleep(wmWindowManager *wm,
bool do_sleep)
{
LISTBASE_FOREACH (wmTimer *, wt, &wm->timers) {
if (wt->flags & WM_TIMER_TAGGED_FOR_REMOVAL) {
continue;
}
if (wt == timer) {
wt->sleep = do_sleep;
break;
@@ -1878,38 +1895,48 @@ wmTimer *WM_event_add_timer_notifier(wmWindowManager *wm,
return wt;
}
void wm_window_delete_removed_timers(wmWindowManager *wm)
{
LISTBASE_FOREACH_MUTABLE (wmTimer *, wt, &wm->timers) {
if ((wt->flags & WM_TIMER_TAGGED_FOR_REMOVAL) == 0) {
continue;
}
/* Actual removal and freeing of the timer. */
BLI_remlink(&wm->timers, wt);
MEM_freeN(wt);
}
}
void WM_event_remove_timer(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *timer)
{
/* extra security check */
wmTimer *wt = NULL;
LISTBASE_FOREACH (wmTimer *, timer_iter, &wm->timers) {
if (timer_iter == timer) {
wt = timer_iter;
}
}
if (wt == NULL) {
/* Extra security check. */
if (BLI_findindex(&wm->timers, timer) < 0) {
return;
}
if (wm->reports.reporttimer == wt) {
timer->flags |= WM_TIMER_TAGGED_FOR_REMOVAL;
/* Clear existing references to the timer. */
if (wm->reports.reporttimer == timer) {
wm->reports.reporttimer = NULL;
}
BLI_remlink(&wm->timers, wt);
if (wt->customdata != NULL && (wt->flags & WM_TIMER_NO_FREE_CUSTOM_DATA) == 0) {
MEM_freeN(wt->customdata);
}
MEM_freeN(wt);
/* there might be events in queue with this timer as customdata */
/* There might be events in queue with this timer as customdata. */
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
LISTBASE_FOREACH (wmEvent *, event, &win->event_queue) {
if (event->customdata == wt) {
if (event->customdata == timer) {
event->customdata = NULL;
event->type = EVENT_NONE; /* Timer users customdata, don't want `NULL == NULL`. */
}
}
}
/* Immediately free customdata if requested, so that invalid usages of that data after
* calling `WM_event_remove_timer` can be easily spotted (through ASAN errors e.g.). */
if (timer->customdata != NULL && (timer->flags & WM_TIMER_NO_FREE_CUSTOM_DATA) == 0) {
MEM_freeN(timer->customdata);
timer->customdata = NULL;
}
}
void WM_event_remove_timer_notifier(wmWindowManager *wm, wmWindow *win, wmTimer *timer)

View File

@@ -112,6 +112,10 @@ void wm_window_IME_begin(wmWindow *win, int x, int y, int w, int h, bool complet
void wm_window_IME_end(wmWindow *win);
#endif
/** Effectively remove timers from the list and delete them. Calling this should only be done by
* internal WM management code, from specific, safe places. */
void wm_window_delete_removed_timers(wmWindowManager *wm);
/* *************** window operators ************** */
int wm_window_close_exec(bContext *C, struct wmOperator *op);