2.5/Posemode:
[blender-staging.git] / source / blender / editors / screen / screen_ops.c
index 10139f9851f0e2c8c54e26cf04594b01776d6c08..9453c7ffe098916378dda89adde9e57ffdd1af49 100644 (file)
 #include "BLI_arithb.h"
 #include "BLI_blenlib.h"
 #include "BLI_editVert.h"
+#include "BLI_dlrbTree.h"
 
 #include "DNA_armature_types.h"
 #include "DNA_image_types.h"
+#include "DNA_lattice_types.h"
 #include "DNA_object_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_curve_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_meta_types.h"
 
 #include "BKE_blender.h"
+#include "BKE_colortools.h"
 #include "BKE_context.h"
 #include "BKE_customdata.h"
 #include "BKE_global.h"
 #include "BKE_mesh.h"
 #include "BKE_multires.h"
 #include "BKE_report.h"
+#include "BKE_scene.h"
 #include "BKE_screen.h"
 #include "BKE_utildefines.h"
+#include "BKE_sound.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
@@ -59,7 +65,9 @@
 #include "ED_util.h"
 #include "ED_screen.h"
 #include "ED_mesh.h"
+#include "ED_object.h"
 #include "ED_screen_types.h"
+#include "ED_keyframes_draw.h"
 
 #include "RE_pipeline.h"
 #include "IMB_imbuf.h"
 #include "UI_interface.h"
 #include "UI_resources.h"
 
+#include "wm_window.h"
+
 #include "screen_intern.h"     /* own module include */
 
+#define KM_MODAL_CANCEL                1
+#define KM_MODAL_APPLY         2
+#define KM_MODAL_STEP10                3
+#define KM_MODAL_STEP10_OFF    4
+
 /* ************** Exported Poll tests ********************** */
 
 int ED_operator_regionactive(bContext *C)
@@ -156,14 +171,15 @@ int ED_operator_buttons_active(bContext *C)
 
 int ED_operator_node_active(bContext *C)
 {
-       if(ed_spacetype_test(C, SPACE_NODE)) {
-               SpaceNode *snode= (SpaceNode *)CTX_wm_space_data(C);
-               if(snode->edittree)
-                       return 1;
-       }
+       SpaceNode *snode= CTX_wm_space_node(C);
+
+       if(snode && snode->edittree)
+               return 1;
+
        return 0;
 }
 
+// XXX rename
 int ED_operator_ipo_active(bContext *C)
 {
        return ed_spacetype_test(C, SPACE_IPO);
@@ -179,6 +195,16 @@ int ED_operator_image_active(bContext *C)
        return ed_spacetype_test(C, SPACE_IMAGE);
 }
 
+int ED_operator_nla_active(bContext *C)
+{
+       return ed_spacetype_test(C, SPACE_NLA);
+}
+
+int ED_operator_logic_active(bContext *C)
+{
+       return ed_spacetype_test(C, SPACE_LOGIC);
+}
+
 int ED_operator_object_active(bContext *C)
 {
        return NULL != CTX_data_active_object(C);
@@ -206,7 +232,7 @@ int ED_operator_posemode(bContext *C)
        Object *obedit= CTX_data_edit_object(C);
        
        if ((obact != obedit) && (obact) && (obact->type==OB_ARMATURE))
-               return (obact->flag & OB_POSEMODE)!=0;
+               return (obact->mode & OB_MODE_POSE)!=0;
                
        return 0;
 }
@@ -225,7 +251,8 @@ int ED_operator_uvedit(bContext *C)
                return 1;
        }
 
-       BKE_mesh_end_editmesh(obedit->data, em);
+       if(obedit)
+               BKE_mesh_end_editmesh(obedit->data, em);
        return 0;
 }
 
@@ -242,7 +269,8 @@ int ED_operator_uvmap(bContext *C)
                return 1;
        }
 
-       BKE_mesh_end_editmesh(obedit->data, em);
+       if(obedit)
+               BKE_mesh_end_editmesh(obedit->data, em);
        return 0;
 }
 
@@ -279,6 +307,22 @@ int ED_operator_editfont(bContext *C)
        return 0;
 }
 
+int ED_operator_editlattice(bContext *C)
+{
+       Object *obedit= CTX_data_edit_object(C);
+       if(obedit && obedit->type==OB_LATTICE)
+               return NULL != ((Lattice *)obedit->data)->editlatt;
+       return 0;
+}
+
+int ED_operator_editmball(bContext *C)
+{
+       Object *obedit= CTX_data_edit_object(C);
+       if(obedit && obedit->type==OB_MBALL)
+               return NULL != ((MetaBall *)obedit->data)->editelems;
+       return 0;
+}
+
 /* *************************** action zone operator ************************** */
 
 /* operator state vars used:  
@@ -323,46 +367,51 @@ static ScrArea *screen_areahascursor(bScreen *scr, int x, int y)
        return sa;
 }
 
+/* quick poll to save operators to be created and handled */
+static int actionzone_area_poll(bContext *C)
+{
+       wmWindow *win= CTX_wm_window(C);
+       ScrArea *sa= CTX_wm_area(C);
+       
+       if(sa && win) {
+               AZone *az;
+               int x= win->eventstate->x;
+               int y= win->eventstate->y;
+               
+               for(az= sa->actionzones.first; az; az= az->next)
+                       if(BLI_in_rcti(&az->rect, x, y))
+                          return 1;
+       }       
+       return 0;
+}
 
 AZone *is_in_area_actionzone(ScrArea *sa, int x, int y)
 {
        AZone *az= NULL;
-       int i= 0;
        
-       for(az= sa->actionzones.first, i= 0; az; az= az->next, i++) {
-               if(az->type == AZONE_TRI) {
-                       if(IsPointInTri2DInts(az->x1, az->y1, az->x2, az->y2, x, y)) 
-                               break;
-               }
-               if(az->type == AZONE_QUAD) {
-                       if(az->x1 < x && x < az->x2 && az->y1 < y && y < az->y2) 
-                               break;
+       for(az= sa->actionzones.first; az; az= az->next) {
+               if(BLI_in_rcti(&az->rect, x, y)) {
+                       if(az->type == AZONE_AREA) {
+                               if(IsPointInTri2DInts(az->x1, az->y1, az->x2, az->y2, x, y)) 
+                                       break;
+                       }
+                       else if(az->type == AZONE_REGION) {
+                               float v1[2], v2[2], v3[2], pt[2];
+                               
+                               v1[0]= az->x1; v1[1]= az->y1;
+                               v2[0]= az->x2; v2[1]= az->y2;
+                               v3[0]= az->x3; v3[1]= az->y3;
+                               pt[0]= x; pt[1]=y;
+
+                               if(IsPointInTri2D(v1, v2, v3, pt)) 
+                                       break;
+                       }
                }
        }
        
        return az;
 }
 
-static int actionzone_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-       AZone *az= is_in_area_actionzone(CTX_wm_area(C), event->x, event->y);
-       sActionzoneData *sad;
-       
-       /* quick escape */
-       if(az==NULL)
-               return OPERATOR_PASS_THROUGH;
-       
-       /* ok we do the actionzone */
-       sad= op->customdata= MEM_callocN(sizeof(sActionzoneData), "sActionzoneData");
-       sad->sa1= CTX_wm_area(C);
-       sad->az= az;
-       sad->x= event->x; sad->y= event->y;
-       
-       /* add modal handler */
-       WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
-       
-       return OPERATOR_RUNNING_MODAL;
-}
 
 static void actionzone_exit(bContext *C, wmOperator *op)
 {
@@ -372,15 +421,19 @@ static void actionzone_exit(bContext *C, wmOperator *op)
 }
 
 /* send EVT_ACTIONZONE event */
-static void actionzone_apply(bContext *C, wmOperator *op)
+static void actionzone_apply(bContext *C, wmOperator *op, int type)
 {
        wmEvent event;
        wmWindow *win= CTX_wm_window(C);
        sActionzoneData *sad= op->customdata;
+       
        sad->modifier= RNA_int_get(op->ptr, "modifier");
        
        event= *(win->eventstate);      /* XXX huh huh? make api call */
-       event.type= EVT_ACTIONZONE;
+       if(type==AZONE_AREA)
+               event.type= EVT_ACTIONZONE_AREA;
+       else
+               event.type= EVT_ACTIONZONE_REGION;
        event.customdata= op->customdata;
        event.customdatafree= TRUE;
        op->customdata= NULL;
@@ -388,10 +441,41 @@ static void actionzone_apply(bContext *C, wmOperator *op)
        wm_event_add(win, &event);
 }
 
+static int actionzone_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       AZone *az= is_in_area_actionzone(CTX_wm_area(C), event->x, event->y);
+       sActionzoneData *sad;
+       
+       /* quick escape */
+       if(az==NULL)
+               return OPERATOR_PASS_THROUGH;
+       
+       /* ok we do the actionzone */
+       sad= op->customdata= MEM_callocN(sizeof(sActionzoneData), "sActionzoneData");
+       sad->sa1= CTX_wm_area(C);
+       sad->az= az;
+       sad->x= event->x; sad->y= event->y;
+       
+       /* region azone directly reacts on mouse clicks */
+       if(sad->az->type==AZONE_REGION) {
+               actionzone_apply(C, op, AZONE_REGION);
+               actionzone_exit(C, op);
+               return OPERATOR_FINISHED;
+       }
+       else {
+               /* add modal handler */
+               WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+               
+               return OPERATOR_RUNNING_MODAL;
+       }
+}
+
+
 static int actionzone_modal(bContext *C, wmOperator *op, wmEvent *event)
 {
        sActionzoneData *sad= op->customdata;
        int deltax, deltay;
+       int mindelta= sad->az->type==AZONE_REGION?1:12;
        
        switch(event->type) {
                case MOUSEMOVE:
@@ -400,36 +484,39 @@ static int actionzone_modal(bContext *C, wmOperator *op, wmEvent *event)
                        deltay= (event->y - sad->y);
                        
                        if(deltay > ABS(deltax))
-                               sad->gesture_dir= AZONE_N;
+                               sad->gesture_dir= 'n';
                        else if(deltax > ABS(deltay))
-                               sad->gesture_dir= AZONE_E;
+                               sad->gesture_dir= 'e';
                        else if(deltay < -ABS(deltax))
-                               sad->gesture_dir= AZONE_S;
+                               sad->gesture_dir= 's';
                        else
-                               sad->gesture_dir= AZONE_W;
+                               sad->gesture_dir= 'w';
                        
                        /* gesture is large enough? */
-                       if(ABS(deltax) > 12 || ABS(deltay) > 12) {
+                       if(ABS(deltax) > mindelta || ABS(deltay) > mindelta) {
                                
                                /* second area, for join */
                                sad->sa2= screen_areahascursor(CTX_wm_screen(C), event->x, event->y);
                                /* apply sends event */
-                               actionzone_apply(C, op);
+                               actionzone_apply(C, op, sad->az->type);
                                actionzone_exit(C, op);
                                
                                return OPERATOR_FINISHED;
                        }
                                break;
                case ESCKEY:
-               case LEFTMOUSE:
                        actionzone_exit(C, op);
                        return OPERATOR_CANCELLED;
+               case LEFTMOUSE:                         
+                       actionzone_exit(C, op);
+                       return OPERATOR_CANCELLED;
+
        }
        
        return OPERATOR_RUNNING_MODAL;
 }
 
-void SCREEN_OT_actionzone(wmOperatorType *ot)
+static void SCREEN_OT_actionzone(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Handle area action zones";
@@ -437,8 +524,10 @@ void SCREEN_OT_actionzone(wmOperatorType *ot)
        
        ot->invoke= actionzone_invoke;
        ot->modal= actionzone_modal;
+       ot->poll= actionzone_area_poll;
+
+       ot->flag= OPTYPE_BLOCKING;
        
-       ot->poll= ED_operator_areaactive;
        RNA_def_int(ot->srna, "modifier", 0, 0, 2, "modifier", "modifier state", 0, 2);
 }
 
@@ -544,7 +633,7 @@ static int area_swap_modal(bContext *C, wmOperator *op, wmEvent *event)
        return OPERATOR_RUNNING_MODAL;
 }
 
-void SCREEN_OT_area_swap(wmOperatorType *ot)
+static void SCREEN_OT_area_swap(wmOperatorType *ot)
 {
        ot->name= "Swap areas";
        ot->idname= "SCREEN_OT_area_swap";
@@ -552,6 +641,8 @@ void SCREEN_OT_area_swap(wmOperatorType *ot)
        ot->invoke= area_swap_invoke;
        ot->modal= area_swap_modal;
        ot->poll= ED_operator_areaactive;
+
+       ot->flag= OPTYPE_BLOCKING;
 }
 
 /* *********** Duplicate area as new window operator ****************** */
@@ -563,18 +654,25 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, wmEvent *event)
        bScreen *newsc, *sc;
        ScrArea *sa;
        rcti rect;
-       sActionzoneData *sad= event->customdata;
-
-       if(sad==NULL)
-               return OPERATOR_PASS_THROUGH;
        
        win= CTX_wm_window(C);
        sc= CTX_wm_screen(C);
-       sa= sad->sa1;
+       sa= CTX_wm_area(C);
+       
+       /* XXX hrmf! */
+       if(event->type==EVT_ACTIONZONE_AREA) {
+               sActionzoneData *sad= event->customdata;
 
+               if(sad==NULL)
+                       return OPERATOR_PASS_THROUGH;
+       
+               sa= sad->sa1;
+       }
+       
        /*  poll() checks area context, but we don't accept full-area windows */
        if(sc->full != SCREENNORMAL) {
-               actionzone_exit(C, op);
+               if(event->type==EVT_ACTIONZONE_AREA)
+                       actionzone_exit(C, op);
                return OPERATOR_CANCELLED;
        }
        
@@ -584,7 +682,7 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, wmEvent *event)
        newwin= WM_window_open(C, &rect);
        
        /* allocs new screen and adds to newly created window, using window size */
-       newsc= screen_add(newwin, CTX_data_scene(C), sc->id.name+2);
+       newsc= ED_screen_add(newwin, CTX_data_scene(C), sc->id.name+2);
        newwin->screen= newsc;
        
        /* copy area to new screen */
@@ -593,12 +691,13 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, wmEvent *event)
        /* screen, areas init */
        WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
 
-       actionzone_exit(C, op);
+       if(event->type==EVT_ACTIONZONE_AREA)
+               actionzone_exit(C, op);
        
        return OPERATOR_FINISHED;
 }
 
-void SCREEN_OT_area_dupli(wmOperatorType *ot)
+static void SCREEN_OT_area_dupli(wmOperatorType *ot)
 {
        ot->name= "Duplicate Area into New Window";
        ot->idname= "SCREEN_OT_area_dupli";
@@ -640,7 +739,7 @@ void SCREEN_OT_area_dupli(wmOperatorType *ot)
 */
 
 typedef struct sAreaMoveData {
-       int bigger, smaller, origval;
+       int bigger, smaller, origval, step;
        char dir;
 } sAreaMoveData;
 
@@ -797,38 +896,46 @@ static int area_move_cancel(bContext *C, wmOperator *op)
 /* modal callback for while moving edges */
 static int area_move_modal(bContext *C, wmOperator *op, wmEvent *event)
 {
-       sAreaMoveData *md;
+       sAreaMoveData *md= op->customdata;
        int delta, x, y;
 
-       md= op->customdata;
-
-       x= RNA_int_get(op->ptr, "x");
-       y= RNA_int_get(op->ptr, "y");
-
        /* execute the events */
        switch(event->type) {
                case MOUSEMOVE:
+                       
+                       x= RNA_int_get(op->ptr, "x");
+                       y= RNA_int_get(op->ptr, "y");
+                       
                        delta= (md->dir == 'v')? event->x - x: event->y - y;
+                       if(md->step) delta= delta - (delta % md->step);
                        RNA_int_set(op->ptr, "delta", delta);
 
                        area_move_apply(C, op);
                        break;
                        
-               case LEFTMOUSE:
-                       if(event->val==0) {
-                               area_move_exit(C, op);
-                               return OPERATOR_FINISHED;
-                       }
-                       break;
+               case EVT_MODAL_MAP:
                        
-               case ESCKEY:
-                       return area_move_cancel(C, op);
+                       switch (event->val) {
+                               case KM_MODAL_APPLY:
+                                       area_move_exit(C, op);
+                                       return OPERATOR_FINISHED;
+
+                               case KM_MODAL_CANCEL:
+                                       return area_move_cancel(C, op);
+                                       
+                               case KM_MODAL_STEP10:
+                                       md->step= 10;
+                                       break;
+                               case KM_MODAL_STEP10_OFF:
+                                       md->step= 0;
+                                       break;
+                       }
        }
        
        return OPERATOR_RUNNING_MODAL;
 }
 
-void SCREEN_OT_area_move(wmOperatorType *ot)
+static void SCREEN_OT_area_move(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Move area edges";
@@ -838,9 +945,10 @@ void SCREEN_OT_area_move(wmOperatorType *ot)
        ot->invoke= area_move_invoke;
        ot->cancel= area_move_cancel;
        ot->modal= area_move_modal;
-
        ot->poll= ED_operator_screen_mainwinactive; /* when mouse is over area-edge */
 
+       ot->flag= OPTYPE_BLOCKING;
+
        /* rna */
        RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
        RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
@@ -1015,7 +1123,7 @@ static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
        sAreaSplitData *sd;
        
-       if(event->type==EVT_ACTIONZONE) {
+       if(event->type==EVT_ACTIONZONE_AREA) {
                sActionzoneData *sad= event->customdata;
                int dir;
 
@@ -1023,6 +1131,10 @@ static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event)
                        return OPERATOR_PASS_THROUGH;
                }
                
+               /* no full window splitting allowed */
+               if(CTX_wm_area(C)->full)
+                       return OPERATOR_PASS_THROUGH;
+               
                /* verify *sad itself */
                if(sad==NULL || sad->sa1==NULL || sad->az==NULL)
                        return OPERATOR_PASS_THROUGH;
@@ -1032,7 +1144,7 @@ static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event)
                        return OPERATOR_PASS_THROUGH;
                
                /* prepare operator state vars */
-               if(sad->gesture_dir==AZONE_N || sad->gesture_dir==AZONE_S) {
+               if(sad->gesture_dir=='n' || sad->gesture_dir=='s') {
                        dir= 'h';
                        RNA_float_set(op->ptr, "factor", ((float)(event->x - sad->sa1->v1->vec.x)) / (float)sad->sa1->winx);
                }
@@ -1135,11 +1247,11 @@ static int area_split_modal(bContext *C, wmOperator *op, wmEvent *event)
 }
 
 static EnumPropertyItem prop_direction_items[] = {
-       {'h', "HORIZONTAL", "Horizontal", ""},
-       {'v', "VERTICAL", "Vertical", ""},
-       {0, NULL, NULL, NULL}};
+       {'h', "HORIZONTAL", 0, "Horizontal", ""},
+       {'v', "VERTICAL", 0, "Vertical", ""},
+       {0, NULL, 0, NULL, NULL}};
 
-void SCREEN_OT_area_split(wmOperatorType *ot)
+static void SCREEN_OT_area_split(wmOperatorType *ot)
 {
        ot->name = "Split area";
        ot->idname = "SCREEN_OT_area_split";
@@ -1149,16 +1261,130 @@ void SCREEN_OT_area_split(wmOperatorType *ot)
        ot->modal= area_split_modal;
        
        ot->poll= ED_operator_areaactive;
-       ot->flag= OPTYPE_REGISTER;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_BLOCKING;
        
        /* rna */
        RNA_def_enum(ot->srna, "direction", prop_direction_items, 'h', "Direction", "");
        RNA_def_float(ot->srna, "factor", 0.5f, 0.0, 1.0, "Factor", "", 0.0, 1.0);
 }
 
-/* ************** frame change operator ***************************** */
 
 
+/* ************** scale region edge operator *********************************** */
+
+typedef struct RegionMoveData {
+       ARegion *ar;
+       int bigger, smaller, origval;
+       int origx, origy;
+       char edge;
+       
+} RegionMoveData;
+
+static int region_scale_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       sActionzoneData *sad= event->customdata;
+       AZone *az= sad->az;
+       
+       if(az->ar) {
+               RegionMoveData *rmd= MEM_callocN(sizeof(RegionMoveData), "RegionMoveData");
+               
+               op->customdata= rmd;
+               
+               rmd->ar= az->ar;
+               rmd->edge= az->edge;
+               rmd->origx= event->x;
+               rmd->origy= event->y;
+               if(rmd->edge=='l' || rmd->edge=='r') 
+                       rmd->origval= rmd->ar->type->minsizex;
+               else
+                       rmd->origval= rmd->ar->type->minsizey;
+               
+               /* add temp handler */
+               WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+               
+               return OPERATOR_RUNNING_MODAL;
+       }
+       
+       return OPERATOR_FINISHED;
+}
+
+static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+       RegionMoveData *rmd= op->customdata;
+       int delta;
+       
+       /* execute the events */
+       switch(event->type) {
+               case MOUSEMOVE:
+                       
+                       if(rmd->edge=='l' || rmd->edge=='r') {
+                               delta= event->x - rmd->origx;
+                               if(rmd->edge=='l') delta= -delta;
+                               rmd->ar->type->minsizex= rmd->origval + delta;
+                               CLAMP(rmd->ar->type->minsizex, 0, 1000);
+                               if(rmd->ar->type->minsizex < 10) {
+                                       rmd->ar->type->minsizex= 10;
+                                       rmd->ar->flag |= RGN_FLAG_HIDDEN;
+                               }
+                               else
+                                       rmd->ar->flag &= ~RGN_FLAG_HIDDEN;
+                       }
+                       else {
+                               delta= event->y - rmd->origy;
+                               if(rmd->edge=='b') delta= -delta;
+                               rmd->ar->type->minsizey= rmd->origval + delta;
+                               CLAMP(rmd->ar->type->minsizey, 0, 1000);
+                               if(rmd->ar->type->minsizey < 10) {
+                                       rmd->ar->type->minsizey= 10;
+                                       rmd->ar->flag |= RGN_FLAG_HIDDEN;
+                               }
+                               else
+                                       rmd->ar->flag &= ~RGN_FLAG_HIDDEN;
+                       }
+                       
+                       WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
+                                       
+                       break;
+                       
+               case LEFTMOUSE:
+                       if(event->val==0) {
+                               
+                               if(ABS(event->x - rmd->origx) < 2 && ABS(event->y - rmd->origy) < 2) {
+                                       rmd->ar->flag ^= RGN_FLAG_HIDDEN;
+                                       WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
+                               }                               
+                               MEM_freeN(op->customdata);
+                               op->customdata = NULL;
+
+                               return OPERATOR_FINISHED;
+                       }
+                       break;
+                       
+               case ESCKEY:
+                       ;
+       }
+       
+       return OPERATOR_RUNNING_MODAL;
+}
+
+
+static void SCREEN_OT_region_scale(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Scale Region Size";
+       ot->idname= "SCREEN_OT_region_scale";
+       
+       ot->invoke= region_scale_invoke;
+       ot->modal= region_scale_modal;
+       
+       ot->poll= ED_operator_areaactive;
+       
+       ot->flag= OPTYPE_BLOCKING;
+}
+
+
+/* ************** frame change operator ***************************** */
+
 /* function to be called outside UI context, or for redo */
 static int frame_offset_exec(bContext *C, wmOperator *op)
 {
@@ -1173,7 +1399,7 @@ static int frame_offset_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void SCREEN_OT_frame_offset(wmOperatorType *ot)
+static void SCREEN_OT_frame_offset(wmOperatorType *ot)
 {
        ot->name = "Frame Offset";
        ot->idname = "SCREEN_OT_frame_offset";
@@ -1187,6 +1413,124 @@ void SCREEN_OT_frame_offset(wmOperatorType *ot)
        RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
 }
 
+
+/* function to be called outside UI context, or for redo */
+static int frame_jump_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene= CTX_data_scene(C);
+       
+       if (RNA_boolean_get(op->ptr, "end"))
+               CFRA= PEFRA;
+       else
+               CFRA= PSFRA;
+
+       WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+
+       return OPERATOR_FINISHED;
+}
+
+static void SCREEN_OT_frame_jump(wmOperatorType *ot)
+{
+       ot->name = "Jump to Endpoint";
+       ot->idname = "SCREEN_OT_frame_jump";
+
+       ot->exec= frame_jump_exec;
+
+       ot->poll= ED_operator_screenactive;
+       ot->flag= 0;
+
+       /* rna */
+       RNA_def_boolean(ot->srna, "end", 0, "Last Frame", "Jump to the last frame of the frame range.");
+}
+
+
+/* ************** jump to keyframe operator ***************************** */
+
+/* helper function - find actkeycolumn that occurs on cframe, or the nearest one if not found */
+// TODO: make this an API func?
+static ActKeyColumn *cfra_find_nearest_next_ak (ActKeyColumn *ak, float cframe, short next)
+{
+       ActKeyColumn *akn= NULL;
+       
+       /* sanity checks */
+       if (ak == NULL)
+               return NULL;
+       
+       /* check if this is a match, or whether it is in some subtree */
+       if (cframe < ak->cfra)
+               akn= cfra_find_nearest_next_ak(ak->left, cframe, next);
+       else if (cframe > ak->cfra)
+               akn= cfra_find_nearest_next_ak(ak->right, cframe, next);
+               
+       /* if no match found (or found match), just use the current one */
+       if (akn == NULL)
+               return ak;
+       else
+               return akn;
+}
+
+/* function to be called outside UI context, or for redo */
+static int keyframe_jump_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene= CTX_data_scene(C);
+       Object *ob= CTX_data_active_object(C);
+       DLRBT_Tree keys;
+       ActKeyColumn *ak;
+       short next= RNA_boolean_get(op->ptr, "next");
+       
+       /* sanity checks */
+       if (scene == NULL)
+               return OPERATOR_CANCELLED;
+       
+       /* init binarytree-list for getting keyframes */
+       BLI_dlrbTree_init(&keys);
+       
+       /* populate tree with keyframe nodes */
+       if (scene && scene->adt)
+               scene_to_keylist(NULL, scene, &keys, NULL);
+       if (ob && ob->adt)
+               ob_to_keylist(NULL, ob, &keys, NULL);
+               
+       /* build linked-list for searching */
+       BLI_dlrbTree_linkedlist_sync(&keys);
+       
+       /* find nearest keyframe in the right direction */
+       ak= cfra_find_nearest_next_ak(keys.root, (float)scene->r.cfra, next);
+       
+       /* set the new frame (if keyframe found) */
+       if (ak) {
+               if (next && ak->next)
+                       scene->r.cfra= (int)ak->next->cfra;
+               else if (!next && ak->prev)
+                       scene->r.cfra= (int)ak->prev->cfra;
+               else {
+                       printf("ERROR: no suitable keyframe found. Using %f as new frame \n", ak->cfra);
+                       scene->r.cfra= (int)ak->cfra; // XXX
+               }
+       }
+               
+       /* free temp stuff */
+       BLI_dlrbTree_free(&keys);
+       
+       WM_event_add_notifier(C, NC_SCENE|ND_FRAME, CTX_data_scene(C));
+
+       return OPERATOR_FINISHED;
+}
+
+static void SCREEN_OT_keyframe_jump(wmOperatorType *ot)
+{
+       ot->name = "Jump to Keyframe";
+       ot->idname = "SCREEN_OT_keyframe_jump";
+
+       ot->exec= keyframe_jump_exec;
+
+       ot->poll= ED_operator_screenactive;
+       ot->flag= 0;
+
+       /* rna */
+       RNA_def_boolean(ot->srna, "next", 1, "Next Keyframe", "");
+}
+
 /* ************** switch screen operator ***************************** */
 
 
@@ -1229,7 +1573,7 @@ static int screen_set_exec(bContext *C, wmOperator *op)
        return OPERATOR_CANCELLED;
 }
 
-void SCREEN_OT_screen_set(wmOperatorType *ot)
+static void SCREEN_OT_screen_set(wmOperatorType *ot)
 {
        ot->name = "Set Screen";
        ot->idname = "SCREEN_OT_screen_set";
@@ -1252,7 +1596,7 @@ static int screen_full_area_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void SCREEN_OT_screen_full_area(wmOperatorType *ot)
+static void SCREEN_OT_screen_full_area(wmOperatorType *ot)
 {
        ot->name = "Toggle Make Area Fullscreen";
        ot->idname = "SCREEN_OT_screen_full_area";
@@ -1383,7 +1727,7 @@ static int area_join_exec(bContext *C, wmOperator *op)
 static int area_join_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
 
-       if(event->type==EVT_ACTIONZONE) {
+       if(event->type==EVT_ACTIONZONE_AREA) {
                sActionzoneData *sad= event->customdata;
 
                if(sad->modifier>0) {
@@ -1524,7 +1868,7 @@ static int area_join_modal(bContext *C, wmOperator *op, wmEvent *event)
 }
 
 /* Operator for joining two areas (space types) */
-void SCREEN_OT_area_join(wmOperatorType *ot)
+static void SCREEN_OT_area_join(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Join area";
@@ -1534,9 +1878,10 @@ void SCREEN_OT_area_join(wmOperatorType *ot)
        ot->exec= area_join_exec;
        ot->invoke= area_join_invoke;
        ot->modal= area_join_modal;
-
        ot->poll= ED_operator_areaactive;
 
+       ot->flag= OPTYPE_BLOCKING;
+
        /* rna */
        RNA_def_int(ot->srna, "x1", -100, INT_MIN, INT_MAX, "X 1", "", INT_MIN, INT_MAX);
        RNA_def_int(ot->srna, "y1", -100, INT_MIN, INT_MAX, "Y 1", "", INT_MIN, INT_MAX);
@@ -1556,7 +1901,7 @@ static int repeat_last_exec(bContext *C, wmOperator *op)
        return OPERATOR_CANCELLED;
 }
 
-void SCREEN_OT_repeat_last(wmOperatorType *ot)
+static void SCREEN_OT_repeat_last(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Repeat Last";
@@ -1608,7 +1953,7 @@ static int repeat_history_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void SCREEN_OT_repeat_history(wmOperatorType *ot)
+static void SCREEN_OT_repeat_history(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Repeat History";
@@ -1641,7 +1986,7 @@ static int redo_last_invoke(bContext *C, wmOperator *op, wmEvent *event)
        return OPERATOR_CANCELLED;
 }
 
-void SCREEN_OT_redo_last(wmOperatorType *ot)
+static void SCREEN_OT_redo_last(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Redo Last";
@@ -1684,7 +2029,7 @@ static int region_split_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void SCREEN_OT_region_split(wmOperatorType *ot)
+static void SCREEN_OT_region_split(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Split Region";
@@ -1773,14 +2118,14 @@ static int region_foursplit_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void SCREEN_OT_region_foursplit(wmOperatorType *ot)
+static void SCREEN_OT_region_foursplit(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Split Region in 4 Parts";
        ot->idname= "SCREEN_OT_region_foursplit";
        
        /* api callbacks */
-       ot->invoke= WM_operator_confirm;
+//     ot->invoke= WM_operator_confirm;
        ot->exec= region_foursplit_exec;
        ot->poll= ED_operator_areaactive;
        ot->flag= OPTYPE_REGISTER;
@@ -1810,90 +2155,213 @@ static int region_flip_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-static void testfunc(bContext *C, void *argv, int arg)
-{
-       printf("arg %d\n", arg);
-}
-
-static void newlevel1(bContext *C, uiLayout *layout, void *arg)
-{
-       uiLayoutFunc(layout, testfunc, NULL);
-       
-       uiItemV(layout, "First", ICON_PROP_ON, 1);
-       uiItemV(layout, "Second", ICON_PROP_CON, 2);
-       uiItemV(layout, "Third", ICON_SMOOTHCURVE, 3);
-       uiItemV(layout, "Fourth", ICON_SHARPCURVE, 4);  
-}
 
-static int testing123(bContext *C, wmOperator *op, wmEvent *event)
+static void SCREEN_OT_region_flip(wmOperatorType *ot)
 {
-       uiPopupMenu *pup= uiPupMenuBegin(C, "Hello world", 0);
-       uiLayout *layout= uiPupMenuLayout(pup);
-       
-       uiLayoutContext(layout, WM_OP_EXEC_DEFAULT);
-       uiItemO(layout, NULL, ICON_PROP_ON, "SCREEN_OT_region_flip");
-       uiItemO(layout, NULL, ICON_PROP_CON, "SCREEN_OT_screen_full_area");
-       uiItemO(layout, NULL, ICON_SMOOTHCURVE, "SCREEN_OT_region_foursplit");
-       uiItemMenuF(layout, "Submenu", 0, newlevel1);
-       
-       uiPupMenuEnd(C, pup);
-       
-       /* this operator is only for a menu, not used further */
-       return OPERATOR_CANCELLED;
-}
-
-void SCREEN_OT_region_flip(wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name= "Flip Region";
-       ot->idname= "SCREEN_OT_region_flip";
+       /* identifiers */
+       ot->name= "Flip Region";
+       ot->idname= "SCREEN_OT_region_flip";
        
        /* api callbacks */
-       ot->invoke= testing123; // XXX WM_operator_confirm;
        ot->exec= region_flip_exec;
        
        ot->poll= ED_operator_areaactive;
        ot->flag= OPTYPE_REGISTER;
-       
-       RNA_def_int(ot->srna, "test", 0, INT_MIN, INT_MAX, "test", "", INT_MIN, INT_MAX);
 
 }
 
-/* ****************** anim player, typically with timer ***************** */
+/* ****************** anim player, with timer ***************** */
 
-static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
+static int match_region_with_redraws(int spacetype, int regiontype, int redraws)
+{
+       if(regiontype==RGN_TYPE_WINDOW) {
+
+               switch (spacetype) {
+                       case SPACE_VIEW3D:
+                               if(redraws & TIME_ALL_3D_WIN)
+                                       return 1;
+                               break;
+                       case SPACE_IPO:
+                       case SPACE_ACTION:
+                       case SPACE_NLA:
+                               if(redraws & TIME_ALL_ANIM_WIN)
+                                       return 1;
+                               break;
+                       case SPACE_TIME:
+                               /* if only 1 window or 3d windows, we do timeline too */
+                               if(redraws & (TIME_ALL_ANIM_WIN|TIME_REGION|TIME_ALL_3D_WIN))
+                                       return 1;
+                               break;
+                       case SPACE_BUTS:
+                               if(redraws & TIME_ALL_BUTS_WIN)
+                                       return 1;
+                               break;
+                       case SPACE_SEQ:
+                               if(redraws & (TIME_SEQ|TIME_ALL_ANIM_WIN))
+                                       return 1;
+                               break;
+                       case SPACE_IMAGE:
+                               if(redraws & TIME_ALL_IMAGE_WIN)
+                                       return 1;
+                               break;
+                               
+               }
+       }
+       else if(regiontype==RGN_TYPE_UI) {
+               if(redraws & TIME_ALL_BUTS_WIN)
+                       return 1;
+       }
+       else if(regiontype==RGN_TYPE_HEADER) {
+               if(spacetype==SPACE_TIME)
+                       return 1;
+       }
+       return 0;
+}
+
+static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event)
 {
        bScreen *screen= CTX_wm_screen(C);
        
        if(screen->animtimer==event->customdata) {
                Scene *scene= CTX_data_scene(C);
+               wmTimer *wt= screen->animtimer;
+               ScreenAnimData *sad= wt->customdata;
+               ScrArea *sa;
                
                if(scene->audio.flag & AUDIO_SYNC) {
-                       wmTimer *wt= screen->animtimer;
                        int step = floor(wt->duration * FPS);
-                       scene->r.cfra += step;
+                       if (sad->flag & ANIMPLAY_FLAG_REVERSE) // XXX does this option work with audio?
+                               scene->r.cfra -= step;
+                       else
+                               scene->r.cfra += step;
                        wt->duration -= ((float)step)/FPS;
                }
-               else
-                       scene->r.cfra++;
+               else {
+                       if (sad->flag & ANIMPLAY_FLAG_REVERSE)
+                               scene->r.cfra--;
+                       else
+                               scene->r.cfra++;
+               }
+               
+               /* reset 'jumped' flag before checking if we need to jump... */
+               sad->flag &= ~ANIMPLAY_FLAG_JUMPED;
                
-               if (scene->r.psfra) {
-                       if(scene->r.cfra > scene->r.pefra)
-                               scene->r.cfra= scene->r.psfra;
+               if (sad->flag & ANIMPLAY_FLAG_REVERSE) {
+                       /* jump back to end? */
+                       if (scene->r.psfra) {
+                               if (scene->r.cfra < scene->r.psfra) {
+                                       scene->r.cfra= scene->r.pefra;
+                                       sad->flag |= ANIMPLAY_FLAG_JUMPED;
+                               }
+                       }
+                       else {
+                               if (scene->r.cfra < scene->r.sfra) {
+                                       scene->r.cfra= scene->r.efra;
+                                       sad->flag |= ANIMPLAY_FLAG_JUMPED;
+                               }
+                       }
                }
                else {
-                       if(scene->r.cfra > scene->r.efra)
-                               scene->r.cfra= scene->r.sfra;
+                       /* jump back to start? */
+                       if (scene->r.psfra) {
+                               if (scene->r.cfra > scene->r.pefra) {
+                                       scene->r.cfra= scene->r.psfra;
+                                       sad->flag |= ANIMPLAY_FLAG_JUMPED;
+                               }
+                       }
+                       else {
+                               if (scene->r.cfra > scene->r.efra) {
+                                       scene->r.cfra= scene->r.sfra;
+                                       sad->flag |= ANIMPLAY_FLAG_JUMPED;
+                               }
+                       }
                }
 
-               WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+               /* since we follow drawflags, we can't send notifier but tag regions ourselves */
+               ED_update_for_newframe(C, 1);
+
+               sound_update_playing(C);
+
+               for(sa= screen->areabase.first; sa; sa= sa->next) {
+                       ARegion *ar;
+                       for(ar= sa->regionbase.first; ar; ar= ar->next) {
+                               if(ar==sad->ar)
+                                       ED_region_tag_redraw(ar);
+                               else
+                                       if(match_region_with_redraws(sa->spacetype, ar->regiontype, sad->redraws))
+                                               ED_region_tag_redraw(ar);
+                       }
+               }
+               
+               //WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
                
                return OPERATOR_FINISHED;
        }
        return OPERATOR_PASS_THROUGH;
 }
 
-void SCREEN_OT_animation_play(wmOperatorType *ot)
+static void SCREEN_OT_animation_step(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Animation Step";
+       ot->idname= "SCREEN_OT_animation_step";
+       
+       /* api callbacks */
+       ot->invoke= screen_animation_step;
+       
+       ot->poll= ED_operator_screenactive;
+       
+}
+
+/* ****************** anim player, starts or ends timer ***************** */
+
+/* helper for screen_animation_play() - only to be used for TimeLine */
+// NOTE: defined in time_header.c for now...
+extern ARegion *time_top_left_3dwindow(bScreen *screen);
+
+/* toggle operator */
+static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
+{
+       bScreen *screen= CTX_wm_screen(C);
+       
+       if(screen->animtimer) {
+               ED_screen_animation_timer(C, 0, 0);
+               sound_stop_all(C);
+       }
+       else {
+               ScrArea *sa= CTX_wm_area(C);
+               int mode= (RNA_boolean_get(op->ptr, "reverse")) ? -1 : 1;
+               
+               /* timeline gets special treatment since it has it's own menu for determining redraws */
+               if ((sa) && (sa->spacetype == SPACE_TIME)) {
+                       SpaceTime *stime= (SpaceTime *)sa->spacedata.first;
+                       
+                       ED_screen_animation_timer(C, stime->redraws, mode);
+                       
+                       /* update region if TIME_REGION was set, to leftmost 3d window */
+                       if(screen->animtimer && (stime->redraws & TIME_REGION)) {
+                               wmTimer *wt= screen->animtimer;
+                               ScreenAnimData *sad= wt->customdata;
+                               
+                               sad->ar= time_top_left_3dwindow(screen);
+                       }
+               }
+               else {
+                       ED_screen_animation_timer(C, TIME_REGION|TIME_ALL_3D_WIN, mode);
+                       
+                       if(screen->animtimer) {
+                               wmTimer *wt= screen->animtimer;
+                               ScreenAnimData *sad= wt->customdata;
+                               
+                               sad->ar= CTX_wm_region(C);
+                       }
+               }
+       }
+       
+       return OPERATOR_FINISHED;
+}
+
+static void SCREEN_OT_animation_play(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Animation player";
@@ -1904,6 +2372,7 @@ void SCREEN_OT_animation_play(wmOperatorType *ot)
        
        ot->poll= ED_operator_screenactive;
        
+       RNA_def_boolean(ot->srna, "reverse", 0, "Play in Reverse", "Animation is played backwards");
 }
 
 /* ************** border select operator (template) ***************************** */
@@ -1941,7 +2410,7 @@ static int border_select_do(bContext *C, wmOperator *op)
        return 1;
 }
 
-void SCREEN_OT_border_select(wmOperatorType *ot)
+static void SCREEN_OT_border_select(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Border select";
@@ -1979,7 +2448,7 @@ static ScrArea *biggest_non_image_area(bContext *C)
        short foundwin= 0;
        
        for(sa= sc->areabase.first; sa; sa= sa->next) {
-               if(sa->winx > 10 && sa->winy > 10) {
+               if(sa->winx > 30 && sa->winy > 30) {
                        size= sa->winx*sa->winy;
                        if(sa->spacetype == SPACE_BUTS) {
                                if(foundwin == 0 && size > bwmaxsize) {
@@ -2032,48 +2501,117 @@ static ScrArea *find_area_showing_r_result(bContext *C)
        return sa;
 }
 
-static void screen_set_image_output(bContext *C)
+static ScrArea *find_area_image_empty(bContext *C)
 {
+       bScreen *sc= CTX_wm_screen(C);
        ScrArea *sa;
        SpaceImage *sima;
        
-       sa= find_area_showing_r_result(C);
+       /* find an imagewindow showing render result */
+       for(sa=sc->areabase.first; sa; sa= sa->next) {
+               if(sa->spacetype==SPACE_IMAGE) {
+                       sima= sa->spacedata.first;
+                       if(!sima->image)
+                               break;
+               }
+       }
+       return sa;
+}
+
+#if 0 // XXX not used
+static ScrArea *find_empty_image_area(bContext *C)
+{
+       bScreen *sc= CTX_wm_screen(C);
+       ScrArea *sa;
+       SpaceImage *sima;
        
-       if(sa==NULL) {
-               /* find largest open non-image area */
-               sa= biggest_non_image_area(C);
-               if(sa) {
-                       ED_area_newspace(C, sa, SPACE_IMAGE);
+       /* find an imagewindow showing render result */
+       for(sa=sc->areabase.first; sa; sa= sa->next) {
+               if(sa->spacetype==SPACE_IMAGE) {
                        sima= sa->spacedata.first;
-                       
-                       /* makes ESC go back to prev space */
-                       sima->flag |= SI_PREVSPACE;
+                       if(!sima->image)
+                               break;
                }
-               else {
-                       /* use any area of decent size */
-                       sa= biggest_area(C);
-                       if(sa->spacetype!=SPACE_IMAGE) {
-                               // XXX newspace(sa, SPACE_IMAGE);
+       }
+       return sa;
+}
+#endif // XXX not used
+
+/* new window uses x,y to set position */
+static void screen_set_image_output(bContext *C, int mx, int my)
+{
+       Scene *scene= CTX_data_scene(C);
+       ScrArea *sa;
+       SpaceImage *sima;
+       
+       if(scene->r.displaymode==R_OUTPUT_WINDOW) {
+               rcti rect;
+               int sizex, sizey;
+               
+               sizex= 10 + (scene->r.xsch*scene->r.size)/100;
+               sizey= 40 + (scene->r.ysch*scene->r.size)/100;
+               
+               /* arbitrary... miniature image window views don't make much sense */
+               if(sizex < 320) sizex= 320;
+               if(sizey < 256) sizey= 256;
+               
+               /* XXX some magic to calculate postition */
+               rect.xmin= mx + CTX_wm_window(C)->posx - sizex/2;
+               rect.ymin= my + CTX_wm_window(C)->posy - sizey/2;
+               rect.xmax= rect.xmin + sizex;
+               rect.ymax= rect.ymin + sizey;
+               
+               /* changes context! */
+               WM_window_open_temp(C, &rect, WM_WINDOW_RENDER);
+               
+               sa= CTX_wm_area(C);
+       }
+       else if(scene->r.displaymode==R_OUTPUT_SCREEN) {
+               /* this function returns with changed context */
+               ED_screen_full_newspace(C, CTX_wm_area(C), SPACE_IMAGE);
+               sa= CTX_wm_area(C);
+       }
+       else {
+       
+               sa= find_area_showing_r_result(C);
+               if(sa==NULL)
+                       sa= find_area_image_empty(C);
+               
+               if(sa==NULL) {
+                       /* find largest open non-image area */
+                       sa= biggest_non_image_area(C);
+                       if(sa) {
+                               ED_area_newspace(C, sa, SPACE_IMAGE);
                                sima= sa->spacedata.first;
                                
                                /* makes ESC go back to prev space */
                                sima->flag |= SI_PREVSPACE;
                        }
+                       else {
+                               /* use any area of decent size */
+                               sa= biggest_area(C);
+                               if(sa->spacetype!=SPACE_IMAGE) {
+                                       // XXX newspace(sa, SPACE_IMAGE);
+                                       sima= sa->spacedata.first;
+                                       
+                                       /* makes ESC go back to prev space */
+                                       sima->flag |= SI_PREVSPACE;
+                               }
+                       }
                }
-       }
-       
+       }       
        sima= sa->spacedata.first;
        
        /* get the correct image, and scale it */
        sima->image= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
        
-       if(G.displaymode==2) { // XXX
-               if(sa->full==0) {
-                       sima->flag |= SI_FULLWINDOW;
+//     if(G.displaymode==2) { // XXX
+               if(sa->full) {
+                       sima->flag |= SI_FULLWINDOW|SI_PREVSPACE;
                        
-                       ed_screen_fullarea(C, sa);
+//                     ed_screen_fullarea(C, sa);
                }
-       }
+//     }
        
 }
 
@@ -2088,7 +2626,7 @@ static int screen_render_exec(bContext *C, wmOperator *op)
        }
        RE_test_break_cb(re, NULL, (int (*)(void *)) blender_test_break);
        
-       if(RNA_boolean_get(op->ptr, "anim"))
+       if(RNA_boolean_get(op->ptr, "animation"))
                RE_BlenderAnim(re, scene, scene->r.sfra, scene->r.efra, scene->frame_step);
        else
                RE_BlenderFrame(re, scene, scene->r.cfra);
@@ -2119,6 +2657,67 @@ static void render_freejob(void *rjv)
        MEM_freeN(rj);
 }
 
+/* str is IMA_RW_MAXTEXT in size */
+static void make_renderinfo_string(RenderStats *rs, Scene *scene, char *str)
+{
+       char info_time_str[32]; // used to be extern to header_info.c
+       uintptr_t mem_in_use, mmap_in_use;
+       float megs_used_memory, mmap_used_memory;
+       char *spos= str;
+       
+       mem_in_use= MEM_get_memory_in_use();
+       mmap_in_use= MEM_get_mapped_memory_in_use();
+       
+       megs_used_memory= (mem_in_use-mmap_in_use)/(1024.0*1024.0);
+       mmap_used_memory= (mmap_in_use)/(1024.0*1024.0);
+       
+       if(scene->lay & 0xFF000000)
+               spos+= sprintf(spos, "Localview | ");
+       else if(scene->r.scemode & R_SINGLE_LAYER)
+               spos+= sprintf(spos, "Single Layer | ");
+       
+       if(rs->statstr) {
+               spos+= sprintf(spos, "%s ", rs->statstr);
+       }
+       else {
+               spos+= sprintf(spos, "Fra:%d  Ve:%d Fa:%d ", (scene->r.cfra), rs->totvert, rs->totface);
+               if(rs->tothalo) spos+= sprintf(spos, "Ha:%d ", rs->tothalo);
+               if(rs->totstrand) spos+= sprintf(spos, "St:%d ", rs->totstrand);
+               spos+= sprintf(spos, "La:%d Mem:%.2fM (%.2fM) ", rs->totlamp, megs_used_memory, mmap_used_memory);
+               
+               if(rs->curfield)
+                       spos+= sprintf(spos, "Field %d ", rs->curfield);
+               if(rs->curblur)
+                       spos+= sprintf(spos, "Blur %d ", rs->curblur);
+       }
+       
+       BLI_timestr(rs->lastframetime, info_time_str);
+       spos+= sprintf(spos, "Time:%s ", info_time_str);
+       
+       if(rs->infostr && rs->infostr[0])
+               spos+= sprintf(spos, "| %s ", rs->infostr);
+       
+       /* very weak... but 512 characters is quite safe */
+       if(spos >= str+IMA_RW_MAXTEXT)
+               printf("WARNING! renderwin text beyond limit \n");
+       
+}
+
+static void image_renderinfo_cb(void *rjv, RenderStats *rs)
+{
+       RenderJob *rj= rjv;
+       
+       /* malloc OK here, stats_draw is not in tile threads */
+       if(rj->image->render_text==NULL)
+               rj->image->render_text= MEM_callocN(IMA_RW_MAXTEXT, "rendertext");
+       
+       make_renderinfo_string(rs, rj->scene, rj->image->render_text);
+       
+       /* make jobs timer to send notifier */
+       *(rj->do_update)= 1;
+
+}
+
 /* called inside thread! */
 static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrect)
 {
@@ -2185,21 +2784,46 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
        rectf+= 4*(rr->rectx*ymin + xmin);
        rectc= (char *)(ibuf->rect + ibuf->x*rymin + rxmin);
 
-       for(y1= 0; y1<ymax; y1++) {
-               float *rf= rectf;
-               char *rc= rectc;
-               
-               /* XXX temp. because crop offset */
-               if( rectc >= (char *)(ibuf->rect)) {
-                       for(x1= 0; x1<xmax; x1++, rf += 4, rc+=4) {
-                               rc[0]= FTOCHAR(rf[0]);
-                               rc[1]= FTOCHAR(rf[1]);
-                               rc[2]= FTOCHAR(rf[2]);
-                               rc[3]= FTOCHAR(rf[3]);
+       /* XXX make nice consistent functions for this */
+       if (rj->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) {
+               for(y1= 0; y1<ymax; y1++) {
+                       float *rf= rectf;
+                       float srgb[3];
+                       char *rc= rectc;
+                       
+                       /* XXX temp. because crop offset */
+                       if( rectc >= (char *)(ibuf->rect)) {
+                               for(x1= 0; x1<xmax; x1++, rf += 4, rc+=4) {
+                                       srgb[0]= linearrgb_to_srgb(rf[0]);
+                                       srgb[1]= linearrgb_to_srgb(rf[1]);
+                                       srgb[2]= linearrgb_to_srgb(rf[2]);
+
+                                       rc[0]= FTOCHAR(srgb[0]);
+                                       rc[1]= FTOCHAR(srgb[1]);
+                                       rc[2]= FTOCHAR(srgb[2]);
+                                       rc[3]= FTOCHAR(rf[3]);
+                               }
                        }
+                       rectf += 4*rr->rectx;
+                       rectc += 4*ibuf->x;
+               }
+       } else {
+               for(y1= 0; y1<ymax; y1++) {
+                       float *rf= rectf;
+                       char *rc= rectc;
+                       
+                       /* XXX temp. because crop offset */
+                       if( rectc >= (char *)(ibuf->rect)) {
+                               for(x1= 0; x1<xmax; x1++, rf += 4, rc+=4) {
+                                       rc[0]= FTOCHAR(rf[0]);
+                                       rc[1]= FTOCHAR(rf[1]);
+                                       rc[2]= FTOCHAR(rf[2]);
+                                       rc[3]= FTOCHAR(rf[3]);
+                               }
+                       }
+                       rectf += 4*rr->rectx;
+                       rectc += 4*ibuf->x;
                }
-               rectf += 4*rr->rectx;
-               rectc += 4*ibuf->x;
        }
        
        /* make jobs timer to send notifier */
@@ -2267,19 +2891,21 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
        /* flush multires changes (for sculpt) */
        multires_force_update(CTX_data_active_object(C));
        
-       // get editmode results
+       /* get editmode results */
+       ED_object_exit_editmode(C, 0);  /* 0 = does not exit editmode */
+       
        // store spare
        // get view3d layer, local layer, make this nice api call to render
        // store spare
        
        /* ensure at least 1 area shows result */
-       screen_set_image_output(C);
+       screen_set_image_output(C, event->x, event->y);
 
        /* job custom data */
        rj= MEM_callocN(sizeof(RenderJob), "render job");
        rj->scene= scene;
        rj->win= CTX_wm_window(C);
-       rj->anim= RNA_boolean_get(op->ptr, "anim");
+       rj->anim= RNA_boolean_get(op->ptr, "animation");
        rj->iuser.scene= scene;
        rj->iuser.ok= 1;
        
@@ -2298,13 +2924,15 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
        re= RE_NewRender(scene->id.name);
        RE_test_break_cb(re, rj, render_breakjob);
        RE_display_draw_cb(re, rj, image_rect_update);
+       RE_stats_draw_cb(re, rj, image_renderinfo_cb);
+       
        rj->re= re;
        G.afbreek= 0;
        
        //      BKE_report in render!
        //      RE_error_cb(re, error_cb);
 
-       WM_jobs_start(steve);
+       WM_jobs_start(CTX_wm_manager(C), steve);
        
        G.afbreek= 0;
        
@@ -2319,7 +2947,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
 
 
 /* contextual render, using current scene, view3d? */
-void SCREEN_OT_render(wmOperatorType *ot)
+static void SCREEN_OT_render(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Render";
@@ -2333,7 +2961,7 @@ void SCREEN_OT_render(wmOperatorType *ot)
        ot->poll= ED_operator_screenactive;
        
        RNA_def_int(ot->srna, "layers", 0, 0, INT_MAX, "Layers", "", 0, INT_MAX);
-       RNA_def_boolean(ot->srna, "anim", 0, "Animation", "");
+       RNA_def_boolean(ot->srna, "animation", 0, "Animation", "");
 }
 
 /* *********************** cancel render viewer *************** */
@@ -2343,7 +2971,12 @@ static int render_view_cancel_exec(bContext *C, wmOperator *unused)
        ScrArea *sa= CTX_wm_area(C);
        SpaceImage *sima= sa->spacedata.first;
        
-       if(sima->flag & SI_PREVSPACE) {
+       /* test if we have a temp screen in front */
+       if(CTX_wm_window(C)->screen->full==SCREENTEMP) {
+               wm_window_lower(CTX_wm_window(C));
+       }
+       /* determine if render already shows */
+       else if(sima->flag & SI_PREVSPACE) {
                sima->flag &= ~SI_PREVSPACE;
                
                if(sima->flag & SI_FULLWINDOW) {
@@ -2361,7 +2994,7 @@ static int render_view_cancel_exec(bContext *C, wmOperator *unused)
        return OPERATOR_FINISHED;
 }
 
-void SCREEN_OT_render_view_cancel(struct wmOperatorType *ot)
+static void SCREEN_OT_render_view_cancel(struct wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Cancel Render View";
@@ -2372,6 +3005,207 @@ void SCREEN_OT_render_view_cancel(struct wmOperatorType *ot)
        ot->poll= ED_operator_image_active;
 }
 
+/* *********************** show render viewer *************** */
+
+static int render_view_show_invoke(bContext *C, wmOperator *unused, wmEvent *event)
+{
+       ScrArea *sa= find_area_showing_r_result(C);
+
+       /* test if we have a temp screen in front */
+       if(CTX_wm_window(C)->screen->full==SCREENTEMP) {
+               wm_window_lower(CTX_wm_window(C));
+       }
+       /* determine if render already shows */
+       else if(sa) {
+               SpaceImage *sima= sa->spacedata.first;
+               
+               if(sima->flag & SI_PREVSPACE) {
+                       sima->flag &= ~SI_PREVSPACE;
+                       
+                       if(sima->flag & SI_FULLWINDOW) {
+                               sima->flag &= ~SI_FULLWINDOW;
+                               ED_screen_full_prevspace(C);
+                       }
+                       else if(sima->next) {
+                               ED_area_newspace(C, sa, sima->next->spacetype);
+                               ED_area_tag_redraw(sa);
+                       }
+               }
+       }
+       else {
+               screen_set_image_output(C, event->x, event->y);
+       }
+       
+       return OPERATOR_FINISHED;
+}
+
+static void SCREEN_OT_render_view_show(struct wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Show/Hide Render View";
+       ot->idname= "SCREEN_OT_render_view_show";
+       
+       /* api callbacks */
+       ot->invoke= render_view_show_invoke;
+       ot->poll= ED_operator_screenactive;
+}
+
+/* *********** show user pref window ****** */
+
+static int userpref_show_invoke(bContext *C, wmOperator *unused, wmEvent *event)
+{
+       ScrArea *sa;
+       rcti rect;
+       int sizex, sizey;
+       
+       sizex= 800;
+       sizey= 480;
+       
+       /* some magic to calculate postition */
+       rect.xmin= event->x + CTX_wm_window(C)->posx - sizex/2;
+       rect.ymin= event->y + CTX_wm_window(C)->posy - sizey/2;
+       rect.xmax= rect.xmin + sizex;
+       rect.ymax= rect.ymin + sizey;
+       
+       /* changes context! */
+       WM_window_open_temp(C, &rect, WM_WINDOW_USERPREFS);
+       
+       sa= CTX_wm_area(C);
+       
+       
+       return OPERATOR_FINISHED;
+}
+
+
+static void SCREEN_OT_userpref_show(struct wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Show/Hide User Preferences";
+       ot->idname= "SCREEN_OT_userpref_show";
+       
+       /* api callbacks */
+       ot->invoke= userpref_show_invoke;
+       ot->poll= ED_operator_screenactive;
+}
+
+/********************* new screen operator *********************/
+
+static int screen_new_exec(bContext *C, wmOperator *op)
+{
+       wmWindow *win= CTX_wm_window(C);
+       bScreen *sc= CTX_wm_screen(C);
+
+       sc= ED_screen_duplicate(win, sc);
+       WM_event_add_notifier(C, NC_SCREEN|ND_SCREENBROWSE, sc);
+
+       return OPERATOR_FINISHED;
+}
+
+void SCREEN_OT_new(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "New Screen";
+       ot->idname= "SCREEN_OT_new";
+       
+       /* api callbacks */
+       ot->exec= screen_new_exec;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/********************* delete screen operator *********************/
+
+static int screen_delete_exec(bContext *C, wmOperator *op)
+{
+       bScreen *sc= CTX_wm_screen(C);
+
+       WM_event_add_notifier(C, NC_SCREEN|ND_SCREENDELETE, sc);
+
+       return OPERATOR_FINISHED;
+}
+
+void SCREEN_OT_delete(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Delete Scene";
+       ot->idname= "SCREEN_OT_delete";
+       
+       /* api callbacks */
+       ot->exec= screen_delete_exec;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/********************* new scene operator *********************/
+
+static int scene_new_exec(bContext *C, wmOperator *op)
+{
+       Scene *newscene, *scene= CTX_data_scene(C);
+       Main *bmain= CTX_data_main(C);
+       int type= RNA_enum_get(op->ptr, "type");
+
+       newscene= copy_scene(bmain, scene, type);
+
+       /* these can't be handled in blenkernel curently, so do them here */
+       if(type == SCE_COPY_LINK_DATA)
+               ED_object_single_users(newscene, 0);
+       else if(type == SCE_COPY_FULL)
+               ED_object_single_users(newscene, 1);
+
+       WM_event_add_notifier(C, NC_SCENE|ND_SCENEBROWSE, newscene);
+
+       return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_new(wmOperatorType *ot)
+{
+       static EnumPropertyItem type_items[]= {
+               {SCE_COPY_EMPTY, "EMPTY", 0, "Empty", "Add empty scene."},
+               {SCE_COPY_LINK_OB, "LINK_OBJECTS", 0, "Link Objects", "Link to the objects from the current scene."},
+               {SCE_COPY_LINK_DATA, "LINK_OBJECT_DATA", 0, "Link Object Data", "Copy objects linked to data from the current scene."},
+               {SCE_COPY_FULL, "FULL_COPY", 0, "Full Copy", "Make a full copy of the current scene."},
+               {0, NULL, 0, NULL, NULL}};
+
+       /* identifiers */
+       ot->name= "New Scene";
+       ot->idname= "SCENE_OT_new";
+       
+       /* api callbacks */
+       ot->exec= scene_new_exec;
+       ot->invoke= WM_menu_invoke;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* properties */
+       RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
+}
+
+/********************* delete scene operator *********************/
+
+static int scene_delete_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene= CTX_data_scene(C);
+
+       WM_event_add_notifier(C, NC_SCENE|ND_SCENEDELETE, scene);
+
+       return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_delete(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Delete Scene";
+       ot->idname= "SCENE_OT_delete";
+       
+       /* api callbacks */
+       ot->exec= scene_delete_exec;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
 
 /* ****************  Assigning operatortypes to global list, adding handlers **************** */
 
@@ -2393,48 +3227,91 @@ void ED_operatortypes_screen(void)
        WM_operatortype_append(SCREEN_OT_region_split);
        WM_operatortype_append(SCREEN_OT_region_foursplit);
        WM_operatortype_append(SCREEN_OT_region_flip);
+       WM_operatortype_append(SCREEN_OT_region_scale);
        WM_operatortype_append(SCREEN_OT_screen_set);
        WM_operatortype_append(SCREEN_OT_screen_full_area);
        WM_operatortype_append(SCREEN_OT_screenshot);
        WM_operatortype_append(SCREEN_OT_screencast);
+       WM_operatortype_append(SCREEN_OT_userpref_show);
        
        /*frame changes*/
        WM_operatortype_append(SCREEN_OT_frame_offset);
+       WM_operatortype_append(SCREEN_OT_frame_jump);
+       WM_operatortype_append(SCREEN_OT_keyframe_jump);
+       
+       WM_operatortype_append(SCREEN_OT_animation_step);
        WM_operatortype_append(SCREEN_OT_animation_play);
        
        /* render */
        WM_operatortype_append(SCREEN_OT_render);
        WM_operatortype_append(SCREEN_OT_render_view_cancel);
-       
+       WM_operatortype_append(SCREEN_OT_render_view_show);
+
+       /* new/delete */
+       WM_operatortype_append(SCREEN_OT_new);
+       WM_operatortype_append(SCREEN_OT_delete);
+       WM_operatortype_append(SCENE_OT_new);
+       WM_operatortype_append(SCENE_OT_delete);
+
        /* tools shared by more space types */
        WM_operatortype_append(ED_OT_undo);
        WM_operatortype_append(ED_OT_redo);     
        
 }
 
+static void keymap_modal_set(wmWindowManager *wm)
+{
+       static EnumPropertyItem modal_items[] = {
+               {KM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
+               {KM_MODAL_APPLY, "APPLY", 0, "Apply", ""},
+               {KM_MODAL_STEP10, "STEP10", 0, "Steps on", ""},
+               {KM_MODAL_STEP10_OFF, "STEP10_OFF", 0, "Steps off", ""},
+               {0, NULL, 0, NULL, NULL}};
+       wmKeyMap *keymap;
+       
+       /* Standard Modal keymap ------------------------------------------------ */
+       keymap= WM_modalkeymap_add(wm, "Standard Modal Map", modal_items);
+       
+       WM_modalkeymap_add_item(keymap, ESCKEY,    KM_PRESS, KM_ANY, 0, KM_MODAL_CANCEL);
+       WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_ANY, KM_ANY, 0, KM_MODAL_APPLY);
+       WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, KM_MODAL_APPLY);
+       WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, KM_MODAL_APPLY);
+
+       WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, KM_MODAL_STEP10);
+       WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, KM_MODAL_STEP10_OFF);
+       
+       WM_modalkeymap_assign(keymap, "SCREEN_OT_area_move");
+
+}
+
 /* called in spacetypes.c */
 void ED_keymap_screen(wmWindowManager *wm)
 {
-       ListBase *keymap= WM_keymap_listbase(wm, "Screen", 0, 0);
+       ListBase *keymap;
+       
+       /* Screen General ------------------------------------------------ */
+       keymap= WM_keymap_listbase(wm, "Screen", 0, 0);
        
        /* standard timers */
-       WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", TIMER0, KM_ANY, KM_ANY, 0);
+       WM_keymap_add_item(keymap, "SCREEN_OT_animation_step", TIMER0, KM_ANY, KM_ANY, 0);
        
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, 0, 0)->ptr, "modifier", 0);
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "modifier", 1);
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "modifier", 2);
        
        /* screen tools */
+       WM_keymap_verify_item(keymap, "SCREEN_OT_area_split", EVT_ACTIONZONE_AREA, 0, 0, 0);
+       WM_keymap_verify_item(keymap, "SCREEN_OT_area_join", EVT_ACTIONZONE_AREA, 0, 0, 0);
+       WM_keymap_verify_item(keymap, "SCREEN_OT_area_dupli", EVT_ACTIONZONE_AREA, 0, KM_SHIFT, 0);
+       WM_keymap_verify_item(keymap, "SCREEN_OT_area_swap", EVT_ACTIONZONE_AREA, 0, KM_ALT, 0);
+       WM_keymap_verify_item(keymap, "SCREEN_OT_region_scale", EVT_ACTIONZONE_REGION, 0, 0, 0);
+                       /* area move after action zones */
        WM_keymap_verify_item(keymap, "SCREEN_OT_area_move", LEFTMOUSE, KM_PRESS, 0, 0);
-       WM_keymap_verify_item(keymap, "SCREEN_OT_area_split", EVT_ACTIONZONE, 0, 0, 0);
-       WM_keymap_verify_item(keymap, "SCREEN_OT_area_join", EVT_ACTIONZONE, 0, 0, 0);
-       WM_keymap_verify_item(keymap, "SCREEN_OT_area_dupli", EVT_ACTIONZONE, 0, KM_SHIFT, 0);
-       WM_keymap_verify_item(keymap, "SCREEN_OT_area_swap", EVT_ACTIONZONE, 0, KM_ALT, 0);
+       
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1);
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", -1);
        WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", UPARROWKEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", DOWNARROWKEY, KM_PRESS, KM_CTRL, 0);
-       WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "SCREEN_OT_screenshot", F3KEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "SCREEN_OT_screencast", F3KEY, KM_PRESS, KM_ALT, 0);
 
@@ -2462,14 +3339,32 @@ void ED_keymap_screen(wmWindowManager *wm)
                                                  
        /* render */
        WM_keymap_add_item(keymap, "SCREEN_OT_render", F12KEY, KM_PRESS, 0, 0);
+       RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_render", F12KEY, KM_PRESS, KM_CTRL, 0)->ptr, "animation", 1);
        WM_keymap_add_item(keymap, "SCREEN_OT_render_view_cancel", ESCKEY, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "SCREEN_OT_render_view_show", F11KEY, KM_PRESS, 0, 0);
        
-       /* frame offsets */
+       /* user prefs */
+       WM_keymap_add_item(keymap, "SCREEN_OT_userpref_show", UKEY, KM_PRESS, KM_ALT, 0);
+       
+       /* Anim Playback ------------------------------------------------ */
        keymap= WM_keymap_listbase(wm, "Frames", 0, 0);
+       
+       /* frame offsets */
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 10);
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", DOWNARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -10);
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -1);
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 1);
        
+       WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", DOWNARROWKEY, KM_PRESS, KM_SHIFT, 0);
+       RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", UPARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", 1);
+       
+       WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", PAGEUPKEY, KM_PRESS, KM_CTRL, 0);
+       RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", PAGEDOWNKEY, KM_PRESS, KM_CTRL, 0)->ptr, "next", 0);
+       
+       /* play (forward and backwards) */
+       WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", AKEY, KM_PRESS, KM_ALT, 0);
+       RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", AKEY, KM_PRESS, KM_ALT|KM_SHIFT, 0)->ptr, "reverse", 1);
+
+       keymap_modal_set(wm);
 }