diff options
author | Ton Roosendaal <ton@blender.org> | 2008-12-02 17:22:52 +0300 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2008-12-02 17:22:52 +0300 |
commit | 54908979c54ab332156f438e995d5dce8ee8420c (patch) | |
tree | 94558d3acad12b5c0f08e902d967ce3d6d0f0723 /source/blender/windowmanager | |
parent | c4fe6d0f00aa2a9656445ebb53161768e0c51342 (diff) |
Lots of stuff; couldn't commit in parts because of refactor work.
* Changes in interface/ module
This commit brings back the way how buttons/menus work under control
of WM event system. The previous implementation extended usage of
handlers and operators in an interesting but confusing way. Better to
try it first according the design specs. :)
Most obviously:
- modal-handler operators are not stored anymore in regions/areas/windows.
such modal handlers own their operator, and should remove it themselves.
- removed code to move handlers from one queue to another.
(needs review with brecht!)
- WM fix: the API call to remove a modal handler got removed. This was a
dangerous thing anyway, and you should leave that to the event system.
Now, if a handler modal() call gets a cancel/finish return, it frees
itself in event system. WM_event_remove_modal_handler was a confusing
call anyway!
Todo:
- allow button-activate to refresh after using button
- re-enable arrow keys for menus
(do both after commit)
- review return values of operator callbacks in interface_ops.c
* Fixes in WM system
- Freeing areas/regions/windows, also on quit, now correctly closes
running modal handlers
- On starting a modal handler, the handler now stores previous area
and region context, so they send proper notifiers etc.
* Other fixes
- Area-split operator had bug, wrong minimal size checking. This
solves error when trying to split a very narrow area.
- removed DNA_USHORT_FIX from screen_types.h, gave warning
- operators didn't get ID name copied when activated, needed for
later re-use or saving.
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 7 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 130 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_init_exit.c | 16 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 8 | ||||
-rw-r--r-- | source/blender/windowmanager/wm_event_system.h | 7 |
5 files changed, 82 insertions, 86 deletions
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 9b2c1409887..4b9c01b3e33 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -69,9 +69,9 @@ void WM_keymap_add_item (ListBase *lb, char *idname, short type, short val, int modifier, short keymodifier); struct wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, ListBase *keymap); void WM_event_remove_keymap_handler(ListBase *handlers, ListBase *keymap); -struct wmEventHandler *WM_event_add_modal_handler(ListBase *handlers, wmOperator *op); -void WM_event_remove_modal_handler(ListBase *handlers, wmOperator *op); -void WM_event_remove_handlers(ListBase *handlers); + +struct wmEventHandler *WM_event_add_modal_handler(bContext *C, ListBase *handlers, wmOperator *op); +void WM_event_remove_handlers (bContext *C, ListBase *handlers); void WM_event_add_message(wmWindowManager *wm, void *customdata, short customdatafree); @@ -97,7 +97,6 @@ wmOperatorType *WM_operatortype_find(const char *idname); void WM_operatortype_append (void (*opfunc)(wmOperatorType*)); int WM_operator_invoke (struct bContext *C, wmOperatorType *ot, struct wmEvent *event); -void WM_operator_cancel (struct bContext *C, ListBase *modalops, wmOperatorType *ot); /* default operator callbacks for border/lasso */ int WM_border_select_invoke (struct bContext *C, wmOperator *op, struct wmEvent *event); 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; diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index c196f7a4fff..fb8101168e2 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -74,6 +74,7 @@ #include "WM_api.h" #include "WM_types.h" +#include "wm_event_system.h" #include "wm.h" #include "wm_files.h" #include "wm_window.h" @@ -157,6 +158,21 @@ extern wchar_t *copybufinfo; /* called in creator.c even... tsk, split this! */ void WM_exit(bContext *C) { + wmWindow *win; + + /* first wrap up running stuff, we assume only the active WM is running */ + /* modal handlers are on window level freed, others too? */ + if(C && C->wm) { + for(win= C->wm->windows.first; win; win= win->next) { + ARegion *ar; + + C->window= win; /* needed by operator close callbacks */ + WM_event_remove_handlers(C, &win->handlers); + + for(ar= win->screen->regionbase.first; ar; ar= ar->next) + WM_event_remove_handlers(C, &ar->handlers); + } + } wm_operatortype_free(); free_ttfont(); /* bke_font.h */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 7dacae6da91..7a4b30af384 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -182,7 +182,7 @@ static void border_select_end(bContext *C, wmOperator *op) WM_gesture_end(C, gesture); /* frees gesture itself, and unregisters from window */ op->customdata= NULL; - WM_event_remove_modal_handler(&C->window->handlers, op); + WM_event_add_notifier(C->wm, C->window, gesture->swinid, WM_NOTE_AREA_REDRAW, 0, NULL); } @@ -192,7 +192,7 @@ int WM_border_select_invoke(bContext *C, wmOperator *op, wmEvent *event) op->customdata= WM_gesture_new(C, event, WM_GESTURE_CROSS_RECT); /* add modal handler */ - WM_event_add_modal_handler(&C->window->handlers, op); + WM_event_add_modal_handler(C, &C->window->handlers, op); WM_event_add_notifier(C->wm, C->window, C->screen->subwinactive, WM_NOTE_GESTURE_REDRAW, 0, NULL); @@ -252,7 +252,7 @@ static int tweak_gesture_invoke(bContext *C, wmOperator *op, wmEvent *event) op->customdata= WM_gesture_new(C, event, WM_GESTURE_TWEAK); /* add modal handler */ - WM_event_add_modal_handler(&C->window->handlers, op); + WM_event_add_modal_handler(C, &C->window->handlers, op); WM_event_add_notifier(C->wm, C->window, C->screen->subwinactive, WM_NOTE_GESTURE_REDRAW, 0, NULL); @@ -265,7 +265,7 @@ static void tweak_gesture_end(bContext *C, wmOperator *op) WM_gesture_end(C, gesture); /* frees gesture itself, and unregisters from window */ op->customdata= NULL; - WM_event_remove_modal_handler(&C->window->handlers, op); + WM_event_add_notifier(C->wm, C->window, gesture->swinid, WM_NOTE_AREA_REDRAW, 0, NULL); } diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h index cbaef2a8c30..1b3b7ce8efb 100644 --- a/source/blender/windowmanager/wm_event_system.h +++ b/source/blender/windowmanager/wm_event_system.h @@ -32,6 +32,8 @@ #define WM_HANDLER_CONTINUE 0 #define WM_HANDLER_BREAK 1 +struct ScrArea; +struct ARegion; /* wmKeyMap is in DNA_windowmanager.h, it's savable */ @@ -44,7 +46,9 @@ typedef struct wmEventHandler { rctf boundbox; /* float, in bContext space (window, area, region) */ - wmOperator *op; /* for derived handlers */ + wmOperator *op; /* for derived/modal handlers */ + struct ScrArea *op_area; /* for derived/modal handlers */ + struct ARegion *op_region; /* for derived/modal handlers */ } wmEventHandler; @@ -65,7 +69,6 @@ enum { void wm_event_add(wmWindow *win, wmEvent *event_to_add); void wm_event_free_all (wmWindow *win); wmEvent *wm_event_next (wmWindow *win); -void wm_event_free_handlers (ListBase *lb); /* goes over entire hierarchy: events -> window -> screen -> area -> region */ void wm_event_do_handlers (bContext *C); |