82e46c1b333293e8fc1380592857882fce657327
[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, wmKeyMap **keymap_r)
933 {
934         wmWindowManager *wm = CTX_wm_manager(C);
935         wmEventHandler *handler;
936         wmKeyMap *keymap;
937         wmKeyMapItem *kmi;
938
939         /* find keymap item in handlers */
940         for (handler = handlers->first; handler; handler = handler->next) {
941                 keymap = WM_keymap_active(wm, handler->keymap);
942
943                 if (keymap && (!keymap->poll || keymap->poll((bContext *)C))) {
944                         for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
945                                 /* skip disabled keymap items [T38447] */
946                                 if (kmi->flag & KMI_INACTIVE)
947                                         continue;
948                                 
949                                 if (STREQ(kmi->idname, opname) && WM_key_event_string(kmi->type)[0]) {
950                                         if (is_hotkey) {
951                                                 if (!ISHOTKEY(kmi->type))
952                                                         continue;
953                                         }
954
955                                         if (properties) {
956                                                 /* example of debugging keymaps */
957 #if 0
958                                                 if (kmi->ptr) {
959                                                         if (STREQ("MESH_OT_rip_move", opname)) {
960                                                                 printf("OPERATOR\n");
961                                                                 IDP_spit(properties);
962                                                                 printf("KEYMAP\n");
963                                                                 IDP_spit(kmi->ptr->data);
964                                                         }
965                                                 }
966 #endif
967
968                                                 if (kmi->ptr && IDP_EqualsProperties_ex(properties, kmi->ptr->data, is_strict)) {
969                                                         if (keymap_r) *keymap_r = keymap;
970                                                         return kmi;
971                                                 }
972                                                 /* Debug only, helps spotting mismatches between menu entries and shortcuts! */
973                                                 else if (G.debug & G_DEBUG_WM) {
974                                                         if (is_strict && kmi->ptr) {
975                                                                 wmOperatorType *ot = WM_operatortype_find(opname, true);
976                                                                 if (ot) {
977                                                                         /* make a copy of the properties and set unset ones to their default values. */
978                                                                         PointerRNA opptr;
979                                                                         IDProperty *properties_default = IDP_CopyProperty(kmi->ptr->data);
980
981                                                                         RNA_pointer_create(NULL, ot->srna, properties_default, &opptr);
982                                                                         WM_operator_properties_default(&opptr, true);
983
984                                                                         if (IDP_EqualsProperties_ex(properties, properties_default, is_strict)) {
985                                                                                 char kmi_str[128];
986                                                                                 WM_keymap_item_to_string(kmi, kmi_str, sizeof(kmi_str));
987                                                                                 /* Note gievn properties could come from other things than menu entry... */
988                                                                                 printf("%s: Some set values in menu entry match default op values, "
989                                                                                        "this might not be desired!\n", opname);
990                                                                                 printf("\tkm: '%s', kmi: '%s'\n", keymap->idname, kmi_str);
991 #ifndef NDEBUG
992                                                                                 printf("OPERATOR\n");
993                                                                                 IDP_spit(properties);
994                                                                                 printf("KEYMAP\n");
995                                                                                 IDP_spit(kmi->ptr->data);
996 #endif
997                                                                                 printf("\n");
998                                                                         }
999
1000                                                                         IDP_FreeProperty(properties_default);
1001                                                                         MEM_freeN(properties_default);
1002                                                                 }
1003                                                         }
1004                                                 }
1005                                         }
1006                                         else {
1007                                                 if (keymap_r) *keymap_r = keymap;
1008                                                 return kmi;
1009                                         }
1010                                 }
1011                         }
1012                 }
1013         }
1014         
1015         /* ensure un-initialized keymap is never used */
1016         if (keymap_r) *keymap_r = NULL;
1017         return NULL;
1018 }
1019
1020 static wmKeyMapItem *wm_keymap_item_find_props(
1021         const bContext *C, const char *opname, int opcontext,
1022         IDProperty *properties, const bool is_strict, const bool is_hotkey, wmKeyMap **keymap_r)
1023 {
1024         wmWindow *win = CTX_wm_window(C);
1025         ScrArea *sa = CTX_wm_area(C);
1026         ARegion *ar = CTX_wm_region(C);
1027         wmKeyMapItem *found = NULL;
1028
1029         /* look into multiple handler lists to find the item */
1030         if (win)
1031                 found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r);
1032
1033         if (sa && found == NULL)
1034                 found = wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r);
1035
1036         if (found == NULL) {
1037                 if (ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) {
1038                         if (sa) {
1039                                 if (!(ar && ar->regiontype == RGN_TYPE_WINDOW))
1040                                         ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
1041                                 
1042                                 if (ar)
1043                                         found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r);
1044                         }
1045                 }
1046                 else if (ELEM(opcontext, WM_OP_EXEC_REGION_CHANNELS, WM_OP_INVOKE_REGION_CHANNELS)) {
1047                         if (!(ar && ar->regiontype == RGN_TYPE_CHANNELS))
1048                                 ar = BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS);
1049
1050                         if (ar)
1051                                 found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r);
1052                 }
1053                 else if (ELEM(opcontext, WM_OP_EXEC_REGION_PREVIEW, WM_OP_INVOKE_REGION_PREVIEW)) {
1054                         if (!(ar && ar->regiontype == RGN_TYPE_PREVIEW))
1055                                 ar = BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW);
1056
1057                         if (ar)
1058                                 found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r);
1059                 }
1060                 else {
1061                         if (ar)
1062                                 found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, is_hotkey, keymap_r);
1063                 }
1064         }
1065
1066         return found;
1067 }
1068
1069 static wmKeyMapItem *wm_keymap_item_find(
1070         const bContext *C, const char *opname, int opcontext,
1071         IDProperty *properties, const bool is_hotkey, bool is_strict, wmKeyMap **keymap_r)
1072 {
1073         wmKeyMapItem *found;
1074
1075         /* XXX Hack! Macro operators in menu entry have their whole props defined, which is not the case for
1076          *     relevant keymap entries. Could be good to check and harmonize this, but for now always
1077          *     compare non-strict in this case.
1078          */
1079         wmOperatorType *ot = WM_operatortype_find(opname, true);
1080         if (ot) {
1081                 is_strict = is_strict && ((ot->flag & OPTYPE_MACRO) == 0);
1082         }
1083
1084         found = wm_keymap_item_find_props(C, opname, opcontext, properties, is_strict, is_hotkey, keymap_r);
1085
1086         /* This block is *only* useful in one case: when op uses an enum menu in its prop member
1087          * (then, we want to rerun a comparison with that 'prop' unset). Note this remains brittle,
1088          * since now any enum prop may be used in UI (specified by name), ot->prop is not so much used...
1089          * Otherwise:
1090          *     * If non-strict, unset properties always match set ones in IDP_EqualsProperties_ex.
1091          *     * If strict, unset properties never match set ones in IDP_EqualsProperties_ex,
1092          *       and we do not want that to change (else we get things like T41757)!
1093          * ...so in either case, re-running a comparison with unset props set to default is useless.
1094          */
1095         if (!found && properties) {
1096                 if (ot && ot->prop) {  /* XXX Shall we also check ot->prop is actually an enum? */
1097                         /* make a copy of the properties and unset the 'ot->prop' one if set. */
1098                         PointerRNA opptr;
1099                         IDProperty *properties_temp = IDP_CopyProperty(properties);
1100
1101                         RNA_pointer_create(NULL, ot->srna, properties_temp, &opptr);
1102
1103                         if (RNA_property_is_set(&opptr, ot->prop)) {
1104                                 /* for operator that has enum menu, unset it so its value does not affect comparison result */
1105                                 RNA_property_unset(&opptr, ot->prop);
1106
1107                                 found = wm_keymap_item_find_props(C, opname, opcontext, properties_temp,
1108                                                                   is_strict, is_hotkey, keymap_r);
1109                         }
1110
1111                         IDP_FreeProperty(properties_temp);
1112                         MEM_freeN(properties_temp);
1113                 }
1114         }
1115
1116         /* Debug only, helps spotting mismatches between menu entries and shortcuts! */
1117         if (G.debug & G_DEBUG_WM) {
1118                 if (!found && is_strict && properties) {
1119                         wmKeyMap *km;
1120                         wmKeyMapItem *kmi;
1121                         if (ot) {
1122                                 /* make a copy of the properties and set unset ones to their default values. */
1123                                 PointerRNA opptr;
1124                                 IDProperty *properties_default = IDP_CopyProperty(properties);
1125
1126                                 RNA_pointer_create(NULL, ot->srna, properties_default, &opptr);
1127                                 WM_operator_properties_default(&opptr, true);
1128
1129                                 kmi = wm_keymap_item_find_props(C, opname, opcontext, properties_default, is_strict, is_hotkey, &km);
1130                                 if (kmi) {
1131                                         char kmi_str[128];
1132                                         WM_keymap_item_to_string(kmi, kmi_str, sizeof(kmi_str));
1133                                         printf("%s: Some set values in keymap entry match default op values, "
1134                                                "this might not be desired!\n", opname);
1135                                         printf("\tkm: '%s', kmi: '%s'\n", km->idname, kmi_str);
1136 #ifndef NDEBUG
1137                                         printf("OPERATOR\n");
1138                                         IDP_spit(properties);
1139                                         printf("KEYMAP\n");
1140                                         IDP_spit(kmi->ptr->data);
1141 #endif
1142                                         printf("\n");
1143                                 }
1144
1145                                 IDP_FreeProperty(properties_default);
1146                                 MEM_freeN(properties_default);
1147                         }
1148                 }
1149         }
1150
1151         return found;
1152 }
1153
1154 char *WM_key_event_operator_string(
1155         const bContext *C, const char *opname, int opcontext,
1156         IDProperty *properties, const bool is_strict, char *str, int len)
1157 {
1158         wmKeyMapItem *kmi = wm_keymap_item_find(C, opname, opcontext, properties, false, is_strict, NULL);
1159         
1160         if (kmi) {
1161                 WM_keymap_item_to_string(kmi, str, len);
1162                 return str;
1163         }
1164
1165         return NULL;
1166 }
1167
1168 int WM_key_event_operator_id(
1169         const bContext *C, const char *opname, int opcontext,
1170         IDProperty *properties, const bool is_hotkey, wmKeyMap **keymap_r)
1171 {
1172         wmKeyMapItem *kmi = wm_keymap_item_find(C, opname, opcontext, properties, is_hotkey, true, keymap_r);
1173         
1174         if (kmi)
1175                 return kmi->id;
1176         else
1177                 return 0;
1178 }
1179
1180 int WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2)
1181 {
1182         int k1type, k2type;
1183
1184         if (k1->flag & KMI_INACTIVE || k2->flag & KMI_INACTIVE)
1185                 return 0;
1186
1187         /* take event mapping into account */
1188         k1type = WM_userdef_event_map(k1->type);
1189         k2type = WM_userdef_event_map(k2->type);
1190
1191         if (k1type != KM_ANY && k2type != KM_ANY && k1type != k2type)
1192                 return 0;
1193
1194         if (k1->val != KM_ANY && k2->val != KM_ANY) {
1195                 /* take click, press, release conflict into account */
1196                 if (k1->val == KM_CLICK && ELEM(k2->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
1197                         return 0;
1198                 if (k2->val == KM_CLICK && ELEM(k1->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
1199                         return 0;
1200                 if (k1->val != k2->val)
1201                         return 0;
1202         }
1203
1204         if (k1->shift != KM_ANY && k2->shift != KM_ANY && k1->shift != k2->shift)
1205                 return 0;
1206
1207         if (k1->ctrl != KM_ANY && k2->ctrl != KM_ANY && k1->ctrl != k2->ctrl)
1208                 return 0;
1209
1210         if (k1->alt != KM_ANY && k2->alt != KM_ANY && k1->alt != k2->alt)
1211                 return 0;
1212
1213         if (k1->oskey != KM_ANY && k2->oskey != KM_ANY && k1->oskey != k2->oskey)
1214                 return 0;
1215
1216         if (k1->keymodifier != k2->keymodifier)
1217                 return 0;
1218
1219         return 1;
1220 }
1221
1222 /************************* Update Final Configuration *************************
1223  * On load or other changes, the final user key configuration is rebuilt from
1224  * the preset, addon and user preferences keymaps. We also test if the final
1225  * configuration changed and write the changes to the user preferences. */
1226
1227 /* so operator removal can trigger update */
1228 enum {
1229         WM_KEYMAP_UPDATE_RECONFIGURE    = (1 << 0),
1230
1231         /* ensure all wmKeyMap have their operator types validated after removing an operator */
1232         WM_KEYMAP_UPDATE_OPERATORTYPE   = (1 << 1),
1233 };
1234
1235 static char wm_keymap_update_flag = 0;
1236
1237 void WM_keyconfig_update_tag(wmKeyMap *km, wmKeyMapItem *kmi)
1238 {
1239         /* quick tag to do delayed keymap updates */
1240         wm_keymap_update_flag |= WM_KEYMAP_UPDATE_RECONFIGURE;
1241
1242         if (km)
1243                 km->flag |= KEYMAP_UPDATE;
1244         if (kmi)
1245                 kmi->flag |= KMI_UPDATE;
1246 }
1247
1248 void WM_keyconfig_update_operatortype(void)
1249 {
1250         wm_keymap_update_flag |= WM_KEYMAP_UPDATE_OPERATORTYPE;
1251 }
1252
1253 static bool wm_keymap_test_and_clear_update(wmKeyMap *km)
1254 {
1255         wmKeyMapItem *kmi;
1256         int update;
1257         
1258         update = (km->flag & KEYMAP_UPDATE);
1259         km->flag &= ~KEYMAP_UPDATE;
1260
1261         for (kmi = km->items.first; kmi; kmi = kmi->next) {
1262                 update = update || (kmi->flag & KMI_UPDATE);
1263                 kmi->flag &= ~KMI_UPDATE;
1264         }
1265         
1266         return (update != 0);
1267 }
1268
1269 static wmKeyMap *wm_keymap_preset(wmWindowManager *wm, wmKeyMap *km)
1270 {
1271         wmKeyConfig *keyconf = WM_keyconfig_active(wm);
1272         wmKeyMap *keymap;
1273
1274         keymap = WM_keymap_list_find(&keyconf->keymaps, km->idname, km->spaceid, km->regionid);
1275         if (!keymap && wm->defaultconf)
1276                 keymap = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, km->spaceid, km->regionid);
1277
1278         return keymap;
1279 }
1280
1281 void WM_keyconfig_update(wmWindowManager *wm)
1282 {
1283         wmKeyMap *km, *defaultmap, *addonmap, *usermap, *kmn;
1284         wmKeyMapItem *kmi;
1285         wmKeyMapDiffItem *kmdi;
1286         bool compat_update = false;
1287
1288         if (G.background)
1289                 return;
1290
1291         if (wm_keymap_update_flag == 0)
1292                 return;
1293
1294         if (wm_keymap_update_flag & WM_KEYMAP_UPDATE_OPERATORTYPE) {
1295                 /* an operatortype has been removed, this wont happen often
1296                  * but when it does we have to check _every_ keymap item */
1297                 wmKeyConfig *kc;
1298
1299                 ListBase *keymaps_lb[] = {
1300                     &U.user_keymaps,
1301                     &wm->userconf->keymaps,
1302                     &wm->defaultconf->keymaps,
1303                     &wm->addonconf->keymaps,
1304                     NULL};
1305
1306                 int i;
1307
1308                 for (i = 0; keymaps_lb[i]; i++) {
1309                         wm_keyconfig_properties_update_ot(keymaps_lb[i]);
1310                 }
1311
1312                 for (kc = wm->keyconfigs.first; kc; kc = kc->next) {
1313                         wm_keyconfig_properties_update_ot(&kc->keymaps);
1314                 }
1315
1316                 wm_keymap_update_flag &= ~WM_KEYMAP_UPDATE_OPERATORTYPE;
1317         }
1318
1319
1320         if (wm_keymap_update_flag == 0)
1321                 return;
1322
1323         
1324         /* update operator properties for non-modal user keymaps */
1325         for (km = U.user_keymaps.first; km; km = km->next) {
1326                 if ((km->flag & KEYMAP_MODAL) == 0) {
1327                         for (kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) {
1328                                 if (kmdi->add_item)
1329                                         wm_keymap_item_properties_set(kmdi->add_item);
1330                                 if (kmdi->remove_item)
1331                                         wm_keymap_item_properties_set(kmdi->remove_item);
1332                         }
1333
1334                         for (kmi = km->items.first; kmi; kmi = kmi->next)
1335                                 wm_keymap_item_properties_set(kmi);
1336                 }
1337         }
1338
1339         /* update U.user_keymaps with user key configuration changes */
1340         for (km = wm->userconf->keymaps.first; km; km = km->next) {
1341                 /* only diff if the user keymap was modified */
1342                 if (wm_keymap_test_and_clear_update(km)) {
1343                         /* find keymaps */
1344                         defaultmap = wm_keymap_preset(wm, km);
1345                         addonmap = WM_keymap_list_find(&wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid);
1346
1347                         /* diff */
1348                         if (defaultmap)
1349                                 wm_keymap_diff_update(&U.user_keymaps, defaultmap, addonmap, km);
1350                 }
1351         }
1352
1353         /* create user key configuration from preset + addon + user preferences */
1354         for (km = wm->defaultconf->keymaps.first; km; km = km->next) {
1355                 /* find keymaps */
1356                 defaultmap = wm_keymap_preset(wm, km);
1357                 addonmap = WM_keymap_list_find(&wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid);
1358                 usermap = WM_keymap_list_find(&U.user_keymaps, km->idname, km->spaceid, km->regionid);
1359
1360                 wm_user_modal_keymap_set_items(wm, defaultmap);
1361
1362                 /* add */
1363                 kmn = wm_keymap_patch_update(&wm->userconf->keymaps, defaultmap, addonmap, usermap);
1364
1365                 if (kmn) {
1366                         kmn->modal_items = km->modal_items;
1367                         kmn->poll = km->poll;
1368                 }
1369
1370                 /* in case of old non-diff keymaps, force extra update to create diffs */
1371                 compat_update = compat_update || (usermap && !(usermap->flag & KEYMAP_DIFF));
1372
1373         }
1374
1375         wm_keymap_update_flag &= ~WM_KEYMAP_UPDATE_RECONFIGURE;
1376
1377         BLI_assert(wm_keymap_update_flag == 0);
1378
1379         if (compat_update) {
1380                 WM_keyconfig_update_tag(NULL, NULL);
1381                 WM_keyconfig_update(wm);
1382         }
1383 }
1384
1385 /********************************* Event Handling *****************************
1386  * Handlers have pointers to the keymap in the default configuration. During
1387  * event handling this function is called to get the keymap from the final
1388  * configuration. */
1389
1390 wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap)
1391 {
1392         wmKeyMap *km;
1393
1394         if (!keymap)
1395                 return NULL;
1396         
1397         /* first user defined keymaps */
1398         km = WM_keymap_list_find(&wm->userconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
1399
1400         if (km)
1401                 return km;
1402
1403         return keymap;
1404 }
1405
1406 /******************************* Keymap Editor ********************************
1407  * In the keymap editor the user key configuration is edited. */
1408
1409 void WM_keymap_restore_item_to_default(bContext *C, wmKeyMap *keymap, wmKeyMapItem *kmi)
1410 {
1411         wmWindowManager *wm = CTX_wm_manager(C);
1412         wmKeyMap *defaultmap, *addonmap;
1413         wmKeyMapItem *orig;
1414
1415         if (!keymap)
1416                 return;
1417
1418         /* construct default keymap from preset + addons */
1419         defaultmap = wm_keymap_preset(wm, keymap);
1420         addonmap = WM_keymap_list_find(&wm->addonconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
1421
1422         if (addonmap) {
1423                 defaultmap = wm_keymap_copy(defaultmap);
1424                 wm_keymap_addon_add(defaultmap, addonmap);
1425         }
1426
1427         /* find original item */
1428         orig = WM_keymap_item_find_id(defaultmap, kmi->id);
1429
1430         if (orig) {
1431                 /* restore to original */
1432                 if (!STREQ(orig->idname, kmi->idname)) {
1433                         BLI_strncpy(kmi->idname, orig->idname, sizeof(kmi->idname));
1434                         WM_keymap_properties_reset(kmi, NULL);
1435                 }
1436
1437                 if (orig->properties) {
1438                         if (kmi->properties) {
1439                                 IDP_FreeProperty(kmi->properties);
1440                                 MEM_freeN(kmi->properties);
1441                                 kmi->properties = NULL;
1442                         }
1443
1444                         kmi->properties = IDP_CopyProperty(orig->properties);
1445                         kmi->ptr->data = kmi->properties;
1446                 }
1447
1448                 kmi->propvalue = orig->propvalue;
1449                 kmi->type = orig->type;
1450                 kmi->val = orig->val;
1451                 kmi->shift = orig->shift;
1452                 kmi->ctrl = orig->ctrl;
1453                 kmi->alt = orig->alt;
1454                 kmi->oskey = orig->oskey;
1455                 kmi->keymodifier = orig->keymodifier;
1456                 kmi->maptype = orig->maptype;
1457
1458                 WM_keyconfig_update_tag(keymap, kmi);
1459         }
1460
1461         /* free temporary keymap */
1462         if (addonmap) {
1463                 WM_keymap_free(defaultmap);
1464                 MEM_freeN(defaultmap);
1465         }
1466 }
1467
1468 void WM_keymap_restore_to_default(wmKeyMap *keymap, bContext *C)
1469 {
1470         wmWindowManager *wm = CTX_wm_manager(C);
1471         wmKeyMap *usermap;
1472
1473         /* remove keymap from U.user_keymaps and update */
1474         usermap = WM_keymap_list_find(&U.user_keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
1475
1476         if (usermap) {
1477                 WM_keymap_free(usermap);
1478                 BLI_freelinkN(&U.user_keymaps, usermap);
1479
1480                 WM_keyconfig_update_tag(NULL, NULL);
1481                 WM_keyconfig_update(wm);
1482         }
1483 }
1484
1485 wmKeyMapItem *WM_keymap_item_find_id(wmKeyMap *keymap, int id)
1486 {
1487         wmKeyMapItem *kmi;
1488         
1489         for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
1490                 if (kmi->id == id) {
1491                         return kmi;
1492                 }
1493         }
1494         
1495         return NULL;
1496 }
1497
1498 /* Guess an appropriate keymap from the operator name */
1499 /* Needs to be kept up to date with Keymap and Operator naming */
1500 wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
1501 {
1502         /* Op types purposely skipped  for now:
1503          *     BRUSH_OT
1504          *     BOID_OT
1505          *     BUTTONS_OT
1506          *     CONSTRAINT_OT
1507          *     PAINT_OT
1508          *     ED_OT
1509          *     FLUID_OT
1510          *     TEXTURE_OT
1511          *     UI_OT
1512          *     VIEW2D_OT
1513          *     WORLD_OT
1514          */
1515
1516         wmKeyMap *km = NULL;
1517         SpaceLink *sl = CTX_wm_space_data(C);
1518         
1519         /* Window */
1520         if (STRPREFIX(opname, "WM_OT")) {
1521                 km = WM_keymap_find_all(C, "Window", 0, 0);
1522         }
1523         /* Screen & Render */
1524         else if (STRPREFIX(opname, "SCREEN_OT") ||
1525                  STRPREFIX(opname, "RENDER_OT") ||
1526                  STRPREFIX(opname, "SOUND_OT") ||
1527                  STRPREFIX(opname, "SCENE_OT"))
1528         {
1529                 km = WM_keymap_find_all(C, "Screen", 0, 0);
1530         }
1531         /* Grease Pencil */
1532         else if (STRPREFIX(opname, "GPENCIL_OT")) {
1533                 km = WM_keymap_find_all(C, "Grease Pencil", 0, 0);
1534         }
1535         /* Markers */
1536         else if (STRPREFIX(opname, "MARKER_OT")) {
1537                 km = WM_keymap_find_all(C, "Markers", 0, 0);
1538         }
1539         /* Import/Export*/
1540         else if (STRPREFIX(opname, "IMPORT_") ||
1541                  STRPREFIX(opname, "EXPORT_"))
1542         {
1543                 km = WM_keymap_find_all(C, "Window", 0, 0);
1544         }
1545         
1546         
1547         /* 3D View */
1548         else if (STRPREFIX(opname, "VIEW3D_OT")) {
1549                 km = WM_keymap_find_all(C, "3D View", sl->spacetype, 0);
1550         }
1551         else if (STRPREFIX(opname, "OBJECT_OT")) {
1552                 /* exception, this needs to work outside object mode too */
1553                 if (STRPREFIX(opname, "OBJECT_OT_mode_set"))
1554                         km = WM_keymap_find_all(C, "Object Non-modal", 0, 0);
1555                 else
1556                         km = WM_keymap_find_all(C, "Object Mode", 0, 0);
1557         }
1558         /* Object mode related */
1559         else if (STRPREFIX(opname, "GROUP_OT") ||
1560                  STRPREFIX(opname, "MATERIAL_OT") ||
1561                  STRPREFIX(opname, "PTCACHE_OT") ||
1562                  STRPREFIX(opname, "RIGIDBODY_OT"))
1563         {
1564                 km = WM_keymap_find_all(C, "Object Mode", 0, 0);
1565         }
1566         
1567         /* Editing Modes */
1568         else if (STRPREFIX(opname, "MESH_OT")) {
1569                 km = WM_keymap_find_all(C, "Mesh", 0, 0);
1570                 
1571                 /* some mesh operators are active in object mode too, like add-prim */
1572                 if (km && km->poll && km->poll((bContext *)C) == 0) {
1573                         km = WM_keymap_find_all(C, "Object Mode", 0, 0);
1574                 }
1575         }
1576         else if (STRPREFIX(opname, "CURVE_OT") ||
1577                  STRPREFIX(opname, "SURFACE_OT"))
1578         {
1579                 km = WM_keymap_find_all(C, "Curve", 0, 0);
1580                 
1581                 /* some curve operators are active in object mode too, like add-prim */
1582                 if (km && km->poll && km->poll((bContext *)C) == 0) {
1583                         km = WM_keymap_find_all(C, "Object Mode", 0, 0);
1584                 }
1585         }
1586         else if (STRPREFIX(opname, "ARMATURE_OT") ||
1587                  STRPREFIX(opname, "SKETCH_OT"))
1588         {
1589                 km = WM_keymap_find_all(C, "Armature", 0, 0);
1590         }
1591         else if (STRPREFIX(opname, "POSE_OT") ||
1592                  STRPREFIX(opname, "POSELIB_OT"))
1593         {
1594                 km = WM_keymap_find_all(C, "Pose", 0, 0);
1595         }
1596         else if (STRPREFIX(opname, "SCULPT_OT")) {
1597                 switch (CTX_data_mode_enum(C)) {
1598                         case OB_MODE_SCULPT:
1599                                 km = WM_keymap_find_all(C, "Sculpt", 0, 0);
1600                                 break;
1601                         case OB_MODE_EDIT:
1602                                 km = WM_keymap_find_all(C, "UV Sculpt", 0, 0);
1603                                 break;
1604                 }
1605         }
1606         else if (STRPREFIX(opname, "MBALL_OT")) {
1607                 km = WM_keymap_find_all(C, "Metaball", 0, 0);
1608                 
1609                 /* some mball operators are active in object mode too, like add-prim */
1610                 if (km && km->poll && km->poll((bContext *)C) == 0) {
1611                         km = WM_keymap_find_all(C, "Object Mode", 0, 0);
1612                 }
1613         }
1614         else if (STRPREFIX(opname, "LATTICE_OT")) {
1615                 km = WM_keymap_find_all(C, "Lattice", 0, 0);
1616         }
1617         else if (STRPREFIX(opname, "PARTICLE_OT")) {
1618                 km = WM_keymap_find_all(C, "Particle", 0, 0);
1619         }
1620         else if (STRPREFIX(opname, "FONT_OT")) {
1621                 km = WM_keymap_find_all(C, "Font", 0, 0);
1622         }
1623         /* Paint Face Mask */
1624         else if (STRPREFIX(opname, "PAINT_OT_face_select")) {
1625                 km = WM_keymap_find_all(C, "Face Mask", 0, 0);
1626         }
1627         else if (STRPREFIX(opname, "PAINT_OT")) {
1628                 /* check for relevant mode */
1629                 switch (CTX_data_mode_enum(C)) {
1630                         case OB_MODE_WEIGHT_PAINT:
1631                                 km = WM_keymap_find_all(C, "Weight Paint", 0, 0);
1632                                 break;
1633                         case OB_MODE_VERTEX_PAINT:
1634                                 km = WM_keymap_find_all(C, "Vertex Paint", 0, 0);
1635                                 break;
1636                         case OB_MODE_TEXTURE_PAINT:
1637                                 km = WM_keymap_find_all(C, "Image Paint", 0, 0);
1638                                 break;
1639                 }
1640         }
1641         /* Timeline */
1642         else if (STRPREFIX(opname, "TIME_OT")) {
1643                 km = WM_keymap_find_all(C, "Timeline", sl->spacetype, 0);
1644         }
1645         /* Image Editor */
1646         else if (STRPREFIX(opname, "IMAGE_OT")) {
1647                 km = WM_keymap_find_all(C, "Image", sl->spacetype, 0);
1648         }
1649         /* Clip Editor */
1650         else if (STRPREFIX(opname, "CLIP_OT")) {
1651                 km = WM_keymap_find_all(C, "Clip", sl->spacetype, 0);
1652         }
1653         else if (STRPREFIX(opname, "MASK_OT")) {
1654                 km = WM_keymap_find_all(C, "Mask Editing", 0, 0);
1655         }
1656         /* UV Editor */
1657         else if (STRPREFIX(opname, "UV_OT")) {
1658                 km = WM_keymap_find_all(C, "UV Editor", sl->spacetype, 0);
1659         }
1660         /* Node Editor */
1661         else if (STRPREFIX(opname, "NODE_OT")) {
1662                 km = WM_keymap_find_all(C, "Node Editor", sl->spacetype, 0);
1663         }
1664         /* Animation Editor Channels */
1665         else if (STRPREFIX(opname, "ANIM_OT_channels")) {
1666                 km = WM_keymap_find_all(C, "Animation Channels", sl->spacetype, 0);
1667         }
1668         /* Animation Generic - after channels */
1669         else if (STRPREFIX(opname, "ANIM_OT")) {
1670                 km = WM_keymap_find_all(C, "Animation", 0, 0);
1671         }
1672         /* Graph Editor */
1673         else if (STRPREFIX(opname, "GRAPH_OT")) {
1674                 km = WM_keymap_find_all(C, "Graph Editor", sl->spacetype, 0);
1675         }
1676         /* Dopesheet Editor */
1677         else if (STRPREFIX(opname, "ACTION_OT")) {
1678                 km = WM_keymap_find_all(C, "Dopesheet", sl->spacetype, 0);
1679         }
1680         /* NLA Editor */
1681         else if (STRPREFIX(opname, "NLA_OT")) {
1682                 km = WM_keymap_find_all(C, "NLA Editor", sl->spacetype, 0);
1683         }
1684         /* Script */
1685         else if (STRPREFIX(opname, "SCRIPT_OT")) {
1686                 km = WM_keymap_find_all(C, "Script", sl->spacetype, 0);
1687         }
1688         /* Text */
1689         else if (STRPREFIX(opname, "TEXT_OT")) {
1690                 km = WM_keymap_find_all(C, "Text", sl->spacetype, 0);
1691         }
1692         /* Sequencer */
1693         else if (STRPREFIX(opname, "SEQUENCER_OT")) {
1694                 km = WM_keymap_find_all(C, "Sequencer", sl->spacetype, 0);
1695         }
1696         /* Console */
1697         else if (STRPREFIX(opname, "CONSOLE_OT")) {
1698                 km = WM_keymap_find_all(C, "Console", sl->spacetype, 0);
1699         }
1700         /* Console */
1701         else if (STRPREFIX(opname, "INFO_OT")) {
1702                 km = WM_keymap_find_all(C, "Info", sl->spacetype, 0);
1703         }
1704         /* File browser */
1705         else if (STRPREFIX(opname, "FILE_OT")) {
1706                 km = WM_keymap_find_all(C, "File Browser", sl->spacetype, 0);
1707         }
1708         /* Logic Editor */
1709         else if (STRPREFIX(opname, "LOGIC_OT")) {
1710                 km = WM_keymap_find_all(C, "Logic Editor", sl->spacetype, 0);
1711         }
1712         /* Outliner */
1713         else if (STRPREFIX(opname, "OUTLINER_OT")) {
1714                 km = WM_keymap_find_all(C, "Outliner", sl->spacetype, 0);
1715         }
1716         /* Transform */
1717         else if (STRPREFIX(opname, "TRANSFORM_OT")) {
1718                 /* check for relevant editor */
1719                 switch (sl->spacetype) {
1720                         case SPACE_VIEW3D:
1721                                 km = WM_keymap_find_all(C, "3D View", sl->spacetype, 0);
1722                                 break;
1723                         case SPACE_IPO:
1724                                 km = WM_keymap_find_all(C, "Graph Editor", sl->spacetype, 0);
1725                                 break;
1726                         case SPACE_ACTION:
1727                                 km = WM_keymap_find_all(C, "Dopesheet", sl->spacetype, 0);
1728                                 break;
1729                         case SPACE_NLA:
1730                                 km = WM_keymap_find_all(C, "NLA Editor", sl->spacetype, 0);
1731                                 break;
1732                         case SPACE_IMAGE:
1733                                 km = WM_keymap_find_all(C, "UV Editor", sl->spacetype, 0);
1734                                 break;
1735                         case SPACE_NODE:
1736                                 km = WM_keymap_find_all(C, "Node Editor", sl->spacetype, 0);
1737                                 break;
1738                         case SPACE_SEQ:
1739                                 km = WM_keymap_find_all(C, "Sequencer", sl->spacetype, 0);
1740                                 break;
1741                 }
1742         }
1743         
1744         return km;
1745 }
1746
1747 const char *WM_bool_as_string(bool test)
1748 {
1749         return test ? IFACE_("ON") : IFACE_("OFF");
1750 }