[Bf-blender-cvs] [1713db2] master: Fix T38042: Keymap crash after reloading operators

Campbell Barton noreply at git.blender.org
Thu Jan 23 09:10:39 CET 2014


Commit: 1713db203583a1b93143b14dfa77eb447697deac
Author: Campbell Barton
Date:   Thu Jan 23 19:00:30 2014 +1100
https://developer.blender.org/rB1713db203583a1b93143b14dfa77eb447697deac

Fix T38042: Keymap crash after reloading operators

After some investigation with mont29, seems like the best way to ensure
keymaps point to valid operators is using WM_keyconfig_update().

===================================================================

M	source/blender/windowmanager/WM_keymap.h
M	source/blender/windowmanager/intern/wm_keymap.c
M	source/blender/windowmanager/intern/wm_operators.c

===================================================================

diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h
index ce6481c..f5488cb 100644
--- a/source/blender/windowmanager/WM_keymap.h
+++ b/source/blender/windowmanager/WM_keymap.h
@@ -51,6 +51,7 @@ void		WM_keyconfig_set_active(struct wmWindowManager *wm, const char *idname);
 
 void		WM_keyconfig_update(struct wmWindowManager *wm);
 void		WM_keyconfig_update_tag(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi);
+void        WM_keyconfig_update_operatortype(void);
 
 /* Keymap */
 
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index 36099d5..1083717 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -98,6 +98,56 @@ static void wm_keymap_item_properties_set(wmKeyMapItem *kmi)
 	WM_operator_properties_sanitize(kmi->ptr, 1);
 }
 
+/**
+ * Similar to #wm_keymap_item_properties_set but checks for the wmOperatorType having changed, see [#38042]
+ */
+static void wm_keymap_item_properties_update_ot(wmKeyMapItem *kmi)
+{
+	if (kmi->idname[0] == 0) {
+		BLI_assert(kmi->ptr == NULL);
+		return;
+	}
+
+	if (kmi->ptr == NULL) {
+		wm_keymap_item_properties_set(kmi);
+	}
+	else {
+		wmOperatorType *ot = WM_operatortype_find(kmi->idname, 0);
+		if (ot) {
+			if (ot->srna != kmi->ptr->type) {
+				/* matches wm_keymap_item_properties_set but doesnt alloc new ptr */
+				WM_operator_properties_create_ptr(kmi->ptr, ot);
+				WM_operator_properties_sanitize(kmi->ptr, 1);
+			}
+		}
+		else {
+			/* zombie keymap item */
+			MEM_SAFE_FREE(kmi->ptr);
+		}
+	}
+}
+
+static void wm_keyconfig_properties_update_ot(ListBase *km_lb)
+{
+	wmKeyMap *km;
+	wmKeyMapItem *kmi;
+
+	for (km = km_lb->first; km; km = km->next) {
+		wmKeyMapDiffItem *kmdi;
+
+		for (kmi = km->items.first; kmi; kmi = kmi->next) {
+			wm_keymap_item_properties_update_ot(kmi);
+		}
+
+		for (kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) {
+			if (kmdi->add_item)
+				wm_keymap_item_properties_update_ot(kmdi->add_item);
+			if (kmdi->remove_item)
+				wm_keymap_item_properties_update_ot(kmdi->remove_item);
+		}
+	}
+}
+
 static int wm_keymap_item_equals_result(wmKeyMapItem *a, wmKeyMapItem *b)
 {
 	if (strcmp(a->idname, b->idname) != 0)
@@ -1087,12 +1137,20 @@ int WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2)
  * the preset, addon and user preferences keymaps. We also test if the final
  * configuration changed and write the changes to the user preferences. */
 
-static bool WM_KEYMAP_UPDATE = false;
+/* so operator removal can trigger update */
+enum {
+	WM_KEYMAP_UPDATE_RECONFIGURE    = (1 << 0),
+
+	/* ensure all wmKeyMap have their operator types validated after removing an operator */
+	WM_KEYMAP_UPDATE_OPERATORTYPE   = (1 << 1),
+};
+
+static char wm_keymap_update_flag = 0;
 
 void WM_keyconfig_update_tag(wmKeyMap *km, wmKeyMapItem *kmi)
 {
 	/* quick tag to do delayed keymap updates */
-	WM_KEYMAP_UPDATE = true;
+	wm_keymap_update_flag |= WM_KEYMAP_UPDATE_RECONFIGURE;
 
 	if (km)
 		km->flag |= KEYMAP_UPDATE;
@@ -1100,6 +1158,11 @@ void WM_keyconfig_update_tag(wmKeyMap *km, wmKeyMapItem *kmi)
 		kmi->flag |= KMI_UPDATE;
 }
 
+void WM_keyconfig_update_operatortype(void)
+{
+	wm_keymap_update_flag |= WM_KEYMAP_UPDATE_OPERATORTYPE;
+}
+
 static int wm_keymap_test_and_clear_update(wmKeyMap *km)
 {
 	wmKeyMapItem *kmi;
@@ -1137,8 +1200,39 @@ void WM_keyconfig_update(wmWindowManager *wm)
 
 	if (G.background)
 		return;
-	if (!WM_KEYMAP_UPDATE)
+
+	if (wm_keymap_update_flag == 0)
+		return;
+
+	if (wm_keymap_update_flag & WM_KEYMAP_UPDATE_OPERATORTYPE) {
+		/* an operatortype has been removed, this wont happen often
+		 * but when it does we have to check _every_ keymap item */
+		wmKeyConfig *kc;
+
+		ListBase *keymaps_lb[] = {
+		    &U.user_keymaps,
+		    &wm->userconf->keymaps,
+		    &wm->defaultconf->keymaps,
+		    &wm->addonconf->keymaps,
+		    NULL};
+
+		int i;
+
+		for (i = 0; keymaps_lb[i]; i++) {
+			wm_keyconfig_properties_update_ot(keymaps_lb[i]);
+		}
+
+		for (kc = wm->keyconfigs.first; kc; kc = kc->next) {
+			wm_keyconfig_properties_update_ot(&kc->keymaps);
+		}
+
+		wm_keymap_update_flag &= ~WM_KEYMAP_UPDATE_OPERATORTYPE;
+	}
+
+
+	if (wm_keymap_update_flag == 0)
 		return;
+
 	
 	/* update operator properties for non-modal user keymaps */
 	for (km = U.user_keymaps.first; km; km = km->next) {
@@ -1188,9 +1282,12 @@ void WM_keyconfig_update(wmWindowManager *wm)
 
 		/* in case of old non-diff keymaps, force extra update to create diffs */
 		compat_update = compat_update || (usermap && !(usermap->flag & KEYMAP_DIFF));
+
 	}
 
-	WM_KEYMAP_UPDATE = false;
+	wm_keymap_update_flag &= ~WM_KEYMAP_UPDATE_RECONFIGURE;
+
+	BLI_assert(wm_keymap_update_flag == 0);
 
 	if (compat_update) {
 		WM_keyconfig_update_tag(NULL, NULL);
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 3638403..64adb6d 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -477,6 +477,8 @@ void WM_operatortype_remove_ptr(wmOperatorType *ot)
 
 	BLI_ghash_remove(global_ops_hash, (void *)ot->idname, NULL, NULL);
 
+	WM_keyconfig_update_operatortype();
+
 	MEM_freeN(ot);
 }




More information about the Bf-blender-cvs mailing list