Cleanup: use r_* prefix for return args
[blender.git] / source / blender / windowmanager / intern / wm_keymap.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2007 Blender Foundation.
19  * All rights reserved.
20  *
21  * 
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/windowmanager/intern/wm_keymap.c
28  *  \ingroup wm
29  *
30  * Configurable key-maps - add/remove/find/compare/patch...
31  */
32
33 #include <string.h>
34
35 #include "DNA_object_types.h"
36 #include "DNA_screen_types.h"
37 #include "DNA_space_types.h"
38 #include "DNA_userdef_types.h"
39 #include "DNA_windowmanager_types.h"
40
41 #include "MEM_guardedalloc.h"
42
43 #include "BLI_blenlib.h"
44 #include "BLI_utildefines.h"
45
46 #include "BKE_context.h"
47 #include "BKE_idprop.h"
48 #include "BKE_global.h"
49 #include "BKE_main.h"
50 #include "BKE_screen.h"
51
52 #include "BLF_translation.h"
53
54 #include "RNA_access.h"
55 #include "RNA_enum_types.h"
56
57 #include "WM_api.h"
58 #include "WM_types.h"
59 #include "wm_event_system.h"
60 #include "wm_event_types.h"
61
62 /******************************* Keymap Item **********************************
63  * Item in a keymap, that maps from an event to an operator or modal map item */
64
65 static wmKeyMapItem *wm_keymap_item_copy(wmKeyMapItem *kmi)
66 {
67         wmKeyMapItem *kmin = MEM_dupallocN(kmi);
68
69         kmin->prev = kmin->next = NULL;
70         kmin->flag &= ~KMI_UPDATE;
71
72         if (kmin->properties) {
73                 kmin->ptr = MEM_callocN(sizeof(PointerRNA), "UserKeyMapItemPtr");
74                 WM_operator_properties_create(kmin->ptr, kmin->idname);
75
76                 kmin->properties = IDP_CopyProperty(kmin->properties);
77                 kmin->ptr->data = kmin->properties;
78         }
79
80         return kmin;
81 }
82
83 static void wm_keymap_item_free(wmKeyMapItem *kmi)
84 {
85         /* not kmi itself */
86         if (kmi->ptr) {
87                 WM_operator_properties_free(kmi->ptr);
88                 MEM_freeN(kmi->ptr);
89         }
90 }
91
92 static void wm_keymap_item_properties_set(wmKeyMapItem *kmi)
93 {
94         WM_operator_properties_alloc(&(kmi->ptr), &(kmi->properties), kmi->idname);
95         WM_operator_properties_sanitize(kmi->ptr, 1);
96 }
97
98 /**
99  * Similar to #wm_keymap_item_properties_set but checks for the wmOperatorType having changed, see [#38042]
100  */
101 static void wm_keymap_item_properties_update_ot(wmKeyMapItem *kmi)
102 {
103         if (kmi->idname[0] == 0) {
104                 BLI_assert(kmi->ptr == NULL);
105                 return;
106         }
107
108         if (kmi->ptr == NULL) {
109                 wm_keymap_item_properties_set(kmi);
110         }
111         else {
112                 wmOperatorType *ot = WM_operatortype_find(kmi->idname, 0);
113                 if (ot) {
114                         if (ot->srna != kmi->ptr->type) {
115                                 /* matches wm_keymap_item_properties_set but doesnt alloc new ptr */
116                                 WM_operator_properties_create_ptr(kmi->ptr, ot);
117                                 WM_operator_properties_sanitize(kmi->ptr, 1);
118                         }
119                 }
120                 else {
121                         /* zombie keymap item */
122                         MEM_SAFE_FREE(kmi->ptr);
123                 }
124         }
125 }
126
127 static void wm_keyconfig_properties_update_ot(ListBase *km_lb)
128 {
129         wmKeyMap *km;
130         wmKeyMapItem *kmi;
131
132         for (km = km_lb->first; km; km = km->next) {
133                 wmKeyMapDiffItem *kmdi;
134
135                 for (kmi = km->items.first; kmi; kmi = kmi->next) {
136                         wm_keymap_item_properties_update_ot(kmi);
137                 }
138
139                 for (kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) {
140                         if (kmdi->add_item)
141                                 wm_keymap_item_properties_update_ot(kmdi->add_item);
142                         if (kmdi->remove_item)
143                                 wm_keymap_item_properties_update_ot(kmdi->remove_item);
144                 }
145         }
146 }
147
148 static bool wm_keymap_item_equals_result(wmKeyMapItem *a, wmKeyMapItem *b)
149 {
150         return (STREQ(a->idname, b->idname) &&
151                 RNA_struct_equals(a->ptr, b->ptr, RNA_EQ_UNSET_MATCH_NONE) &&
152                 (a->flag & KMI_INACTIVE) == (b->flag & KMI_INACTIVE) &&
153                 a->propvalue == b->propvalue);
154 }
155
156 static bool wm_keymap_item_equals(wmKeyMapItem *a, wmKeyMapItem *b)
157 {
158         return (wm_keymap_item_equals_result(a, b) &&
159                 a->type == b->type &&
160                 a->val == b->val &&
161                 a->shift == b->shift &&
162                 a->ctrl == b->ctrl &&
163                 a->alt == b->alt &&
164                 a->oskey == b->oskey &&
165                 a->keymodifier == b->keymodifier &&
166                 a->maptype == b->maptype);
167 }
168
169 /* properties can be NULL, otherwise the arg passed is used and ownership is given to the kmi */
170 void WM_keymap_properties_reset(wmKeyMapItem *kmi, struct IDProperty *properties)
171 {
172         if (LIKELY(kmi->ptr)) {
173                 WM_operator_properties_free(kmi->ptr);
174                 MEM_freeN(kmi->ptr);
175
176                 kmi->ptr = NULL;
177         }
178
179         kmi->properties = properties;
180
181         wm_keymap_item_properties_set(kmi);
182 }
183
184 int WM_keymap_map_type_get(wmKeyMapItem *kmi)
185 {
186         if (ISTIMER(kmi->type)) {
187                 return KMI_TYPE_TIMER;
188         }
189         if (ISKEYBOARD(kmi->type)) {
190                 return KMI_TYPE_KEYBOARD;
191         }
192         if (ISTWEAK(kmi->type)) {
193                 return KMI_TYPE_TWEAK;
194         }
195         if (ISMOUSE(kmi->type)) {
196                 return KMI_TYPE_MOUSE;
197         }
198         if (ISNDOF(kmi->type)) {
199                 return KMI_TYPE_NDOF;
200         }
201         if (kmi->type == KM_TEXTINPUT) {
202                 return KMI_TYPE_TEXTINPUT;
203         }
204         return KMI_TYPE_KEYBOARD;
205 }
206
207
208 /**************************** Keymap Diff Item *********************************
209  * Item in a diff keymap, used for saving diff of keymaps in user preferences */
210
211 static wmKeyMapDiffItem *wm_keymap_diff_item_copy(wmKeyMapDiffItem *kmdi)
212 {
213         wmKeyMapDiffItem *kmdin = MEM_dupallocN(kmdi);
214
215         kmdin->next = kmdin->prev = NULL;
216         if (kmdi->add_item)
217                 kmdin->add_item = wm_keymap_item_copy(kmdi->add_item);
218         if (kmdi->remove_item)
219                 kmdin->remove_item = wm_keymap_item_copy(kmdi->remove_item);
220         
221         return kmdin;
222 }
223
224 static void wm_keymap_diff_item_free(wmKeyMapDiffItem *kmdi)
225 {
226         if (kmdi->remove_item) {
227                 wm_keymap_item_free(kmdi->remove_item);
228                 MEM_freeN(kmdi->remove_item);
229         }
230         if (kmdi->add_item) {
231                 wm_keymap_item_free(kmdi->add_item);
232                 MEM_freeN(kmdi->add_item);
233         }
234 }
235
236 /***************************** Key Configuration ******************************
237  * List of keymaps for all editors, modes, ... . There is a builtin default key
238  * configuration, a user key configuration, and other preset configurations. */
239
240 wmKeyConfig *WM_keyconfig_new(wmWindowManager *wm, const char *idname)
241 {
242         wmKeyConfig *keyconf;
243         
244         keyconf = MEM_callocN(sizeof(wmKeyConfig), "wmKeyConfig");
245         BLI_strncpy(keyconf->idname, idname, sizeof(keyconf->idname));
246         BLI_addtail(&wm->keyconfigs, keyconf);
247
248         return keyconf;
249 }
250
251 wmKeyConfig *WM_keyconfig_new_user(wmWindowManager *wm, const char *idname)
252 {
253         wmKeyConfig *keyconf = WM_keyconfig_new(wm, idname);
254
255         keyconf->flag |= KEYCONF_USER;
256
257         return keyconf;
258 }
259
260 bool WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf)
261 {
262         if (BLI_findindex(&wm->keyconfigs, keyconf) != -1) {
263                 if (STREQLEN(U.keyconfigstr, keyconf->idname, sizeof(U.keyconfigstr))) {
264                         BLI_strncpy(U.keyconfigstr, wm->defaultconf->idname, sizeof(U.keyconfigstr));
265                         WM_keyconfig_update_tag(NULL, NULL);
266                 }
267
268                 BLI_remlink(&wm->keyconfigs, keyconf);
269                 WM_keyconfig_free(keyconf);
270
271                 return true;
272         }
273         else {
274                 return false;
275         }
276 }
277
278 void WM_keyconfig_free(wmKeyConfig *keyconf)
279 {
280         wmKeyMap *km;
281
282         while ((km = keyconf->keymaps.first)) {
283                 WM_keymap_free(km);
284                 BLI_freelinkN(&keyconf->keymaps, km);
285         }
286
287         MEM_freeN(keyconf);
288 }
289
290 static wmKeyConfig *WM_keyconfig_active(wmWindowManager *wm)
291 {
292         wmKeyConfig *keyconf;
293
294         /* first try from preset */
295         keyconf = BLI_findstring(&wm->keyconfigs, U.keyconfigstr, offsetof(wmKeyConfig, idname));
296         if (keyconf)
297                 return keyconf;
298         
299         /* otherwise use default */
300         return wm->defaultconf;
301 }
302
303 void WM_keyconfig_set_active(wmWindowManager *wm, const char *idname)
304 {
305         /* setting a different key configuration as active: we ensure all is
306          * updated properly before and after making the change */
307
308         WM_keyconfig_update(wm);
309
310         BLI_strncpy(U.keyconfigstr, idname, sizeof(U.keyconfigstr));
311
312         WM_keyconfig_update_tag(NULL, NULL);
313         WM_keyconfig_update(wm);
314 }
315
316 /********************************** Keymap *************************************
317  * List of keymap items for one editor, mode, modal operator, ... */
318
319 static wmKeyMap *wm_keymap_new(const char *idname, int spaceid, int regionid)
320 {
321         wmKeyMap *km = MEM_callocN(sizeof(struct wmKeyMap), "keymap list");
322
323         BLI_strncpy(km->idname, idname, KMAP_MAX_NAME);
324         km->spaceid = spaceid;
325         km->regionid = regionid;
326
327         return km;
328 }
329
330 static wmKeyMap *wm_keymap_copy(wmKeyMap *keymap)
331 {
332         wmKeyMap *keymapn = MEM_dupallocN(keymap);
333         wmKeyMapItem *kmi, *kmin;
334         wmKeyMapDiffItem *kmdi, *kmdin;
335
336         keymapn->modal_items = keymap->modal_items;
337         keymapn->poll = keymap->poll;
338         BLI_listbase_clear(&keymapn->items);
339         keymapn->flag &= ~(KEYMAP_UPDATE | KEYMAP_EXPANDED);
340
341         for (kmdi = keymap->diff_items.first; kmdi; kmdi = kmdi->next) {
342                 kmdin = wm_keymap_diff_item_copy(kmdi);
343                 BLI_addtail(&keymapn->items, kmdin);
344         }
345
346         for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
347                 kmin = wm_keymap_item_copy(kmi);
348                 BLI_addtail(&keymapn->items, kmin);
349         }
350
351         return keymapn;
352 }
353
354 void WM_keymap_free(wmKeyMap *keymap)
355 {
356         wmKeyMapItem *kmi;
357         wmKeyMapDiffItem *kmdi;
358
359         for (kmdi = keymap->diff_items.first; kmdi; kmdi = kmdi->next)
360                 wm_keymap_diff_item_free(kmdi);
361
362         for (kmi = keymap->items.first; kmi; kmi = kmi->next)
363                 wm_keymap_item_free(kmi);
364
365         BLI_freelistN(&keymap->diff_items);
366         BLI_freelistN(&keymap->items);
367 }
368
369 bool WM_keymap_remove(wmKeyConfig *keyconf, wmKeyMap *keymap)
370 {
371         if (BLI_findindex(&keyconf->keymaps, keymap) != -1) {
372
373                 WM_keymap_free(keymap);
374                 BLI_remlink(&keyconf->keymaps, keymap);
375                 MEM_freeN(keymap);
376
377                 return true;
378         }
379         else {
380                 return false;
381         }
382 }
383
384 static void keymap_event_set(wmKeyMapItem *kmi, short type, short val, int modifier, short keymodifier)
385 {
386         kmi->type = type;
387         kmi->val = val;
388         kmi->keymodifier = keymodifier;
389
390         if (modifier == KM_ANY) {
391                 kmi->shift = kmi->ctrl = kmi->alt = kmi->oskey = KM_ANY;
392         }
393         else {
394                 kmi->shift = (modifier & KM_SHIFT) ? KM_MOD_FIRST : ((modifier & KM_SHIFT2) ? KM_MOD_SECOND : false);
395                 kmi->ctrl =  (modifier & KM_CTRL)  ? KM_MOD_FIRST : ((modifier & KM_CTRL2)  ? KM_MOD_SECOND : false);
396                 kmi->alt =   (modifier & KM_ALT)   ? KM_MOD_FIRST : ((modifier & KM_ALT2)   ? KM_MOD_SECOND : false);
397                 kmi->oskey = (modifier & KM_OSKEY) ? KM_MOD_FIRST : ((modifier & KM_OSKEY2) ? KM_MOD_SECOND : false);
398         }
399 }
400
401 static void keymap_item_set_id(wmKeyMap *keymap, wmKeyMapItem *kmi)
402 {
403         keymap->kmi_id++;
404         if ((keymap->flag & KEYMAP_USER) == 0) {
405                 kmi->id = keymap->kmi_id;
406         }
407         else {
408                 kmi->id = -keymap->kmi_id; /* User defined keymap entries have negative ids */
409         }
410 }
411
412 /* if item was added, then bail out */
413 wmKeyMapItem *WM_keymap_verify_item(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
414 {
415         wmKeyMapItem *kmi;
416         
417         for (kmi = keymap->items.first; kmi; kmi = kmi->next)
418                 if (STREQLEN(kmi->idname, idname, OP_MAX_TYPENAME))
419                         break;
420         if (kmi == NULL) {
421                 kmi = MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
422                 
423                 BLI_addtail(&keymap->items, kmi);
424                 BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME);
425                 
426                 keymap_item_set_id(keymap, kmi);
427
428                 keymap_event_set(kmi, type, val, modifier, keymodifier);
429                 wm_keymap_item_properties_set(kmi);
430         }
431         return kmi;
432 }
433
434 /* always add item */
435 wmKeyMapItem *WM_keymap_add_item(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
436 {
437         wmKeyMapItem *kmi = MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
438         
439         BLI_addtail(&keymap->items, kmi);
440         BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME);
441
442         keymap_event_set(kmi, type, val, modifier, keymodifier);
443         wm_keymap_item_properties_set(kmi);
444
445         keymap_item_set_id(keymap, kmi);
446
447         WM_keyconfig_update_tag(keymap, kmi);
448
449         return kmi;
450 }
451
452 /* menu wrapper for WM_keymap_add_item */
453 wmKeyMapItem *WM_keymap_add_menu(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
454 {
455         wmKeyMapItem *kmi = WM_keymap_add_item(keymap, "WM_OT_call_menu", type, val, modifier, keymodifier);
456         RNA_string_set(kmi->ptr, "name", idname);
457         return kmi;
458 }
459
460 wmKeyMapItem *WM_keymap_add_menu_pie(wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
461 {
462         wmKeyMapItem *kmi = WM_keymap_add_item(keymap, "WM_OT_call_menu_pie", type, val, modifier, keymodifier);
463         RNA_string_set(kmi->ptr, "name", idname);
464         return kmi;
465 }
466
467 bool WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi)
468 {
469         if (BLI_findindex(&keymap->items, kmi) != -1) {
470                 if (kmi->ptr) {
471                         WM_operator_properties_free(kmi->ptr);
472                         MEM_freeN(kmi->ptr);
473                 }
474                 BLI_freelinkN(&keymap->items, kmi);
475
476                 WM_keyconfig_update_tag(keymap, NULL);
477                 return true;
478         }
479         else {
480                 return false;
481         }
482 }
483
484 /************************** Keymap Diff and Patch ****************************
485  * Rather than saving the entire keymap for user preferences, we only save a
486  * diff so that changes in the defaults get synced. This system is not perfect
487  * but works better than overriding the keymap entirely when only few items
488  * are changed. */
489
490 static void wm_keymap_addon_add(wmKeyMap *keymap, wmKeyMap *addonmap)
491 {
492         wmKeyMapItem *kmi, *kmin;
493
494         for (kmi = addonmap->items.first; kmi; kmi = kmi->next) {
495                 kmin = wm_keymap_item_copy(kmi);
496                 keymap_item_set_id(keymap, kmin);
497                 BLI_addhead(&keymap->items, kmin);
498         }
499 }
500
501 static wmKeyMapItem *wm_keymap_find_item_equals(wmKeyMap *km, wmKeyMapItem *needle)
502 {
503         wmKeyMapItem *kmi;
504
505         for (kmi = km->items.first; kmi; kmi = kmi->next)
506                 if (wm_keymap_item_equals(kmi, needle))
507                         return kmi;
508         
509         return NULL;
510 }
511
512 static wmKeyMapItem *wm_keymap_find_item_equals_result(wmKeyMap *km, wmKeyMapItem *needle)
513 {
514         wmKeyMapItem *kmi;
515
516         for (kmi = km->items.first; kmi; kmi = kmi->next)
517                 if (wm_keymap_item_equals_result(kmi, needle))
518                         return kmi;
519         
520         return NULL;
521 }
522
523 static void wm_keymap_diff(wmKeyMap *diff_km, wmKeyMap *from_km, wmKeyMap *to_km, wmKeyMap *orig_km, wmKeyMap *addon_km)
524 {
525         wmKeyMapItem *kmi, *to_kmi, *orig_kmi;
526         wmKeyMapDiffItem *kmdi;
527
528         for (kmi = from_km->items.first; kmi; kmi = kmi->next) {
529                 to_kmi = WM_keymap_item_find_id(to_km, kmi->id);
530
531                 if (!to_kmi) {
532                         /* remove item */
533                         kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem");
534                         kmdi->remove_item = wm_keymap_item_copy(kmi);
535                         BLI_addtail(&diff_km->diff_items, kmdi);
536                 }
537                 else if (to_kmi && !wm_keymap_item_equals(kmi, to_kmi)) {
538                         /* replace item */
539                         kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem");
540                         kmdi->remove_item = wm_keymap_item_copy(kmi);
541                         kmdi->add_item = wm_keymap_item_copy(to_kmi);
542                         BLI_addtail(&diff_km->diff_items, kmdi);
543                 }
544
545                 /* sync expanded flag back to original so we don't loose it on repatch */
546                 if (to_kmi) {
547                         orig_kmi = WM_keymap_item_find_id(orig_km, kmi->id);
548
549                         if (!orig_kmi)
550                                 orig_kmi = wm_keymap_find_item_equals(addon_km, kmi);
551
552                         if (orig_kmi) {
553                                 orig_kmi->flag &= ~KMI_EXPANDED;
554                                 orig_kmi->flag |= (to_kmi->flag & KMI_EXPANDED);
555                         }
556                 }
557         }
558
559         for (kmi = to_km->items.first; kmi; kmi = kmi->next) {
560                 if (kmi->id < 0) {
561                         /* add item */
562                         kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem");
563                         kmdi->add_item = wm_keymap_item_copy(kmi);
564                         BLI_addtail(&diff_km->diff_items, kmdi);
565                 }
566         }
567 }
568
569 static void wm_keymap_patch(wmKeyMap *km, wmKeyMap *diff_km)
570 {
571         wmKeyMapDiffItem *kmdi;
572         wmKeyMapItem *kmi_remove, *kmi_add;
573
574         for (kmdi = diff_km->diff_items.first; kmdi; kmdi = kmdi->next) {
575                 /* find item to remove */
576                 kmi_remove = NULL;
577                 if (kmdi->remove_item) {
578                         kmi_remove = wm_keymap_find_item_equals(km, kmdi->remove_item);
579                         if (!kmi_remove)
580                                 kmi_remove = wm_keymap_find_item_equals_result(km, kmdi->remove_item);
581                 }
582
583                 /* add item */
584                 if (kmdi->add_item) {
585                         /* Do not re-add an already existing keymap item! See T42088. */
586                         /* We seek only for exact copy here! See T42137. */
587                         kmi_add = wm_keymap_find_item_equals(km, kmdi->add_item);
588                         /* only if nothing to remove or item to remove found */
589                         if (!kmi_add && (!kmdi->remove_item || kmi_remove)) {
590                                 kmi_add = wm_keymap_item_copy(kmdi->add_item);
591                                 kmi_add->flag |= KMI_USER_MODIFIED;
592
593                                 if (kmi_remove) {
594                                         kmi_add->flag &= ~KMI_EXPANDED;
595                                         kmi_add->flag |= (kmi_remove->flag & KMI_EXPANDED);
596                                         kmi_add->id = kmi_remove->id;
597                                         BLI_insertlinkbefore(&km->items, kmi_remove, kmi_add);
598                                 }
599                                 else {
600                                         keymap_item_set_id(km, kmi_add);
601                                         BLI_addtail(&km->items, kmi_add);
602                                 }
603                         }
604                 }
605
606                 /* remove item */
607                 if (kmi_remove) {
608                         wm_keymap_item_free(kmi_remove);
609                         BLI_freelinkN(&km->items, kmi_remove);
610                 }
611         }
612 }
613
614 static wmKeyMap *wm_keymap_patch_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap *addonmap, wmKeyMap *usermap)
615 {
616         wmKeyMap *km;
617         int expanded = 0;
618
619         /* remove previous keymap in list, we will replace it */
620         km = WM_keymap_list_find(lb, defaultmap->idname, defaultmap->spaceid, defaultmap->regionid);
621         if (km) {
622                 expanded = (km->flag & (KEYMAP_EXPANDED | KEYMAP_CHILDREN_EXPANDED));
623                 WM_keymap_free(km);
624                 BLI_freelinkN(lb, km);
625         }
626
627         /* copy new keymap from an existing one */
628         if (usermap && !(usermap->flag & KEYMAP_DIFF)) {
629                 /* for compatibility with old user preferences with non-diff
630                  * keymaps we override the original entirely */
631                 wmKeyMapItem *kmi, *orig_kmi;
632
633                 km = wm_keymap_copy(usermap);
634
635                 /* try to find corresponding id's for items */
636                 for (kmi = km->items.first; kmi; kmi = kmi->next) {
637                         orig_kmi = wm_keymap_find_item_equals(defaultmap, kmi);
638                         if (!orig_kmi)
639                                 orig_kmi = wm_keymap_find_item_equals_result(defaultmap, kmi);
640
641                         if (orig_kmi)
642                                 kmi->id = orig_kmi->id;
643                         else
644                                 kmi->id = -(km->kmi_id++);
645                 }
646
647                 km->flag |= KEYMAP_UPDATE; /* update again to create diff */
648         }
649         else
650                 km = wm_keymap_copy(defaultmap);
651
652         /* add addon keymap items */
653         if (addonmap)
654                 wm_keymap_addon_add(km, addonmap);
655
656         /* tag as being user edited */
657         if (usermap)
658                 km->flag |= KEYMAP_USER_MODIFIED;
659         km->flag |= KEYMAP_USER | expanded;
660
661         /* apply user changes of diff keymap */
662         if (usermap && (usermap->flag & KEYMAP_DIFF))
663                 wm_keymap_patch(km, usermap);
664
665         /* add to list */
666         BLI_addtail(lb, km);
667         
668         return km;
669 }
670
671 static void wm_keymap_diff_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap *addonmap, wmKeyMap *km)
672 {
673         wmKeyMap *diffmap, *prevmap, *origmap;
674
675         /* create temporary default + addon keymap for diff */
676         origmap = defaultmap;
677
678         if (addonmap) {
679                 defaultmap = wm_keymap_copy(defaultmap);
680                 wm_keymap_addon_add(defaultmap, addonmap);
681         }
682
683         /* remove previous diff keymap in list, we will replace it */
684         prevmap = WM_keymap_list_find(lb, km->idname, km->spaceid, km->regionid);
685         if (prevmap) {
686                 WM_keymap_free(prevmap);
687                 BLI_freelinkN(lb, prevmap);
688         }
689
690         /* create diff keymap */
691         diffmap = wm_keymap_new(km->idname, km->spaceid, km->regionid);
692         diffmap->flag |= KEYMAP_DIFF;
693         if (defaultmap->flag & KEYMAP_MODAL)
694                 diffmap->flag |= KEYMAP_MODAL;
695         wm_keymap_diff(diffmap, defaultmap, km, origmap, addonmap);
696
697         /* add to list if not empty */
698         if (diffmap->diff_items.first) {
699                 BLI_addtail(lb, diffmap);
700         }
701         else {
702                 WM_keymap_free(diffmap);
703                 MEM_freeN(diffmap);
704         }
705
706         /* free temporary default map */
707         if (addonmap) {
708                 WM_keymap_free(defaultmap);
709                 MEM_freeN(defaultmap);
710         }
711 }
712
713 /* ****************** storage in WM ************ */
714
715 /* name id's are for storing general or multiple keymaps, 
716  * space/region ids are same as DNA_space_types.h */
717 /* gets freed in wm.c */
718
719 wmKeyMap *WM_keymap_list_find(ListBase *lb, const char *idname, int spaceid, int regionid)
720 {
721         wmKeyMap *km;
722
723         for (km = lb->first; km; km = km->next)
724                 if (km->spaceid == spaceid && km->regionid == regionid)
725                         if (STREQLEN(idname, km->idname, KMAP_MAX_NAME))
726                                 return km;
727         
728         return NULL;
729 }
730
731 wmKeyMap *WM_keymap_find(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
732 {
733         wmKeyMap *km = WM_keymap_list_find(&keyconf->keymaps, idname, spaceid, regionid);
734         
735         if (km == NULL) {
736                 km = wm_keymap_new(idname, spaceid, regionid);
737                 BLI_addtail(&keyconf->keymaps, km);
738
739                 WM_keyconfig_update_tag(km, NULL);
740         }
741         
742         return km;
743 }
744
745 wmKeyMap *WM_keymap_find_all(const bContext *C, const char *idname, int spaceid, int regionid)
746 {
747         wmWindowManager *wm = CTX_wm_manager(C);
748
749         return WM_keymap_list_find(&wm->userconf->keymaps, idname, spaceid, regionid);
750 }
751
752 /* ****************** modal keymaps ************ */
753
754 /* modal maps get linked to a running operator, and filter the keys before sending to modal() callback */
755
756 wmKeyMap *WM_modalkeymap_add(wmKeyConfig *keyconf, const char *idname, EnumPropertyItem *items)
757 {
758         wmKeyMap *km = WM_keymap_find(keyconf, idname, 0, 0);
759         km->flag |= KEYMAP_MODAL;
760         km->modal_items = items;
761
762         if (!items) {
763                 /* init modal items from default config */
764                 wmWindowManager *wm = G.main->wm.first;
765                 if (wm->defaultconf) {
766                         wmKeyMap *defaultkm = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, 0, 0);
767
768                         if (defaultkm) {
769                                 km->modal_items = defaultkm->modal_items;
770                                 km->poll = defaultkm->poll;
771                         }
772                 }
773         }
774         
775         return km;
776 }
777
778 wmKeyMap *WM_modalkeymap_get(wmKeyConfig *keyconf, const char *idname)
779 {
780         wmKeyMap *km;
781         
782         for (km = keyconf->keymaps.first; km; km = km->next)
783                 if (km->flag & KEYMAP_MODAL)
784                         if (STREQLEN(idname, km->idname, KMAP_MAX_NAME))
785                                 break;
786         
787         return km;
788 }
789
790
791 wmKeyMapItem *WM_modalkeymap_add_item(wmKeyMap *km, int type, int val, int modifier, int keymodifier, int value)
792 {
793         wmKeyMapItem *kmi = MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
794         
795         BLI_addtail(&km->items, kmi);
796         kmi->propvalue = value;
797         
798         keymap_event_set(kmi, type, val, modifier, keymodifier);
799
800         keymap_item_set_id(km, kmi);
801
802         WM_keyconfig_update_tag(km, kmi);
803
804         return kmi;
805 }
806
807 wmKeyMapItem *WM_modalkeymap_add_item_str(wmKeyMap *km, int type, int val, int modifier, int keymodifier, const char *value)
808 {
809         wmKeyMapItem *kmi = MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
810
811         BLI_addtail(&km->items, kmi);
812         BLI_strncpy(kmi->propvalue_str, value, sizeof(kmi->propvalue_str));
813
814         keymap_event_set(kmi, type, val, modifier, keymodifier);
815
816         keymap_item_set_id(km, kmi);
817
818         WM_keyconfig_update_tag(km, kmi);
819
820         return kmi;
821 }
822
823 wmKeyMapItem *WM_modalkeymap_find_propvalue(wmKeyMap *km, const int propvalue)
824 {
825
826         if (km->flag & KEYMAP_MODAL) {
827                 wmKeyMapItem *kmi;
828                 for (kmi = km->items.first; kmi; kmi = kmi->next) {
829                         if (kmi->propvalue == propvalue) {
830                                 return kmi;
831                         }
832                 }
833         }
834         else {
835                 BLI_assert(!"called with non modal keymap");
836         }
837
838         return NULL;
839 }
840
841 void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
842 {
843         wmOperatorType *ot = WM_operatortype_find(opname, 0);
844         
845         if (ot)
846                 ot->modalkeymap = km;
847         else
848                 printf("error: modalkeymap_assign, unknown operator %s\n", opname);
849 }
850
851 static void wm_user_modal_keymap_set_items(wmWindowManager *wm, wmKeyMap *km)
852 {
853         /* here we convert propvalue string values delayed, due to python keymaps
854          * being created before the actual modal keymaps, so no modal_items */
855         wmKeyMap *defaultkm;
856         wmKeyMapItem *kmi;
857         int propvalue;
858
859         if (km && (km->flag & KEYMAP_MODAL) && !km->modal_items) {
860                 if (wm->defaultconf == NULL) {
861                         return;
862                 }
863
864                 defaultkm = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, 0, 0);
865
866                 if (!defaultkm)
867                         return;
868
869                 km->modal_items = defaultkm->modal_items;
870                 km->poll = defaultkm->poll;
871
872                 for (kmi = km->items.first; kmi; kmi = kmi->next) {
873                         if (kmi->propvalue_str[0]) {
874                                 if (RNA_enum_value_from_id(km->modal_items, kmi->propvalue_str, &propvalue))
875                                         kmi->propvalue = propvalue;
876                                 kmi->propvalue_str[0] = '\0';
877                         }
878                 }
879         }
880 }
881
882 /* ***************** get string from key events **************** */
883
884 const char *WM_key_event_string(short type)
885 {
886         const char *name = NULL;
887         if (RNA_enum_name(event_type_items, (int)type, &name))
888                 return name;
889         
890         return "";
891 }
892
893 int WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, const int len)
894 {
895         char buf[128];
896         char *p = buf;
897
898         buf[0] = 0;
899
900         if (kmi->shift == KM_ANY &&
901             kmi->ctrl == KM_ANY &&
902             kmi->alt == KM_ANY &&
903             kmi->oskey == KM_ANY)
904         {
905                 p += BLI_strcpy_rlen(p, "Any ");
906         }
907         else {
908                 if (kmi->shift)
909                         p += BLI_strcpy_rlen(p, "Shift ");
910
911                 if (kmi->ctrl)
912                         p += BLI_strcpy_rlen(p, "Ctrl ");
913
914                 if (kmi->alt)
915                         p += BLI_strcpy_rlen(p, "Alt ");
916
917                 if (kmi->oskey)
918                         p += BLI_strcpy_rlen(p, "Cmd ");
919         }
920                 
921         if (kmi->keymodifier) {
922                 p += BLI_strcpy_rlen(p, WM_key_event_string(kmi->keymodifier));
923                 p += BLI_strcpy_rlen(p, " ");
924         }
925
926         p += BLI_strcpy_rlen(p, WM_key_event_string(kmi->type));
927         return BLI_strncpy_rlen(str, buf, len);
928 }
929
930 static wmKeyMapItem *wm_keymap_item_find_handlers(
931         const bContext *C, ListBase *handlers, const char *opname, int UNUSED(opcontext),
932         IDProperty *properties, const bool is_strict, const bool is_hotkey,
933         wmKeyMap **r_keymap)
934 {
935         wmWindowManager *wm = CTX_wm_manager(C);
936         wmEventHandler *handler;
937         wmKeyMap *keymap;
938         wmKeyMapItem *kmi;
939
940         /* find keymap item in handlers */
941         for (handler = handlers->first; handler; handler = handler->next) {
942                 keymap = WM_keymap_active(wm, handler->keymap);
943
944                 if (keymap && (!keymap->poll || keymap->poll((bContext *)C))) {
945                         for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
946                                 /* skip disabled keymap items [T38447] */
947                                 if (kmi->flag & KMI_INACTIVE)
948                                         continue;
949                                 
950                                 if (STREQ(kmi->idname, opname) && WM_key_event_string(kmi->type)[0]) {
951                                         if (is_hotkey) {
952                                                 if (!ISHOTKEY(kmi->type))
953                                                         continue;
954                                         }
955
956                                         if (properties) {
957                                                 /* example of debugging keymaps */
958 #if 0
959                                                 if (kmi->ptr) {
960                                                         if (STREQ("MESH_OT_rip_move", opname)) {
961                                                                 printf("OPERATOR\n");
962                                                                 IDP_spit(properties);
963                                                                 printf("KEYMAP\n");
964                                                                 IDP_spit(kmi->ptr->data);
965                                                         }
966                                                 }
967 #endif
968
969                                                 if (kmi->ptr && IDP_EqualsProperties_ex(properties, kmi->ptr->data, is_strict)) {
970                                                         if (r_keymap) *r_keymap = keymap;
971                                                         return kmi;
972                                                 }
973                                                 /* Debug only, helps spotting mismatches between menu entries and shortcuts! */
974                                                 else if (G.debug & G_DEBUG_WM) {
975                                                         if (is_strict && kmi->ptr) {
976                                                                 wmOperatorType *ot = WM_operatortype_find(opname, true);
977                                                                 if (ot) {
978                                                                         /* make a copy of the properties and set unset ones to their default values. */
979                                                                         PointerRNA opptr;
980                                                                         IDProperty *properties_default = IDP_CopyProperty(kmi->ptr->data);
981
982                                                                         RNA_pointer_create(NULL, ot->srna, properties_default, &opptr);
983                                                                         WM_operator_properties_default(&opptr, true);
984
985                                                                         if (IDP_EqualsProperties_ex(properties, properties_default, is_strict)) {
986                                                                                 char kmi_str[128];
987                                                                                 WM_keymap_item_to_string(kmi, kmi_str, sizeof(kmi_str));
988                                                                                 /* Note gievn properties could come from other things than menu entry... */
989                                                                                 printf("%s: Some set values in menu entry match default op values, "
990                                                                                        "this might not be desired!\n", opname);
991                                                                                 printf("\tkm: '%s', kmi: '%s'\n", keymap->idname, kmi_str);
992 #ifndef NDEBUG
993                                                                                 printf("OPERATOR\n");
994                                                                                 IDP_spit(properties);
995                                                                                 printf("KEYMAP\n");
996                                                                                 IDP_spit(kmi->ptr->data);
997 #endif
998                                                                                 printf("\n");
999                                                                         }
1000
1001                                                                         IDP_FreeProperty(properties_default);
1002                                                                         MEM_freeN(properties_default);
1003                                                                 }
1004                                                         }
1005                                                 }
1006                                         }
1007                                         else {
1008                                                 if (r_keymap) *r_keymap = keymap;
1009                                                 return kmi;
1010                                         }
1011                                 }
1012                         }
1013                 }
1014         }
1015         
1016         /* ensure un-initialized keymap is never used */
1017         if (r_keymap) *r_keymap = NULL;
1018         return NULL;
1019 }
1020
1021 static wmKeyMapItem *wm_keymap_item_find_props(
1022         const bContext *C, const char *opname, int opcontext,
1023         IDProperty *properties, const bool is_strict, const bool is_hotkey,
1024         wmKeyMap **r_keymap)
1025 {
1026         wmWindow *win = CTX_wm_window(C);
1027         ScrArea *sa = CTX_wm_area(C);
1028         ARegion *ar = CTX_wm_region(C);
1029         wmKeyMapItem *found = NULL;
1030
1031         /* look into multiple handler lists to find the item */
1032         if (win)
1033                 found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
1034
1035         if (sa && found == NULL)
1036                 found = wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
1037
1038         if (found == NULL) {
1039                 if (ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) {
1040                         if (sa) {
1041                                 if (!(ar && ar->regiontype == RGN_TYPE_WINDOW))
1042                                         ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
1043                                 
1044                                 if (ar)
1045                                         found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
1046                         }
1047                 }
1048                 else if (ELEM(opcontext, WM_OP_EXEC_REGION_CHANNELS, WM_OP_INVOKE_REGION_CHANNELS)) {
1049                         if (!(ar && ar->regiontype == RGN_TYPE_CHANNELS))
1050                                 ar = BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS);
1051
1052                         if (ar)
1053                                 found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
1054                 }
1055                 else if (ELEM(opcontext, WM_OP_EXEC_REGION_PREVIEW, WM_OP_INVOKE_REGION_PREVIEW)) {
1056                         if (!(ar && ar->regiontype == RGN_TYPE_PREVIEW))
1057                                 ar = BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW);
1058
1059                         if (ar)
1060                                 found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
1061                 }
1062                 else {
1063                         if (ar)
1064                                 found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
1065                 }
1066         }
1067
1068         return found;
1069 }
1070
1071 static wmKeyMapItem *wm_keymap_item_find(
1072         const bContext *C, const char *opname, int opcontext,
1073         IDProperty *properties, const bool is_hotkey, bool is_strict,
1074         wmKeyMap **r_keymap)
1075 {
1076         wmKeyMapItem *found;
1077
1078         /* XXX Hack! Macro operators in menu entry have their whole props defined, which is not the case for
1079          *     relevant keymap entries. Could be good to check and harmonize this, but for now always
1080          *     compare non-strict in this case.
1081          */
1082         wmOperatorType *ot = WM_operatortype_find(opname, true);
1083         if (ot) {
1084                 is_strict = is_strict && ((ot->flag & OPTYPE_MACRO) == 0);
1085         }
1086
1087         found = wm_keymap_item_find_props(C, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
1088
1089         /* This block is *only* useful in one case: when op uses an enum menu in its prop member
1090          * (then, we want to rerun a comparison with that 'prop' unset). Note this remains brittle,
1091          * since now any enum prop may be used in UI (specified by name), ot->prop is not so much used...
1092          * Otherwise:
1093          *     * If non-strict, unset properties always match set ones in IDP_EqualsProperties_ex.
1094          *     * If strict, unset properties never match set ones in IDP_EqualsProperties_ex,
1095          *       and we do not want that to change (else we get things like T41757)!
1096          * ...so in either case, re-running a comparison with unset props set to default is useless.
1097          */
1098         if (!found && properties) {
1099                 if (ot && ot->prop) {  /* XXX Shall we also check ot->prop is actually an enum? */
1100                         /* make a copy of the properties and unset the 'ot->prop' one if set. */
1101                         PointerRNA opptr;
1102                         IDProperty *properties_temp = IDP_CopyProperty(properties);
1103
1104                         RNA_pointer_create(NULL, ot->srna, properties_temp, &opptr);
1105
1106                         if (RNA_property_is_set(&opptr, ot->prop)) {
1107                                 /* for operator that has enum menu, unset it so its value does not affect comparison result */
1108                                 RNA_property_unset(&opptr, ot->prop);
1109
1110                                 found = wm_keymap_item_find_props(C, opname, opcontext, properties_temp,
1111                                                                   is_strict, is_hotkey, r_keymap);
1112                         }
1113
1114                         IDP_FreeProperty(properties_temp);
1115                         MEM_freeN(properties_temp);
1116                 }
1117         }
1118
1119         /* Debug only, helps spotting mismatches between menu entries and shortcuts! */
1120         if (G.debug & G_DEBUG_WM) {
1121                 if (!found && is_strict && properties) {
1122                         wmKeyMap *km;
1123                         wmKeyMapItem *kmi;
1124                         if (ot) {
1125                                 /* make a copy of the properties and set unset ones to their default values. */
1126                                 PointerRNA opptr;
1127                                 IDProperty *properties_default = IDP_CopyProperty(properties);
1128
1129                                 RNA_pointer_create(NULL, ot->srna, properties_default, &opptr);
1130                                 WM_operator_properties_default(&opptr, true);
1131
1132                                 kmi = wm_keymap_item_find_props(C, opname, opcontext, properties_default, is_strict, is_hotkey, &km);
1133                                 if (kmi) {
1134                                         char kmi_str[128];
1135                                         WM_keymap_item_to_string(kmi, kmi_str, sizeof(kmi_str));
1136                                         printf("%s: Some set values in keymap entry match default op values, "
1137                                                "this might not be desired!\n", opname);
1138                                         printf("\tkm: '%s', kmi: '%s'\n", km->idname, kmi_str);
1139 #ifndef NDEBUG
1140                                         printf("OPERATOR\n");
1141                                         IDP_spit(properties);
1142                                         printf("KEYMAP\n");
1143                                         IDP_spit(kmi->ptr->data);
1144 #endif
1145                                         printf("\n");
1146                                 }
1147
1148                                 IDP_FreeProperty(properties_default);
1149                                 MEM_freeN(properties_default);
1150                         }
1151                 }
1152         }
1153
1154         return found;
1155 }
1156
1157 char *WM_key_event_operator_string(
1158         const bContext *C, const char *opname, int opcontext,
1159         IDProperty *properties, const bool is_strict, char *str, int len)
1160 {
1161         wmKeyMapItem *kmi = wm_keymap_item_find(C, opname, opcontext, properties, false, is_strict, NULL);
1162         
1163         if (kmi) {
1164                 WM_keymap_item_to_string(kmi, str, len);
1165                 return str;
1166         }
1167
1168         return NULL;
1169 }
1170
1171 int WM_key_event_operator_id(
1172         const bContext *C, const char *opname, int opcontext,
1173         IDProperty *properties, const bool is_hotkey,
1174         wmKeyMap **r_keymap)
1175 {
1176         wmKeyMapItem *kmi = wm_keymap_item_find(C, opname, opcontext, properties, is_hotkey, true, r_keymap);
1177         
1178         if (kmi)
1179                 return kmi->id;
1180         else
1181                 return 0;
1182 }
1183
1184 int WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2)
1185 {
1186         int k1type, k2type;
1187
1188         if (k1->flag & KMI_INACTIVE || k2->flag & KMI_INACTIVE)
1189                 return 0;
1190
1191         /* take event mapping into account */
1192         k1type = WM_userdef_event_map(k1->type);
1193         k2type = WM_userdef_event_map(k2->type);
1194
1195         if (k1type != KM_ANY && k2type != KM_ANY && k1type != k2type)
1196                 return 0;
1197
1198         if (k1->val != KM_ANY && k2->val != KM_ANY) {
1199                 /* take click, press, release conflict into account */
1200                 if (k1->val == KM_CLICK && ELEM(k2->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
1201                         return 0;
1202                 if (k2->val == KM_CLICK && ELEM(k1->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
1203                         return 0;
1204                 if (k1->val != k2->val)
1205                         return 0;
1206         }
1207
1208         if (k1->shift != KM_ANY && k2->shift != KM_ANY && k1->shift != k2->shift)
1209                 return 0;
1210
1211         if (k1->ctrl != KM_ANY && k2->ctrl != KM_ANY && k1->ctrl != k2->ctrl)
1212                 return 0;
1213
1214         if (k1->alt != KM_ANY && k2->alt != KM_ANY && k1->alt != k2->alt)
1215                 return 0;
1216
1217         if (k1->oskey != KM_ANY && k2->oskey != KM_ANY && k1->oskey != k2->oskey)
1218                 return 0;
1219
1220         if (k1->keymodifier != k2->keymodifier)
1221                 return 0;
1222
1223         return 1;
1224 }
1225
1226 /************************* Update Final Configuration *************************
1227  * On load or other changes, the final user key configuration is rebuilt from
1228  * the preset, addon and user preferences keymaps. We also test if the final
1229  * configuration changed and write the changes to the user preferences. */
1230
1231 /* so operator removal can trigger update */
1232 enum {
1233         WM_KEYMAP_UPDATE_RECONFIGURE    = (1 << 0),
1234
1235         /* ensure all wmKeyMap have their operator types validated after removing an operator */
1236         WM_KEYMAP_UPDATE_OPERATORTYPE   = (1 << 1),
1237 };
1238
1239 static char wm_keymap_update_flag = 0;
1240
1241 void WM_keyconfig_update_tag(wmKeyMap *km, wmKeyMapItem *kmi)
1242 {
1243         /* quick tag to do delayed keymap updates */
1244         wm_keymap_update_flag |= WM_KEYMAP_UPDATE_RECONFIGURE;
1245
1246         if (km)
1247                 km->flag |= KEYMAP_UPDATE;
1248         if (kmi)
1249                 kmi->flag |= KMI_UPDATE;
1250 }
1251
1252 void WM_keyconfig_update_operatortype(void)
1253 {
1254         wm_keymap_update_flag |= WM_KEYMAP_UPDATE_OPERATORTYPE;
1255 }
1256
1257 static bool wm_keymap_test_and_clear_update(wmKeyMap *km)
1258 {
1259         wmKeyMapItem *kmi;
1260         int update;
1261         
1262         update = (km->flag & KEYMAP_UPDATE);
1263         km->flag &= ~KEYMAP_UPDATE;
1264
1265         for (kmi = km->items.first; kmi; kmi = kmi->next) {
1266                 update = update || (kmi->flag & KMI_UPDATE);
1267                 kmi->flag &= ~KMI_UPDATE;
1268         }
1269         
1270         return (update != 0);
1271 }
1272
1273 static wmKeyMap *wm_keymap_preset(wmWindowManager *wm, wmKeyMap *km)
1274 {
1275         wmKeyConfig *keyconf = WM_keyconfig_active(wm);
1276         wmKeyMap *keymap;
1277
1278         keymap = WM_keymap_list_find(&keyconf->keymaps, km->idname, km->spaceid, km->regionid);
1279         if (!keymap && wm->defaultconf)
1280                 keymap = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, km->spaceid, km->regionid);
1281
1282         return keymap;
1283 }
1284
1285 void WM_keyconfig_update(wmWindowManager *wm)
1286 {
1287         wmKeyMap *km, *defaultmap, *addonmap, *usermap, *kmn;
1288         wmKeyMapItem *kmi;
1289         wmKeyMapDiffItem *kmdi;
1290         bool compat_update = false;
1291
1292         if (G.background)
1293                 return;
1294
1295         if (wm_keymap_update_flag == 0)
1296                 return;
1297
1298         if (wm_keymap_update_flag & WM_KEYMAP_UPDATE_OPERATORTYPE) {
1299                 /* an operatortype has been removed, this wont happen often
1300                  * but when it does we have to check _every_ keymap item */
1301                 wmKeyConfig *kc;
1302
1303                 ListBase *keymaps_lb[] = {
1304                     &U.user_keymaps,
1305                     &wm->userconf->keymaps,
1306                     &wm->defaultconf->keymaps,
1307                     &wm->addonconf->keymaps,
1308                     NULL};
1309
1310                 int i;
1311
1312                 for (i = 0; keymaps_lb[i]; i++) {
1313                         wm_keyconfig_properties_update_ot(keymaps_lb[i]);
1314                 }
1315
1316                 for (kc = wm->keyconfigs.first; kc; kc = kc->next) {
1317                         wm_keyconfig_properties_update_ot(&kc->keymaps);
1318                 }
1319
1320                 wm_keymap_update_flag &= ~WM_KEYMAP_UPDATE_OPERATORTYPE;
1321         }
1322
1323
1324         if (wm_keymap_update_flag == 0)
1325                 return;
1326
1327         
1328         /* update operator properties for non-modal user keymaps */
1329         for (km = U.user_keymaps.first; km; km = km->next) {
1330                 if ((km->flag & KEYMAP_MODAL) == 0) {
1331                         for (kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) {
1332                                 if (kmdi->add_item)
1333                                         wm_keymap_item_properties_set(kmdi->add_item);
1334                                 if (kmdi->remove_item)
1335                                         wm_keymap_item_properties_set(kmdi->remove_item);
1336                         }
1337
1338                         for (kmi = km->items.first; kmi; kmi = kmi->next)
1339                                 wm_keymap_item_properties_set(kmi);
1340                 }
1341         }
1342
1343         /* update U.user_keymaps with user key configuration changes */
1344         for (km = wm->userconf->keymaps.first; km; km = km->next) {
1345                 /* only diff if the user keymap was modified */
1346                 if (wm_keymap_test_and_clear_update(km)) {
1347                         /* find keymaps */
1348                         defaultmap = wm_keymap_preset(wm, km);
1349                         addonmap = WM_keymap_list_find(&wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid);
1350
1351                         /* diff */
1352                         if (defaultmap)
1353                                 wm_keymap_diff_update(&U.user_keymaps, defaultmap, addonmap, km);
1354                 }
1355         }
1356
1357         /* create user key configuration from preset + addon + user preferences */
1358         for (km = wm->defaultconf->keymaps.first; km; km = km->next) {
1359                 /* find keymaps */
1360                 defaultmap = wm_keymap_preset(wm, km);
1361                 addonmap = WM_keymap_list_find(&wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid);
1362                 usermap = WM_keymap_list_find(&U.user_keymaps, km->idname, km->spaceid, km->regionid);
1363
1364                 wm_user_modal_keymap_set_items(wm, defaultmap);
1365
1366                 /* add */
1367                 kmn = wm_keymap_patch_update(&wm->userconf->keymaps, defaultmap, addonmap, usermap);
1368
1369                 if (kmn) {
1370                         kmn->modal_items = km->modal_items;
1371                         kmn->poll = km->poll;
1372                 }
1373
1374                 /* in case of old non-diff keymaps, force extra update to create diffs */
1375                 compat_update = compat_update || (usermap && !(usermap->flag & KEYMAP_DIFF));
1376
1377         }
1378
1379         wm_keymap_update_flag &= ~WM_KEYMAP_UPDATE_RECONFIGURE;
1380
1381         BLI_assert(wm_keymap_update_flag == 0);
1382
1383         if (compat_update) {
1384                 WM_keyconfig_update_tag(NULL, NULL);
1385                 WM_keyconfig_update(wm);
1386         }
1387 }
1388
1389 /********************************* Event Handling *****************************
1390  * Handlers have pointers to the keymap in the default configuration. During
1391  * event handling this function is called to get the keymap from the final
1392  * configuration. */
1393
1394 wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap)
1395 {
1396         wmKeyMap *km;
1397
1398         if (!keymap)
1399                 return NULL;
1400         
1401         /* first user defined keymaps */
1402         km = WM_keymap_list_find(&wm->userconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
1403
1404         if (km)
1405                 return km;
1406
1407         return keymap;
1408 }
1409
1410 /******************************* Keymap Editor ********************************
1411  * In the keymap editor the user key configuration is edited. */
1412
1413 void WM_keymap_restore_item_to_default(bContext *C, wmKeyMap *keymap, wmKeyMapItem *kmi)
1414 {
1415         wmWindowManager *wm = CTX_wm_manager(C);
1416         wmKeyMap *defaultmap, *addonmap;
1417         wmKeyMapItem *orig;
1418
1419         if (!keymap)
1420                 return;
1421
1422         /* construct default keymap from preset + addons */
1423         defaultmap = wm_keymap_preset(wm, keymap);
1424         addonmap = WM_keymap_list_find(&wm->addonconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
1425
1426         if (addonmap) {
1427                 defaultmap = wm_keymap_copy(defaultmap);
1428                 wm_keymap_addon_add(defaultmap, addonmap);
1429         }
1430
1431         /* find original item */
1432         orig = WM_keymap_item_find_id(defaultmap, kmi->id);
1433
1434         if (orig) {
1435                 /* restore to original */
1436                 if (!STREQ(orig->idname, kmi->idname)) {
1437                         BLI_strncpy(kmi->idname, orig->idname, sizeof(kmi->idname));
1438                         WM_keymap_properties_reset(kmi, NULL);
1439                 }
1440
1441                 if (orig->properties) {
1442                         if (kmi->properties) {
1443                                 IDP_FreeProperty(kmi->properties);
1444                                 MEM_freeN(kmi->properties);
1445                                 kmi->properties = NULL;
1446                         }
1447
1448                         kmi->properties = IDP_CopyProperty(orig->properties);
1449                         kmi->ptr->data = kmi->properties;
1450                 }
1451
1452                 kmi->propvalue = orig->propvalue;
1453                 kmi->type = orig->type;
1454                 kmi->val = orig->val;
1455                 kmi->shift = orig->shift;
1456                 kmi->ctrl = orig->ctrl;
1457                 kmi->alt = orig->alt;
1458                 kmi->oskey = orig->oskey;
1459                 kmi->keymodifier = orig->keymodifier;
1460                 kmi->maptype = orig->maptype;
1461
1462                 WM_keyconfig_update_tag(keymap, kmi);
1463         }
1464
1465         /* free temporary keymap */
1466         if (addonmap) {
1467                 WM_keymap_free(defaultmap);
1468                 MEM_freeN(defaultmap);
1469         }
1470 }
1471
1472 void WM_keymap_restore_to_default(wmKeyMap *keymap, bContext *C)
1473 {
1474         wmWindowManager *wm = CTX_wm_manager(C);
1475         wmKeyMap *usermap;
1476
1477         /* remove keymap from U.user_keymaps and update */
1478         usermap = WM_keymap_list_find(&U.user_keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
1479
1480         if (usermap) {
1481                 WM_keymap_free(usermap);
1482                 BLI_freelinkN(&U.user_keymaps, usermap);
1483
1484                 WM_keyconfig_update_tag(NULL, NULL);
1485                 WM_keyconfig_update(wm);
1486         }
1487 }
1488
1489 wmKeyMapItem *WM_keymap_item_find_id(wmKeyMap *keymap, int id)
1490 {
1491         wmKeyMapItem *kmi;
1492         
1493         for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
1494                 if (kmi->id == id) {
1495                         return kmi;
1496                 }
1497         }
1498         
1499         return NULL;
1500 }
1501
1502 /* Guess an appropriate keymap from the operator name */
1503 /* Needs to be kept up to date with Keymap and Operator naming */
1504 wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
1505 {
1506         /* Op types purposely skipped  for now:
1507          *     BRUSH_OT
1508          *     BOID_OT
1509          *     BUTTONS_OT
1510          *     CONSTRAINT_OT
1511          *     PAINT_OT
1512          *     ED_OT
1513          *     FLUID_OT
1514          *     TEXTURE_OT
1515          *     UI_OT
1516          *     VIEW2D_OT
1517          *     WORLD_OT
1518          */
1519
1520         wmKeyMap *km = NULL;
1521         SpaceLink *sl = CTX_wm_space_data(C);
1522         
1523         /* Window */
1524         if (STRPREFIX(opname, "WM_OT")) {
1525                 km = WM_keymap_find_all(C, "Window", 0, 0);
1526         }
1527         /* Screen & Render */
1528         else if (STRPREFIX(opname, "SCREEN_OT") ||
1529                  STRPREFIX(opname, "RENDER_OT") ||
1530                  STRPREFIX(opname, "SOUND_OT") ||
1531                  STRPREFIX(opname, "SCENE_OT"))
1532         {
1533                 km = WM_keymap_find_all(C, "Screen", 0, 0);
1534         }
1535         /* Grease Pencil */
1536         else if (STRPREFIX(opname, "GPENCIL_OT")) {
1537                 km = WM_keymap_find_all(C, "Grease Pencil", 0, 0);
1538         }
1539         /* Markers */
1540         else if (STRPREFIX(opname, "MARKER_OT")) {
1541                 km = WM_keymap_find_all(C, "Markers", 0, 0);
1542         }
1543         /* Import/Export*/
1544         else if (STRPREFIX(opname, "IMPORT_") ||
1545                  STRPREFIX(opname, "EXPORT_"))
1546         {
1547                 km = WM_keymap_find_all(C, "Window", 0, 0);
1548         }
1549         
1550         
1551         /* 3D View */
1552         else if (STRPREFIX(opname, "VIEW3D_OT")) {
1553                 km = WM_keymap_find_all(C, "3D View", sl->spacetype, 0);
1554         }
1555         else if (STRPREFIX(opname, "OBJECT_OT")) {
1556                 /* exception, this needs to work outside object mode too */
1557                 if (STRPREFIX(opname, "OBJECT_OT_mode_set"))
1558                         km = WM_keymap_find_all(C, "Object Non-modal", 0, 0);
1559                 else
1560                         km = WM_keymap_find_all(C, "Object Mode", 0, 0);
1561         }
1562         /* Object mode related */
1563         else if (STRPREFIX(opname, "GROUP_OT") ||
1564                  STRPREFIX(opname, "MATERIAL_OT") ||
1565                  STRPREFIX(opname, "PTCACHE_OT") ||
1566                  STRPREFIX(opname, "RIGIDBODY_OT"))
1567         {
1568                 km = WM_keymap_find_all(C, "Object Mode", 0, 0);
1569         }
1570         
1571         /* Editing Modes */
1572         else if (STRPREFIX(opname, "MESH_OT")) {
1573                 km = WM_keymap_find_all(C, "Mesh", 0, 0);
1574                 
1575                 /* some mesh operators are active in object mode too, like add-prim */
1576                 if (km && km->poll && km->poll((bContext *)C) == 0) {
1577                         km = WM_keymap_find_all(C, "Object Mode", 0, 0);
1578                 }
1579         }
1580         else if (STRPREFIX(opname, "CURVE_OT") ||
1581                  STRPREFIX(opname, "SURFACE_OT"))
1582         {
1583                 km = WM_keymap_find_all(C, "Curve", 0, 0);
1584                 
1585                 /* some curve operators are active in object mode too, like add-prim */
1586                 if (km && km->poll && km->poll((bContext *)C) == 0) {
1587                         km = WM_keymap_find_all(C, "Object Mode", 0, 0);
1588                 }
1589         }
1590         else if (STRPREFIX(opname, "ARMATURE_OT") ||
1591                  STRPREFIX(opname, "SKETCH_OT"))
1592         {
1593                 km = WM_keymap_find_all(C, "Armature", 0, 0);
1594         }
1595         else if (STRPREFIX(opname, "POSE_OT") ||
1596                  STRPREFIX(opname, "POSELIB_OT"))
1597         {
1598                 km = WM_keymap_find_all(C, "Pose", 0, 0);
1599         }
1600         else if (STRPREFIX(opname, "SCULPT_OT")) {
1601                 switch (CTX_data_mode_enum(C)) {
1602                         case OB_MODE_SCULPT:
1603                                 km = WM_keymap_find_all(C, "Sculpt", 0, 0);
1604                                 break;
1605                         case OB_MODE_EDIT:
1606                                 km = WM_keymap_find_all(C, "UV Sculpt", 0, 0);
1607                                 break;
1608                 }
1609         }
1610         else if (STRPREFIX(opname, "MBALL_OT")) {
1611                 km = WM_keymap_find_all(C, "Metaball", 0, 0);
1612                 
1613                 /* some mball operators are active in object mode too, like add-prim */
1614                 if (km && km->poll && km->poll((bContext *)C) == 0) {
1615                         km = WM_keymap_find_all(C, "Object Mode", 0, 0);
1616                 }
1617         }
1618         else if (STRPREFIX(opname, "LATTICE_OT")) {
1619                 km = WM_keymap_find_all(C, "Lattice", 0, 0);
1620         }
1621         else if (STRPREFIX(opname, "PARTICLE_OT")) {
1622                 km = WM_keymap_find_all(C, "Particle", 0, 0);
1623         }
1624         else if (STRPREFIX(opname, "FONT_OT")) {
1625                 km = WM_keymap_find_all(C, "Font", 0, 0);
1626         }
1627         /* Paint Face Mask */
1628         else if (STRPREFIX(opname, "PAINT_OT_face_select")) {
1629                 km = WM_keymap_find_all(C, "Face Mask", 0, 0);
1630         }
1631         else if (STRPREFIX(opname, "PAINT_OT")) {
1632                 /* check for relevant mode */
1633                 switch (CTX_data_mode_enum(C)) {
1634                         case OB_MODE_WEIGHT_PAINT:
1635                                 km = WM_keymap_find_all(C, "Weight Paint", 0, 0);
1636                                 break;
1637                         case OB_MODE_VERTEX_PAINT:
1638                                 km = WM_keymap_find_all(C, "Vertex Paint", 0, 0);
1639                                 break;
1640                         case OB_MODE_TEXTURE_PAINT:
1641                                 km = WM_keymap_find_all(C, "Image Paint", 0, 0);
1642                                 break;
1643                 }
1644         }
1645         /* Timeline */
1646         else if (STRPREFIX(opname, "TIME_OT")) {
1647                 km = WM_keymap_find_all(C, "Timeline", sl->spacetype, 0);
1648         }
1649         /* Image Editor */
1650         else if (STRPREFIX(opname, "IMAGE_OT")) {
1651                 km = WM_keymap_find_all(C, "Image", sl->spacetype, 0);
1652         }
1653         /* Clip Editor */
1654         else if (STRPREFIX(opname, "CLIP_OT")) {
1655                 km = WM_keymap_find_all(C, "Clip", sl->spacetype, 0);
1656         }
1657         else if (STRPREFIX(opname, "MASK_OT")) {
1658                 km = WM_keymap_find_all(C, "Mask Editing", 0, 0);
1659         }
1660         /* UV Editor */
1661         else if (STRPREFIX(opname, "UV_OT")) {
1662                 km = WM_keymap_find_all(C, "UV Editor", sl->spacetype, 0);
1663         }
1664         /* Node Editor */
1665         else if (STRPREFIX(opname, "NODE_OT")) {
1666                 km = WM_keymap_find_all(C, "Node Editor", sl->spacetype, 0);
1667         }
1668         /* Animation Editor Channels */
1669         else if (STRPREFIX(opname, "ANIM_OT_channels")) {
1670                 km = WM_keymap_find_all(C, "Animation Channels", sl->spacetype, 0);
1671         }
1672         /* Animation Generic - after channels */
1673         else if (STRPREFIX(opname, "ANIM_OT")) {
1674                 km = WM_keymap_find_all(C, "Animation", 0, 0);
1675         }
1676         /* Graph Editor */
1677         else if (STRPREFIX(opname, "GRAPH_OT")) {
1678                 km = WM_keymap_find_all(C, "Graph Editor", sl->spacetype, 0);
1679         }
1680         /* Dopesheet Editor */
1681         else if (STRPREFIX(opname, "ACTION_OT")) {
1682                 km = WM_keymap_find_all(C, "Dopesheet", sl->spacetype, 0);
1683         }
1684         /* NLA Editor */
1685         else if (STRPREFIX(opname, "NLA_OT")) {
1686                 km = WM_keymap_find_all(C, "NLA Editor", sl->spacetype, 0);
1687         }
1688         /* Script */
1689         else if (STRPREFIX(opname, "SCRIPT_OT")) {
1690                 km = WM_keymap_find_all(C, "Script", sl->spacetype, 0);
1691         }
1692         /* Text */
1693         else if (STRPREFIX(opname, "TEXT_OT")) {
1694                 km = WM_keymap_find_all(C, "Text", sl->spacetype, 0);
1695         }
1696         /* Sequencer */
1697         else if (STRPREFIX(opname, "SEQUENCER_OT")) {
1698                 km = WM_keymap_find_all(C, "Sequencer", sl->spacetype, 0);
1699         }
1700         /* Console */
1701         else if (STRPREFIX(opname, "CONSOLE_OT")) {
1702                 km = WM_keymap_find_all(C, "Console", sl->spacetype, 0);
1703         }
1704         /* Console */
1705         else if (STRPREFIX(opname, "INFO_OT")) {
1706                 km = WM_keymap_find_all(C, "Info", sl->spacetype, 0);
1707         }
1708         /* File browser */
1709         else if (STRPREFIX(opname, "FILE_OT")) {
1710                 km = WM_keymap_find_all(C, "File Browser", sl->spacetype, 0);
1711         }
1712         /* Logic Editor */
1713         else if (STRPREFIX(opname, "LOGIC_OT")) {
1714                 km = WM_keymap_find_all(C, "Logic Editor", sl->spacetype, 0);
1715         }
1716         /* Outliner */
1717         else if (STRPREFIX(opname, "OUTLINER_OT")) {
1718                 km = WM_keymap_find_all(C, "Outliner", sl->spacetype, 0);
1719         }
1720         /* Transform */
1721         else if (STRPREFIX(opname, "TRANSFORM_OT")) {
1722                 /* check for relevant editor */
1723                 switch (sl->spacetype) {
1724                         case SPACE_VIEW3D:
1725                                 km = WM_keymap_find_all(C, "3D View", sl->spacetype, 0);
1726                                 break;
1727                         case SPACE_IPO:
1728                                 km = WM_keymap_find_all(C, "Graph Editor", sl->spacetype, 0);
1729                                 break;
1730                         case SPACE_ACTION:
1731                                 km = WM_keymap_find_all(C, "Dopesheet", sl->spacetype, 0);
1732                                 break;
1733                         case SPACE_NLA:
1734                                 km = WM_keymap_find_all(C, "NLA Editor", sl->spacetype, 0);
1735                                 break;
1736                         case SPACE_IMAGE:
1737                                 km = WM_keymap_find_all(C, "UV Editor", sl->spacetype, 0);
1738                                 break;
1739                         case SPACE_NODE:
1740                                 km = WM_keymap_find_all(C, "Node Editor", sl->spacetype, 0);
1741                                 break;
1742                         case SPACE_SEQ:
1743                                 km = WM_keymap_find_all(C, "Sequencer", sl->spacetype, 0);
1744                                 break;
1745                 }
1746         }
1747         
1748         return km;
1749 }
1750
1751 const char *WM_bool_as_string(bool test)
1752 {
1753         return test ? IFACE_("ON") : IFACE_("OFF");
1754 }