bugfix [#24466] Selecting of object with pattern leads to strange behavior

The undo problem was caused by python operators returning 'RUNNING_MODAL' rather then the return value from wm.invoke_props_popup(self, event) - 'FINISHED'.

This was done because returning FINISHED would free the operator causing the buttons redo handler to try and run a freed operator and crash.

So the real fix is to disallow any operators to use wm.invoke_props_popup(self, event) if they dont have the REGISTER option enabled, fixing the crash and redo problem.
This commit is contained in:
Campbell Barton
2010-10-31 14:43:30 +00:00
parent 391c547208
commit 184b5fd6db
5 changed files with 23 additions and 15 deletions

View File

@@ -60,9 +60,7 @@ class SelectPattern(bpy.types.Operator):
def invoke(self, context, event):
wm = context.window_manager
# return wm.invoke_props_popup(self, event)
wm.invoke_props_popup(self, event)
return {'RUNNING_MODAL'}
return wm.invoke_props_popup(self, event)
def draw(self, context):
layout = self.layout

View File

@@ -29,6 +29,7 @@ class AddPresetBase():
- preset_subdir '''
# bl_idname = "script.preset_base_add"
# bl_label = "Add a Python Preset"
bl_options = {'REGISTER'} # only because invoke_props_popup requires.
name = bpy.props.StringProperty(name="Name", description="Name of the preset, used to make the path name", maxlen=64, default="")
remove_active = bpy.props.BoolProperty(default=False, options={'HIDDEN'})
@@ -110,11 +111,7 @@ class AddPresetBase():
def invoke(self, context, event):
if not self.remove_active:
wm = context.window_manager
#crashes, TODO - fix
#return wm.invoke_props_popup(self, event)
wm.invoke_props_popup(self, event)
return {'RUNNING_MODAL'}
return wm.invoke_props_popup(self, event)
else:
return self.execute(context)

View File

@@ -661,6 +661,7 @@ class WM_OT_properties_edit(bpy.types.Operator):
'''Internal use (edit a property data_path)'''
bl_idname = "wm.properties_edit"
bl_label = "Edit Property"
bl_options = {'REGISTER'} # only because invoke_props_popup requires.
data_path = rna_path
property = rna_property
@@ -721,11 +722,7 @@ class WM_OT_properties_edit(bpy.types.Operator):
self.description = prop_ui.get("description", "")
wm = context.window_manager
# This crashes, TODO - fix
#return wm.invoke_props_popup(self, event)
wm.invoke_props_popup(self, event)
return {'RUNNING_MODAL'}
return wm.invoke_props_popup(self, event)
class WM_OT_properties_add(bpy.types.Operator):

View File

@@ -364,9 +364,9 @@ int WM_operator_poll(bContext *C, wmOperatorType *ot)
wmOperatorTypeMacro *otmacro;
for(otmacro= ot->macro.first; otmacro; otmacro= otmacro->next) {
wmOperatorType *ot= WM_operatortype_find(otmacro->idname, 0);
wmOperatorType *ot_macro= WM_operatortype_find(otmacro->idname, 0);
if(0==WM_operator_poll(C, ot))
if(0==WM_operator_poll(C, ot_macro))
return 0;
}

View File

@@ -31,6 +31,7 @@
#include <ctype.h>
#include <stdio.h>
#include <stddef.h>
#include <assert.h>
#ifdef WIN32
#include <windows.h>
#include <io.h>
@@ -889,6 +890,11 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op)
block= uiBeginBlock(C, ar, "redo_popup", UI_EMBOSS);
uiBlockClearFlag(block, UI_BLOCK_LOOP);
uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN|UI_BLOCK_RET_1|UI_BLOCK_MOVEMOUSE_QUIT);
/* if register is not enabled, the operator gets freed on OPERATOR_FINISHED
* ui_apply_but_funcs_after calls redo_cb and crashes */
assert(op->type->flag & OPTYPE_REGISTER);
uiBlockSetHandleFunc(block, redo_cb, arg_op);
if(!op->properties) {
@@ -1021,6 +1027,11 @@ int WM_operator_props_popup(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
{
int retval= OPERATOR_CANCELLED;
if((op->type->flag & OPTYPE_REGISTER)==0) {
BKE_reportf(op->reports, RPT_ERROR, "Operator '%s' does not have register enabled, incorrect invoke function.", op->type->idname);
return OPERATOR_CANCELLED;
}
if(op->type->exec) {
retval= op->type->exec(C, op);
@@ -1059,6 +1070,11 @@ int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height)
int WM_operator_redo_popup(bContext *C, wmOperator *op)
{
if((op->type->flag & OPTYPE_REGISTER)==0) {
BKE_reportf(op->reports, RPT_ERROR, "Operator '%s' does not have register enabled, incorrect invoke function.", op->type->idname);
return OPERATOR_CANCELLED;
}
uiPupBlock(C, wm_block_create_redo, op);
return OPERATOR_CANCELLED;