Fix #19311: adding/opening datablocks did not always make the right
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 1 Oct 2009 23:32:57 +0000 (23:32 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 1 Oct 2009 23:32:57 +0000 (23:32 +0000)
one active. Now there's a function to get the pointer + property from
the UI, just like for the animation operators.

Also two fixes for fileselect events, regions are now preserved so that
context is restored to the old region, and the cancel callback is called
when the operator is cancelled.

source/blender/blenkernel/intern/world.c
source/blender/editors/include/UI_interface.h
source/blender/editors/interface/interface_templates.c
source/blender/editors/physics/particle_boids.c
source/blender/editors/render/render_shading.c
source/blender/editors/screen/area.c
source/blender/editors/space_action/action_edit.c
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_text/text_ops.c
source/blender/makesrna/RNA_types.h
source/blender/windowmanager/intern/wm_event_system.c

index f795c14..c75c927 100644 (file)
@@ -86,15 +86,20 @@ World *add_world(char *name)
 
        wrld= alloc_libblock(&G.main->world, ID_WO, name);
        
-       wrld->horb= 0.6f;
-       wrld->skytype= WO_SKYBLEND;
+       wrld->horr= 0.25f;
+       wrld->horg= 0.25f;
+       wrld->horb= 0.25f;
+       wrld->zenr= 0.1f;
+       wrld->zeng= 0.1f;
+       wrld->zenb= 0.1f;
+       wrld->skytype= 0;
        wrld->stardist= 15.0f;
        wrld->starsize= 2.0f;
        
        wrld->exp= 0.0f;
        wrld->exposure=wrld->range= 1.0f;
 
-       wrld->aodist= 5.0f;
+       wrld->aodist= 10.0f;
        wrld->aosamp= 5;
        wrld->aoenergy= 1.0f;
        wrld->aobias= 0.05f;
index e176299..7fea4b1 100644 (file)
@@ -670,6 +670,7 @@ void uiItemMenuEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *
 /* Helpers for Operators */
 void uiAnimContextProperty(const struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop, int *index);
 void uiFileBrowseContextProperty(const struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop);
+void uiIDContextProperty(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA **prop);
 
 /* Styled text draw */
 void uiStyleFontSet(struct uiFontStyle *fs);
index 57dc484..5b93f9e 100644 (file)
@@ -153,6 +153,36 @@ static uiBlock *search_menu(bContext *C, ARegion *ar, void *arg_litem)
 
 /************************ ID Template ***************************/
 
+/* for new/open operators */
+void uiIDContextProperty(bContext *C, PointerRNA *ptr, PropertyRNA **prop)
+{
+       TemplateID *template;
+       ARegion *ar= CTX_wm_region(C);
+       uiBlock *block;
+       uiBut *but;
+
+       memset(ptr, 0, sizeof(*ptr));
+       *prop= NULL;
+
+       if(!ar)
+               return;
+
+       for(block=ar->uiblocks.first; block; block=block->next) {
+               for(but=block->buttons.first; but; but= but->next) {
+                       /* find the button before the active one */
+                       if((but->flag & (UI_BUT_LAST_ACTIVE|UI_ACTIVE))) {
+                               if(but->func_argN) {
+                                       template= but->func_argN;
+                                       *ptr= template->ptr;
+                                       *prop= template->prop;
+                                       return;
+                               }
+                       }
+               }
+       }
+}
+
+
 static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
 {
        TemplateID *template= (TemplateID*)arg_litem;
@@ -167,11 +197,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
                        break;
                case UI_ID_OPEN:
                case UI_ID_ADD_NEW:
-                       if(template->idlb->last) {
-                               RNA_id_pointer_create(template->idlb->last, &idptr);
-                               RNA_property_pointer_set(&template->ptr, template->prop, idptr);
-                               RNA_property_update(C, &template->ptr, template->prop);
-                       }
+                       /* these call uiIDContextPropertySet */
                        break;
                case UI_ID_DELETE:
                        memset(&idptr, 0, sizeof(idptr));
@@ -291,7 +317,7 @@ static void template_ID(bContext *C, uiBlock *block, TemplateID *template, Struc
                int w= id?UI_UNIT_X: (flag & UI_ID_OPEN)? UI_UNIT_X*3: UI_UNIT_X*6;
                
                if(newop) {
-                       but= uiDefIconTextButO(block, BUT, newop, WM_OP_EXEC_REGION_WIN, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL);
+                       but= uiDefIconTextButO(block, BUT, newop, WM_OP_EXEC_DEFAULT, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL);
                        uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
                }
                else {
@@ -307,7 +333,7 @@ static void template_ID(bContext *C, uiBlock *block, TemplateID *template, Struc
                int w= id?UI_UNIT_X: (flag & UI_ID_ADD_NEW)? UI_UNIT_X*3: UI_UNIT_X*6;
                
                if(openop) {
-                       but= uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_REGION_WIN, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL);
+                       but= uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL);
                        uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
                }
                else {
index 0b63f1a..b7a97d1 100644 (file)
@@ -52,7 +52,6 @@
 /************************ add/del boid rule operators *********************/
 static int rule_add_exec(bContext *C, wmOperator *op)
 {
-       Scene *scene = CTX_data_scene(C);
        PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
        ParticleSystem *psys= ptr.data;
        Object *ob= ptr.id.data;
@@ -152,7 +151,6 @@ void BOID_OT_rule_del(wmOperatorType *ot)
 /************************ move up/down boid rule operators *********************/
 static int rule_move_up_exec(bContext *C, wmOperator *op)
 {
-       Scene *scene= CTX_data_scene(C);
        PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
        ParticleSystem *psys= ptr.data;
        Object *ob = ptr.id.data;
@@ -191,7 +189,6 @@ void BOID_OT_rule_move_up(wmOperatorType *ot)
 
 static int rule_move_down_exec(bContext *C, wmOperator *op)
 {
-       Scene *scene= CTX_data_scene(C);
        PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
        ParticleSystem *psys= ptr.data;
        Object *ob = ptr.id.data;
@@ -363,7 +360,6 @@ void BOID_OT_state_move_up(wmOperatorType *ot)
 
 static int state_move_down_exec(bContext *C, wmOperator *op)
 {
-       Scene *scene= CTX_data_scene(C);
        PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
        ParticleSystem *psys= ptr.data;
        BoidSettings *boids;
index a31a60e..56605ad 100644 (file)
@@ -436,9 +436,8 @@ void OBJECT_OT_material_slot_deselect(wmOperatorType *ot)
 static int new_material_exec(bContext *C, wmOperator *op)
 {
        Material *ma= CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
-       Object *ob;
-       PointerRNA ptr;
-       int index;
+       PointerRNA ptr, idptr;
+       PropertyRNA *prop;
 
        /* add or copy material */
        if(ma)
@@ -446,18 +445,17 @@ static int new_material_exec(bContext *C, wmOperator *op)
        else
                ma= add_material("Material");
 
-       ma->id.us--; /* compensating for us++ in assign_material */
-
-       /* attempt to assign to material slot */
-       ptr= CTX_data_pointer_get_type(C, "material_slot", &RNA_MaterialSlot);
-
-       if(ptr.data) {
-               ob= ptr.id.data;
-               index= (Material**)ptr.data - ob->mat;
+       /* hook into UI */
+       uiIDContextProperty(C, &ptr, &prop);
 
-               assign_material(ob, ma, index+1);
+       if(prop) {
+               /* when creating new ID blocks, use is already 1, but RNA
+                * pointer se also increases user, so this compensates it */
+               ma->id.us--;
 
-               WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+               RNA_id_pointer_create(&ma->id, &idptr);
+               RNA_property_pointer_set(&ptr, prop, idptr);
+               RNA_property_update(C, &ptr, prop);
        }
 
        WM_event_add_notifier(C, NC_MATERIAL|NA_ADDED, ma);
@@ -484,9 +482,8 @@ void MATERIAL_OT_new(wmOperatorType *ot)
 static int new_texture_exec(bContext *C, wmOperator *op)
 {
        Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
-       ID *id;
-       MTex *mtex;
-       PointerRNA ptr;
+       PointerRNA ptr, idptr;
+       PropertyRNA *prop;
 
        /* add or copy texture */
        if(tex)
@@ -494,23 +491,17 @@ static int new_texture_exec(bContext *C, wmOperator *op)
        else
                tex= add_texture("Texture");
 
-       id_us_min(&tex->id);
-
-       /* attempt to assign to texture slot */
-       ptr= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot);
-
-       if(ptr.data) {
-               id= ptr.id.data;
-               mtex= ptr.data;
+       /* hook into UI */
+       uiIDContextProperty(C, &ptr, &prop);
 
-               if(mtex) {
-                       if(mtex->tex)
-                               id_us_min(&mtex->tex->id);
-                       mtex->tex= tex;
-                       id_us_plus(&tex->id);
-               }
+       if(prop) {
+               /* when creating new ID blocks, use is already 1, but RNA
+                * pointer se also increases user, so this compensates it */
+               tex->id.us--;
 
-               /* XXX nodes, notifier .. */
+               RNA_id_pointer_create(&tex->id, &idptr);
+               RNA_property_pointer_set(&ptr, prop, idptr);
+               RNA_property_update(C, &ptr, prop);
        }
 
        WM_event_add_notifier(C, NC_TEXTURE|NA_ADDED, tex);
@@ -536,8 +527,9 @@ void TEXTURE_OT_new(wmOperatorType *ot)
 
 static int new_world_exec(bContext *C, wmOperator *op)
 {
-       Scene *scene= CTX_data_scene(C);
        World *wo= CTX_data_pointer_get_type(C, "world", &RNA_World).data;
+       PointerRNA ptr, idptr;
+       PropertyRNA *prop;
 
        /* add or copy world */
        if(wo)
@@ -545,10 +537,18 @@ static int new_world_exec(bContext *C, wmOperator *op)
        else
                wo= add_world("World");
 
-       /* assign to scene */
-       if(scene->world)
-               id_us_min(&scene->world->id);
-       scene->world= wo;
+       /* hook into UI */
+       uiIDContextProperty(C, &ptr, &prop);
+
+       if(prop) {
+               /* when creating new ID blocks, use is already 1, but RNA
+                * pointer se also increases user, so this compensates it */
+               wo->id.us--;
+
+               RNA_id_pointer_create(&wo->id, &idptr);
+               RNA_property_pointer_set(&ptr, prop, idptr);
+               RNA_property_update(C, &ptr, prop);
+       }
 
        WM_event_add_notifier(C, NC_WORLD|NA_ADDED, wo);
        
index 87901d7..fb78283 100644 (file)
@@ -958,17 +958,22 @@ void area_copy_data(ScrArea *sa1, ScrArea *sa2, int swap_space)
        /* Note; SPACE_EMPTY is possible on new screens */
        
        /* regions */
-       if(swap_space<2) {
-               st= BKE_spacetype_from_id(sa1->spacetype);
-               for(ar= sa1->regionbase.first; ar; ar= ar->next)
-                       BKE_area_region_free(st, ar);
-               BLI_freelistN(&sa1->regionbase);
+       if(swap_space == 1) {
+               SWAP(ListBase, sa1->regionbase, sa2->regionbase);
        }
-       
-       st= BKE_spacetype_from_id(sa2->spacetype);
-       for(ar= sa2->regionbase.first; ar; ar= ar->next) {
-               ARegion *newar= BKE_area_region_copy(st, ar);
-               BLI_addtail(&sa1->regionbase, newar);
+       else {
+               if(swap_space<2) {
+                       st= BKE_spacetype_from_id(sa1->spacetype);
+                       for(ar= sa1->regionbase.first; ar; ar= ar->next)
+                               BKE_area_region_free(st, ar);
+                       BLI_freelistN(&sa1->regionbase);
+               }
+               
+               st= BKE_spacetype_from_id(sa2->spacetype);
+               for(ar= sa2->regionbase.first; ar; ar= ar->next) {
+                       ARegion *newar= BKE_area_region_copy(st, ar);
+                       BLI_addtail(&sa1->regionbase, newar);
+               }
        }
 }
 
index 865d072..0bcf4b0 100644 (file)
@@ -86,6 +86,8 @@
 #include "WM_api.h"
 #include "WM_types.h"
 
+#include "UI_interface.h"
+
 #include "action_intern.h"
 
 /* ************************************************************************** */
 static int act_new_exec(bContext *C, wmOperator *op)
 {
        bAction *action;
+       PointerRNA ptr, idptr;
+       PropertyRNA *prop;
 
        // XXX need to restore behaviour to copy old actions...
        action= add_empty_action("Action");
 
-       /* combined with RNA property, this will assign & increase user,
-          so decrease here to compensate for that */
-       action->id.us--;
-       
+       /* hook into UI */
+       uiIDContextProperty(C, &ptr, &prop);
+
+       if(prop) {
+               /* when creating new ID blocks, use is already 1, but RNA
+                * pointer se also increases user, so this compensates it */
+               action->id.us--;
+
+               RNA_id_pointer_create(&action->id, &idptr);
+               RNA_property_pointer_set(&ptr, prop, idptr);
+               RNA_property_update(C, &ptr, prop);
+       }
+
        /* set notifier that keyframes have changed */
        WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
        
index 89427ba..91316fb 100644 (file)
@@ -616,27 +616,61 @@ static void image_filesel(bContext *C, wmOperator *op, const char *path)
 
 /******************** open image operator ********************/
 
+static void open_init(bContext *C, wmOperator *op)
+{
+       PropertyPointerRNA *pprop;
+
+       op->customdata= pprop= MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
+       uiIDContextProperty(C, &pprop->ptr, &pprop->prop);
+}
+
+static int open_cancel(bContext *C, wmOperator *op)
+{
+       MEM_freeN(op->customdata);
+       op->customdata= NULL;
+       return OPERATOR_CANCELLED;
+}
+
 static int open_exec(bContext *C, wmOperator *op)
 {
        SpaceImage *sima= CTX_wm_space_image(C);
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
+       PropertyPointerRNA *pprop;
+       PointerRNA idptr;
        Image *ima= NULL;
        char str[FILE_MAX];
 
        RNA_string_get(op->ptr, "path", str);
        ima= BKE_add_image_file(str, scene->r.cfra);
 
-       if(!ima)
+       if(!ima) {
+               if(op->customdata) MEM_freeN(op->customdata);
                return OPERATOR_CANCELLED;
+       }
        
-       /* already set later */
-       ima->id.us--;
+       if(!op->customdata)
+               open_init(C, op);
+
+       /* hook into UI */
+       pprop= op->customdata;
+
+       if(pprop->prop) {
+               /* when creating new ID blocks, use is already 1, but RNA
+                * pointer se also increases user, so this compensates it */
+               ima->id.us--;
+
+               RNA_id_pointer_create(&ima->id, &idptr);
+               RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
+               RNA_property_update(C, &pprop->ptr, pprop->prop);
+       }
+       else if(sima)
+               ED_space_image_set(C, sima, scene, obedit, ima);
 
        // XXX other users?
        BKE_image_signal(ima, (sima)? &sima->iuser: NULL, IMA_SIGNAL_RELOAD);
-       if(sima)
-               ED_space_image_set(C, sima, scene, obedit, ima);
+
+       MEM_freeN(op->customdata);
 
        return OPERATOR_FINISHED;
 }
@@ -649,6 +683,8 @@ static int open_invoke(bContext *C, wmOperator *op, wmEvent *event)
        if(RNA_property_is_set(op->ptr, "path"))
                return open_exec(C, op);
        
+       open_init(C, op);
+
        image_filesel(C, op, path);
 
        return OPERATOR_RUNNING_MODAL;
@@ -663,6 +699,7 @@ void IMAGE_OT_open(wmOperatorType *ot)
        /* api callbacks */
        ot->exec= open_exec;
        ot->invoke= open_invoke;
+       ot->cancel= open_cancel;
 
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@@ -1060,6 +1097,8 @@ static int new_exec(bContext *C, wmOperator *op)
        Scene *scene;
        Object *obedit;
        Image *ima;
+       PointerRNA ptr, idptr;
+       PropertyRNA *prop;
        char name[22];
        float color[4];
        int width, height, floatbuf, uvtestgrid;
@@ -1078,12 +1117,27 @@ static int new_exec(bContext *C, wmOperator *op)
        color[3]= RNA_float_get(op->ptr, "alpha");
 
        ima = BKE_add_image_size(width, height, name, floatbuf, uvtestgrid, color);
-       ima->id.us--; /* already set later */
 
-       if(sima) { // XXX other users?
-               BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
-               ED_space_image_set(C, sima, scene, obedit, ima);
+       if(!ima)
+               return OPERATOR_CANCELLED;
+
+       /* hook into UI */
+       uiIDContextProperty(C, &ptr, &prop);
+
+       if(prop) {
+               /* when creating new ID blocks, use is already 1, but RNA
+                * pointer se also increases user, so this compensates it */
+               ima->id.us--;
+
+               RNA_id_pointer_create(&ima->id, &idptr);
+               RNA_property_pointer_set(&ptr, prop, idptr);
+               RNA_property_update(C, &ptr, prop);
        }
+       else if(sima)
+               ED_space_image_set(C, sima, scene, obedit, ima);
+
+       // XXX other users?
+       BKE_image_signal(ima, (sima)? &sima->iuser: NULL, IMA_SIGNAL_USER_NEW_IMAGE);
        
        return OPERATOR_FINISHED;
 }
index 8e81336..44f7a09 100644 (file)
@@ -159,10 +159,24 @@ static int new_exec(bContext *C, wmOperator *op)
 {
        SpaceText *st= CTX_wm_space_text(C);
        Text *text;
+       PointerRNA ptr, idptr;
+       PropertyRNA *prop;
 
        text= add_empty_text("Text");
 
-       if(st) {
+       /* hook into UI */
+       uiIDContextProperty(C, &ptr, &prop);
+
+       if(prop) {
+               /* when creating new ID blocks, use is already 1, but RNA
+                * pointer se also increases user, so this compensates it */
+               text->id.us--;
+
+               RNA_id_pointer_create(&text->id, &idptr);
+               RNA_property_pointer_set(&ptr, prop, idptr);
+               RNA_property_update(C, &ptr, prop);
+       }
+       else if(st) {
                st->text= text;
                st->top= 0;
        }
@@ -186,23 +200,61 @@ void TEXT_OT_new(wmOperatorType *ot)
 
 /******************* open operator *********************/
 
+static void open_init(bContext *C, wmOperator *op)
+{
+       PropertyPointerRNA *pprop;
+
+       op->customdata= pprop= MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
+       uiIDContextProperty(C, &pprop->ptr, &pprop->prop);
+}
+
+static int open_cancel(bContext *C, wmOperator *op)
+{
+       MEM_freeN(op->customdata);
+       return OPERATOR_CANCELLED;
+}
+
 static int open_exec(bContext *C, wmOperator *op)
 {
        SpaceText *st= CTX_wm_space_text(C);
        Text *text;
+       PropertyPointerRNA *pprop;
+       PointerRNA idptr;
        char str[FILE_MAX];
 
        RNA_string_get(op->ptr, "path", str);
 
        text= add_text(str, G.sce);
 
-       if(st) {
+       if(!text) {
+               if(op->customdata) MEM_freeN(op->customdata);
+               return OPERATOR_CANCELLED;
+       }
+
+       if(!op->customdata)
+               open_init(C, op);
+
+       /* hook into UI */
+       pprop= op->customdata;
+
+       if(pprop->prop) {
+               /* when creating new ID blocks, use is already 1, but RNA
+                * pointer se also increases user, so this compensates it */
+               text->id.us--;
+
+               RNA_id_pointer_create(&text->id, &idptr);
+               RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
+               RNA_property_update(C, &pprop->ptr, pprop->prop);
+       }
+       else if(st) {
                st->text= text;
                st->top= 0;
        }
 
        WM_event_add_notifier(C, NC_TEXT|NA_ADDED, text);
 
+       MEM_freeN(op->customdata);
+
        return OPERATOR_FINISHED;
 }
 
@@ -214,6 +266,7 @@ static int open_invoke(bContext *C, wmOperator *op, wmEvent *event)
        if(RNA_property_is_set(op->ptr, "path"))
                return open_exec(C, op);
        
+       open_init(C, op);
        RNA_string_set(op->ptr, "path", path);
        WM_event_add_fileselect(C, op); 
 
@@ -230,6 +283,7 @@ void TEXT_OT_open(wmOperatorType *ot)
        /* api callbacks */
        ot->exec= open_exec;
        ot->invoke= open_invoke;
+       ot->cancel= open_cancel;
        ot->poll= text_new_poll;
 
        /* properties */
index 98df8c3..df44789 100644 (file)
@@ -54,6 +54,11 @@ typedef struct PointerRNA {
        void *data;
 } PointerRNA;
 
+typedef struct PropertyPointerRNA {
+       PointerRNA ptr;
+       struct PropertyRNA *prop;
+} PropertyPointerRNA;
+
 /* Property */
 
 typedef enum PropertyType {
index b7156a1..80878cf 100644 (file)
@@ -298,6 +298,8 @@ static int wm_operator_exec(bContext *C, wmOperator *op, int repeat)
                        uiPupMenuReports(C, op->reports);
        
        if(retval & OPERATOR_FINISHED) {
+               op->customdata= NULL;
+
                if(op->type->flag & OPTYPE_UNDO)
                        ED_undo_push_op(C, op);
                
@@ -427,6 +429,8 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P
                }
 
                if(retval & OPERATOR_FINISHED) {
+                       op->customdata= NULL;
+
                        if(ot->flag & OPTYPE_UNDO)
                                ED_undo_push_op(C, op);
                        
@@ -813,6 +817,8 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
                        }                       
 
                        if(retval & OPERATOR_FINISHED) {
+                               op->customdata= NULL;
+
                                if(ot->flag & OPTYPE_UNDO)
                                        ED_undo_push_op(C, op);
                                
@@ -936,9 +942,9 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa
                                /* remlink now, for load file case */
                                BLI_remlink(handlers, handler);
                                
+                               wm_handler_op_context(C, handler);
+
                                if(event->val==EVT_FILESELECT_EXEC) {
-                                       wm_handler_op_context(C, handler);
-                               
                                        /* a bit weak, might become arg for WM_event_fileselect? */
                                        /* XXX also extension code in image-save doesnt work for this yet */
                                        if(strncmp(handler->op->type->name, "Save", 4)==0) {
@@ -954,11 +960,15 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa
                                                
                                                WM_operator_free(handler->op);
                                        }
-                                       
-                                       CTX_wm_area_set(C, NULL);
                                }
-                               else 
+                               else {
+                                       if(handler->op->type->cancel)
+                                               handler->op->type->cancel(C, handler->op);
+
                                        WM_operator_free(handler->op);
+                               }
+
+                               CTX_wm_area_set(C, NULL);
                                
                                wm_event_free_handler(handler);
                                if(path)