Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/windowmanager/intern/wm_event_system.c')
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c130
1 files changed, 54 insertions, 76 deletions
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index e4c4406b8ae..9432036b4bc 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -279,17 +279,6 @@ void wm_draw_update(bContext *C)
/* ********************* operators ******************* */
-static ListBase *wm_modalops_list(bContext *C)
-{
- if(C->region)
- return &C->region->modalops;
- else if(C->area)
- return &C->area->modalops;
- else if(C->window)
- return &C->window->modalops;
- else
- return NULL;
-}
int WM_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event)
{
@@ -298,8 +287,10 @@ int WM_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event)
if(ot->poll==NULL || ot->poll(C)) {
wmOperator *op= MEM_callocN(sizeof(wmOperator), "wmOperator");
+ /* XXX adding new operator could be function, only happens here now */
op->type= ot;
-
+ BLI_strncpy(op->idname, ot->idname, OP_MAX_TYPENAME);
+
op->ptr= MEM_callocN(sizeof(PointerRNA), "wmOperatorPtrRNA");
RNA_pointer_create(&RNA_WindowManager, &C->wm->id, ot->srna, op, op->ptr);
@@ -314,59 +305,38 @@ int WM_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event)
else if(!(retval & OPERATOR_RUNNING_MODAL)) {
wm_operator_free(op);
}
- else {
- op->modallist= wm_modalops_list(C);
- BLI_addtail(op->modallist, op);
- }
}
return retval;
}
-void WM_operator_cancel(bContext *C, ListBase *lb, wmOperatorType *type)
-{
- wmOperator *op, *nextop;
-
- if(!lb)
- lb= wm_modalops_list(C);
- if(!lb)
- return;
-
- for(op=lb->first; op; op=nextop) {
- nextop= op->next;
-
- if(type == NULL || op->type == type) {
- if(op->type->cancel)
- op->type->cancel(C, op);
-
- BLI_remlink(op->modallist, op);
- op->modallist= NULL;
-
- wm_operator_free(op);
- }
- }
-}
-
/* ********************* handlers *************** */
-/* not handler itself */
+
+/* not handler itself, is called by UI to move handlers to other queues, so don't close modal ones */
static void wm_event_free_handler(wmEventHandler *handler)
{
+
}
-void wm_event_free_handlers(ListBase *lb)
+/* called on exit or remove area, only here call cancel callback */
+void WM_event_remove_handlers(bContext *C, ListBase *handlers)
{
wmEventHandler *handler;
- for(handler= lb->first; handler; handler= handler->next)
+ /* C is zero on freeing database, modal handlers then already were freed */
+ while((handler=handlers->first)) {
+ /* we have to remove the handler first, to prevent op->type->cancel() to remove modal handler too */
+ BLI_remlink(handlers, handler);
+
+ if(C && handler->op) {
+ if(handler->op->type->cancel)
+ handler->op->type->cancel(C, handler->op);
+ wm_operator_free(handler->op);
+ }
wm_event_free_handler(handler);
-
- BLI_freelistN(lb);
-}
-
-void WM_event_remove_handlers(ListBase *handlers)
-{
- wm_event_free_handlers(handlers);
+ MEM_freeN(handler);
+ }
}
static int wm_eventmatch(wmEvent *winevent, wmKeymapItem *km)
@@ -389,8 +359,8 @@ static int wm_eventmatch(wmEvent *winevent, wmKeymapItem *km)
return 1;
}
-/* note: this might free the handler from the operator */
-static int wm_handler_operator_call(bContext *C, wmEventHandler *handler, wmEvent *event)
+/* Warning: this function removes a modal handler, when finished */
+static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHandler *handler, wmEvent *event)
{
int retval= OPERATOR_PASS_THROUGH;
@@ -400,18 +370,38 @@ static int wm_handler_operator_call(bContext *C, wmEventHandler *handler, wmEven
wmOperatorType *ot= op->type;
if(ot->modal) {
+ /* we set context to where modal handler came from */
+ ScrArea *area= C->area;
+ ARegion *region= C->region;
+
+ C->area= handler->op_area;
+ C->region= handler->op_region;
+
retval= ot->modal(C, op, event);
+ /* putting back screen context */
+ C->area= area;
+ C->region= region;
+
if((retval & OPERATOR_FINISHED) && (ot->flag & OPTYPE_REGISTER)) {
- BLI_remlink(op->modallist, op);
- op->modallist= NULL;
wm_operator_register(C->wm, op);
+ handler->op= NULL;
}
else if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
- BLI_remlink(op->modallist, op);
- op->modallist= NULL;
wm_operator_free(op);
+ handler->op= NULL;
}
+
+ /* remove modal handler, operator itself should have been cancelled and freed */
+ if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
+ BLI_remlink(handlers, handler);
+ wm_event_free_handler(handler);
+ MEM_freeN(handler);
+
+ /* prevent silly errors from operator users */
+ retval &= ~OPERATOR_PASS_THROUGH;
+ }
+
}
else
printf("wm_handler_operator_call error\n");
@@ -442,8 +432,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
if(handlers==NULL) return action;
- /* in this loop, the handler might be freed in wm_handler_operator_call,
- * and new handler might be added to the head of the list */
+ /* modal handlers can get removed in this loop, we keep the loop this way */
for(handler= handlers->first; handler; handler= nexthandler) {
nexthandler= handler->next;
@@ -461,15 +450,15 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
event->keymap_idname= km->idname; /* weak, but allows interactive callback to not use rawkey */
- action= wm_handler_operator_call(C, handler, event);
- if(!wm_event_always_pass(event) && action==WM_HANDLER_BREAK)
+ action= wm_handler_operator_call(C, handlers, handler, event);
+ if(action==WM_HANDLER_BREAK) /* not wm_event_always_pass(event) here, it denotes removed handler */
break;
}
}
}
else {
/* modal, swallows all */
- action= wm_handler_operator_call(C, handler, event);
+ action= wm_handler_operator_call(C, handlers, handler, event);
}
if(!wm_event_always_pass(event) && action==WM_HANDLER_BREAK)
@@ -587,7 +576,7 @@ void WM_event_set_handler_flag(wmEventHandler *handler, int flag)
handler->flag= flag;
}
-wmEventHandler *WM_event_add_modal_handler(ListBase *handlers, wmOperator *op)
+wmEventHandler *WM_event_add_modal_handler(bContext *C, ListBase *handlers, wmOperator *op)
{
/* debug test; operator not in registry */
if(op->type->flag & OPTYPE_REGISTER) {
@@ -596,6 +585,9 @@ wmEventHandler *WM_event_add_modal_handler(ListBase *handlers, wmOperator *op)
else {
wmEventHandler *handler= MEM_callocN(sizeof(wmEventHandler), "event handler");
handler->op= op;
+ handler->op_area= C->area; /* means frozen screen context for modal handlers! */
+ handler->op_region= C->region;
+
BLI_addhead(handlers, handler);
return handler;
@@ -603,20 +595,6 @@ wmEventHandler *WM_event_add_modal_handler(ListBase *handlers, wmOperator *op)
return NULL;
}
-void WM_event_remove_modal_handler(ListBase *handlers, wmOperator *op)
-{
- wmEventHandler *handler;
-
- for(handler= handlers->first; handler; handler= handler->next) {
- if(handler->op==op) {
- BLI_remlink(handlers, handler);
- wm_event_free_handler(handler);
- MEM_freeN(handler);
- break;
- }
- }
-}
-
wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, ListBase *keymap)
{
wmEventHandler *handler;