diff options
author | Ton Roosendaal <ton@blender.org> | 2009-07-21 15:03:07 +0400 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2009-07-21 15:03:07 +0400 |
commit | ed921058573dca5277f062e992ad0db0393071fe (patch) | |
tree | 75a86f6b33c38242cd1e116e37206555383ed376 /source/blender/windowmanager | |
parent | 0865bf295947e5cd0b59429edf084f738321aef0 (diff) |
2.5
Modal keymaps.
I've tried to make it as simple as possible, yet still using sufficient facilities to enable self-documenting UIs, saving/reading in files, and proper Python support.
The simplicity is: the 'modal keymap' just checks an event, uses event matching similarly to other keymap matching, and if there's a match it changes the event type, and sets the event value to what the modal keymap has defined. The event values are being defined using EnumPropertyItem structs, so the UI will be able to show all options in self-documenting way.
This system also allows to still handle hardcoded own events.
Tech doc:
1) define keymap
- Create map with unique name, WM_modalkeymap_add()
- Give map property definitions (EnumPropertyItem *)
This only for UI, so user can get information on available options
2) items
- WM_modalkeymap_add_item(): give it an enum value for events
3) activate
- In keymap definition code, assign the modal keymap to operatortype
WM_modalkeymap_assign()
4) event manager
- The event handler will check for modal keymap, if so:
- If the modal map has a match:
- Sets event->type to EVT_MODAL_MAP
- Sets event->val to the enum value
5) modal handler
- If event type is EVT_MODAL_MAP:
- Check event->val, handle it
- Other events can just be handled still
Two examples added in the code:
editors/transform/transform.c: transform_modal_keymap()
editors/screen/screen_ops.c: keymap_modal_set()
Also: to support 'key release' the define KM_RELEASE now is officially
used in event manager, this is not '0', so don't check key events with
the old convention if(event->val) but use if(event->val==KM_PRESS)
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 9 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 26 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_keymap.c | 57 | ||||
-rw-r--r-- | source/blender/windowmanager/wm_event_types.h | 4 |
4 files changed, 89 insertions, 7 deletions
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 609d599a09a..542a747d454 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -40,6 +40,7 @@ struct wmJob; struct wmNotifier; struct rcti; struct PointerRNA; +struct EnumPropertyItem; typedef struct wmJob wmJob; @@ -79,7 +80,13 @@ wmKeymapItem *WM_keymap_add_item(ListBase *lb, char *idname, short type, short val, int modifier, short keymodifier); void WM_keymap_tweak (ListBase *lb, short type, short val, int modifier, short keymodifier); ListBase *WM_keymap_listbase (struct wmWindowManager *wm, const char *nameid, - int spaceid, int regionid); + short spaceid, short regionid); + +wmKeyMap *WM_modalkeymap_add(struct wmWindowManager *wm, const char *nameid, struct EnumPropertyItem *items); +wmKeyMap *WM_modalkeymap_get(struct wmWindowManager *wm, const char *nameid); +void WM_modalkeymap_add_item(wmKeyMap *km, short type, short val, int modifier, short keymodifier, short value); +void WM_modalkeymap_assign(wmKeyMap *km, const char *opname); + const char *WM_key_event_string(short type); char *WM_key_event_operator_string(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, char *str, int len); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index ffd1054d954..0df0679f98b 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -652,6 +652,23 @@ static int wm_event_always_pass(wmEvent *event) return ELEM5(event->type, TIMER, TIMER0, TIMER1, TIMER2, TIMERJOBS); } +/* operator exists */ +static void wm_event_modalkeymap(wmOperator *op, wmEvent *event) +{ + if(op->type->modalkeymap) { + wmKeymapItem *kmi; + + for(kmi= op->type->modalkeymap->keymap.first; kmi; kmi= kmi->next) { + if(wm_eventmatch(event, kmi)) { + + event->type= EVT_MODAL_MAP; + event->val= kmi->propvalue; + printf("found modal event %s %d\n", kmi->idname, kmi->propvalue); + } + } + } +} + /* Warning: this function removes a modal handler, when finished */ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHandler *handler, wmEvent *event, PointerRNA *properties) { @@ -668,8 +685,9 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand ARegion *region= CTX_wm_region(C); wm_handler_op_context(C, handler); - wm_region_mouse_co(C, event); + wm_event_modalkeymap(op, event); + retval= ot->modal(C, op, event); /* putting back screen context, reval can pass trough after modal failures! */ @@ -1446,7 +1464,7 @@ void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata) GHOST_TEventKeyData *kd= customdata; event.type= convert_key(kd->key); event.ascii= kd->ascii; - event.val= (type==GHOST_kEventKeyDown); /* XXX eventmatch uses defines, bad code... */ + event.val= (type==GHOST_kEventKeyDown)?KM_PRESS:KM_RELEASE; /* exclude arrow keys, esc, etc from text input */ if(type==GHOST_kEventKeyUp || (event.ascii<32 && event.ascii>14)) @@ -1474,10 +1492,10 @@ void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata) event.oskey= evt->oskey = 3; // define? } - /* if test_break set, it catches this. Keep global for now? */ + /* if test_break set, it catches this. XXX Keep global for now? */ if(event.type==ESCKEY) G.afbreek= 1; - + wm_event_add(win, &event); break; diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index b914e63788d..764b209d755 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -132,7 +132,7 @@ wmKeymapItem *WM_keymap_add_item(ListBase *lb, char *idname, short type, short v space/region ids are same as DNA_space_types.h */ /* gets free'd in wm.c */ -ListBase *WM_keymap_listbase(wmWindowManager *wm, const char *nameid, int spaceid, int regionid) +static wmKeyMap *wm_keymap_add(wmWindowManager *wm, const char *nameid, short spaceid, short regionid) { wmKeyMap *km; @@ -140,7 +140,7 @@ ListBase *WM_keymap_listbase(wmWindowManager *wm, const char *nameid, int spacei if(km->spaceid==spaceid && km->regionid==regionid) if(0==strncmp(nameid, km->nameid, KMAP_MAX_NAME)) break; - + if(km==NULL) { km= MEM_callocN(sizeof(struct wmKeyMap), "keymap list"); BLI_strncpy(km->nameid, nameid, KMAP_MAX_NAME); @@ -149,9 +149,62 @@ ListBase *WM_keymap_listbase(wmWindowManager *wm, const char *nameid, int spacei BLI_addtail(&wm->keymaps, km); } + return km; +} + +ListBase *WM_keymap_listbase(wmWindowManager *wm, const char *nameid, short spaceid, short regionid) +{ + wmKeyMap *km= wm_keymap_add(wm, nameid, spaceid, regionid); return &km->keymap; } +/* ****************** modal keymaps ************ */ + +/* modal maps get linked to a running operator, and filter the keys before sending to modal() callback */ + +wmKeyMap *WM_modalkeymap_add(wmWindowManager *wm, const char *nameid, EnumPropertyItem *items) +{ + wmKeyMap *km= wm_keymap_add(wm, nameid, 0, 0); + km->is_modal= 1; + km->items= items; + + return km; +} + +wmKeyMap *WM_modalkeymap_get(wmWindowManager *wm, const char *nameid) +{ + wmKeyMap *km; + + for(km= wm->keymaps.first; km; km= km->next) + if(km->is_modal) + if(0==strncmp(nameid, km->nameid, KMAP_MAX_NAME)) + break; + + return km; +} + + +void WM_modalkeymap_add_item(wmKeyMap *km, short type, short val, int modifier, short keymodifier, short value) +{ + wmKeymapItem *kmi= MEM_callocN(sizeof(wmKeymapItem), "keymap entry"); + + BLI_addtail(&km->keymap, kmi); + kmi->propvalue= value; + + keymap_event_set(kmi, type, val, modifier, keymodifier); +} + +void WM_modalkeymap_assign(wmKeyMap *km, const char *opname) +{ + wmOperatorType *ot= WM_operatortype_find(opname, 0); + + if(ot) + ot->modalkeymap= km; + else + printf("error: modalkeymap_assign, unknown operator %s\n", opname); +} + + /* ***************** get string from key events **************** */ const char *WM_key_event_string(short type) diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index 39c267b132c..6f64cdbde32 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -238,7 +238,11 @@ #define EVT_FILESELECT_EXEC 3 #define EVT_FILESELECT_CANCEL 4 +/* event->type */ #define EVT_BUT_OPEN 0x5021 +#define EVT_MODAL_MAP 0x5022 + + #endif /* WM_EVENT_TYPES_H */ |