2.5
authorTon Roosendaal <ton@blender.org>
Mon, 22 Dec 2008 12:57:53 +0000 (12:57 +0000)
committerTon Roosendaal <ton@blender.org>
Mon, 22 Dec 2008 12:57:53 +0000 (12:57 +0000)
Better implementation of own window timers, not using ghost.
That makes blender's WM nice in control, and gives callers
of timers the opportunitie to evaluate time passed since
previous step. This system also only generates one timer
event per main loop (events - handlers - notifiers - draw)

Small fix: allow keymap modifier to give KM_ANY to ignore
modifier keys, this to have TIMER keymap work.

15 files changed:
source/blender/blenloader/intern/readfile.c
source/blender/editors/include/ED_screen.h
source/blender/editors/interface/interface_handlers.c
source/blender/editors/screen/screen_edit.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/space_time/time_header.c
source/blender/makesdna/DNA_screen_types.h
source/blender/makesdna/DNA_windowmanager_types.h
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/WM_types.h
source/blender/windowmanager/intern/wm.c
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_keymap.c
source/blender/windowmanager/intern/wm_window.c
source/blender/windowmanager/wm_window.h

index 94d215b..e3dc7c7 100644 (file)
@@ -3772,6 +3772,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
                win->eventstate= NULL;
                win->curswin= NULL;
                
+               win->timers.first= win->timers.last= NULL;
                win->queue.first= win->queue.last= NULL;
                win->handlers.first= win->handlers.last= NULL;
                win->subwindows.first= win->subwindows.last= NULL;
index c6e1764..4149219 100644 (file)
@@ -74,7 +74,7 @@ void  ED_screen_do_listen(struct wmWindow *win, struct wmNotifier *note);
 bScreen *ED_screen_duplicate(struct wmWindow *win, struct bScreen *sc);
 void   ED_screen_set_subwinactive(struct wmWindow *win, struct wmEvent *event);
 void   ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen);
-void   ED_animation_timer(struct wmWindow *win, int enable);
+void   ED_screen_animation_timer(struct bContext *C, int enable);
 
 void   ED_operatortypes_screen(void);
 void   ED_keymap_screen(struct wmWindowManager *wm);
index 9d3d489..a368f48 100644 (file)
@@ -58,8 +58,8 @@
 
 /***************** structs and defines ****************/
 
-#define BUTTON_TOOLTIP_DELAY           500
-#define BUTTON_FLASH_DELAY                     20
+#define BUTTON_TOOLTIP_DELAY           0.500
+#define BUTTON_FLASH_DELAY                     0.020
 #define BUTTON_AUTO_OPEN_THRESH                0.3
 #define BUTTON_MOUSE_TOWARDS_THRESH    1.0
 
@@ -94,7 +94,7 @@ typedef struct uiHandleButtonData {
        uiHandleButtonState state;
        int cancel, retval;
        int applied, appliedinteractive;
-       wmTimerHandle *flashtimer;
+       wmTimer *flashtimer;
 
        /* edited value */
        char *str, *origstr;
@@ -106,8 +106,8 @@ typedef struct uiHandleButtonData {
 
        /* tooltip */
        ARegion *tooltip;
-       wmTimerHandle *tooltiptimer;
-       wmTimerHandle *autoopentimer;
+       wmTimer *tooltiptimer;
+       wmTimer *autoopentimer;
 
        /* text selection/editing */
        int maxlen, selextend, selstartx;
@@ -2761,7 +2761,7 @@ static void button_tooltip_timer_reset(uiBut *but)
 
        if(U.flag & USER_TOOLTIPS)
                if(!but->block->tooltipdisabled)
-                       data->tooltiptimer= WM_event_add_window_timer(data->window, BUTTON_TOOLTIP_DELAY, ~0);
+                       data->tooltiptimer= WM_event_add_window_timer(data->window, BUTTON_TOOLTIP_DELAY);
 }
 
 static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state)
@@ -2789,7 +2789,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, time*20, ~0);
+                                       data->autoopentimer= WM_event_add_window_timer(data->window, 0.02*(double)time);
                        }
                }
        }
@@ -2831,7 +2831,7 @@ 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, BUTTON_FLASH_DELAY, ~0);
+               data->flashtimer= WM_event_add_window_timer(data->window, BUTTON_FLASH_DELAY);
        }
        else if(data->flashtimer) {
                WM_event_remove_window_timer(data->window, data->flashtimer);
index 3c83792..b298799 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "DNA_vec_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
 
 #include "BLI_blenlib.h"
 
@@ -994,6 +995,10 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
                ED_area_initialize(wm, win, sa);
        }
 
+       /* wake up animtimer */
+       if(win->screen->animtimer)
+               WM_event_window_timer_sleep(win, win->screen->animtimer, 0);
+       
        if(G.f & G_DEBUG) printf("set screen\n");
        win->screen->do_refresh= 0;
 }
@@ -1053,6 +1058,10 @@ 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);
+       screen->animtimer= NULL;
+       
        for(ar= screen->regionbase.first; ar; ar= ar->next)
                ED_region_exit(C, ar);
 
@@ -1170,6 +1179,8 @@ int ED_screen_area_active(const bContext *C)
 /* Do NOT call in area/region queues! */
 void ed_screen_set(bContext *C, bScreen *sc)
 {
+       bScreen *oldscreen= CTX_wm_screen(C);
+       
        if(sc->full) {                          /* find associated full */
                bScreen *sc1;
                for(sc1= G.main->screen.first; sc1; sc1= sc1->id.next) {
@@ -1182,8 +1193,17 @@ void ed_screen_set(bContext *C, bScreen *sc)
                if(sc1==NULL) printf("set screen error\n");
        }
        
-       if (CTX_wm_screen(C) != sc) {
-               ED_screen_exit(C, CTX_wm_window(C), CTX_wm_screen(C));
+       if (oldscreen != sc) {
+               wmTimer *wt= oldscreen->animtimer;
+               
+               /* 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(CTX_wm_window(C), wt, 1);
+               
+               ED_screen_exit(C, CTX_wm_window(C), oldscreen);
+               oldscreen->animtimer= wt;
+               
                CTX_wm_window(C)->screen= sc;
                
                ED_screen_refresh(CTX_wm_manager(C), CTX_wm_window(C));
@@ -1225,6 +1245,10 @@ void ed_screen_fullarea(bContext *C)
                        
                        old->full= NULL;
                        
+                       /* animtimer back */
+                       sc->animtimer= oldscreen->animtimer;
+                       oldscreen->animtimer= NULL;
+                       
                        ed_screen_set(C, sc);
                        
                        free_screen(oldscreen);
@@ -1242,6 +1266,10 @@ void ed_screen_fullarea(bContext *C)
                
                sc= screen_add(CTX_wm_window(C), "temp");
                
+               /* timer */
+               sc->animtimer= oldscreen->animtimer;
+               oldscreen->animtimer= NULL;
+               
                /* returns the top small area */
                newa= area_split(CTX_wm_window(C), sc, (ScrArea *)sc->areabase.first, 'h', 0.99f);
                area_newspace(C, newa, SPACE_INFO);
@@ -1264,14 +1292,17 @@ void ed_screen_fullarea(bContext *C)
 
 }
 
-void ED_animation_timer(wmWindow *win, int enable)
+void ED_screen_animation_timer(bContext *C, int enable)
 {
+       bScreen *screen= CTX_wm_screen(C);
+       wmWindow *win= CTX_wm_window(C);
+       Scene *scene= CTX_data_scene(C);
        
-//     if(win->animtimer)
-//             WM_event_remove_window_timer(win, win->animtimer);
-//     win->animtimer= NULL;
+       if(screen->animtimer)
+               WM_event_remove_window_timer(win, screen->animtimer);
+       screen->animtimer= NULL;
        
-//     if(enable)
-//             win->animtimer= WM_event_add_window_timer(win, (int)(1000/FPS), (int)(1000/FPS));
+       if(enable)
+               screen->animtimer= WM_event_add_window_timer(win, (1.0/FPS));
 }
 
index 3c729ec..0f94184 100644 (file)
@@ -1325,19 +1325,21 @@ void ED_SCR_OT_region_flip(wmOperatorType *ot)
 
 static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
 {
-       wmWindow *win= CTX_wm_window(C);
+       bScreen *screen= CTX_wm_screen(C);
        
-       if(win->animtimer==event->customdata) {
+       if(screen->animtimer==event->customdata) {
                Scene *scene= CTX_data_scene(C);
                
                scene->r.cfra++;
                
-               /* XXX TODO: 
-                * 'preview' range (psfra and pefra instead of sfra and efra)
-                * should be used instead if set...     
-                */
-               if(scene->r.cfra > scene->r.efra)
-                       scene->r.cfra= scene->r.sfra;
+               if (scene->r.psfra) {
+                       if(scene->r.cfra > scene->r.pefra)
+                               scene->r.cfra= scene->r.psfra;
+               }
+               else {
+                       if(scene->r.cfra > scene->r.efra)
+                               scene->r.cfra= scene->r.sfra;
+               }
 
                WM_event_add_notifier(C, WM_NOTE_WINDOW_REDRAW, 0, NULL);
                
@@ -1467,7 +1469,7 @@ void ED_keymap_screen(wmWindowManager *wm)
        RNA_enum_set(WM_keymap_add_item(keymap, "ED_SCR_OT_region_split", SKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "dir", 'v');
                                                  
        /*frame offsets*/
-       WM_keymap_add_item(keymap, "ED_SCR_OT_animation_play", TIMER, KM_ANY, 0, 0);
+       WM_keymap_add_item(keymap, "ED_SCR_OT_animation_play", TIMER, KM_ANY, KM_ANY, 0);
        RNA_int_set(WM_keymap_add_item(keymap, "ED_SCR_OT_frame_offset", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 10);
        RNA_int_set(WM_keymap_add_item(keymap, "ED_SCR_OT_frame_offset", DOWNARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -10);
        RNA_int_set(WM_keymap_add_item(keymap, "ED_SCR_OT_frame_offset", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -1);
index 57705eb..406ccf0 100644 (file)
@@ -370,10 +370,10 @@ void do_time_buttons(bContext *C, void *arg, int event)
                        //update_for_newframe();
                        break;
                case B_TL_PLAY:
-                       ED_animation_timer(CTX_wm_window(C), 1);
+                       ED_screen_animation_timer(C, 1);
                        break;
                case B_TL_STOP:
-                       ED_animation_timer(CTX_wm_window(C), 0);
+                       ED_screen_animation_timer(C, 0);
                        WM_event_add_notifier(C, WM_NOTE_WINDOW_REDRAW, 0, NULL);
                        break;
                case B_TL_FF:
@@ -508,7 +508,7 @@ void time_header_buttons(const bContext *C, ARegion *ar)
                                 xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Skip to previous keyframe (Ctrl PageDown)");
        xco+= XIC+4;
        
-       if(CTX_wm_window(C)->animtimer)
+       if(CTX_wm_screen(C)->animtimer)
                uiDefIconBut(block, BUT, B_TL_STOP, ICON_PAUSE,
                                         xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Stop Playing Timeline");
        else       
index c932c0b..a15c57d 100644 (file)
@@ -38,6 +38,7 @@ struct SpaceType;
 struct SpaceLink;
 struct ARegionType;
 struct Scene;
+struct wmTimer;
 
 typedef struct bScreen {
        ID id;
@@ -58,6 +59,8 @@ typedef struct bScreen {
        short mainwin;                                          /* screensize subwindow, for screenedges and global menus */
        short subwinactive;                                     /* active subwindow */
        
+       struct wmTimer *animtimer;                      /* if set, screen has timer handler added in window */
+       
        short handler[8];                                       /* similar to space handler */
 } bScreen;
 
index 874dd86..4112336 100644 (file)
@@ -47,7 +47,7 @@ struct wmLocal;
 struct bScreen;
 struct uiBlock;
 struct wmSubWindow;
-struct wmTimerHandle;
+struct wmTimer;
 struct StructRNA;
 struct PointerRNA;
 
@@ -94,7 +94,7 @@ typedef struct wmWindow {
        
        struct wmSubWindow *curswin;    /* internal for wm_subwindow.c only */
        
-       struct wmTimerHandle *animtimer;
+       ListBase timers;
        
        ListBase queue;                         /* all events (ghost level events were handled) */
        ListBase handlers;                      /* window+screen handlers, overriding all queues */
index cca9794..6a91e3c 100644 (file)
@@ -99,9 +99,10 @@ void         WM_event_add_notifier(struct bContext *C, int type, int value, void *data)
 
 void           wm_event_add            (wmWindow *win, struct wmEvent *event_to_add); /* XXX only for warning */
 
-                       /* one-shot timer, returns wmTimerData.handle */
-struct wmTimerHandle *WM_event_add_window_timer(wmWindow *win, int delay_ms, int interval_ms);
-void           WM_event_remove_window_timer(wmWindow *wm, struct wmTimerHandle *handle);
+                       /* at maximum, every timestep seconds it triggers TIMER events */
+struct wmTimer *WM_event_add_window_timer(wmWindow *win, double timestep);
+void           WM_event_remove_window_timer(wmWindow *win, struct wmTimer *timer);
+void           WM_event_window_timer_sleep(wmWindow *win, struct wmTimer *timer, int dosleep);
 
                        /* operator api, default callbacks */
                        /* confirm menu + exec */
index bccbcc1..8944429 100644 (file)
@@ -163,8 +163,17 @@ typedef struct wmTabletData {
        float Ytilt;            /* as above */
 } wmTabletData;
 
-struct wmTimerHandle;
-typedef struct wmTimerHandle wmTimerHandle;
+typedef struct wmTimer {
+       struct wmTimer *next, *prev;
+       double timestep;                /* set by timer user */
+       
+       double duration;                /* total running time in seconds */
+       double delta;                   /* time since previous step in seconds */
+       
+       double ltime;                   /* internal, last time timer was activated */
+       int sleep;                              /* internal, put timers to sleep when needed */
+} wmTimer;
+
 
 /* ****************** Messages ********************* */
 
index 5e89ad1..32d55fe 100644 (file)
@@ -184,8 +184,7 @@ void WM_main(bContext *C)
        while(1) {
                
                /* get events from ghost, handle window events, add to window queues */
-               /* WM_init has assigned to ghost the bContext already */
-               wm_window_process_events(1); 
+               wm_window_process_events(C); 
                
                /* per window, all events to the window, screen, area and region handlers */
                wm_event_do_handlers(C);
index abd562a..d1047ca 100644 (file)
@@ -441,11 +441,14 @@ static int wm_eventmatch(wmEvent *winevent, wmKeymapItem *kmi)
        
        if(kmi->val!=KM_ANY)
                if(winevent->val!=kmi->val) return 0;
-       
-       if(winevent->shift!=kmi->shift) return 0;
-       if(winevent->ctrl!=kmi->ctrl) return 0;
-       if(winevent->alt!=kmi->alt) return 0;
-       if(winevent->oskey!=kmi->oskey) return 0;
+       if(kmi->shift!=KM_ANY)
+               if(winevent->shift!=kmi->shift) return 0;
+       if(kmi->ctrl!=KM_ANY)
+               if(winevent->ctrl!=kmi->ctrl) return 0;
+       if(kmi->alt!=KM_ANY)
+               if(winevent->alt!=kmi->alt) return 0;
+       if(kmi->oskey!=KM_ANY)
+               if(winevent->oskey!=kmi->oskey) return 0;
        if(kmi->keymodifier)
                if(winevent->keymodifier!=kmi->keymodifier) return 0;
        
index a7ce67a..dc53bff 100644 (file)
@@ -57,22 +57,28 @@ static void keymap_event_set(wmKeymapItem *kmi, short type, short val, int modif
        kmi->val= val;
        kmi->keymodifier= keymodifier;
        
-       if(modifier & KM_SHIFT)
-               kmi->shift= 1;
-       else if(modifier & KM_SHIFT2)
-               kmi->shift= 2;
-       if(modifier & KM_CTRL)
-               kmi->ctrl= 1;
-       else if(modifier & KM_CTRL2)
-               kmi->ctrl= 2;
-       if(modifier & KM_ALT)
-               kmi->alt= 1;
-       else if(modifier & KM_ALT2)
-               kmi->alt= 2;
-       if(modifier & KM_OSKEY)
-               kmi->oskey= 1;
-       else if(modifier & KM_OSKEY2)
-               kmi->oskey= 2;  
+       if(modifier == KM_ANY) {
+               kmi->shift= kmi->ctrl= kmi->alt= kmi->oskey= KM_ANY;
+       }
+       else {
+               
+               if(modifier & KM_SHIFT)
+                       kmi->shift= 1;
+               else if(modifier & KM_SHIFT2)
+                       kmi->shift= 2;
+               if(modifier & KM_CTRL)
+                       kmi->ctrl= 1;
+               else if(modifier & KM_CTRL2)
+                       kmi->ctrl= 2;
+               if(modifier & KM_ALT)
+                       kmi->alt= 1;
+               else if(modifier & KM_ALT2)
+                       kmi->alt= 2;
+               if(modifier & KM_OSKEY)
+                       kmi->oskey= 1;
+               else if(modifier & KM_OSKEY2)
+                       kmi->oskey= 2;  
+       }
 }
 
 static void keymap_properties_set(wmKeymapItem *kmi)
index 7fba9a6..5773fd8 100644 (file)
@@ -55,6 +55,8 @@
 
 #include "ED_screen.h"
 
+#include "PIL_time.h"
+
 #include "GPU_draw.h"
 
 /* the global to talk to ghost */
@@ -102,7 +104,8 @@ void wm_window_free(bContext *C, wmWindow *win)
        }       
        
        if(win->eventstate) MEM_freeN(win->eventstate);
-
+       BLI_freelistN(&win->timers);
+       
        wm_event_free_all(win);
        wm_subwindows_free(win);
        
@@ -496,23 +499,49 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
        return 1;
 }
 
-void wm_window_process_events(int wait_for_event) 
+
+/* This timer system only gives maximum 1 timer event per redraw cycle,
+   to prevent queues to get overloaded. 
+   Timer handlers should check for delta to decide if they just
+   update, or follow real time 
+*/
+static int wm_window_timer(const bContext *C)
 {
-       int handled= 0;
+       wmWindowManager *wm= CTX_wm_manager(C);
+       wmWindow *win;
+       double time= PIL_check_seconds_timer();
+       int retval= 0;
        
-       /* ghost only processes 1 (timer?) event a time... we want to accumulate all */
-       while(1) {
-               if(GHOST_ProcessEvents(g_system, 0)) {
-                       GHOST_DispatchEvents(g_system);
-                       handled= 1;
+       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(wt->timestep < time - wt->ltime) {
+                                       wt->delta= time - wt->ltime;
+                                       wt->duration += wt->delta;
+                                       wt->ltime= time;
+                                       
+                                       wm_event_add_ghostevent(win, GHOST_kEventTimer, wt);
+                                       retval= 1;
+                               }
+                       }
                }
-               else
-                       break;
        }
-       if(handled==0 && wait_for_event) {
-               GHOST_ProcessEvents(g_system, wait_for_event);
+       return retval;
+}
+
+void wm_window_process_events(const bContext *C) 
+{
+       int hasevent= GHOST_ProcessEvents(g_system, 0); /* 0 is no wait */
+       
+       if(hasevent)
                GHOST_DispatchEvents(g_system);
-       }
+       
+       hasevent |= wm_window_timer(C);
+
+       /* no event, we sleep 5 milliseconds */
+       if(hasevent==0)
+               PIL_sleep_ms(5);
 }
 
 /* **************** init ********************** */
@@ -529,24 +558,42 @@ void wm_ghost_init(bContext *C)
 
 /* **************** timer ********************** */
 
-static void window_event_timer_proc(GHOST_TimerTaskHandle timer, GHOST_TUns64 time)
+/* to (de)activate running timers temporary */
+void WM_event_window_timer_sleep(wmWindow *win, wmTimer *timer, int dosleep)
 {
-       wmWindow *window;
-
-       window= GHOST_GetTimerTaskUserData(timer);
-
-       wm_event_add_ghostevent(window, GHOST_kEventTimer, (wmTimerHandle*)timer);
+       wmTimer *wt;
+       
+       for(wt= win->timers.first; wt; wt= wt->next)
+               if(wt==timer)
+                       break;
+       if(wt) {
+               wt->sleep= dosleep;
+       }               
 }
 
-wmTimerHandle *WM_event_add_window_timer(wmWindow *win, int delay_ms, int interval_ms)
+wmTimer *WM_event_add_window_timer(wmWindow *win, double timestep)
 {
-       return (wmTimerHandle*)GHOST_InstallTimer(g_system, delay_ms, interval_ms,
-               window_event_timer_proc, win);
+       wmTimer *wt= MEM_callocN(sizeof(wmTimer), "window timer");
+       
+       wt->ltime= PIL_check_seconds_timer();
+       wt->timestep= timestep;
+       
+       BLI_addtail(&win->timers, wt);
+       
+       return wt;
 }
 
-void WM_event_remove_window_timer(wmWindow *wm, wmTimerHandle *handle)
+void WM_event_remove_window_timer(wmWindow *win, wmTimer *timer)
 {
-       GHOST_RemoveTimer(g_system, (GHOST_TimerTaskHandle)handle);
+       wmTimer *wt;
+       
+       for(wt= win->timers.first; wt; wt= wt->next)
+               if(wt==timer)
+                       break;
+       if(wt) {
+               BLI_remlink(&win->timers, wt);
+               MEM_freeN(wt);
+       }
 }
 
 /* ************************************ */
index b02a163..03f2060 100644 (file)
@@ -37,7 +37,7 @@ void          wm_ghost_init                   (bContext *C);
 wmWindow       *wm_window_new                  (bContext *C);
 void           wm_window_free                  (bContext *C, wmWindow *win);
 void           wm_window_add_ghostwindows      (wmWindowManager *wm);
-void           wm_window_process_events        (int wait_for_event);
+void           wm_window_process_events        (const bContext *C);
 
 void           wm_window_make_drawable(bContext *C, wmWindow *win);