diff options
33 files changed, 325 insertions, 221 deletions
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index d40ce4145f5..5e6bb93d9ba 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -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); diff --git a/release/scripts/ui/space_info.py b/release/scripts/ui/space_info.py index f9feef6f023..d1e4ac13ab7 100644 --- a/release/scripts/ui/space_info.py +++ b/release/scripts/ui/space_info.py @@ -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() diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 5d0b89220d5..ccd21603c49 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -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 diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 2df5b7c173c..7570369827b 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -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); } diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index 52295dc3092..408d07b965c 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -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; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 761fc8b079a..ca2e5f4de75 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index e3d061d8e4b..f0c584b6267 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -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) { diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 29d84076533..554e729e0e2 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -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 */ diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 2123b412d61..20cd6ebf971 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -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; diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 2cc5500c3ef..6b71ccaba10 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -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; diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 7596191e781..21651afe417 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -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; } diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index b83352ae70c..6e256bee7f2 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -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); diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 77a1b671054..2a1bb8b4add 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -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. */ } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 482750e5b2e..ffc737eb9af 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -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)) diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index ae496158a46..12654bdac14 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -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; diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index c7258e616fa..019ac33dfd0 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -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; } diff --git a/source/blender/makesdna/DNA_fileglobal_types.h b/source/blender/makesdna/DNA_fileglobal_types.h index 43ab895b398..271c8d2a33e 100644 --- a/source/blender/makesdna/DNA_fileglobal_types.h +++ b/source/blender/makesdna/DNA_fileglobal_types.h @@ -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; diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 7a024e35ff0..5cdd74c8262 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -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 */ diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 1acf3c8effa..f9192a9473e 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -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); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 2189412783a..e2e50b695fd 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -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 diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 59f3bcd4edc..224338e557a 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -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" */ diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 31cb5ee0832..0ef7e9670dc 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -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 */ diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index f4baa42515c..1d173005d85 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -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)) { diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 93ecd4076a3..e7c04141ad3 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -44,6 +44,8 @@ #include "ED_screen.h" +#include "GPU_extensions.h" + #include "WM_api.h" #include "WM_types.h" #include "wm.h" diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 8eca0a1b416..f301a20a7c1 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -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 */ diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index ff0e69b74d4..b2e55c8532e 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -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())); + +#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 - get_autosave_location(tstr); + BLI_make_file_string("/", filename, U.tempdir, pidstr); +} - /* force save as regular blend file */ - write_flags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN); +void WM_autosave_init(bContext *C) +{ + wmWindowManager *wm= CTX_wm_manager(C); + wm_autosave_timer_ended(wm); - /* error reporting to console */ - BLO_write_file(CTX_data_main(C), tstr, write_flags, NULL); + if(U.flag & USER_AUTOSAVE) + wm->autosavetimer= WM_event_add_timer(wm, NULL, TIMERAUTOSAVE, U.savetime*60.0); } -/* if global undo; remove tempsave, otherwise rename */ -void delete_autosave(void) +void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt) { - char tstr[FILE_MAXDIR+FILE_MAXFILE]; + 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); + + /* force save as regular blend file */ + fileflags = G.fileflags & ~(G_FILE_COMPRESS|G_FILE_LOCK|G_FILE_SIGN); + + /* no error reporting to console */ + BLO_write_file(CTX_data_main(C), filename, fileflags, NULL); - if (BLI_exists(tstr)) { + /* 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(U.uiflag & USER_GLOBALUNDO) BLI_delete(tstr, 0, 0); - else BLI_rename(tstr, str); + /* 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); +} diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 2e456669cb1..8097822acbc 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -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"); diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c index 498306484e9..c2ecf0c59e7 100644 --- a/source/blender/windowmanager/intern/wm_jobs.c +++ b/source/blender/windowmanager/intern/wm_jobs.c @@ -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; - -} diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index cc5967ab23a..7a97ebf0de7 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -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__ diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index f7116a2bd1f..70d40df4532 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -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); diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h index 832558b961f..609b6142640 100644 --- a/source/blender/windowmanager/wm.h +++ b/source/blender/windowmanager/wm.h @@ -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 */ diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index b33c4bd14e8..c7588795a15 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -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) diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index 44c31e7cb69..f0a2c0ec9a9 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -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); |