22189b1707ccfb5d37a29e200b680a4ad095394d
[blender-staging.git] / source / blender / windowmanager / intern / wm_keymap.c
1 /**
2  * $Id:
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2007 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <string.h>
30
31 #include "DNA_screen_types.h"
32 #include "DNA_windowmanager_types.h"
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_blenlib.h"
37
38 #include "BKE_blender.h"
39 #include "BKE_context.h"
40 #include "BKE_idprop.h"
41 #include "BKE_library.h"
42 #include "BKE_main.h"
43 #include "BKE_utildefines.h"
44
45 #include "RNA_access.h"
46 #include "RNA_types.h"
47
48 #include "WM_api.h"
49 #include "WM_types.h"
50 #include "wm_window.h"
51 #include "wm_event_system.h"
52 #include "wm_event_types.h"
53
54 /* ***************** generic call, exported **************** */
55
56 static void keymap_event_set(wmKeymapItem *kmi, short type, short val, int modifier, short keymodifier)
57 {
58         kmi->type= type;
59         kmi->val= val;
60         kmi->keymodifier= keymodifier;
61         
62         if(modifier == KM_ANY) {
63                 kmi->shift= kmi->ctrl= kmi->alt= kmi->oskey= KM_ANY;
64         }
65         else {
66                 
67                 /* defines? */
68                 if(modifier & KM_SHIFT)
69                         kmi->shift= 1;
70                 else if(modifier & KM_SHIFT2)
71                         kmi->shift= 2;
72                 if(modifier & KM_CTRL)
73                         kmi->ctrl= 1;
74                 else if(modifier & KM_CTRL2)
75                         kmi->ctrl= 2;
76                 if(modifier & KM_ALT)
77                         kmi->alt= 1;
78                 else if(modifier & KM_ALT2)
79                         kmi->alt= 2;
80                 if(modifier & KM_OSKEY)
81                         kmi->oskey= 1;
82                 else if(modifier & KM_OSKEY2)
83                         kmi->oskey= 2;  
84         }
85 }
86
87 static void keymap_properties_set(wmKeymapItem *kmi)
88 {
89         if(!kmi->ptr) {
90                 kmi->ptr= MEM_callocN(sizeof(PointerRNA), "wmKeymapItemPtr");
91                 WM_operator_properties_create(kmi->ptr, kmi->idname);
92         }
93 }
94
95 /* if item was added, then bail out */
96 wmKeymapItem *WM_keymap_verify_item(ListBase *lb, char *idname, short type, short val, int modifier, short keymodifier)
97 {
98         wmKeymapItem *kmi;
99         
100         for(kmi= lb->first; kmi; kmi= kmi->next)
101                 if(strncmp(kmi->idname, idname, OP_MAX_TYPENAME)==0)
102                         break;
103         if(kmi==NULL) {
104                 kmi= MEM_callocN(sizeof(wmKeymapItem), "keymap entry");
105                 
106                 BLI_addtail(lb, kmi);
107                 BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME);
108                 
109                 keymap_event_set(kmi, type, val, modifier, keymodifier);
110                 keymap_properties_set(kmi);
111         }
112         return kmi;
113 }
114
115 /* always add item */
116 wmKeymapItem *WM_keymap_add_item(ListBase *lb, char *idname, short type, short val, int modifier, short keymodifier)
117 {
118         wmKeymapItem *kmi= MEM_callocN(sizeof(wmKeymapItem), "keymap entry");
119         
120         BLI_addtail(lb, kmi);
121         BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME);
122
123         keymap_event_set(kmi, type, val, modifier, keymodifier);
124         keymap_properties_set(kmi);
125         return kmi;
126 }
127
128 /* enables tweak for mouse/modifier combo
129    on tweak fail, it passes on event with 'val=1', so other keymap items can test */
130 void WM_keymap_tweak(ListBase *lb, short type, short val, int modifier, short keymodifier)
131 {
132         wmKeymapItem *km= WM_keymap_add_item(lb, "WM_OT_tweak_gesture", type, val, modifier, keymodifier);
133         km->is_tweak= 1;
134 }
135
136
137 /* ****************** storage in WM ************ */
138
139 /* name id's are for storing general or multiple keymaps, 
140    space/region ids are same as DNA_space_types.h */
141 /* gets free'd in wm.c */
142
143 ListBase *WM_keymap_listbase(wmWindowManager *wm, const char *nameid, int spaceid, int regionid)
144 {
145         wmKeyMap *km;
146         
147         for(km= wm->keymaps.first; km; km= km->next)
148                 if(km->spaceid==spaceid && km->regionid==regionid)
149                         if(0==strncmp(nameid, km->nameid, KMAP_MAX_NAME))
150                                 break;
151
152         if(km==NULL) {
153                 km= MEM_callocN(sizeof(struct wmKeyMap), "keymap list");
154                 BLI_strncpy(km->nameid, nameid, KMAP_MAX_NAME);
155                 km->spaceid= spaceid;
156                 km->regionid= regionid;
157                 BLI_addtail(&wm->keymaps, km);
158         }
159         
160         return &km->keymap;
161 }
162
163 /* ***************** get string from key events **************** */
164
165 char *WM_key_event_string(short type)
166 {
167         /* not returned: CAPSLOCKKEY, UNKNOWNKEY, COMMANDKEY, GRLESSKEY */
168
169         switch(type) {
170         case AKEY:
171                 return "A";
172                 break;
173         case BKEY:
174                 return "B";
175                 break;
176         case CKEY:
177                 return "C";
178                 break;
179         case DKEY:
180                 return "D";
181                 break;
182         case EKEY:
183                 return "E";
184                 break;
185         case FKEY:
186                 return "F";
187                 break;
188         case GKEY:
189                 return "G";
190                 break;
191         case HKEY:
192                 return "H";
193                 break;
194         case IKEY:
195                 return "I";
196                 break;
197         case JKEY:
198                 return "J";
199                 break;
200         case KKEY:
201                 return "K";
202                 break;
203         case LKEY:
204                 return "L";
205                 break;
206         case MKEY:
207                 return "M";
208                 break;
209         case NKEY:
210                 return "N";
211                 break;
212         case OKEY:
213                 return "O";
214                 break;
215         case PKEY:
216                 return "P";
217                 break;
218         case QKEY:
219                 return "Q";
220                 break;
221         case RKEY:
222                 return "R";
223                 break;
224         case SKEY:
225                 return "S";
226                 break;
227         case TKEY:
228                 return "T";
229                 break;
230         case UKEY:
231                 return "U";
232                 break;
233         case VKEY:
234                 return "V";
235                 break;
236         case WKEY:
237                 return "W";
238                 break;
239         case XKEY:
240                 return "X";
241                 break;
242         case YKEY:
243                 return "Y";
244                 break;
245         case ZKEY:
246                 return "Z";
247                 break;
248
249         case ZEROKEY:
250                 return "Zero";
251                 break;
252         case ONEKEY:
253                 return "One";
254                 break;
255         case TWOKEY:
256                 return "Two";
257                 break;
258         case THREEKEY:
259                 return "Three";
260                 break;
261         case FOURKEY:
262                 return "Four";
263                 break;
264         case FIVEKEY:
265                 return "Five";
266                 break;
267         case SIXKEY:
268                 return "Six";
269                 break;
270         case SEVENKEY:
271                 return "Seven";
272                 break;
273         case EIGHTKEY:
274                 return "Eight";
275                 break;
276         case NINEKEY:
277                 return "Nine";
278                 break;
279
280         case LEFTCTRLKEY:
281                 return "Leftctrl";
282                 break;
283         case LEFTALTKEY:
284                 return "Leftalt";
285                 break;
286         case RIGHTALTKEY:
287                 return "Rightalt";
288                 break;
289         case RIGHTCTRLKEY:
290                 return "Rightctrl";
291                 break;
292         case RIGHTSHIFTKEY:
293                 return "Rightshift";
294                 break;
295         case LEFTSHIFTKEY:
296                 return "Leftshift";
297                 break;
298
299         case ESCKEY:
300                 return "Esc";
301                 break;
302         case TABKEY:
303                 return "Tab";
304                 break;
305         case RETKEY:
306                 return "Ret";
307                 break;
308         case SPACEKEY:
309                 return "Space";
310                 break;
311         case LINEFEEDKEY:
312                 return "Linefeed";
313                 break;
314         case BACKSPACEKEY:
315                 return "Backspace";
316                 break;
317         case DELKEY:
318                 return "Del";
319                 break;
320         case SEMICOLONKEY:
321                 return "Semicolon";
322                 break;
323         case PERIODKEY:
324                 return "Period";
325                 break;
326         case COMMAKEY:
327                 return "Comma";
328                 break;
329         case QUOTEKEY:
330                 return "Quote";
331                 break;
332         case ACCENTGRAVEKEY:
333                 return "Accentgrave";
334                 break;
335         case MINUSKEY:
336                 return "Minus";
337                 break;
338         case SLASHKEY:
339                 return "Slash";
340                 break;
341         case BACKSLASHKEY:
342                 return "Backslash";
343                 break;
344         case EQUALKEY:
345                 return "Equal";
346                 break;
347         case LEFTBRACKETKEY:
348                 return "Leftbracket";
349                 break;
350         case RIGHTBRACKETKEY:
351                 return "Rightbracket";
352                 break;
353
354         case LEFTARROWKEY:
355                 return "Leftarrow";
356                 break;
357         case DOWNARROWKEY:
358                 return "Downarrow";
359                 break;
360         case RIGHTARROWKEY:
361                 return "Rightarrow";
362                 break;
363         case UPARROWKEY:
364                 return "Uparrow";
365                 break;
366
367         case PAD2:
368                 return "Numpad 2";
369                 break;
370         case PAD4:
371                 return "Numpad 4";
372                 break;
373         case PAD6:
374                 return "Numpad 6";
375                 break;
376         case PAD8:
377                 return "Numpad 8";
378                 break;
379         case PAD1:
380                 return "Numpad 1";
381                 break;
382         case PAD3:
383                 return "Numpad 3";
384                 break;
385         case PAD5:
386                 return "Numpad 5";
387                 break;
388         case PAD7:
389                 return "Numpad 7";
390                 break;
391         case PAD9:
392                 return "Numpad 9";
393                 break;
394
395         case PADPERIOD:
396                 return "Numpad .";
397                 break;
398         case PADSLASHKEY:
399                 return "Numpad /";
400                 break;
401         case PADASTERKEY:
402                 return "Numpad *";
403                 break;
404
405         case PAD0:
406                 return "Numpad 0";
407                 break;
408         case PADMINUS:
409                 return "Numpad -";
410                 break;
411         case PADENTER:
412                 return "Numpad Enter";
413                 break;
414         case PADPLUSKEY:
415                 return "Numpad +";
416                 break;
417
418         case F1KEY:
419                 return "F1";
420                 break;
421         case F2KEY:
422                 return "F2";
423                 break;
424         case F3KEY:
425                 return "F3";
426                 break;
427         case F4KEY:
428                 return "F4";
429                 break;
430         case F5KEY:
431                 return "F5";
432                 break;
433         case F6KEY:
434                 return "F6";
435                 break;
436         case F7KEY:
437                 return "F7";
438                 break;
439         case F8KEY:
440                 return "F8";
441                 break;
442         case F9KEY:
443                 return "F9";
444                 break;
445         case F10KEY:
446                 return "F10";
447                 break;
448         case F11KEY:
449                 return "F11";
450                 break;
451         case F12KEY:
452                 return "F12";
453                 break;
454
455         case PAUSEKEY:
456                 return "Pause";
457                 break;
458         case INSERTKEY:
459                 return "Insert";
460                 break;
461         case HOMEKEY:
462                 return "Home";
463                 break;
464         case PAGEUPKEY:
465                 return "Pageup";
466                 break;
467         case PAGEDOWNKEY:
468                 return "Pagedown";
469                 break;
470         case ENDKEY:
471                 return "End";
472                 break;
473         }
474         
475         return "";
476 }
477
478 static char *wm_keymap_item_to_string(wmKeymapItem *kmi, char *str, int len)
479 {
480         char buf[100];
481
482         buf[0]= 0;
483
484         if(kmi->shift)
485                 strcat(buf, "Shift ");
486
487         if(kmi->ctrl)
488                 strcat(buf, "Ctrl ");
489
490         if(kmi->alt)
491                 strcat(buf, "Alt ");
492
493         if(kmi->oskey)
494                 strcat(buf, "OS ");
495
496         strcat(buf, WM_key_event_string(kmi->type));
497         BLI_strncpy(str, buf, len);
498
499         return str;
500 }
501
502 static char *wm_keymap_item_find(ListBase *handlers, const char *opname, int opcontext, IDProperty *properties, char *str, int len)
503 {
504         wmEventHandler *handler;
505         wmKeymapItem *kmi;
506
507         /* find keymap item in handlers */
508         for(handler=handlers->first; handler; handler=handler->next)
509                 if(handler->keymap)
510                         for(kmi=handler->keymap->first; kmi; kmi=kmi->next)
511                                 if(strcmp(kmi->idname, opname) == 0 && WM_key_event_string(kmi->type)[0])
512                                         if(kmi->ptr && IDP_EqualsProperties(properties, kmi->ptr->data))
513                                                 return wm_keymap_item_to_string(kmi, str, len);
514         
515         return NULL;
516 }
517
518 char *WM_key_event_operator_string(const bContext *C, const char *opname, int opcontext, IDProperty *properties, char *str, int len)
519 {
520         char *found= NULL;
521
522         /* look into multiple handler lists to find the item */
523         if(CTX_wm_window(C))
524                 if((found= wm_keymap_item_find(&CTX_wm_window(C)->handlers, opname, opcontext, properties, str, len)))
525                         return found;
526
527         if(CTX_wm_area(C))
528                 if((found= wm_keymap_item_find(&CTX_wm_area(C)->handlers, opname, opcontext, properties, str, len)))
529                         return found;
530
531         if(ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) {
532                 if(CTX_wm_area(C)) {
533                         ARegion *ar= CTX_wm_area(C)->regionbase.first;
534                         for(; ar; ar= ar->next)
535                                 if(ar->regiontype==RGN_TYPE_WINDOW)
536                                         break;
537
538                         if(ar)
539                                 if((found= wm_keymap_item_find(&ar->handlers, opname, opcontext, properties, str, len)))
540                                         return found;
541                 }
542         }
543         else {
544                 if(CTX_wm_region(C))
545                         if((found= wm_keymap_item_find(&CTX_wm_region(C)->handlers, opname, opcontext, properties, str, len)))
546                                 return found;
547         }
548
549         return NULL;
550 }
551