Auto Save

Auto save is now working again in 2.5. It will also remember now what
the location of the original file was when recovering it, so that
library links still work and saving the restored file does not save to
the temp directory. There is also a new Recover Auto Save operator
which will open the filebrowser in the temp directory and show the
auto saved .blends.

Implemenation Notes:

* Timer storage was moved from window to windowmanager, so we can have
  windowmanager level timers too now, doesn't make sense to have
  autosave timer attached to a particular window.
* FileGlobal now has a filename field storing where the file was saved.
  Note that this is only used when loading a file through the recover
  operators, regular file read doesn't use it, so copying the quit.blend
  manually over the original file will still work as expected.
* Jobs timer no longer uses operator now, this seems more like an
  internal thing, changing keymaps should not make it possible to break
  the jobs manager.
* Autosave is postponed by 10 seconds when a modal operator is running,
  e.g. transform or file browsing.
* Moved setting G.sce in setup_app_data before depsgraph updates, these
  can use the filename for pointcaches.
This commit is contained in:
Brecht Van Lommel 2009-10-20 13:58:53 +00:00
parent b8eec2b8fe
commit cb8f7fd385
Notes: blender-bot 2023-05-02 17:50:06 +02:00
Referenced by issue #77825, Autosave is postponed by 10 seconds when a modal operator is running
Referenced by pull request #107555, WM: don't skip AutoSave if modal operator is 'fileselect'
33 changed files with 329 additions and 225 deletions

View File

@ -1412,7 +1412,7 @@ setWindowCursorGrab(
setWindowCursorVisibility(false);
}
XGrabPointer(m_display, m_window, True, ButtonPressMask| ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
//XGrabPointer(m_display, m_window, True, ButtonPressMask| ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
}
else {
if (m_cursorGrab==GHOST_kGrabHide) {
@ -1430,7 +1430,7 @@ setWindowCursorGrab(
/* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
setCursorGrabAccum(0, 0);
m_cursorGrabBounds.m_l= m_cursorGrabBounds.m_r= -1; /* disable */
XUngrabPointer(m_display, CurrentTime);
//XUngrabPointer(m_display, CurrentTime);
}
XFlush(m_display);

View File

@ -54,6 +54,7 @@ class INFO_MT_file(bpy.types.Menu):
layout.itemO("wm.open_mainfile", text="Open...", icon='ICON_FILE_FOLDER')
layout.item_menu_enumO("wm.open_recentfile", "file", text="Open Recent")
layout.itemO("wm.recover_last_session")
layout.itemO("wm.recover_auto_save", text="Recover Auto Save...")
layout.itemS()

View File

@ -145,6 +145,7 @@ typedef struct Global {
#define G_FILE_GLSL_NO_NODES (1 << 20) /* deprecated */
#define G_FILE_GLSL_NO_EXTRA_TEX (1 << 21) /* deprecated */
#define G_FILE_IGNORE_DEPRECATION_WARNINGS (1 << 22) /* deprecated */
#define G_FILE_RECOVER (1 << 23)
/* G.windowstate */
#define G_WINDOWSTATE_USERDEF 0

View File

@ -281,12 +281,15 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
Object *ob;
bScreen *curscreen= NULL;
Scene *curscene= NULL;
int recover;
char mode;
/* 'u' = undo save, 'n' = no UI load */
if(bfd->main->screen.first==NULL) mode= 'u';
else if(G.fileflags & G_FILE_NO_UI) mode= 'n';
else mode= 0;
recover= (G.fileflags & G_FILE_RECOVER);
clean_paths(bfd->main);
@ -371,6 +374,16 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
if(G.main->versionfile < 250)
do_versions_ipos_to_animato(G.main); // XXX fixme... complicated versionpatching
/* in case of autosave or quit.blend, use original filename instead */
if(recover && bfd->filename[0])
filename= bfd->filename;
/* these are the same at times, should never copy to the same location */
if(G.sce != filename)
BLI_strncpy(G.sce, filename, FILE_MAX);
BLI_strncpy(G.main->name, filename, FILE_MAX); /* is guaranteed current file */
/* baseflags, groups, make depsgraph, etc */
set_scene_bg(CTX_data_scene(C));
@ -383,11 +396,6 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
/* now tag update flags, to ensure deformers get calculated on redraw */
DAG_scene_update_flags(CTX_data_scene(C), CTX_data_scene(C)->lay);
if (G.sce != filename) /* these are the same at times, should never copy to the same location */
strcpy(G.sce, filename);
BLI_strncpy(G.main->name, filename, FILE_MAX); /* is guaranteed current file */
MEM_freeN(bfd);
}

View File

@ -62,6 +62,7 @@ typedef struct BlendFileData {
int fileflags;
int displaymode;
int globalf;
char filename[240]; /* 240 = FILE_MAX */
struct bScreen* curscreen;
struct Scene* curscene;

View File

@ -4432,7 +4432,6 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
win->curswin= NULL;
win->tweak= NULL;
win->timers.first= win->timers.last= NULL;
win->queue.first= win->queue.last= NULL;
win->handlers.first= win->handlers.last= NULL;
win->modalhandlers.first= win->modalhandlers.last= NULL;
@ -4444,6 +4443,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
win->drawfail= 0;
}
wm->timers.first= wm->timers.last= NULL;
wm->operators.first= wm->operators.last= NULL;
wm->paintcursors.first= wm->paintcursors.last= NULL;
wm->queue.first= wm->queue.last= NULL;
@ -5468,6 +5468,7 @@ static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
bfd->fileflags= fg->fileflags;
bfd->displaymode= fg->displaymode;
bfd->globalf= fg->globalf;
BLI_strncpy(bfd->filename, fg->filename, sizeof(bfd->filename));
bfd->curscreen= fg->curscreen;
bfd->curscene= fg->curscene;

View File

@ -2308,7 +2308,7 @@ static void write_scripts(WriteData *wd, ListBase *idbase)
/* context is usually defined by WM, two cases where no WM is available:
* - for forward compatibility, curscreen has to be saved
* - for undofile, curscene needs to be saved */
static void write_global(WriteData *wd, Main *mainvar)
static void write_global(WriteData *wd, int fileflags, Main *mainvar)
{
FileGlobal fg;
bScreen *screen;
@ -2321,8 +2321,9 @@ static void write_global(WriteData *wd, Main *mainvar)
fg.curscene= screen->scene;
fg.displaymode= G.displaymode;
fg.winpos= G.winpos;
fg.fileflags= (G.fileflags & ~G_FILE_NO_UI); // prevent to save this, is not good convention, and feature with concerns...
fg.fileflags= (fileflags & ~G_FILE_NO_UI); // prevent to save this, is not good convention, and feature with concerns...
fg.globalf= G.f;
BLI_strncpy(fg.filename, mainvar->name, sizeof(fg.filename));
sprintf(subvstr, "%4d", BLENDER_SUBVERSION);
memcpy(fg.subvstr, subvstr, 4);
@ -2351,7 +2352,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
mywrite(wd, buf, 12);
write_renderinfo(wd, mainvar);
write_global(wd, mainvar);
write_global(wd, write_flags, mainvar);
/* no UI save in undo */
if(current==NULL) {

View File

@ -92,6 +92,7 @@ typedef enum uiHandleButtonState {
} uiHandleButtonState;
typedef struct uiHandleButtonData {
wmWindowManager *wm;
wmWindow *window;
ARegion *region;
@ -3677,7 +3678,7 @@ static void button_timers_tooltip_remove(bContext *C, uiBut *but)
data= but->active;
if(data->tooltiptimer) {
WM_event_remove_window_timer(data->window, data->tooltiptimer);
WM_event_remove_timer(data->wm, data->window, data->tooltiptimer);
data->tooltiptimer= NULL;
}
if(data->tooltip) {
@ -3686,7 +3687,7 @@ static void button_timers_tooltip_remove(bContext *C, uiBut *but)
}
if(data->autoopentimer) {
WM_event_remove_window_timer(data->window, data->autoopentimer);
WM_event_remove_timer(data->wm, data->window, data->autoopentimer);
data->autoopentimer= NULL;
}
}
@ -3698,13 +3699,13 @@ static void button_tooltip_timer_reset(uiBut *but)
data= but->active;
if(data->tooltiptimer) {
WM_event_remove_window_timer(data->window, data->tooltiptimer);
WM_event_remove_timer(data->wm, data->window, data->tooltiptimer);
data->tooltiptimer= NULL;
}
if(U.flag & USER_TOOLTIPS)
if(!but->block->tooltipdisabled)
data->tooltiptimer= WM_event_add_window_timer(data->window, TIMER, BUTTON_TOOLTIP_DELAY);
data->tooltiptimer= WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_TOOLTIP_DELAY);
}
static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state)
@ -3732,7 +3733,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
else time= -1;
if(time >= 0)
data->autoopentimer= WM_event_add_window_timer(data->window, TIMER, 0.02*(double)time);
data->autoopentimer= WM_event_add_timer(data->wm, data->window, TIMER, 0.02*(double)time);
}
}
}
@ -3765,10 +3766,10 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
/* add a short delay before exiting, to ensure there is some feedback */
if(state == BUTTON_STATE_WAIT_FLASH) {
data->flashtimer= WM_event_add_window_timer(data->window, TIMER, BUTTON_FLASH_DELAY);
data->flashtimer= WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_FLASH_DELAY);
}
else if(data->flashtimer) {
WM_event_remove_window_timer(data->window, data->flashtimer);
WM_event_remove_timer(data->wm, data->window, data->flashtimer);
data->flashtimer= NULL;
}
@ -3799,6 +3800,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
/* setup struct */
data= MEM_callocN(sizeof(uiHandleButtonData), "uiHandleButtonData");
data->wm= CTX_wm_manager(C);
data->window= CTX_wm_window(C);
data->region= ar;
if( ELEM(but->type, BUT_CURVE, SEARCH_MENU) ); // XXX curve is temp
@ -4036,7 +4038,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
case TIMER: {
/* handle tooltip timer */
if(event->customdata == data->tooltiptimer) {
WM_event_remove_window_timer(data->window, data->tooltiptimer);
WM_event_remove_timer(data->wm, data->window, data->tooltiptimer);
data->tooltiptimer= NULL;
if(!data->tooltip)
@ -4044,7 +4046,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
}
/* handle menu auto open timer */
else if(event->customdata == data->autoopentimer) {
WM_event_remove_window_timer(data->window, data->autoopentimer);
WM_event_remove_timer(data->wm, data->window, data->autoopentimer);
data->autoopentimer= NULL;
if(ui_mouse_inside_button(ar, but, event->x, event->y))
@ -4058,7 +4060,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
case MIDDLEMOUSE:
/* XXX hardcoded keymap check... but anyway, while view changes, tooltips should be removed */
if(data->tooltiptimer) {
WM_event_remove_window_timer(data->window, data->tooltiptimer);
WM_event_remove_timer(data->wm, data->window, data->tooltiptimer);
data->tooltiptimer= NULL;
}
/* pass on purposedly */

View File

@ -1189,7 +1189,7 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
pa->flag |= PNL_SELECT;
if(data && data->animtimer) {
WM_event_remove_window_timer(win, data->animtimer);
WM_event_remove_timer(CTX_wm_manager(C), win, data->animtimer);
data->animtimer= NULL;
}
@ -1208,7 +1208,7 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
}
if(ELEM(state, PANEL_STATE_ANIMATION, PANEL_STATE_DRAG))
data->animtimer= WM_event_add_window_timer(win, TIMER, ANIMATION_INTERVAL);
data->animtimer= WM_event_add_timer(CTX_wm_manager(C), win, TIMER, ANIMATION_INTERVAL);
data->state= state;
data->startx= win->eventstate->x;

View File

@ -1040,7 +1040,7 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
/* wake up animtimer */
if(win->screen->animtimer)
WM_event_window_timer_sleep(win, win->screen->animtimer, 0);
WM_event_timer_sleep(wm, win, win->screen->animtimer, 0);
if(G.f & G_DEBUG) printf("set screen\n");
win->screen->do_refresh= 0;
@ -1097,6 +1097,7 @@ void ED_area_exit(bContext *C, ScrArea *sa)
void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
{
wmWindowManager *wm= CTX_wm_manager(C);
wmWindow *prevwin= CTX_wm_window(C);
ScrArea *sa;
ARegion *ar;
@ -1104,7 +1105,7 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
CTX_wm_window_set(C, window);
if(screen->animtimer)
WM_event_remove_window_timer(window, screen->animtimer);
WM_event_remove_timer(wm, window, screen->animtimer);
screen->animtimer= NULL;
if(screen->mainwin)
@ -1232,6 +1233,7 @@ int ED_screen_area_active(const bContext *C)
/* Do NOT call in area/region queues! */
void ED_screen_set(bContext *C, bScreen *sc)
{
wmWindowManager *wm= CTX_wm_manager(C);
wmWindow *win= CTX_wm_window(C);
bScreen *oldscreen= CTX_wm_screen(C);
ID *id;
@ -1264,7 +1266,7 @@ void ED_screen_set(bContext *C, bScreen *sc)
/* we put timer to sleep, so screen_exit has to think there's no timer */
oldscreen->animtimer= NULL;
if(wt)
WM_event_window_timer_sleep(win, wt, 1);
WM_event_timer_sleep(wm, win, wt, 1);
ED_screen_exit(C, win, oldscreen);
oldscreen->animtimer= wt;
@ -1519,17 +1521,18 @@ void ED_screen_full_prevspace(bContext *C)
void ED_screen_animation_timer(bContext *C, int redraws, int sync, int enable)
{
bScreen *screen= CTX_wm_screen(C);
wmWindowManager *wm= CTX_wm_manager(C);
wmWindow *win= CTX_wm_window(C);
Scene *scene= CTX_data_scene(C);
if(screen->animtimer)
WM_event_remove_window_timer(win, screen->animtimer);
WM_event_remove_timer(wm, win, screen->animtimer);
screen->animtimer= NULL;
if(enable) {
struct ScreenAnimData *sad= MEM_callocN(sizeof(ScreenAnimData), "ScreenAnimData");
screen->animtimer= WM_event_add_window_timer(win, TIMER0, (1.0/FPS));
screen->animtimer= WM_event_add_timer(wm, win, TIMER0, (1.0/FPS));
sad->ar= CTX_wm_region(C);
sad->redraws= redraws;
sad->flag |= (enable < 0)? ANIMPLAY_FLAG_REVERSE: 0;

View File

@ -4645,7 +4645,7 @@ static void paint_exit(bContext *C, wmOperator *op)
PaintOperation *pop= op->customdata;
if(pop->timer)
WM_event_remove_window_timer(CTX_wm_window(C), pop->timer);
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), pop->timer);
settings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
imapaint_canvas_free(&pop->s);
@ -4757,7 +4757,7 @@ static int paint_invoke(bContext *C, wmOperator *op, wmEvent *event)
WM_event_add_modal_handler(C, op);
if(pop->s.brush->flag & BRUSH_AIRBRUSH)
pop->timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER, 0.01f);
pop->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
return OPERATOR_RUNNING_MODAL;
}

View File

@ -243,7 +243,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
WM_paint_cursor_activate(CTX_wm_manager(C), paint_poll, paint_draw_smooth_stroke, stroke);
if(stroke->brush->flag & BRUSH_AIRBRUSH)
stroke->timer = WM_event_add_window_timer(CTX_wm_window(C), TIMER, stroke->brush->rate);
stroke->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, stroke->brush->rate);
}
ED_region_tag_redraw(ar);
@ -270,7 +270,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
WM_paint_cursor_end(CTX_wm_manager(C), stroke->smooth_stroke_cursor);
if(stroke->timer)
WM_event_remove_window_timer(CTX_wm_window(C), stroke->timer);
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), stroke->timer);
stroke->done(C, stroke);
MEM_freeN(stroke);

View File

@ -610,7 +610,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
}
if (!sfile->loadimage_timer)
sfile->loadimage_timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER1, 1.0/30.0); /* max 30 frames/sec. */
sfile->loadimage_timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER1, 1.0/30.0); /* max 30 frames/sec. */
}

View File

@ -1680,7 +1680,7 @@ static void record_composite_exit(bContext *C, wmOperator *op)
WM_cursor_restore(CTX_wm_window(C));
if(rcd->timer)
WM_event_remove_window_timer(CTX_wm_window(C), rcd->timer);
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), rcd->timer);
WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, sima->image);
@ -1711,7 +1711,7 @@ static int record_composite_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_CANCELLED;
rcd= op->customdata;
rcd->timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER, 0.0f);
rcd->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.0f);
WM_event_add_modal_handler(C, op);
if(!record_composite_apply(C, op))

View File

@ -292,9 +292,9 @@ void smooth_view(bContext *C, Object *oldcamera, Object *camera, float *ofs, flo
rv3d->sms= MEM_mallocN(sizeof(struct SmoothViewStore), "smoothview v3d");
*rv3d->sms= sms;
if(rv3d->smooth_timer)
WM_event_remove_window_timer(CTX_wm_window(C), rv3d->smooth_timer);
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), rv3d->smooth_timer);
/* TIMER1 is hardcoded in keymap */
rv3d->smooth_timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER1, 1.0/30.0); /* max 30 frs/sec */
rv3d->smooth_timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER1, 1.0/30.0); /* max 30 frs/sec */
return;
}
@ -346,7 +346,7 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *op, wmEvent *event)
MEM_freeN(rv3d->sms);
rv3d->sms= NULL;
WM_event_remove_window_timer(CTX_wm_window(C), rv3d->smooth_timer);
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), rv3d->smooth_timer);
rv3d->smooth_timer= NULL;
}
else {
@ -1798,7 +1798,7 @@ int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *event)
fly->dvec_prev[0]= fly->dvec_prev[1]= fly->dvec_prev[2]= 0.0f;
fly->timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER, 0.01f);
fly->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
/* we have to rely on events to give proper mousecoords after a warp_pointer */
@ -1867,7 +1867,7 @@ static int flyEnd(bContext *C, FlyInfo *fly)
if(fly->state == FLY_RUNNING)
return OPERATOR_RUNNING_MODAL;
WM_event_remove_window_timer(CTX_wm_window(C), fly->timer);
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), fly->timer);
rv3d->dist= fly->dist_backup;

View File

@ -303,7 +303,7 @@ static void minimize_stretch_exit(bContext *C, wmOperator *op, int cancel)
if(sa)
ED_area_headerprint(sa, NULL);
if(ms->timer)
WM_event_remove_window_timer(CTX_wm_window(C), ms->timer);
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), ms->timer);
if(cancel)
param_flush_restore(ms->handle);
@ -343,7 +343,7 @@ static int minimize_stretch_invoke(bContext *C, wmOperator *op, wmEvent *event)
ms= op->customdata;
WM_event_add_modal_handler(C, op);
ms->timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER, 0.01f);
ms->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
return OPERATOR_RUNNING_MODAL;
}

View File

@ -47,6 +47,9 @@ typedef struct FileGlobal {
struct Scene *curscene;
int fileflags;
int globalf;
/* file path where this was saved, for recover */
char filename[240]; /* 240 = FILE_MAX */
} FileGlobal;

View File

@ -124,6 +124,9 @@ typedef struct wmWindowManager {
ListBase keyconfigs; /* known key configurations */
struct wmKeyConfig *defaultconf; /* default configuration, not saved */
int defaultactmap, pad2; /* active keymap from default for editing */
ListBase timers; /* active timers */
struct wmTimer *autosavetimer; /* timer for auto save */
} wmWindowManager;
/* wmWindowManager.initialized */
@ -160,8 +163,6 @@ typedef struct wmWindow {
int drawmethod, drawfail; /* internal for wm_draw.c only */
void *drawdata; /* internal for wm_draw.c only */
ListBase timers;
ListBase queue; /* all events (ghost level events were handled) */
ListBase handlers; /* window+screen handlers, handled last */
ListBase modalhandlers; /* priority handlers, handled first */

View File

@ -146,7 +146,11 @@ static void rna_UserDef_weight_color_update(bContext *C, PointerRNA *ptr)
rna_userdef_update(C, ptr);
}
static void rna_userdef_autosave_update(bContext *C, PointerRNA *ptr)
{
WM_autosave_init(C);
rna_userdef_update(C, ptr);
}
#else
@ -2344,11 +2348,13 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna)
prop= RNA_def_property(srna, "auto_save_temporary_files", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_AUTOSAVE);
RNA_def_property_ui_text(prop, "Auto Save Temporary Files", "Automatic saving of temporary files.");
RNA_def_property_update(prop, 0, "rna_userdef_autosave_update");
prop= RNA_def_property(srna, "auto_save_time", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "savetime");
RNA_def_property_range(prop, 1, 60);
RNA_def_property_ui_text(prop, "Auto Save Time", "The time (in minutes) to wait between automatic temporary saves.");
RNA_def_property_update(prop, 0, "rna_userdef_autosave_update");
prop= RNA_def_property(srna, "recent_files", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 0, 30);

View File

@ -93,7 +93,6 @@ EnumPropertyItem event_timer_type_items[]= {
{TIMER0, "TIMER0", 0, "Timer 0", ""},
{TIMER1, "TIMER1", 0, "Timer 1", ""},
{TIMER2, "TIMER2", 0, "Timer 2", ""},
{TIMERJOBS, "JOBS_TIMER", 0, "Jobs Timer", ""},
{0, NULL, 0, NULL, NULL}};
/* not returned: CAPSLOCKKEY, UNKNOWNKEY, GRLESSKEY */
@ -229,7 +228,6 @@ EnumPropertyItem event_type_items[] = {
{TIMER0, "TIMER0", 0, "Timer 0", ""},
{TIMER1, "TIMER1", 0, "Timer 1", ""},
{TIMER2, "TIMER2", 0, "Timer 2", ""},
{TIMERJOBS, "JOBS_TIMER", 0, "Jobs Timer", ""},
{0, NULL, 0, NULL, NULL}};
#define KMI_TYPE_KEYBOARD 0

View File

@ -67,9 +67,9 @@ void WM_window_open_temp (struct bContext *C, struct rcti *position, int type);
int WM_read_homefile (struct bContext *C, struct wmOperator *op);
int WM_write_homefile (struct bContext *C, struct wmOperator *op);
void WM_read_file (struct bContext *C, char *name, struct ReportList *reports);
void WM_write_file (struct bContext *C, char *target, int compress, struct ReportList *reports);
void WM_write_file (struct bContext *C, char *target, int fileflags, struct ReportList *reports);
void WM_read_autosavefile(struct bContext *C);
void WM_write_autosave (struct bContext *C);
void WM_autosave_init (struct bContext *C);
/* mouse cursors */
void WM_cursor_set (struct wmWindow *win, int curs);
@ -141,9 +141,9 @@ void WM_main_add_notifier(unsigned int type, void *reference);
void wm_event_add (struct wmWindow *win, struct wmEvent *event_to_add); /* XXX only for warning */
/* at maximum, every timestep seconds it triggers event_type events */
struct wmTimer *WM_event_add_window_timer(struct wmWindow *win, int event_type, double timestep);
void WM_event_remove_window_timer(struct wmWindow *win, struct wmTimer *timer);
void WM_event_window_timer_sleep(struct wmWindow *win, struct wmTimer *timer, int dosleep);
struct wmTimer *WM_event_add_timer(struct wmWindowManager *wm, struct wmWindow *win, int event_type, double timestep);
void WM_event_remove_timer(struct wmWindowManager *wm, struct wmWindow *win, struct wmTimer *timer);
void WM_event_timer_sleep(struct wmWindowManager *wm, struct wmWindow *win, struct wmTimer *timer, int dosleep);
/* operator api, default callbacks */
/* invoke callback, uses enum property named "type" */

View File

@ -289,6 +289,9 @@ typedef struct wmTabletData {
typedef struct wmTimer {
struct wmTimer *next, *prev;
struct wmWindow *win; /* window this timer is attached to (optional) */
double timestep; /* set by timer user */
int event_type; /* set by timer user, goes to event system */
void *customdata; /* set by timer user, to allow custom values */

View File

@ -209,8 +209,10 @@ void wm_check(bContext *C)
if(wm->windows.first==NULL) return;
/* case: fileread */
if((wm->initialized & WM_INIT_WINDOW) == 0)
if((wm->initialized & WM_INIT_WINDOW) == 0) {
WM_keymap_init(C);
WM_autosave_init(C);
}
/* case: no open windows at all, for old file reads */
wm_window_add_ghostwindows(wm);
@ -269,12 +271,15 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
wmWindow *win;
wmOperator *op;
wmKeyConfig *keyconf;
if(wm->autosavetimer)
wm_autosave_timer_ended(wm);
while((win= wm->windows.first)) {
BLI_remlink(&wm->windows, win);
win->screen= NULL; /* prevent draw clear to use screen */
wm_draw_window_clear(win);
wm_window_free(C, win);
wm_window_free(C, wm, win);
}
while((op= wm->operators.first)) {

View File

@ -44,6 +44,8 @@
#include "ED_screen.h"
#include "GPU_extensions.h"
#include "WM_api.h"
#include "WM_types.h"
#include "wm.h"

View File

@ -791,7 +791,7 @@ static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi)
static int wm_event_always_pass(wmEvent *event)
{
/* some events we always pass on, to ensure proper communication */
return ELEM5(event->type, TIMER, TIMER0, TIMER1, TIMER2, TIMERJOBS);
return ELEM4(event->type, TIMER, TIMER0, TIMER1, TIMER2);
}
/* operator exists */

View File

@ -95,6 +95,7 @@
#include "WM_types.h"
#include "wm.h"
#include "wm_window.h"
#include "wm_event_system.h"
static void writeBlog(void);
@ -348,49 +349,6 @@ int WM_read_homefile(bContext *C, wmOperator *op)
}
static void get_autosave_location(char buf[FILE_MAXDIR+FILE_MAXFILE])
{
char pidstr[32];
#ifdef WIN32
char subdir[9];
char savedir[FILE_MAXDIR];
#endif
sprintf(pidstr, "%d.blend", abs(getpid()));
#ifdef WIN32
if (!BLI_exists(U.tempdir)) {
BLI_strncpy(subdir, "autosave", sizeof(subdir));
BLI_make_file_string("/", savedir, BLI_gethome(), subdir);
/* create a new autosave dir
* function already checks for existence or not */
BLI_recurdir_fileops(savedir);
BLI_make_file_string("/", buf, savedir, pidstr);
return;
}
#endif
BLI_make_file_string("/", buf, U.tempdir, pidstr);
}
void WM_read_autosavefile(bContext *C)
{
char tstr[FILE_MAX], scestr[FILE_MAX];
int save_over;
BLI_strncpy(scestr, G.sce, FILE_MAX); /* temporal store */
get_autosave_location(tstr);
save_over = G.save_over;
BKE_read_file(C, tstr, NULL, NULL);
G.save_over = save_over;
BLI_strncpy(G.sce, scestr, FILE_MAX);
}
void read_Blog(void)
{
char name[FILE_MAX];
@ -496,10 +454,10 @@ static void do_history(char *name, ReportList *reports)
BKE_report(reports, RPT_ERROR, "Unable to make version backup");
}
void WM_write_file(bContext *C, char *target, int compress, ReportList *reports)
void WM_write_file(bContext *C, char *target, int fileflags, ReportList *reports)
{
Library *li;
int writeflags, len;
int len;
char di[FILE_MAX];
len = strlen(target);
@ -537,20 +495,14 @@ void WM_write_file(bContext *C, char *target, int compress, ReportList *reports)
do_history(di, reports);
writeflags= G.fileflags;
/* set compression flag */
if(compress) writeflags |= G_FILE_COMPRESS;
else writeflags &= ~G_FILE_COMPRESS;
if (BLO_write_file(CTX_data_main(C), di, writeflags, reports)) {
if (BLO_write_file(CTX_data_main(C), di, fileflags, reports)) {
strcpy(G.sce, di);
G.relbase_valid = 1;
strcpy(G.main->name, di); /* is guaranteed current file */
G.save_over = 1; /* disable untitled.blend convention */
if(compress) G.fileflags |= G_FILE_COMPRESS;
if(fileflags & G_FILE_COMPRESS) G.fileflags |= G_FILE_COMPRESS;
else G.fileflags &= ~G_FILE_COMPRESS;
writeBlog();
@ -562,56 +514,125 @@ void WM_write_file(bContext *C, char *target, int compress, ReportList *reports)
/* operator entry */
int WM_write_homefile(bContext *C, wmOperator *op)
{
wmWindowManager *wm= CTX_wm_manager(C);
wmWindow *win= CTX_wm_window(C);
char tstr[FILE_MAXDIR+FILE_MAXFILE];
int write_flags;
int fileflags;
/* check current window and close it if temp */
if(win->screen->full == SCREENTEMP) {
wm_window_close(C, win);
}
if(win->screen->full == SCREENTEMP)
wm_window_close(C, wm, win);
BLI_make_file_string("/", tstr, BLI_gethome(), ".B25.blend");
/* force save as regular blend file */
write_flags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN);
fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN);
BLO_write_file(CTX_data_main(C), tstr, write_flags, op->reports);
BLO_write_file(CTX_data_main(C), tstr, fileflags, op->reports);
G.save_over= 0;
return OPERATOR_FINISHED;
}
void WM_write_autosave(bContext *C)
/************************ autosave ****************************/
void wm_autosave_location(char *filename)
{
char tstr[FILE_MAXDIR+FILE_MAXFILE];
int write_flags;
char pidstr[32];
#ifdef WIN32
char subdir[9];
char savedir[FILE_MAXDIR];
#endif
sprintf(pidstr, "%d.blend", abs(getpid()));
get_autosave_location(tstr);
/* force save as regular blend file */
write_flags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN);
/* error reporting to console */
BLO_write_file(CTX_data_main(C), tstr, write_flags, NULL);
#ifdef WIN32
if (!BLI_exists(U.tempdir)) {
BLI_strncpy(subdir, "autosave", sizeof(subdir));
BLI_make_file_string("/", savedir, BLI_gethome(), subdir);
/* create a new autosave dir
* function already checks for existence or not */
BLI_recurdir_fileops(savedir);
BLI_make_file_string("/", filename, savedir, pidstr);
return;
}
#endif
BLI_make_file_string("/", filename, U.tempdir, pidstr);
}
/* if global undo; remove tempsave, otherwise rename */
void delete_autosave(void)
void WM_autosave_init(bContext *C)
{
char tstr[FILE_MAXDIR+FILE_MAXFILE];
wmWindowManager *wm= CTX_wm_manager(C);
wm_autosave_timer_ended(wm);
if(U.flag & USER_AUTOSAVE)
wm->autosavetimer= WM_event_add_timer(wm, NULL, TIMERAUTOSAVE, U.savetime*60.0);
}
void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
{
wmWindow *win;
wmEventHandler *handler;
char filename[FILE_MAX];
int fileflags;
WM_event_remove_timer(wm, NULL, wm->autosavetimer);
/* if a modal operator is running, don't autosave, but try again in 10 seconds */
for(win=wm->windows.first; win; win=win->next) {
for(handler=win->modalhandlers.first; handler; handler=handler->next) {
if(handler->op) {
wm->autosavetimer= WM_event_add_timer(wm, NULL, TIMERAUTOSAVE, 10.0);
return;
}
}
}
get_autosave_location(tstr);
wm_autosave_location(filename);
if (BLI_exists(tstr)) {
char str[FILE_MAXDIR+FILE_MAXFILE];
BLI_make_file_string("/", str, U.tempdir, "quit.blend");
/* force save as regular blend file */
fileflags = G.fileflags & ~(G_FILE_COMPRESS|G_FILE_LOCK|G_FILE_SIGN);
if(U.uiflag & USER_GLOBALUNDO) BLI_delete(tstr, 0, 0);
else BLI_rename(tstr, str);
/* no error reporting to console */
BLO_write_file(CTX_data_main(C), filename, fileflags, NULL);
/* do timer after file write, just in case file write takes a long time */
wm->autosavetimer= WM_event_add_timer(wm, NULL, TIMERAUTOSAVE, U.savetime*60.0);
}
void wm_autosave_timer_ended(wmWindowManager *wm)
{
if(wm->autosavetimer) {
WM_event_remove_timer(wm, NULL, wm->autosavetimer);
wm->autosavetimer= NULL;
}
}
/***/
void wm_autosave_delete(void)
{
char filename[FILE_MAX];
wm_autosave_location(filename);
if(BLI_exists(filename)) {
char str[FILE_MAXDIR+FILE_MAXFILE];
BLI_make_file_string("/", str, U.tempdir, "quit.blend");
/* if global undo; remove tempsave, otherwise rename */
if(U.uiflag & USER_GLOBALUNDO) BLI_delete(filename, 0, 0);
else BLI_rename(filename, str);
}
}
void wm_autosave_read(bContext *C, ReportList *reports)
{
char filename[FILE_MAX];
wm_autosave_location(filename);
WM_read_file(C, filename, reports);
}

View File

@ -283,7 +283,7 @@ void WM_exit(bContext *C)
printf("Error Totblock: %d\n", MEM_get_memory_blocks_in_use());
MEM_printmemlist();
}
// delete_autosave();
wm_autosave_delete();
printf("\nBlender quit\n");

View File

@ -255,7 +255,7 @@ void WM_jobs_start(wmWindowManager *wm, wmJob *steve)
/* restarted job has timer already */
if(steve->wt==NULL)
steve->wt= WM_event_add_window_timer(steve->win, TIMERJOBS, steve->timestep);
steve->wt= WM_event_add_timer(wm, steve->win, TIMERJOBS, steve->timestep);
}
else printf("job fails, not initialized\n");
}
@ -271,7 +271,7 @@ static void wm_jobs_kill_job(wmWindowManager *wm, wmJob *steve)
}
if(steve->wt)
WM_event_remove_window_timer(steve->win, steve->wt);
WM_event_remove_timer(wm, steve->win, steve->wt);
if(steve->customdata)
steve->free(steve->customdata);
if(steve->run_customdata)
@ -317,14 +317,13 @@ void wm_jobs_timer_ended(wmWindowManager *wm, wmTimer *wt)
}
/* hardcoded to event TIMERJOBS */
static int wm_jobs_timer(bContext *C, wmOperator *op, wmEvent *evt)
void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt)
{
wmWindowManager *wm= CTX_wm_manager(C);
wmJob *steve= wm->jobs.first;
for(; steve; steve= steve->next) {
if(evt->customdata==steve->wt) {
if(steve->wt==wt) {
/* running threads */
if(steve->threads.first) {
@ -358,7 +357,7 @@ static int wm_jobs_timer(bContext *C, wmOperator *op, wmEvent *evt)
WM_jobs_start(wm, steve);
}
else {
WM_event_remove_window_timer(steve->win, steve->wt);
WM_event_remove_timer(wm, steve->win, steve->wt);
steve->wt= NULL;
/* remove steve */
@ -370,23 +369,7 @@ static int wm_jobs_timer(bContext *C, wmOperator *op, wmEvent *evt)
else if(steve->suspended) {
WM_jobs_start(wm, steve);
}
return OPERATOR_FINISHED;
}
}
return OPERATOR_PASS_THROUGH;
}
void WM_OT_jobs_timer(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Jobs timer";
ot->idname= "WM_OT_jobs_timer";
ot->description="Jobs timer operator.";
/* api callbacks */
ot->invoke= wm_jobs_timer;
ot->poll= ED_operator_screenactive;
}

View File

@ -972,7 +972,7 @@ static int wm_open_mainfile_exec(bContext *C, wmOperator *op)
WM_read_file(C, path, op->reports);
return 0;
return OPERATOR_FINISHED;
}
static void WM_OT_open_mainfile(wmOperatorType *ot)
@ -1154,12 +1154,9 @@ static void WM_OT_link_append(wmOperatorType *ot)
static int wm_recover_last_session_exec(bContext *C, wmOperator *op)
{
char scestr[FILE_MAX], filename[FILE_MAX];
int save_over;
char filename[FILE_MAX];
/* back up some values */
BLI_strncpy(scestr, G.sce, sizeof(scestr));
save_over = G.save_over;
G.fileflags |= G_FILE_RECOVER;
// XXX wm in context is not set correctly after WM_read_file -> crash
// do it before for now, but is this correct with multiple windows?
@ -1169,11 +1166,9 @@ static int wm_recover_last_session_exec(bContext *C, wmOperator *op)
BLI_make_file_string("/", filename, btempdir, "quit.blend");
WM_read_file(C, filename, op->reports);
/* restore */
G.save_over = save_over;
BLI_strncpy(G.sce, scestr, sizeof(G.sce));
G.fileflags &= ~G_FILE_RECOVER;
return 0;
return OPERATOR_FINISHED;
}
static void WM_OT_recover_last_session(wmOperatorType *ot)
@ -1186,6 +1181,52 @@ static void WM_OT_recover_last_session(wmOperatorType *ot)
ot->poll= WM_operator_winactive;
}
/* *************** recover auto save **************** */
static int wm_recover_auto_save_exec(bContext *C, wmOperator *op)
{
char path[FILE_MAX];
RNA_string_get(op->ptr, "path", path);
G.fileflags |= G_FILE_RECOVER;
// XXX wm in context is not set correctly after WM_read_file -> crash
// do it before for now, but is this correct with multiple windows?
WM_event_add_notifier(C, NC_WINDOW, NULL);
/* load file */
WM_read_file(C, path, op->reports);
G.fileflags &= ~G_FILE_RECOVER;
return OPERATOR_FINISHED;
}
static int wm_recover_auto_save_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
char filename[FILE_MAX];
wm_autosave_location(filename);
RNA_string_set(op->ptr, "path", filename);
WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
}
static void WM_OT_recover_auto_save(wmOperatorType *ot)
{
ot->name= "Recover Auto Save";
ot->idname= "WM_OT_recover_auto_save";
ot->description="Open an automatically saved file to recover it.";
ot->exec= wm_recover_auto_save_exec;
ot->invoke= wm_recover_auto_save_invoke;
ot->poll= WM_operator_winactive;
WM_operator_properties_filesel(ot, BLENDERFILE, FILE_BLENDER);
}
/* *************** save file as **************** */
static void untitled(char *name)
@ -1229,10 +1270,9 @@ static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *even
static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
{
char path[FILE_MAX];
int compress;
int fileflags;
save_set_compress(op);
compress= RNA_boolean_get(op->ptr, "compress");
if(RNA_property_is_set(op->ptr, "path"))
RNA_string_get(op->ptr, "path", path);
@ -1241,7 +1281,15 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
untitled(path);
}
WM_write_file(C, path, compress, op->reports);
fileflags= G.fileflags;
/* set compression flag */
if(RNA_boolean_get(op->ptr, "compress"))
fileflags |= G_FILE_COMPRESS;
else
fileflags &= ~G_FILE_COMPRESS;
WM_write_file(C, path, fileflags, op->reports);
WM_event_add_notifier(C, NC_WM|ND_FILESAVE, NULL);
@ -2173,7 +2221,7 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_open_mainfile);
WM_operatortype_append(WM_OT_link_append);
WM_operatortype_append(WM_OT_recover_last_session);
WM_operatortype_append(WM_OT_jobs_timer);
WM_operatortype_append(WM_OT_recover_auto_save);
WM_operatortype_append(WM_OT_save_as_mainfile);
WM_operatortype_append(WM_OT_save_mainfile);
WM_operatortype_append(WM_OT_redraw_timer);
@ -2188,9 +2236,6 @@ void wm_window_keymap(wmKeyConfig *keyconf)
wmKeyMap *keymap= WM_keymap_find(keyconf, "Window", 0, 0);
wmKeyMapItem *km;
/* items to make WM work */
WM_keymap_verify_item(keymap, "WM_OT_jobs_timer", TIMERJOBS, KM_ANY, KM_ANY, 0);
/* note, this doesn't replace existing keymap items */
WM_keymap_verify_item(keymap, "WM_OT_window_duplicate", WKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
#ifdef __APPLE__

View File

@ -130,37 +130,39 @@ static void wm_ghostwindow_destroy(wmWindow *win)
/* including window itself, C can be NULL.
ED_screen_exit should have been called */
void wm_window_free(bContext *C, wmWindow *win)
void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win)
{
wmTimer *wt, *wtnext;
/* update context */
if(C) {
wmWindowManager *wm= CTX_wm_manager(C);
if(wm->windrawable==win)
wm->windrawable= NULL;
if(wm->winactive==win)
wm->winactive= NULL;
if(CTX_wm_window(C)==win)
CTX_wm_window_set(C, NULL);
WM_event_remove_handlers(C, &win->handlers);
WM_event_remove_handlers(C, &win->modalhandlers);
/* end running jobs, a job end also removes its timer */
for(wt= win->timers.first; wt; wt= wtnext) {
wtnext= wt->next;
if(wt->event_type==TIMERJOBS)
wm_jobs_timer_ended(wm, wt);
}
if(CTX_wm_window(C)==win)
CTX_wm_window_set(C, NULL);
}
if(win->eventstate) MEM_freeN(win->eventstate);
if(wm->windrawable==win)
wm->windrawable= NULL;
if(wm->winactive==win)
wm->winactive= NULL;
/* end running jobs, a job end also removes its timer */
for(wt= wm->timers.first; wt; wt= wtnext) {
wtnext= wt->next;
if(wt->win==win && wt->event_type==TIMERJOBS)
wm_jobs_timer_ended(wm, wt);
}
/* timer removing, need to call this api function */
while((wt= win->timers.first))
WM_event_remove_window_timer(win, wt);
for(wt= wm->timers.first; wt; wt=wtnext) {
wtnext= wt->next;
if(wt->win==win)
WM_event_remove_timer(wm, win, wt);
}
if(win->eventstate) MEM_freeN(win->eventstate);
wm_event_free_all(win);
wm_subwindows_free(win);
@ -223,14 +225,13 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *winorig)
}
/* this is event from ghost, or exit-blender op */
void wm_window_close(bContext *C, wmWindow *win)
void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
{
wmWindowManager *wm= CTX_wm_manager(C);
BLI_remlink(&wm->windows, win);
wm_draw_window_clear(win);
ED_screen_exit(C, win, win->screen);
wm_window_free(C, win);
wm_window_free(C, wm, win);
/* check remaining windows */
if(wm->windows.first) {
@ -544,6 +545,7 @@ void wm_window_make_drawable(bContext *C, wmWindow *win)
static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
{
bContext *C= private;
wmWindowManager *wm= CTX_wm_manager(C);
GHOST_TEventType type= GHOST_GetEventType(evt);
if (type == GHOST_kEventQuit) {
@ -576,7 +578,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
GHOST_TEventKeyData kdata;
int cx, cy, wx, wy;
CTX_wm_manager(C)->winactive= win; /* no context change! c->wm->windrawable is drawable, or for area queues */
wm->winactive= win; /* no context change! c->wm->windrawable is drawable, or for area queues */
win->active= 1;
// window_handle(win, INPUTCHANGE, win->active);
@ -619,7 +621,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
break;
}
case GHOST_kEventWindowClose: {
wm_window_close(C, win);
wm_window_close(C, wm, win);
break;
}
case GHOST_kEventWindowUpdate: {
@ -719,22 +721,29 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
static int wm_window_timer(const bContext *C)
{
wmWindowManager *wm= CTX_wm_manager(C);
wmTimer *wt, *wtnext;
wmWindow *win;
double time= PIL_check_seconds_timer();
int retval= 0;
for(win= wm->windows.first; win; win= win->next) {
wmTimer *wt;
for(wt= win->timers.first; wt; wt= wt->next) {
if(wt->sleep==0) {
if(time > wt->ntime) {
for(wt= wm->timers.first; wt; wt= wtnext) {
wtnext= wt->next; /* in case timer gets removed */
win= wt->win;
if(wt->sleep==0) {
if(time > wt->ntime) {
wt->delta= time - wt->ltime;
wt->duration += wt->delta;
wt->ltime= time;
wt->ntime= wt->stime + wt->timestep*ceil(wt->duration/wt->timestep);
if(wt->event_type == TIMERJOBS)
wm_jobs_timer(C, wm, wt);
else if(wt->event_type == TIMERAUTOSAVE)
wm_autosave_timer(C, wm, wt);
else if(win) {
wmEvent event= *(win->eventstate);
wt->delta= time - wt->ltime;
wt->duration += wt->delta;
wt->ltime= time;
wt->ntime= wt->stime + wt->timestep*ceil(wt->duration/wt->timestep);
event.type= wt->event_type;
event.custom= EVT_DATA_TIMER;
event.customdata= wt;
@ -810,19 +819,19 @@ void wm_ghost_exit(void)
/* **************** timer ********************** */
/* to (de)activate running timers temporary */
void WM_event_window_timer_sleep(wmWindow *win, wmTimer *timer, int dosleep)
void WM_event_timer_sleep(wmWindowManager *wm, wmWindow *win, wmTimer *timer, int dosleep)
{
wmTimer *wt;
for(wt= win->timers.first; wt; wt= wt->next)
for(wt= wm->timers.first; wt; wt= wt->next)
if(wt==timer)
break;
if(wt) {
if(wt)
wt->sleep= dosleep;
}
}
wmTimer *WM_event_add_window_timer(wmWindow *win, int event_type, double timestep)
wmTimer *WM_event_add_timer(wmWindowManager *wm, wmWindow *win, int event_type, double timestep)
{
wmTimer *wt= MEM_callocN(sizeof(wmTimer), "window timer");
@ -831,23 +840,24 @@ wmTimer *WM_event_add_window_timer(wmWindow *win, int event_type, double timeste
wt->ntime= wt->ltime + timestep;
wt->stime= wt->ltime;
wt->timestep= timestep;
wt->win= win;
BLI_addtail(&win->timers, wt);
BLI_addtail(&wm->timers, wt);
return wt;
}
void WM_event_remove_window_timer(wmWindow *win, wmTimer *timer)
void WM_event_remove_timer(wmWindowManager *wm, wmWindow *win, wmTimer *timer)
{
wmTimer *wt;
/* extra security check */
for(wt= win->timers.first; wt; wt= wt->next)
for(wt= wm->timers.first; wt; wt= wt->next)
if(wt==timer)
break;
if(wt) {
BLI_remlink(&win->timers, wt);
BLI_remlink(&wm->timers, wt);
if(wt->customdata)
MEM_freeN(wt->customdata);
MEM_freeN(wt);

View File

@ -29,6 +29,7 @@
#define WM_H
struct wmWindow;
struct ReportList;
typedef struct wmPaintCursor {
struct wmPaintCursor *next, *prev;
@ -64,9 +65,16 @@ void wm_gesture_draw(struct wmWindow *win);
int wm_gesture_evaluate(bContext *C, wmGesture *gesture);
void wm_gesture_tag_redraw(bContext *C);
/* wm_jobs.h */
void WM_OT_jobs_timer(struct wmOperatorType *ot);
/* wm_jobs.c */
void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt);
void wm_jobs_timer_ended(wmWindowManager *wm, wmTimer *wt);
/* wm_files.c */
void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt);
void wm_autosave_timer_ended(wmWindowManager *wm);
void wm_autosave_delete(void);
void wm_autosave_read(bContext *C, struct ReportList *reports);
void wm_autosave_location(char *filename);
#endif /* WM_H */

View File

@ -75,6 +75,7 @@
#define TIMER1 0x0112 /* timer event, slot for internal use */
#define TIMER2 0x0113 /* timer event, slot for internal use */
#define TIMERJOBS 0x0114 /* timer event, internal use */
#define TIMERAUTOSAVE 0x0115 /* timer event, internal use */
/* standard keyboard */
#define AKEY 'a'
@ -203,7 +204,7 @@
#define ISMOUSE(event) (event >= LEFTMOUSE && event <= WHEELOUTMOUSE)
/* test wether the event is timer event */
#define ISTIMER(event) (event >= TIMER && event <= TIMERJOBS)
#define ISTIMER(event) (event >= TIMER && event <= TIMERAUTOSAVE)
/* test wether the event is tweak event */
#define ISTWEAK(event) (event >= EVT_TWEAK_L && event <= EVT_GESTURE)

View File

@ -36,8 +36,8 @@ void wm_ghost_init (bContext *C);
void wm_ghost_exit(void);
wmWindow *wm_window_new (bContext *C);
void wm_window_free (bContext *C, wmWindow *win);
void wm_window_close (bContext *C, wmWindow *win);
void wm_window_free (bContext *C, wmWindowManager *wm, wmWindow *win);
void wm_window_close (bContext *C, wmWindowManager *wm, wmWindow *win);
void wm_window_title (wmWindowManager *wm, wmWindow *win);
void wm_window_add_ghostwindows (wmWindowManager *wm);