Blender  V3.3
wm_keymap.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2007 Blender Foundation. All rights reserved. */
3 
10 #include <string.h>
11 
12 #include "DNA_object_types.h"
13 #include "DNA_screen_types.h"
14 #include "DNA_space_types.h"
15 #include "DNA_userdef_types.h"
17 #include "DNA_workspace_types.h"
18 
19 #include "CLG_log.h"
20 #include "MEM_guardedalloc.h"
21 
22 #include "BLI_blenlib.h"
23 #include "BLI_math.h"
24 #include "BLI_utildefines.h"
25 
26 #include "BLF_api.h"
27 
28 #include "BKE_context.h"
29 #include "BKE_global.h"
30 #include "BKE_idprop.h"
31 #include "BKE_main.h"
32 #include "BKE_screen.h"
33 #include "BKE_workspace.h"
34 
35 #include "BLT_translation.h"
36 
37 #include "RNA_access.h"
38 #include "RNA_enum_types.h"
39 
40 #include "WM_api.h"
41 #include "WM_types.h"
42 #include "wm_event_system.h"
43 #include "wm_event_types.h"
44 
46  bool (*filter_fn)(const wmKeyMap *km, const wmKeyMapItem *kmi, void *user_data);
47  void *user_data;
48 };
49 
50 /* -------------------------------------------------------------------- */
57 {
58  wmKeyMapItem *kmin = MEM_dupallocN(kmi);
59 
60  kmin->prev = kmin->next = NULL;
61  kmin->flag &= ~KMI_UPDATE;
62 
63  if (kmin->properties) {
64  kmin->ptr = MEM_callocN(sizeof(PointerRNA), "UserKeyMapItemPtr");
66 
67  /* Signal for no context, see #STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID. */
68  kmin->ptr->owner_id = NULL;
69 
70  kmin->properties = IDP_CopyProperty(kmin->properties);
71  kmin->ptr->data = kmin->properties;
72  }
73  else {
74  kmin->properties = NULL;
75  kmin->ptr = NULL;
76  }
77 
78  return kmin;
79 }
80 
82 {
83  /* not kmi itself */
84  if (kmi->ptr) {
86  MEM_freeN(kmi->ptr);
87  kmi->ptr = NULL;
88  kmi->properties = NULL;
89  }
90 }
91 
93 {
94  WM_operator_properties_alloc(&(kmi->ptr), &(kmi->properties), kmi->idname);
96 
97  /* Signal for no context, see #STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID. */
98  kmi->ptr->owner_id = NULL;
99 }
100 
106 {
107  if (kmi->idname[0] == 0) {
108  BLI_assert(kmi->ptr == NULL);
109  return;
110  }
111 
112  if (kmi->ptr == NULL) {
114  }
115  else {
117  if (ot) {
118  if (ot->srna != kmi->ptr->type) {
119  /* matches wm_keymap_item_properties_set but doesn't alloc new ptr */
121  /* 'kmi->ptr->data' NULL'd above, keep using existing properties.
122  * NOTE: the operators property types may have changed,
123  * we will need a more comprehensive sanitize function to support this properly.
124  */
125  if (kmi->properties) {
126  kmi->ptr->data = kmi->properties;
127  }
129 
130  /* Signal for no context, see #STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID. */
131  kmi->ptr->owner_id = NULL;
132  }
133  }
134  else {
135  /* zombie keymap item */
136  wm_keymap_item_free(kmi);
137  }
138  }
139 }
140 
142 {
143  LISTBASE_FOREACH (wmKeyMap *, km, km_lb) {
144  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &km->items) {
146  }
147 
148  LISTBASE_FOREACH (wmKeyMapDiffItem *, kmdi, &km->diff_items) {
149  if (kmdi->add_item) {
150  wm_keymap_item_properties_update_ot(kmdi->add_item);
151  }
152  if (kmdi->remove_item) {
153  wm_keymap_item_properties_update_ot(kmdi->remove_item);
154  }
155  }
156  }
157 }
158 
160 {
161  return (STREQ(a->idname, b->idname) &&
162  /* We do not really care about which Main we pass here, tbh. */
164  (a->flag & KMI_INACTIVE) == (b->flag & KMI_INACTIVE) && a->propvalue == b->propvalue);
165 }
166 
168 {
169  return (wm_keymap_item_equals_result(a, b) && a->type == b->type && a->val == b->val &&
170  a->shift == b->shift && a->ctrl == b->ctrl && a->alt == b->alt && a->oskey == b->oskey &&
171  a->keymodifier == b->keymodifier && a->maptype == b->maptype &&
172  ((a->val != KM_CLICK_DRAG) || (a->direction == b->direction)) &&
173  ((ISKEYBOARD(a->type) == 0) ||
174  (a->flag & KMI_REPEAT_IGNORE) == (b->flag & KMI_REPEAT_IGNORE)));
175 }
176 
178 {
179  if (LIKELY(kmi->ptr)) {
181  MEM_freeN(kmi->ptr);
182 
183  kmi->ptr = NULL;
184  }
185 
186  kmi->properties = properties;
187 
189 }
190 
192 {
193  if (ISTIMER(kmi->type)) {
194  return KMI_TYPE_TIMER;
195  }
196  if (ISKEYBOARD(kmi->type)) {
197  return KMI_TYPE_KEYBOARD;
198  }
199  if (ISMOUSE(kmi->type)) {
200  return KMI_TYPE_MOUSE;
201  }
202  if (ISNDOF(kmi->type)) {
203  return KMI_TYPE_NDOF;
204  }
205  if (kmi->type == KM_TEXTINPUT) {
206  return KMI_TYPE_TEXTINPUT;
207  }
208  if (ELEM(kmi->type, TABLET_STYLUS, TABLET_ERASER)) {
209  return KMI_TYPE_MOUSE;
210  }
211  return KMI_TYPE_KEYBOARD;
212 }
213 
216 /* -------------------------------------------------------------------- */
223 {
224  wmKeyMapDiffItem *kmdin = MEM_dupallocN(kmdi);
225 
226  kmdin->next = kmdin->prev = NULL;
227  if (kmdi->add_item) {
228  kmdin->add_item = wm_keymap_item_copy(kmdi->add_item);
229  }
230  if (kmdi->remove_item) {
232  }
233 
234  return kmdin;
235 }
236 
238 {
239  if (kmdi->remove_item) {
241  MEM_freeN(kmdi->remove_item);
242  }
243  if (kmdi->add_item) {
245  MEM_freeN(kmdi->add_item);
246  }
247 }
248 
251 /* -------------------------------------------------------------------- */
259 wmKeyConfig *WM_keyconfig_new(wmWindowManager *wm, const char *idname, bool user_defined)
260 {
261  wmKeyConfig *keyconf = BLI_findstring(&wm->keyconfigs, idname, offsetof(wmKeyConfig, idname));
262  if (keyconf) {
263  if (keyconf == wm->defaultconf) {
264  /* For default configuration, we need to keep keymap
265  * modal items and poll functions intact. */
266  LISTBASE_FOREACH (wmKeyMap *, km, &keyconf->keymaps) {
267  WM_keymap_clear(km);
268  }
269  }
270  else {
271  /* For user defined key configuration, clear all keymaps. */
272  WM_keyconfig_clear(keyconf);
273  }
274 
275  return keyconf;
276  }
277 
278  /* Create new configuration. */
279  keyconf = MEM_callocN(sizeof(wmKeyConfig), "wmKeyConfig");
280  BLI_strncpy(keyconf->idname, idname, sizeof(keyconf->idname));
281  BLI_addtail(&wm->keyconfigs, keyconf);
282 
283  if (user_defined) {
284  keyconf->flag |= KEYCONF_USER;
285  }
286 
287  return keyconf;
288 }
289 
291 {
292  return WM_keyconfig_new(wm, idname, true);
293 }
294 
296 {
297  if (BLI_findindex(&wm->keyconfigs, keyconf) != -1) {
298  if (STREQLEN(U.keyconfigstr, keyconf->idname, sizeof(U.keyconfigstr))) {
299  BLI_strncpy(U.keyconfigstr, wm->defaultconf->idname, sizeof(U.keyconfigstr));
300  U.runtime.is_dirty = true;
302  }
303 
304  BLI_remlink(&wm->keyconfigs, keyconf);
305  WM_keyconfig_free(keyconf);
306 
307  return true;
308  }
309  return false;
310 }
311 
313 {
314  LISTBASE_FOREACH (wmKeyMap *, km, &keyconf->keymaps) {
315  WM_keymap_clear(km);
316  }
317 
318  BLI_freelistN(&keyconf->keymaps);
319 }
320 
322 {
323  WM_keyconfig_clear(keyconf);
324  MEM_freeN(keyconf);
325 }
326 
328 {
329  wmKeyConfig *keyconf;
330 
331  /* first try from preset */
332  keyconf = BLI_findstring(&wm->keyconfigs, U.keyconfigstr, offsetof(wmKeyConfig, idname));
333  if (keyconf) {
334  return keyconf;
335  }
336 
337  /* otherwise use default */
338  return wm->defaultconf;
339 }
340 
341 void WM_keyconfig_set_active(wmWindowManager *wm, const char *idname)
342 {
343  /* setting a different key configuration as active: we ensure all is
344  * updated properly before and after making the change */
345 
347 
348  BLI_strncpy(U.keyconfigstr, idname, sizeof(U.keyconfigstr));
349  if (wm->initialized & WM_KEYCONFIG_IS_INIT) {
350  U.runtime.is_dirty = true;
351  }
352 
355 }
356 
359 /* -------------------------------------------------------------------- */
365 static wmKeyMap *wm_keymap_new(const char *idname, int spaceid, int regionid)
366 {
367  wmKeyMap *km = MEM_callocN(sizeof(struct wmKeyMap), "keymap list");
368 
369  BLI_strncpy(km->idname, idname, KMAP_MAX_NAME);
370  km->spaceid = spaceid;
371  km->regionid = regionid;
372 
373  {
374  const char *owner_id = RNA_struct_state_owner_get();
375  if (owner_id) {
376  BLI_strncpy(km->owner_id, owner_id, sizeof(km->owner_id));
377  }
378  }
379  return km;
380 }
381 
383 {
384  wmKeyMap *keymapn = MEM_dupallocN(keymap);
385 
386  keymapn->modal_items = keymap->modal_items;
387  keymapn->poll = keymap->poll;
388  keymapn->poll_modal_item = keymap->poll_modal_item;
389  BLI_listbase_clear(&keymapn->items);
390  keymapn->flag &= ~(KEYMAP_UPDATE | KEYMAP_EXPANDED);
391 
392  LISTBASE_FOREACH (wmKeyMapDiffItem *, kmdi, &keymap->diff_items) {
393  wmKeyMapDiffItem *kmdi_new = wm_keymap_diff_item_copy(kmdi);
394  BLI_addtail(&keymapn->items, kmdi_new);
395  }
396 
397  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) {
398  wmKeyMapItem *kmi_new = wm_keymap_item_copy(kmi);
399  BLI_addtail(&keymapn->items, kmi_new);
400  }
401 
402  return keymapn;
403 }
404 
406 {
407  LISTBASE_FOREACH (wmKeyMapDiffItem *, kmdi, &keymap->diff_items) {
409  }
410 
411  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) {
412  wm_keymap_item_free(kmi);
413  }
414 
415  BLI_freelistN(&keymap->diff_items);
416  BLI_freelistN(&keymap->items);
417 }
418 
419 bool WM_keymap_remove(wmKeyConfig *keyconf, wmKeyMap *keymap)
420 {
421  if (BLI_findindex(&keyconf->keymaps, keymap) != -1) {
422 
423  WM_keymap_clear(keymap);
424  BLI_remlink(&keyconf->keymaps, keymap);
425  MEM_freeN(keymap);
426 
427  return true;
428  }
429  return false;
430 }
431 
433 {
434  /* If we're tagged, only use compatible. */
435  if (keymap->owner_id[0] != '\0') {
436  const WorkSpace *workspace = CTX_wm_workspace(C);
437  if (BKE_workspace_owner_id_check(workspace, keymap->owner_id) == false) {
438  return false;
439  }
440  }
441 
442  if (UNLIKELY(BLI_listbase_is_empty(&keymap->items))) {
443  /* Empty key-maps may be missing more there may be a typo in the name.
444  * Warn early to avoid losing time investigating each case.
445  * When developing a customized Blender though you may want empty keymaps. */
446  if (!U.app_template[0] &&
447  /* Fallback key-maps may be intentionally empty, don't flood the output. */
448  !BLI_str_endswith(keymap->idname, " (fallback)") &&
449  /* This is an exception which may be empty.
450  * Longer term we might want a flag to indicate an empty key-map is intended. */
451  !STREQ(keymap->idname, "Node Tool: Tweak")) {
452  CLOG_WARN(WM_LOG_KEYMAPS, "empty keymap '%s'", keymap->idname);
453  }
454  }
455 
456  if (keymap->poll != NULL) {
457  return keymap->poll(C);
458  }
459  return true;
460 }
461 
463 {
464  kmi->type = params->type;
465  kmi->val = params->value;
466  kmi->keymodifier = params->keymodifier;
467  kmi->direction = params->direction;
468 
469  if (params->modifier == KM_ANY) {
470  kmi->shift = kmi->ctrl = kmi->alt = kmi->oskey = KM_ANY;
471  }
472  else {
473  /* Only one of the flags should be set. */
474  BLI_assert(((params->modifier & (KM_SHIFT | KM_SHIFT_ANY)) != (KM_SHIFT | KM_SHIFT_ANY)) &&
475  ((params->modifier & (KM_CTRL | KM_CTRL_ANY)) != (KM_CTRL | KM_CTRL_ANY)) &&
476  ((params->modifier & (KM_ALT | KM_ALT_ANY)) != (KM_ALT | KM_ALT_ANY)) &&
477  ((params->modifier & (KM_OSKEY | KM_OSKEY_ANY)) != (KM_OSKEY | KM_OSKEY_ANY)));
478 
479  kmi->shift = ((params->modifier & KM_SHIFT) ?
480  KM_MOD_HELD :
481  ((params->modifier & KM_SHIFT_ANY) ? KM_ANY : KM_NOTHING));
482  kmi->ctrl = ((params->modifier & KM_CTRL) ?
483  KM_MOD_HELD :
484  ((params->modifier & KM_CTRL_ANY) ? KM_ANY : KM_NOTHING));
485  kmi->alt = ((params->modifier & KM_ALT) ?
486  KM_MOD_HELD :
487  ((params->modifier & KM_ALT_ANY) ? KM_ANY : KM_NOTHING));
488  kmi->oskey = ((params->modifier & KM_OSKEY) ?
489  KM_MOD_HELD :
490  ((params->modifier & KM_OSKEY_ANY) ? KM_ANY : KM_NOTHING));
491  }
492 }
493 
494 static void keymap_item_set_id(wmKeyMap *keymap, wmKeyMapItem *kmi)
495 {
496  keymap->kmi_id++;
497  if ((keymap->flag & KEYMAP_USER) == 0) {
498  kmi->id = keymap->kmi_id;
499  }
500  else {
501  kmi->id = -keymap->kmi_id; /* User defined keymap entries have negative ids */
502  }
503 }
504 
506  const char *idname,
507  const KeyMapItem_Params *params)
508 {
509  wmKeyMapItem *kmi = MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
510 
511  BLI_addtail(&keymap->items, kmi);
512  BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME);
513 
514  keymap_event_set(kmi, params);
516 
517  keymap_item_set_id(keymap, kmi);
518 
519  WM_keyconfig_update_tag(keymap, kmi);
520 
521  return kmi;
522 }
523 
525 {
526  wmKeyMapItem *kmi_dst = wm_keymap_item_copy(kmi_src);
527 
528  BLI_addtail(&keymap->items, kmi_dst);
529 
530  keymap_item_set_id(keymap, kmi_dst);
531 
532  WM_keyconfig_update_tag(keymap, kmi_dst);
533 
534  return kmi_dst;
535 }
536 
538 {
539  if (BLI_findindex(&keymap->items, kmi) != -1) {
540  if (kmi->ptr) {
542  MEM_freeN(kmi->ptr);
543  }
544  BLI_freelinkN(&keymap->items, kmi);
545 
546  WM_keyconfig_update_tag(keymap, NULL);
547  return true;
548  }
549  return false;
550 }
551 
554 /* -------------------------------------------------------------------- */
563 static void wm_keymap_addon_add(wmKeyMap *keymap, wmKeyMap *addonmap)
564 {
565  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &addonmap->items) {
566  wmKeyMapItem *kmi_new = wm_keymap_item_copy(kmi);
567  keymap_item_set_id(keymap, kmi_new);
568  BLI_addhead(&keymap->items, kmi_new);
569  }
570 }
571 
573 {
574  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &km->items) {
575  if (wm_keymap_item_equals(kmi, needle)) {
576  return kmi;
577  }
578  }
579 
580  return NULL;
581 }
582 
584 {
585  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &km->items) {
586  if (wm_keymap_item_equals_result(kmi, needle)) {
587  return kmi;
588  }
589  }
590 
591  return NULL;
592 }
593 
594 static void wm_keymap_diff(
595  wmKeyMap *diff_km, wmKeyMap *from_km, wmKeyMap *to_km, wmKeyMap *orig_km, wmKeyMap *addon_km)
596 {
597  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &from_km->items) {
598  wmKeyMapItem *to_kmi = WM_keymap_item_find_id(to_km, kmi->id);
599 
600  if (!to_kmi) {
601  /* remove item */
602  wmKeyMapDiffItem *kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem");
603  kmdi->remove_item = wm_keymap_item_copy(kmi);
604  BLI_addtail(&diff_km->diff_items, kmdi);
605  }
606  else if (to_kmi && !wm_keymap_item_equals(kmi, to_kmi)) {
607  /* replace item */
608  wmKeyMapDiffItem *kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem");
609  kmdi->remove_item = wm_keymap_item_copy(kmi);
610  kmdi->add_item = wm_keymap_item_copy(to_kmi);
611  BLI_addtail(&diff_km->diff_items, kmdi);
612  }
613 
614  /* sync expanded flag back to original so we don't lose it on repatch */
615  if (to_kmi) {
616  wmKeyMapItem *orig_kmi = WM_keymap_item_find_id(orig_km, kmi->id);
617 
618  if (!orig_kmi && addon_km) {
619  orig_kmi = wm_keymap_find_item_equals(addon_km, kmi);
620  }
621 
622  if (orig_kmi) {
623  orig_kmi->flag &= ~KMI_EXPANDED;
624  orig_kmi->flag |= (to_kmi->flag & KMI_EXPANDED);
625  }
626  }
627  }
628 
629  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &to_km->items) {
630  if (kmi->id < 0) {
631  /* add item */
632  wmKeyMapDiffItem *kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem");
633  kmdi->add_item = wm_keymap_item_copy(kmi);
634  BLI_addtail(&diff_km->diff_items, kmdi);
635  }
636  }
637 }
638 
639 static void wm_keymap_patch(wmKeyMap *km, wmKeyMap *diff_km)
640 {
641  LISTBASE_FOREACH (wmKeyMapDiffItem *, kmdi, &diff_km->diff_items) {
642  /* find item to remove */
643  wmKeyMapItem *kmi_remove = NULL;
644  if (kmdi->remove_item) {
645  kmi_remove = wm_keymap_find_item_equals(km, kmdi->remove_item);
646  if (!kmi_remove) {
647  kmi_remove = wm_keymap_find_item_equals_result(km, kmdi->remove_item);
648  }
649  }
650 
651  /* add item */
652  if (kmdi->add_item) {
653  /* Do not re-add an already existing keymap item! See T42088. */
654  /* We seek only for exact copy here! See T42137. */
655  wmKeyMapItem *kmi_add = wm_keymap_find_item_equals(km, kmdi->add_item);
656 
673  if (kmi_add != NULL && kmi_add == kmi_remove) {
674  kmi_remove = NULL;
675  }
676  /* only if nothing to remove or item to remove found */
677  else if (!kmi_add && (!kmdi->remove_item || kmi_remove)) {
678  kmi_add = wm_keymap_item_copy(kmdi->add_item);
679  kmi_add->flag |= KMI_USER_MODIFIED;
680 
681  if (kmi_remove) {
682  kmi_add->flag &= ~KMI_EXPANDED;
683  kmi_add->flag |= (kmi_remove->flag & KMI_EXPANDED);
684  kmi_add->id = kmi_remove->id;
685  BLI_insertlinkbefore(&km->items, kmi_remove, kmi_add);
686  }
687  else {
688  keymap_item_set_id(km, kmi_add);
689  BLI_addtail(&km->items, kmi_add);
690  }
691  }
692  }
693 
694  /* remove item */
695  if (kmi_remove) {
696  wm_keymap_item_free(kmi_remove);
697  BLI_freelinkN(&km->items, kmi_remove);
698  }
699  }
700 }
701 
703  wmKeyMap *defaultmap,
704  wmKeyMap *addonmap,
705  wmKeyMap *usermap)
706 {
707  int expanded = 0;
708 
709  /* remove previous keymap in list, we will replace it */
711  lb, defaultmap->idname, defaultmap->spaceid, defaultmap->regionid);
712  if (km) {
713  expanded = (km->flag & (KEYMAP_EXPANDED | KEYMAP_CHILDREN_EXPANDED));
714  WM_keymap_clear(km);
715  BLI_freelinkN(lb, km);
716  }
717 
718  /* copy new keymap from an existing one */
719  if (usermap && !(usermap->flag & KEYMAP_DIFF)) {
720  /* for compatibility with old user preferences with non-diff
721  * keymaps we override the original entirely */
722 
723  km = wm_keymap_copy(usermap);
724 
725  /* try to find corresponding id's for items */
726  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &km->items) {
727  wmKeyMapItem *orig_kmi = wm_keymap_find_item_equals(defaultmap, kmi);
728  if (!orig_kmi) {
729  orig_kmi = wm_keymap_find_item_equals_result(defaultmap, kmi);
730  }
731 
732  if (orig_kmi) {
733  kmi->id = orig_kmi->id;
734  }
735  else {
736  kmi->id = -(km->kmi_id++);
737  }
738  }
739 
740  km->flag |= KEYMAP_UPDATE; /* update again to create diff */
741  }
742  else {
743  km = wm_keymap_copy(defaultmap);
744  }
745 
746  /* add addon keymap items */
747  if (addonmap) {
748  wm_keymap_addon_add(km, addonmap);
749  }
750 
751  /* tag as being user edited */
752  if (usermap) {
753  km->flag |= KEYMAP_USER_MODIFIED;
754  }
755  km->flag |= KEYMAP_USER | expanded;
756 
757  /* apply user changes of diff keymap */
758  if (usermap && (usermap->flag & KEYMAP_DIFF)) {
759  wm_keymap_patch(km, usermap);
760  }
761 
762  /* add to list */
763  BLI_addtail(lb, km);
764 
765  return km;
766 }
767 
769  wmKeyMap *defaultmap,
770  wmKeyMap *addonmap,
771  wmKeyMap *km)
772 {
773  /* create temporary default + addon keymap for diff */
774  wmKeyMap *origmap = defaultmap;
775 
776  if (addonmap) {
777  defaultmap = wm_keymap_copy(defaultmap);
778  wm_keymap_addon_add(defaultmap, addonmap);
779  }
780 
781  /* remove previous diff keymap in list, we will replace it */
782  wmKeyMap *prevmap = WM_keymap_list_find(lb, km->idname, km->spaceid, km->regionid);
783  if (prevmap) {
784  WM_keymap_clear(prevmap);
785  BLI_freelinkN(lb, prevmap);
786  }
787 
788  /* create diff keymap */
789  wmKeyMap *diffmap = wm_keymap_new(km->idname, km->spaceid, km->regionid);
790  diffmap->flag |= KEYMAP_DIFF;
791  if (defaultmap->flag & KEYMAP_MODAL) {
792  diffmap->flag |= KEYMAP_MODAL;
793  }
794  wm_keymap_diff(diffmap, defaultmap, km, origmap, addonmap);
795 
796  /* add to list if not empty */
797  if (diffmap->diff_items.first) {
798  BLI_addtail(lb, diffmap);
799  }
800  else {
801  WM_keymap_clear(diffmap);
802  MEM_freeN(diffmap);
803  }
804 
805  /* free temporary default map */
806  if (addonmap) {
807  WM_keymap_clear(defaultmap);
808  MEM_freeN(defaultmap);
809  }
810 }
811 
814 /* -------------------------------------------------------------------- */
823 wmKeyMap *WM_keymap_list_find(ListBase *lb, const char *idname, int spaceid, int regionid)
824 {
825  LISTBASE_FOREACH (wmKeyMap *, km, lb) {
826  if (km->spaceid == spaceid && km->regionid == regionid) {
827  if (STREQLEN(idname, km->idname, KMAP_MAX_NAME)) {
828  return km;
829  }
830  }
831  }
832 
833  return NULL;
834 }
835 
837  const char *idname,
838  int spaceid,
839  int regionid)
840 {
841  LISTBASE_FOREACH (wmKeyMap *, km, lb) {
842  if (ELEM(km->spaceid, spaceid, SPACE_EMPTY) && km->regionid == regionid) {
843  if (STREQLEN(idname, km->idname, KMAP_MAX_NAME)) {
844  return km;
845  }
846  }
847  }
848 
849  return NULL;
850 }
851 
852 wmKeyMap *WM_keymap_ensure(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
853 {
854  wmKeyMap *km = WM_keymap_list_find(&keyconf->keymaps, idname, spaceid, regionid);
855 
856  if (km == NULL) {
857  km = wm_keymap_new(idname, spaceid, regionid);
858  BLI_addtail(&keyconf->keymaps, km);
859 
861  }
862 
863  return km;
864 }
865 
866 wmKeyMap *WM_keymap_find_all(wmWindowManager *wm, const char *idname, int spaceid, int regionid)
867 {
868  return WM_keymap_list_find(&wm->userconf->keymaps, idname, spaceid, regionid);
869 }
870 
872  const char *idname,
873  int spaceid,
874  int regionid)
875 {
876  return WM_keymap_list_find_spaceid_or_empty(&wm->userconf->keymaps, idname, spaceid, regionid);
877 }
878 
881 /* -------------------------------------------------------------------- */
889  const char *idname,
890  const EnumPropertyItem *items)
891 {
892  wmKeyMap *km = WM_keymap_ensure(keyconf, idname, 0, 0);
893  km->flag |= KEYMAP_MODAL;
894 
895  /* init modal items from default config */
896  wmWindowManager *wm = G_MAIN->wm.first;
897  if (wm->defaultconf && wm->defaultconf != keyconf) {
898  wmKeyMap *defaultkm = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, 0, 0);
899 
900  if (defaultkm) {
901  km->modal_items = defaultkm->modal_items;
902  km->poll = defaultkm->poll;
903  km->poll_modal_item = defaultkm->poll_modal_item;
904  }
905  }
906 
907  if (items) {
908  km->modal_items = items;
909  }
910 
911  return km;
912 }
913 
914 wmKeyMap *WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
915 {
916  LISTBASE_FOREACH (wmKeyMap *, km, &keyconf->keymaps) {
917  if (km->flag & KEYMAP_MODAL) {
918  if (STREQLEN(idname, km->idname, KMAP_MAX_NAME)) {
919  return km;
920  }
921  }
922  }
923 
924  return NULL;
925 }
926 
928 {
929  wmKeyMapItem *kmi = MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
930 
931  BLI_addtail(&km->items, kmi);
932  kmi->propvalue = value;
933 
934  keymap_event_set(kmi, params);
935 
936  keymap_item_set_id(km, kmi);
937 
938  WM_keyconfig_update_tag(km, kmi);
939 
940  return kmi;
941 }
942 
944  const KeyMapItem_Params *params,
945  const char *value)
946 {
947  wmKeyMapItem *kmi = MEM_callocN(sizeof(wmKeyMapItem), "keymap entry");
948 
949  BLI_addtail(&km->items, kmi);
950  BLI_strncpy(kmi->propvalue_str, value, sizeof(kmi->propvalue_str));
951 
952  keymap_event_set(kmi, params);
953 
954  keymap_item_set_id(km, kmi);
955 
956  WM_keyconfig_update_tag(km, kmi);
957 
958  return kmi;
959 }
960 
962  const wmKeyMapItem *kmi,
963  const int propvalue)
964 {
965  if (km->flag & KEYMAP_MODAL) {
966  kmi = kmi ? kmi->next : km->items.first;
967  for (; kmi; kmi = kmi->next) {
968  if (kmi->propvalue == propvalue) {
969  return kmi;
970  }
971  }
972  }
973  else {
974  BLI_assert_msg(0, "called with non modal keymap");
975  }
976 
977  return NULL;
978 }
979 
980 const wmKeyMapItem *WM_modalkeymap_find_propvalue(const wmKeyMap *km, const int propvalue)
981 {
982  return wm_modalkeymap_find_propvalue_iter(km, NULL, propvalue);
983 }
984 
985 void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
986 {
987  wmOperatorType *ot = WM_operatortype_find(opname, 0);
988 
989  if (ot) {
990  ot->modalkeymap = km;
991  }
992  else {
993  CLOG_ERROR(WM_LOG_KEYMAPS, "unknown operator '%s'", opname);
994  }
995 }
996 
998 {
999  /* here we convert propvalue string values delayed, due to python keymaps
1000  * being created before the actual modal keymaps, so no modal_items */
1001 
1002  if (km && (km->flag & KEYMAP_MODAL) && !km->modal_items) {
1003  if (wm->defaultconf == NULL) {
1004  return;
1005  }
1006 
1007  wmKeyMap *defaultkm = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, 0, 0);
1008  if (!defaultkm) {
1009  return;
1010  }
1011 
1012  km->modal_items = defaultkm->modal_items;
1013  km->poll = defaultkm->poll;
1014  km->poll_modal_item = defaultkm->poll_modal_item;
1015 
1016  if (km->modal_items) {
1017  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &km->items) {
1018  if (kmi->propvalue_str[0]) {
1019  int propvalue;
1020  if (RNA_enum_value_from_id(km->modal_items, kmi->propvalue_str, &propvalue)) {
1021  kmi->propvalue = propvalue;
1022  }
1023  kmi->propvalue_str[0] = '\0';
1024  }
1025  }
1026  }
1027  }
1028 }
1029 
1032 /* -------------------------------------------------------------------- */
1036 static const char *key_event_glyph_or_text(const int font_id,
1037  const char *text,
1038  const char *single_glyph)
1039 {
1040  BLI_assert(single_glyph == NULL || (BLI_strlen_utf8(single_glyph) == 1));
1041  return (single_glyph && BLF_has_glyph(font_id, BLI_str_utf8_as_unicode(single_glyph))) ?
1042  single_glyph :
1043  text;
1044 }
1045 
1046 const char *WM_key_event_string(const short type, const bool compact)
1047 {
1048  if (compact) {
1049  /* String storing a single unicode character or NULL. */
1050  const char *single_glyph = NULL;
1051  int font_id = BLF_default();
1052  const enum {
1053  UNIX,
1054  MACOS,
1055  MSWIN,
1056  } platform =
1057 
1058 #if defined(__APPLE__)
1059  MACOS
1060 #elif defined(_WIN32)
1061  MSWIN
1062 #else
1063  UNIX
1064 #endif
1065  ;
1066 
1067  switch (type) {
1068  case EVT_LEFTSHIFTKEY:
1069  case EVT_RIGHTSHIFTKEY: {
1070  if (platform == MACOS) {
1071  single_glyph = "\xe2\x87\xa7";
1072  }
1073  return key_event_glyph_or_text(
1074  font_id, CTX_IFACE_(BLT_I18NCONTEXT_ID_WINDOWMANAGER, "Shift"), single_glyph);
1075  }
1076  case EVT_LEFTCTRLKEY:
1077  case EVT_RIGHTCTRLKEY:
1078  if (platform == MACOS) {
1079  return key_event_glyph_or_text(font_id, "^", "\xe2\x8c\x83");
1080  }
1081  return IFACE_("Ctrl");
1082  case EVT_LEFTALTKEY:
1083  case EVT_RIGHTALTKEY: {
1084  if (platform == MACOS) {
1085  /* Option symbol on Mac keyboard. */
1086  single_glyph = "\xe2\x8c\xa5";
1087  }
1088  return key_event_glyph_or_text(font_id, IFACE_("Alt"), single_glyph);
1089  }
1090  case EVT_OSKEY: {
1091  if (platform == MACOS) {
1092  return key_event_glyph_or_text(font_id, IFACE_("Cmd"), "\xe2\x8c\x98");
1093  }
1094  if (platform == MSWIN) {
1095  return key_event_glyph_or_text(font_id, IFACE_("Win"), "\xe2\x9d\x96");
1096  }
1097  return IFACE_("OS");
1098  } break;
1099  case EVT_TABKEY:
1100  return key_event_glyph_or_text(font_id, IFACE_("Tab"), "\xe2\xad\xbe");
1101  case EVT_BACKSPACEKEY:
1102  return key_event_glyph_or_text(font_id, IFACE_("Bksp"), "\xe2\x8c\xab");
1103  case EVT_ESCKEY:
1104  if (platform == MACOS) {
1105  single_glyph = "\xe2\x8e\x8b";
1106  }
1107  return key_event_glyph_or_text(font_id, IFACE_("Esc"), single_glyph);
1108  case EVT_RETKEY:
1109  return key_event_glyph_or_text(font_id, IFACE_("Enter"), "\xe2\x86\xb5");
1110  case EVT_SPACEKEY:
1111  return key_event_glyph_or_text(font_id, IFACE_("Space"), "\xe2\x90\xa3");
1112  case EVT_LEFTARROWKEY:
1113  return key_event_glyph_or_text(font_id, IFACE_("Left"), "\xe2\x86\x90");
1114  case EVT_UPARROWKEY:
1115  return key_event_glyph_or_text(font_id, IFACE_("Up"), "\xe2\x86\x91");
1116  case EVT_RIGHTARROWKEY:
1117  return key_event_glyph_or_text(font_id, IFACE_("Right"), "\xe2\x86\x92");
1118  case EVT_DOWNARROWKEY:
1119  return key_event_glyph_or_text(font_id, IFACE_("Down"), "\xe2\x86\x93");
1120  }
1121  }
1122 
1123  const EnumPropertyItem *it;
1124  const int i = RNA_enum_from_value(rna_enum_event_type_items, (int)type);
1125 
1126  if (i == -1) {
1127  return "";
1128  }
1129  it = &rna_enum_event_type_items[i];
1130 
1131  /* We first try enum items' description (abused as shortname here),
1132  * and fall back to usual name if empty. */
1133  if (compact && it->description[0]) {
1134  /* XXX No context for enum descriptions... In practice shall not be an issue though. */
1135  return IFACE_(it->description);
1136  }
1137 
1139 }
1140 
1141 int WM_keymap_item_raw_to_string(const short shift,
1142  const short ctrl,
1143  const short alt,
1144  const short oskey,
1145  const short keymodifier,
1146  const short val,
1147  const short type,
1148  const bool compact,
1149  char *result,
1150  const int result_len)
1151 {
1152  /* TODO: also support (some) value, like e.g. double-click? */
1153 
1154 #define ADD_SEP \
1155  if (p != buf) { \
1156  *p++ = ' '; \
1157  } \
1158  (void)0
1159 
1160  char buf[128];
1161  char *p = buf;
1162 
1163  buf[0] = '\0';
1164 
1165  if (shift == KM_ANY && ctrl == KM_ANY && alt == KM_ANY && oskey == KM_ANY) {
1166  /* Don't show anything for any mapping. */
1167  }
1168  else {
1169  if (shift) {
1170  ADD_SEP;
1172  }
1173 
1174  if (ctrl) {
1175  ADD_SEP;
1177  }
1178 
1179  if (alt) {
1180  ADD_SEP;
1182  }
1183 
1184  if (oskey) {
1185  ADD_SEP;
1187  }
1188  }
1189 
1190  if (keymodifier) {
1191  ADD_SEP;
1192  p += BLI_strcpy_rlen(p, WM_key_event_string(keymodifier, compact));
1193  }
1194 
1195  if (type) {
1196  ADD_SEP;
1197  if (val == KM_DBL_CLICK) {
1198  p += BLI_strcpy_rlen(p, IFACE_("dbl-"));
1199  }
1200  p += BLI_strcpy_rlen(p, WM_key_event_string(type, compact));
1201  }
1202 
1203  /* We assume size of buf is enough to always store any possible shortcut,
1204  * but let's add a debug check about it! */
1205  BLI_assert(p - buf < sizeof(buf));
1206 
1207  /* We need utf8 here, otherwise we may 'cut' some unicode chars like arrows... */
1208  return BLI_strncpy_utf8_rlen(result, buf, result_len);
1209 
1210 #undef ADD_SEP
1211 }
1212 
1214  const bool compact,
1215  char *result,
1216  const int result_len)
1217 {
1218  return WM_keymap_item_raw_to_string(kmi->shift,
1219  kmi->ctrl,
1220  kmi->alt,
1221  kmi->oskey,
1222  kmi->keymodifier,
1223  kmi->val,
1224  kmi->type,
1225  compact,
1226  result,
1227  result_len);
1228 }
1229 
1231  const int propvalue,
1232  const bool compact,
1233  char *result,
1234  const int result_len)
1235 {
1236  int totlen = 0;
1237  bool add_sep = false;
1238 
1239  if (km) {
1240  const wmKeyMapItem *kmi;
1241 
1242  /* Find all shortcuts related to that propvalue! */
1243  for (kmi = WM_modalkeymap_find_propvalue(km, propvalue); kmi && totlen < (result_len - 2);
1244  kmi = wm_modalkeymap_find_propvalue_iter(km, kmi, propvalue)) {
1245  if (add_sep) {
1246  result[totlen++] = '/';
1247  result[totlen] = '\0';
1248  }
1249  else {
1250  add_sep = true;
1251  }
1252  totlen += WM_keymap_item_to_string(kmi, compact, &result[totlen], result_len - totlen);
1253  }
1254  }
1255 
1256  return totlen;
1257 }
1258 
1260  const int propvalue,
1261  const bool compact,
1262  char *result,
1263  const int result_len)
1264 {
1265  wmWindowManager *wm = G_MAIN->wm.first;
1266  wmKeyMap *keymap = WM_keymap_active(wm, ot->modalkeymap);
1267  return WM_modalkeymap_items_to_string(keymap, propvalue, compact, result, result_len);
1268 }
1269 
1271  const int propvalue,
1272  const bool compact,
1273  const int max_len,
1274  int *r_available_len,
1275  char **r_result)
1276 {
1277  char *ret = *r_result;
1278 
1279  if (*r_available_len > 1) {
1281  ot, propvalue, compact, ret, min_ii(*r_available_len, max_len)) +
1282  1;
1283 
1284  *r_available_len -= used_len;
1285  *r_result += used_len;
1286  if (*r_available_len == 0) {
1287  (*r_result)--; /* So that *result keeps pointing on a valid char, we'll stay on it anyway. */
1288  }
1289  }
1290  else {
1291  *ret = '\0';
1292  }
1293 
1294  return ret;
1295 }
1296 
1299 /* -------------------------------------------------------------------- */
1304  const char *opname,
1305  IDProperty *properties,
1306  const bool is_strict,
1307  const struct wmKeyMapItemFind_Params *params)
1308 {
1309  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) {
1310  /* skip disabled keymap items [T38447] */
1311  if (kmi->flag & KMI_INACTIVE) {
1312  continue;
1313  }
1314 
1315  bool kmi_match = false;
1316 
1317  if (STREQ(kmi->idname, opname)) {
1318  if (properties) {
1319  /* example of debugging keymaps */
1320 #if 0
1321  if (kmi->ptr) {
1322  if (STREQ("MESH_OT_rip_move", opname)) {
1323  printf("OPERATOR\n");
1324  IDP_print(properties);
1325  printf("KEYMAP\n");
1326  IDP_print(kmi->ptr->data);
1327  }
1328  }
1329 #endif
1330 
1331  if (kmi->ptr && IDP_EqualsProperties_ex(properties, kmi->ptr->data, is_strict)) {
1332  kmi_match = true;
1333  }
1334  /* Debug only, helps spotting mismatches between menu entries and shortcuts! */
1335  else if (G.debug & G_DEBUG_WM) {
1336  if (is_strict && kmi->ptr) {
1337  wmOperatorType *ot = WM_operatortype_find(opname, true);
1338  if (ot) {
1339  /* make a copy of the properties and set unset ones to their default values. */
1340  PointerRNA opptr;
1341  IDProperty *properties_default = IDP_CopyProperty(kmi->ptr->data);
1342 
1343  RNA_pointer_create(NULL, ot->srna, properties_default, &opptr);
1344  WM_operator_properties_default(&opptr, true);
1345 
1346  if (IDP_EqualsProperties_ex(properties, properties_default, is_strict)) {
1347  char kmi_str[128];
1348  WM_keymap_item_to_string(kmi, false, kmi_str, sizeof(kmi_str));
1349  /* NOTE: given properties could come from other things than menu entry. */
1350  printf(
1351  "%s: Some set values in menu entry match default op values, "
1352  "this might not be desired!\n",
1353  opname);
1354  printf("\tkm: '%s', kmi: '%s'\n", keymap->idname, kmi_str);
1355 #ifndef NDEBUG
1356 # ifdef WITH_PYTHON
1357  printf("OPERATOR\n");
1358  IDP_print(properties);
1359  printf("KEYMAP\n");
1360  IDP_print(kmi->ptr->data);
1361 # endif
1362 #endif
1363  printf("\n");
1364  }
1365 
1366  IDP_FreeProperty(properties_default);
1367  }
1368  }
1369  }
1370  }
1371  else {
1372  kmi_match = true;
1373  }
1374 
1375  if (kmi_match) {
1376  if ((params == NULL) || params->filter_fn(keymap, kmi, params->user_data)) {
1377  return kmi;
1378  }
1379  }
1380  }
1381  }
1382  return NULL;
1383 }
1384 
1386  wmWindowManager *wm,
1387  wmWindow *win,
1388  ListBase *handlers,
1389  const char *opname,
1390  wmOperatorCallContext UNUSED(opcontext),
1391  IDProperty *properties,
1392  const bool is_strict,
1393  const struct wmKeyMapItemFind_Params *params,
1394  wmKeyMap **r_keymap)
1395 {
1396  /* find keymap item in handlers */
1397  LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) {
1398  if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) {
1399  wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base;
1400  wmEventHandler_KeymapResult km_result;
1401  WM_event_get_keymaps_from_handler(wm, win, handler, &km_result);
1402  for (int km_index = 0; km_index < km_result.keymaps_len; km_index++) {
1403  wmKeyMap *keymap = km_result.keymaps[km_index];
1404  if (WM_keymap_poll((bContext *)C, keymap)) {
1406  keymap, opname, properties, is_strict, params);
1407  if (kmi != NULL) {
1408  if (r_keymap) {
1409  *r_keymap = keymap;
1410  }
1411  return kmi;
1412  }
1413  }
1414  }
1415  }
1416  }
1417  /* ensure un-initialized keymap is never used */
1418  if (r_keymap) {
1419  *r_keymap = NULL;
1420  }
1421  return NULL;
1422 }
1423 
1425  const char *opname,
1426  wmOperatorCallContext opcontext,
1427  IDProperty *properties,
1428  const bool is_strict,
1429  const struct wmKeyMapItemFind_Params *params,
1430  wmKeyMap **r_keymap)
1431 {
1433  wmWindow *win = CTX_wm_window(C);
1434  ScrArea *area = CTX_wm_area(C);
1435  ARegion *region = CTX_wm_region(C);
1436  wmKeyMapItem *found = NULL;
1437 
1438  /* look into multiple handler lists to find the item */
1439  if (win) {
1441  wm,
1442  win,
1443  &win->modalhandlers,
1444  opname,
1445  opcontext,
1446  properties,
1447  is_strict,
1448  params,
1449  r_keymap);
1450  if (found == NULL) {
1452  C, wm, win, &win->handlers, opname, opcontext, properties, is_strict, params, r_keymap);
1453  }
1454  }
1455 
1456  if (area && found == NULL) {
1458  C, wm, win, &area->handlers, opname, opcontext, properties, is_strict, params, r_keymap);
1459  }
1460 
1461  if (found == NULL) {
1463  if (area) {
1464  if (!(region && region->regiontype == RGN_TYPE_WINDOW)) {
1466  }
1467 
1468  if (region) {
1470  wm,
1471  win,
1472  &region->handlers,
1473  opname,
1474  opcontext,
1475  properties,
1476  is_strict,
1477  params,
1478  r_keymap);
1479  }
1480  }
1481  }
1483  if (!(region && region->regiontype == RGN_TYPE_CHANNELS)) {
1485  }
1486 
1487  if (region) {
1489  wm,
1490  win,
1491  &region->handlers,
1492  opname,
1493  opcontext,
1494  properties,
1495  is_strict,
1496  params,
1497  r_keymap);
1498  }
1499  }
1501  if (!(region && region->regiontype == RGN_TYPE_PREVIEW)) {
1503  }
1504 
1505  if (region) {
1507  wm,
1508  win,
1509  &region->handlers,
1510  opname,
1511  opcontext,
1512  properties,
1513  is_strict,
1514  params,
1515  r_keymap);
1516  }
1517  }
1518  else {
1519  if (region) {
1521  wm,
1522  win,
1523  &region->handlers,
1524  opname,
1525  opcontext,
1526  properties,
1527  is_strict,
1528  params,
1529  r_keymap);
1530  }
1531  }
1532  }
1533 
1534  return found;
1535 }
1536 
1538  const char *opname,
1539  wmOperatorCallContext opcontext,
1540  IDProperty *properties,
1541  bool is_strict,
1542  const struct wmKeyMapItemFind_Params *params,
1543  wmKeyMap **r_keymap)
1544 {
1545  /* XXX Hack! Macro operators in menu entry have their whole props defined,
1546  * which is not the case for relevant keymap entries.
1547  * Could be good to check and harmonize this,
1548  * but for now always compare non-strict in this case. */
1549  wmOperatorType *ot = WM_operatortype_find(opname, true);
1550  if (ot) {
1551  is_strict = is_strict && ((ot->flag & OPTYPE_MACRO) == 0);
1552  }
1553 
1555  C, opname, opcontext, properties, is_strict, params, r_keymap);
1556 
1557  /* This block is *only* useful in one case: when op uses an enum menu in its prop member
1558  * (then, we want to rerun a comparison with that 'prop' unset). Note this remains brittle,
1559  * since now any enum prop may be used in UI (specified by name), ot->prop is not so much used...
1560  * Otherwise:
1561  * * If non-strict, unset properties always match set ones in IDP_EqualsProperties_ex.
1562  * * If strict, unset properties never match set ones in IDP_EqualsProperties_ex,
1563  * and we do not want that to change (else we get things like T41757)!
1564  * ...so in either case, re-running a comparison with unset props set to default is useless.
1565  */
1566  if (!found && properties) {
1567  if (ot && ot->prop) { /* XXX Shall we also check ot->prop is actually an enum? */
1568  /* make a copy of the properties and unset the 'ot->prop' one if set. */
1569  PointerRNA opptr;
1570  IDProperty *properties_temp = IDP_CopyProperty(properties);
1571 
1572  RNA_pointer_create(NULL, ot->srna, properties_temp, &opptr);
1573 
1574  if (RNA_property_is_set(&opptr, ot->prop)) {
1575  /* For operator that has enum menu,
1576  * unset it so its value does not affect comparison result. */
1577  RNA_property_unset(&opptr, ot->prop);
1578 
1579  found = wm_keymap_item_find_props(
1580  C, opname, opcontext, properties_temp, is_strict, params, r_keymap);
1581  }
1582 
1583  IDP_FreeProperty(properties_temp);
1584  }
1585  }
1586 
1587  /* Debug only, helps spotting mismatches between menu entries and shortcuts! */
1588  if (G.debug & G_DEBUG_WM) {
1589  if (!found && is_strict && properties) {
1590  if (ot) {
1591  /* make a copy of the properties and set unset ones to their default values. */
1592  PointerRNA opptr;
1593  IDProperty *properties_default = IDP_CopyProperty(properties);
1594 
1595  RNA_pointer_create(NULL, ot->srna, properties_default, &opptr);
1596  WM_operator_properties_default(&opptr, true);
1597 
1598  wmKeyMap *km;
1600  C, opname, opcontext, properties_default, is_strict, params, &km);
1601  if (kmi) {
1602  char kmi_str[128];
1603  WM_keymap_item_to_string(kmi, false, kmi_str, sizeof(kmi_str));
1604  printf(
1605  "%s: Some set values in keymap entry match default op values, "
1606  "this might not be desired!\n",
1607  opname);
1608  printf("\tkm: '%s', kmi: '%s'\n", km->idname, kmi_str);
1609 #ifndef NDEBUG
1610 # ifdef WITH_PYTHON
1611  printf("OPERATOR\n");
1612  IDP_print(properties);
1613  printf("KEYMAP\n");
1614  IDP_print(kmi->ptr->data);
1615 # endif
1616 #endif
1617  printf("\n");
1618  }
1619 
1620  IDP_FreeProperty(properties_default);
1621  }
1622  }
1623  }
1624 
1625  return found;
1626 }
1627 
1628 static bool kmi_filter_is_visible(const wmKeyMap *UNUSED(km),
1629  const wmKeyMapItem *kmi,
1630  void *UNUSED(user_data))
1631 {
1632  return ((WM_key_event_string(kmi->type, false)[0] != '\0') &&
1633  (IS_EVENT_ACTIONZONE(kmi->type) == false));
1634 }
1635 
1637  const char *opname,
1638  wmOperatorCallContext opcontext,
1639  IDProperty *properties,
1640  const bool is_strict,
1641  char *result,
1642  const int result_len)
1643 {
1645  opname,
1646  opcontext,
1647  properties,
1648  is_strict,
1649  &(struct wmKeyMapItemFind_Params){
1650  .filter_fn = kmi_filter_is_visible,
1651  .user_data = NULL,
1652  },
1653  NULL);
1654  if (kmi) {
1655  WM_keymap_item_to_string(kmi, false, result, result_len);
1656  return result;
1657  }
1658 
1659  return NULL;
1660 }
1661 
1663  const wmKeyMapItem *kmi,
1664  void *user_data)
1665 {
1666  short *mask_pair = user_data;
1667  return ((WM_event_type_mask_test(kmi->type, mask_pair[0]) == true) &&
1668  (WM_event_type_mask_test(kmi->type, mask_pair[1]) == false) &&
1669  kmi_filter_is_visible(km, kmi, user_data));
1670 }
1671 
1673  const char *opname,
1674  wmOperatorCallContext opcontext,
1675  IDProperty *properties,
1676  const short include_mask,
1677  const short exclude_mask,
1678  wmKeyMap **r_keymap)
1679 {
1680  short user_data_mask[2] = {include_mask, exclude_mask};
1681  bool use_mask = (include_mask != EVT_TYPE_MASK_ALL) || (exclude_mask != 0);
1682  return wm_keymap_item_find(
1683  C,
1684  opname,
1685  opcontext,
1686  properties,
1687  true,
1688  &(struct wmKeyMapItemFind_Params){
1689  .filter_fn = use_mask ? kmi_filter_is_visible_type_mask : kmi_filter_is_visible,
1690  .user_data = use_mask ? user_data_mask : NULL,
1691  },
1692  r_keymap);
1693 }
1694 
1696  const char *opname,
1697  IDProperty *properties,
1698  const short include_mask,
1699  const short exclude_mask)
1700 {
1701  short user_data_mask[2] = {include_mask, exclude_mask};
1702  bool use_mask = (include_mask != EVT_TYPE_MASK_ALL) || (exclude_mask != 0);
1704  keymap,
1705  opname,
1706  properties,
1707  true,
1708  &(struct wmKeyMapItemFind_Params){
1709  .filter_fn = use_mask ? kmi_filter_is_visible_type_mask : kmi_filter_is_visible,
1710  .user_data = use_mask ? user_data_mask : NULL,
1711  });
1712 }
1713 
1715 {
1716  if (k1->flag & KMI_INACTIVE || k2->flag & KMI_INACTIVE) {
1717  return 0;
1718  }
1719 
1720  /* take event mapping into account */
1721  int k1type = WM_userdef_event_map(k1->type);
1722  int k2type = WM_userdef_event_map(k2->type);
1723 
1724  if (k1type != KM_ANY && k2type != KM_ANY && k1type != k2type) {
1725  return 0;
1726  }
1727 
1728  if (k1->val != KM_ANY && k2->val != KM_ANY) {
1729  /* take click, press, release conflict into account */
1730  if (k1->val == KM_CLICK && ELEM(k2->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0) {
1731  return 0;
1732  }
1733  if (k2->val == KM_CLICK && ELEM(k1->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0) {
1734  return 0;
1735  }
1736  if (k1->val != k2->val) {
1737  return 0;
1738  }
1739  if (k1->val == KM_CLICK_DRAG && (k1->direction != k2->direction)) {
1740  return 0;
1741  }
1742  }
1743 
1744  if (k1->shift != KM_ANY && k2->shift != KM_ANY && k1->shift != k2->shift) {
1745  return 0;
1746  }
1747 
1748  if (k1->ctrl != KM_ANY && k2->ctrl != KM_ANY && k1->ctrl != k2->ctrl) {
1749  return 0;
1750  }
1751 
1752  if (k1->alt != KM_ANY && k2->alt != KM_ANY && k1->alt != k2->alt) {
1753  return 0;
1754  }
1755 
1756  if (k1->oskey != KM_ANY && k2->oskey != KM_ANY && k1->oskey != k2->oskey) {
1757  return 0;
1758  }
1759 
1760  if (k1->keymodifier != k2->keymodifier) {
1761  return 0;
1762  }
1763 
1764  return 1;
1765 }
1766 
1769 /* -------------------------------------------------------------------- */
1777 /* so operator removal can trigger update */
1778 enum {
1780 
1781  /* ensure all wmKeyMap have their operator types validated after removing an operator */
1783 };
1784 
1785 static char wm_keymap_update_flag = 0;
1786 
1788 {
1789  /* quick tag to do delayed keymap updates */
1791 
1792  if (keymap) {
1793  keymap->flag |= KEYMAP_UPDATE;
1794  }
1795  if (kmi) {
1796  kmi->flag |= KMI_UPDATE;
1797  }
1798 }
1799 
1801 {
1803 }
1804 
1806 {
1807  int update = (km->flag & KEYMAP_UPDATE);
1808  km->flag &= ~KEYMAP_UPDATE;
1809 
1810  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &km->items) {
1811  update = update || (kmi->flag & KMI_UPDATE);
1812  kmi->flag &= ~KMI_UPDATE;
1813  }
1814 
1815  return (update != 0);
1816 }
1817 
1819 {
1820  wmKeyConfig *keyconf = WM_keyconfig_active(wm);
1821  wmKeyMap *keymap = WM_keymap_list_find(&keyconf->keymaps, km->idname, km->spaceid, km->regionid);
1822  if (!keymap && wm->defaultconf) {
1823  keymap = WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, km->spaceid, km->regionid);
1824  }
1825 
1826  return keymap;
1827 }
1828 
1830 {
1831  bool compat_update = false;
1832 
1833  if (wm_keymap_update_flag == 0) {
1834  return;
1835  }
1836 
1838  /* an operatortype has been removed, this won't happen often
1839  * but when it does we have to check _every_ keymap item */
1840  ListBase *keymaps_lb[] = {
1841  &U.user_keymaps,
1842  &wm->userconf->keymaps,
1843  &wm->defaultconf->keymaps,
1844  &wm->addonconf->keymaps,
1845  NULL,
1846  };
1847 
1848  int i;
1849 
1850  for (i = 0; keymaps_lb[i]; i++) {
1852  }
1853 
1854  LISTBASE_FOREACH (wmKeyConfig *, kc, &wm->keyconfigs) {
1856  }
1857 
1859  }
1860 
1862  /* update operator properties for non-modal user keymaps */
1863  LISTBASE_FOREACH (wmKeyMap *, km, &U.user_keymaps) {
1864  if ((km->flag & KEYMAP_MODAL) == 0) {
1865  LISTBASE_FOREACH (wmKeyMapDiffItem *, kmdi, &km->diff_items) {
1866  if (kmdi->add_item) {
1867  wm_keymap_item_properties_set(kmdi->add_item);
1868  }
1869  if (kmdi->remove_item) {
1870  wm_keymap_item_properties_set(kmdi->remove_item);
1871  }
1872  }
1873 
1874  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &km->items) {
1876  }
1877  }
1878  }
1879 
1880  /* update U.user_keymaps with user key configuration changes */
1881  LISTBASE_FOREACH (wmKeyMap *, km, &wm->userconf->keymaps) {
1882  /* only diff if the user keymap was modified */
1884  /* find keymaps */
1885  wmKeyMap *defaultmap = wm_keymap_preset(wm, km);
1886  wmKeyMap *addonmap = WM_keymap_list_find(
1887  &wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid);
1888 
1889  /* diff */
1890  if (defaultmap) {
1891  wm_keymap_diff_update(&U.user_keymaps, defaultmap, addonmap, km);
1892  }
1893  }
1894  }
1895 
1896  /* create user key configuration from preset + addon + user preferences */
1897  LISTBASE_FOREACH (wmKeyMap *, km, &wm->defaultconf->keymaps) {
1898  /* find keymaps */
1899  wmKeyMap *defaultmap = wm_keymap_preset(wm, km);
1900  wmKeyMap *addonmap = WM_keymap_list_find(
1901  &wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid);
1902  wmKeyMap *usermap = WM_keymap_list_find(
1903  &U.user_keymaps, km->idname, km->spaceid, km->regionid);
1904 
1905  /* For now only the default map defines modal key-maps,
1906  * if we support modal keymaps for 'addonmap', these will need to be enabled too. */
1907  wm_user_modal_keymap_set_items(wm, defaultmap);
1908 
1909  /* add */
1911  &wm->userconf->keymaps, defaultmap, addonmap, usermap);
1912 
1913  if (kmn) {
1914  kmn->modal_items = km->modal_items;
1915  kmn->poll = km->poll;
1916  kmn->poll_modal_item = km->poll_modal_item;
1917  }
1918 
1919  /* in case of old non-diff keymaps, force extra update to create diffs */
1920  compat_update = compat_update || (usermap && !(usermap->flag & KEYMAP_DIFF));
1921  }
1922 
1924  }
1925 
1927 
1928  if (compat_update) {
1930  WM_keyconfig_update(wm);
1931  }
1932 }
1933 
1936 /* -------------------------------------------------------------------- */
1944 {
1945  if (!keymap) {
1946  return NULL;
1947  }
1948 
1949  /* first user defined keymaps */
1951  &wm->userconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
1952 
1953  if (km) {
1954  return km;
1955  }
1956 
1957  return keymap;
1958 }
1959 
1962 /* -------------------------------------------------------------------- */
1969 {
1970  if (!keymap) {
1971  return;
1972  }
1973 
1974  /* construct default keymap from preset + addons */
1975  wmKeyMap *defaultmap = wm_keymap_preset(wm, keymap);
1976  wmKeyMap *addonmap = WM_keymap_list_find(
1977  &wm->addonconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
1978 
1979  if (addonmap) {
1980  defaultmap = wm_keymap_copy(defaultmap);
1981  wm_keymap_addon_add(defaultmap, addonmap);
1982  }
1983 
1984  /* find original item */
1985  wmKeyMapItem *orig = WM_keymap_item_find_id(defaultmap, kmi->id);
1986 
1987  if (orig) {
1988  /* restore to original */
1989  if (!STREQ(orig->idname, kmi->idname)) {
1990  BLI_strncpy(kmi->idname, orig->idname, sizeof(kmi->idname));
1992  }
1993 
1994  if (orig->properties) {
1995  if (kmi->properties) {
1997  kmi->properties = NULL;
1998  }
1999 
2000  kmi->properties = IDP_CopyProperty(orig->properties);
2001  kmi->ptr->data = kmi->properties;
2002  }
2003 
2004  kmi->propvalue = orig->propvalue;
2005  kmi->type = orig->type;
2006  kmi->val = orig->val;
2007  kmi->shift = orig->shift;
2008  kmi->ctrl = orig->ctrl;
2009  kmi->alt = orig->alt;
2010  kmi->oskey = orig->oskey;
2011  kmi->keymodifier = orig->keymodifier;
2012  kmi->maptype = orig->maptype;
2013  kmi->flag = (kmi->flag & ~(KMI_REPEAT_IGNORE | KMI_INACTIVE)) |
2014  (orig->flag & KMI_REPEAT_IGNORE);
2015 
2016  WM_keyconfig_update_tag(keymap, kmi);
2017  }
2018 
2019  /* free temporary keymap */
2020  if (addonmap) {
2021  WM_keymap_clear(defaultmap);
2022  MEM_freeN(defaultmap);
2023  }
2024 }
2025 
2027 {
2028  /* remove keymap from U.user_keymaps and update */
2029  wmKeyMap *usermap = WM_keymap_list_find(
2030  &U.user_keymaps, keymap->idname, keymap->spaceid, keymap->regionid);
2031 
2032  if (usermap) {
2033  WM_keymap_clear(usermap);
2034  BLI_freelinkN(&U.user_keymaps, usermap);
2035 
2037  WM_keyconfig_update(wm);
2038  }
2039 }
2040 
2042 {
2043  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) {
2044  if (kmi->id == id) {
2045  return kmi;
2046  }
2047  }
2048 
2049  return NULL;
2050 }
2051 
2052 const char *WM_bool_as_string(bool test)
2053 {
2054  return test ? IFACE_("ON") : IFACE_("OFF");
2055 }
2056 
struct WorkSpace * CTX_wm_workspace(const bContext *C)
Definition: context.c:728
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
#define G_MAIN
Definition: BKE_global.h:267
@ G_DEBUG_WM
Definition: BKE_global.h:179
void IDP_print(const struct IDProperty *prop)
void IDP_FreeProperty(struct IDProperty *prop)
Definition: idprop.c:1093
bool IDP_EqualsProperties_ex(struct IDProperty *prop1, struct IDProperty *prop2, bool is_strict) ATTR_WARN_UNUSED_RESULT
Definition: idprop.c:795
struct IDProperty * IDP_CopyProperty(const struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
struct ARegion * BKE_area_find_region_type(const struct ScrArea *area, int type)
bool BKE_workspace_owner_id_check(const struct WorkSpace *workspace, const char *owner_id) ATTR_NONNULL()
int BLF_default(void)
Definition: blf_default.c:44
bool BLF_has_glyph(int fontid, unsigned int unicode)
Definition: blf.c:121
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:60
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:239
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:273
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:340
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int min_ii(int a, int b)
size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:134
bool BLI_str_endswith(const char *__restrict str, const char *__restrict end) ATTR_NONNULL()
Definition: string.c:887
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
unsigned int BLI_str_utf8_as_unicode(const char *p) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: string_utf8.c:478
size_t BLI_strlen_utf8(const char *strc) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
Definition: string_utf8.c:317
char size_t BLI_strncpy_utf8_rlen(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
#define STREQLEN(a, b, n)
#define UNUSED(x)
#define UNLIKELY(x)
#define ELEM(...)
#define STREQ(a, b)
#define LIKELY(x)
#define BLT_I18NCONTEXT_ID_WINDOWMANAGER
#define CTX_IFACE_(context, msgid)
#define IFACE_(msgid)
#define BLT_I18NCONTEXT_UI_EVENTS
#define CLOG_ERROR(clg_ref,...)
Definition: CLG_log.h:190
#define CLOG_WARN(clg_ref,...)
Definition: CLG_log.h:189
Object is a sort of wrapper for general info.
@ RGN_TYPE_CHANNELS
@ RGN_TYPE_WINDOW
@ RGN_TYPE_PREVIEW
@ SPACE_EMPTY
#define OP_MAX_TYPENAME
@ KMI_TYPE_TEXTINPUT
@ KMI_TYPE_KEYBOARD
#define KMAP_MAX_NAME
@ KMI_REPEAT_IGNORE
@ KMI_USER_MODIFIED
@ WM_KEYCONFIG_IS_INIT
@ KEYMAP_USER_MODIFIED
@ KEYMAP_CHILDREN_EXPANDED
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
@ RNA_EQ_UNSET_MATCH_NONE
Definition: RNA_access.h:775
#define C
Definition: RandGen.cpp:25
@ KM_NOTHING
Definition: WM_types.h:266
@ KM_ANY
Definition: WM_types.h:265
@ KM_PRESS
Definition: WM_types.h:267
@ KM_CLICK_DRAG
Definition: WM_types.h:275
@ KM_DBL_CLICK
Definition: WM_types.h:270
@ KM_RELEASE
Definition: WM_types.h:268
@ KM_CLICK
Definition: WM_types.h:269
@ OPTYPE_MACRO
Definition: WM_types.h:151
struct CLG_LogRef * WM_LOG_KEYMAPS
wmOperatorCallContext
Definition: WM_types.h:199
@ WM_OP_INVOKE_REGION_WIN
Definition: WM_types.h:202
@ WM_OP_EXEC_REGION_WIN
Definition: WM_types.h:209
@ WM_OP_EXEC_REGION_PREVIEW
Definition: WM_types.h:211
@ WM_OP_INVOKE_REGION_PREVIEW
Definition: WM_types.h:204
@ WM_OP_EXEC_REGION_CHANNELS
Definition: WM_types.h:210
@ WM_OP_INVOKE_REGION_CHANNELS
Definition: WM_types.h:203
@ KM_CTRL
Definition: WM_types.h:239
@ KM_ALT
Definition: WM_types.h:240
@ KM_ALT_ANY
Definition: WM_types.h:247
@ KM_OSKEY_ANY
Definition: WM_types.h:248
@ KM_SHIFT_ANY
Definition: WM_types.h:245
@ KM_OSKEY
Definition: WM_types.h:242
@ KM_CTRL_ANY
Definition: WM_types.h:246
@ KM_SHIFT
Definition: WM_types.h:238
@ KM_TEXTINPUT
Definition: WM_types.h:260
#define KM_MOD_HELD
Definition: WM_types.h:253
unsigned int U
Definition: btGjkEpa3.h:78
void * user_data
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define G(x, y, z)
static unsigned a[3]
Definition: RandGen.cpp:78
static void area(int d1, int d2, int e1, int e2, float weights[2])
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static void update(bNodeTree *ntree)
return ret
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:136
bool RNA_enum_value_from_id(const EnumPropertyItem *item, const char *identifier, int *r_value)
Definition: rna_access.c:5076
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:5271
int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
Definition: rna_access.c:1736
const char * RNA_struct_state_owner_get(void)
Definition: rna_access.c:6816
void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:5281
bool RNA_struct_equals(Main *bmain, PointerRNA *ptr_a, PointerRNA *ptr_b, eRNACompareMode mode)
const EnumPropertyItem rna_enum_event_type_items[]
Definition: rna_wm.c:145
ListBase handlers
short regiontype
const char * name
Definition: RNA_types.h:465
const char * description
Definition: RNA_types.h:467
IDPropertyData data
Definition: DNA_ID.h:117
void * first
Definition: DNA_listBase.h:31
struct StructRNA * type
Definition: RNA_types.h:37
void * data
Definition: RNA_types.h:38
struct ID * owner_id
Definition: RNA_types.h:36
wmKeyMap * keymaps[3]
Definition: WM_api.h:335
struct wmKeyMapDiffItem * next
struct wmKeyMapDiffItem * prev
bool(* filter_fn)(const wmKeyMap *km, const wmKeyMapItem *kmi, void *user_data)
Definition: wm_keymap.c:46
struct PointerRNA * ptr
struct wmKeyMapItem * next
struct wmKeyMapItem * prev
bool(* poll_modal_item)(const struct wmOperator *op, int value)
bool(* poll)(struct bContext *)
const void * modal_items
struct wmKeyMap * modalkeymap
Definition: WM_types.h:987
struct StructRNA * srna
Definition: WM_types.h:969
PropertyRNA * prop
Definition: WM_types.h:981
struct wmKeyConfig * defaultconf
struct wmKeyConfig * userconf
struct wmKeyConfig * addonconf
int WM_userdef_event_map(int kmitype)
bool WM_event_type_mask_test(const int event_type, const enum eEventType_Mask mask)
void WM_event_get_keymaps_from_handler(wmWindowManager *wm, wmWindow *win, wmEventHandler_Keymap *handler, wmEventHandler_KeymapResult *km_result)
@ WM_HANDLER_TYPE_KEYMAP
@ EVT_RIGHTCTRLKEY
@ EVT_TABKEY
@ EVT_DOWNARROWKEY
@ EVT_OSKEY
@ EVT_LEFTCTRLKEY
@ TABLET_ERASER
@ EVT_RIGHTARROWKEY
@ EVT_SPACEKEY
@ TABLET_STYLUS
@ EVT_RIGHTALTKEY
@ EVT_UPARROWKEY
@ EVT_LEFTARROWKEY
@ EVT_LEFTALTKEY
@ EVT_ESCKEY
@ EVT_BACKSPACEKEY
@ EVT_RIGHTSHIFTKEY
@ EVT_LEFTSHIFTKEY
@ EVT_RETKEY
#define ISTIMER(event_type)
#define IS_EVENT_ACTIONZONE(event_type)
#define ISKEYBOARD(event_type)
#define EVT_TYPE_MASK_ALL
#define ISNDOF(event_type)
#define ISMOUSE(event_type)
wmOperatorType * ot
Definition: wm_files.c:3479
static wmKeyMapItem * wm_keymap_item_find_handlers(const bContext *C, wmWindowManager *wm, wmWindow *win, ListBase *handlers, const char *opname, wmOperatorCallContext UNUSED(opcontext), IDProperty *properties, const bool is_strict, const struct wmKeyMapItemFind_Params *params, wmKeyMap **r_keymap)
Definition: wm_keymap.c:1385
void WM_keyconfig_clear(wmKeyConfig *keyconf)
Definition: wm_keymap.c:312
static char wm_keymap_update_flag
Definition: wm_keymap.c:1785
static wmKeyMapItem * wm_keymap_item_find_in_keymap(wmKeyMap *keymap, const char *opname, IDProperty *properties, const bool is_strict, const struct wmKeyMapItemFind_Params *params)
Definition: wm_keymap.c:1303
static void wm_user_modal_keymap_set_items(wmWindowManager *wm, wmKeyMap *km)
Definition: wm_keymap.c:997
static void keymap_item_set_id(wmKeyMap *keymap, wmKeyMapItem *kmi)
Definition: wm_keymap.c:494
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition: wm_keymap.c:914
static wmKeyConfig * WM_keyconfig_active(wmWindowManager *wm)
Definition: wm_keymap.c:327
const char * WM_key_event_string(const short type, const bool compact)
Definition: wm_keymap.c:1046
int WM_modalkeymap_operator_items_to_string(wmOperatorType *ot, const int propvalue, const bool compact, char *result, const int result_len)
Definition: wm_keymap.c:1259
static wmKeyMapDiffItem * wm_keymap_diff_item_copy(wmKeyMapDiffItem *kmdi)
Definition: wm_keymap.c:222
static wmKeyMapItem * wm_keymap_item_find_props(const bContext *C, const char *opname, wmOperatorCallContext opcontext, IDProperty *properties, const bool is_strict, const struct wmKeyMapItemFind_Params *params, wmKeyMap **r_keymap)
Definition: wm_keymap.c:1424
static wmKeyMapItem * wm_keymap_find_item_equals_result(wmKeyMap *km, wmKeyMapItem *needle)
Definition: wm_keymap.c:583
wmKeyMapItem * WM_keymap_item_find_id(wmKeyMap *keymap, int id)
Definition: wm_keymap.c:2041
void WM_keymap_item_restore_to_default(wmWindowManager *wm, wmKeyMap *keymap, wmKeyMapItem *kmi)
Definition: wm_keymap.c:1968
static void wm_keymap_item_properties_update_ot_from_list(ListBase *km_lb)
Definition: wm_keymap.c:141
void WM_keymap_restore_to_default(wmKeyMap *keymap, wmWindowManager *wm)
Definition: wm_keymap.c:2026
static void wm_keymap_item_properties_set(wmKeyMapItem *kmi)
Definition: wm_keymap.c:92
wmKeyMap * WM_keymap_ensure(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
Definition: wm_keymap.c:852
wmKeyMap * WM_keymap_find_all(wmWindowManager *wm, const char *idname, int spaceid, int regionid)
Definition: wm_keymap.c:866
void WM_keyconfig_update(wmWindowManager *wm)
Definition: wm_keymap.c:1829
static wmKeyMapItem * wm_keymap_item_copy(wmKeyMapItem *kmi)
Definition: wm_keymap.c:56
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
Definition: wm_keymap.c:985
void WM_keymap_clear(wmKeyMap *keymap)
Definition: wm_keymap.c:405
static void wm_keymap_addon_add(wmKeyMap *keymap, wmKeyMap *addonmap)
Definition: wm_keymap.c:563
int WM_modalkeymap_items_to_string(const wmKeyMap *km, const int propvalue, const bool compact, char *result, const int result_len)
Definition: wm_keymap.c:1230
wmKeyMapItem * WM_key_event_operator_from_keymap(wmKeyMap *keymap, const char *opname, IDProperty *properties, const short include_mask, const short exclude_mask)
Definition: wm_keymap.c:1695
const char * WM_bool_as_string(bool test)
Definition: wm_keymap.c:2052
wmKeyMap * WM_keymap_list_find(ListBase *lb, const char *idname, int spaceid, int regionid)
Definition: wm_keymap.c:823
int WM_keymap_item_to_string(const wmKeyMapItem *kmi, const bool compact, char *result, const int result_len)
Definition: wm_keymap.c:1213
static wmKeyMap * wm_keymap_new(const char *idname, int spaceid, int regionid)
Definition: wm_keymap.c:365
static void wm_keymap_patch(wmKeyMap *km, wmKeyMap *diff_km)
Definition: wm_keymap.c:639
bool WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi)
Definition: wm_keymap.c:537
wmKeyMap * WM_keymap_active(const wmWindowManager *wm, wmKeyMap *keymap)
Definition: wm_keymap.c:1943
static bool wm_keymap_test_and_clear_update(wmKeyMap *km)
Definition: wm_keymap.c:1805
char * WM_key_event_operator_string(const bContext *C, const char *opname, wmOperatorCallContext opcontext, IDProperty *properties, const bool is_strict, char *result, const int result_len)
Definition: wm_keymap.c:1636
void WM_keyconfig_update_operatortype(void)
Definition: wm_keymap.c:1800
int WM_keymap_item_map_type_get(const wmKeyMapItem *kmi)
Definition: wm_keymap.c:191
wmKeyMap * WM_keymap_find_all_spaceid_or_empty(wmWindowManager *wm, const char *idname, int spaceid, int regionid)
Definition: wm_keymap.c:871
static void wm_keymap_diff_item_free(wmKeyMapDiffItem *kmdi)
Definition: wm_keymap.c:237
@ WM_KEYMAP_UPDATE_RECONFIGURE
Definition: wm_keymap.c:1779
@ WM_KEYMAP_UPDATE_OPERATORTYPE
Definition: wm_keymap.c:1782
wmKeyMapItem * WM_modalkeymap_add_item(wmKeyMap *km, const KeyMapItem_Params *params, int value)
Definition: wm_keymap.c:927
void WM_keyconfig_free(wmKeyConfig *keyconf)
Definition: wm_keymap.c:321
bool WM_keymap_poll(bContext *C, wmKeyMap *keymap)
Definition: wm_keymap.c:432
static const char * key_event_glyph_or_text(const int font_id, const char *text, const char *single_glyph)
Definition: wm_keymap.c:1036
bool WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf)
Definition: wm_keymap.c:295
bool WM_keymap_remove(wmKeyConfig *keyconf, wmKeyMap *keymap)
Definition: wm_keymap.c:419
wmKeyMapItem * WM_key_event_operator(const bContext *C, const char *opname, wmOperatorCallContext opcontext, IDProperty *properties, const short include_mask, const short exclude_mask, wmKeyMap **r_keymap)
Definition: wm_keymap.c:1672
static void wm_keymap_diff_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap *addonmap, wmKeyMap *km)
Definition: wm_keymap.c:768
wmKeyMapItem * WM_keymap_add_item(wmKeyMap *keymap, const char *idname, const KeyMapItem_Params *params)
Definition: wm_keymap.c:505
wmKeyConfig * WM_keyconfig_new(wmWindowManager *wm, const char *idname, bool user_defined)
Definition: wm_keymap.c:259
static void wm_keymap_item_properties_update_ot(wmKeyMapItem *kmi)
Definition: wm_keymap.c:105
static bool kmi_filter_is_visible_type_mask(const wmKeyMap *km, const wmKeyMapItem *kmi, void *user_data)
Definition: wm_keymap.c:1662
static wmKeyMap * wm_keymap_preset(wmWindowManager *wm, wmKeyMap *km)
Definition: wm_keymap.c:1818
static wmKeyMapItem * wm_keymap_item_find(const bContext *C, const char *opname, wmOperatorCallContext opcontext, IDProperty *properties, bool is_strict, const struct wmKeyMapItemFind_Params *params, wmKeyMap **r_keymap)
Definition: wm_keymap.c:1537
static wmKeyMap * wm_keymap_copy(wmKeyMap *keymap)
Definition: wm_keymap.c:382
void WM_keyconfig_set_active(wmWindowManager *wm, const char *idname)
Definition: wm_keymap.c:341
static wmKeyMapItem * wm_keymap_find_item_equals(wmKeyMap *km, wmKeyMapItem *needle)
Definition: wm_keymap.c:572
const wmKeyMapItem * WM_modalkeymap_find_propvalue(const wmKeyMap *km, const int propvalue)
Definition: wm_keymap.c:980
static const wmKeyMapItem * wm_modalkeymap_find_propvalue_iter(const wmKeyMap *km, const wmKeyMapItem *kmi, const int propvalue)
Definition: wm_keymap.c:961
static void wm_keymap_diff(wmKeyMap *diff_km, wmKeyMap *from_km, wmKeyMap *to_km, wmKeyMap *orig_km, wmKeyMap *addon_km)
Definition: wm_keymap.c:594
static void wm_keymap_item_free(wmKeyMapItem *kmi)
Definition: wm_keymap.c:81
static wmKeyMap * wm_keymap_patch_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap *addonmap, wmKeyMap *usermap)
Definition: wm_keymap.c:702
static bool wm_keymap_item_equals(wmKeyMapItem *a, wmKeyMapItem *b)
Definition: wm_keymap.c:167
static bool kmi_filter_is_visible(const wmKeyMap *UNUSED(km), const wmKeyMapItem *kmi, void *UNUSED(user_data))
Definition: wm_keymap.c:1628
void WM_keyconfig_update_tag(wmKeyMap *keymap, wmKeyMapItem *kmi)
Definition: wm_keymap.c:1787
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition: wm_keymap.c:888
bool WM_keymap_item_compare(const wmKeyMapItem *k1, const wmKeyMapItem *k2)
Definition: wm_keymap.c:1714
void WM_keymap_item_properties_reset(wmKeyMapItem *kmi, struct IDProperty *properties)
Definition: wm_keymap.c:177
wmKeyMapItem * WM_modalkeymap_add_item_str(wmKeyMap *km, const KeyMapItem_Params *params, const char *value)
Definition: wm_keymap.c:943
wmKeyMap * WM_keymap_list_find_spaceid_or_empty(ListBase *lb, const char *idname, int spaceid, int regionid)
Definition: wm_keymap.c:836
char * WM_modalkeymap_operator_items_to_string_buf(wmOperatorType *ot, const int propvalue, const bool compact, const int max_len, int *r_available_len, char **r_result)
Definition: wm_keymap.c:1270
int WM_keymap_item_raw_to_string(const short shift, const short ctrl, const short alt, const short oskey, const short keymodifier, const short val, const short type, const bool compact, char *result, const int result_len)
Definition: wm_keymap.c:1141
static bool wm_keymap_item_equals_result(wmKeyMapItem *a, wmKeyMapItem *b)
Definition: wm_keymap.c:159
static void keymap_event_set(wmKeyMapItem *kmi, const KeyMapItem_Params *params)
Definition: wm_keymap.c:462
wmKeyMapItem * WM_keymap_add_item_copy(struct wmKeyMap *keymap, wmKeyMapItem *kmi_src)
Definition: wm_keymap.c:524
#define ADD_SEP
wmKeyConfig * WM_keyconfig_new_user(wmWindowManager *wm, const char *idname)
Definition: wm_keymap.c:290
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
void WM_operator_properties_alloc(PointerRNA **ptr, IDProperty **properties, const char *opstring)
Definition: wm_operators.c:680
void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
Definition: wm_operators.c:661
bool WM_operator_properties_default(PointerRNA *ptr, const bool do_update)
Definition: wm_operators.c:730
void WM_operator_properties_create(PointerRNA *ptr, const char *opstring)
Definition: wm_operators.c:667
void WM_operator_properties_free(PointerRNA *ptr)
Definition: wm_operators.c:783
void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context)
Definition: wm_operators.c:701