From 7aae28af2d7dd9d593c4208d8c73d06d9e274044 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 12 Nov 2018 14:53:08 +0100 Subject: Keymaps: refactor loading of default keymap, fix bugs. This refactors loading of key configurations to clear and refill existing ones, rather than adding a new one and then removing the old one. This fixes broken loading of non-default configurations after recent changes, and prepares for future changes to make it possible to dynamically change key configurations based on user preferences. --- release/scripts/modules/bpy/utils/__init__.py | 51 +++++++++---------- release/scripts/presets/keyconfig/blender_27x.py | 2 +- source/blender/windowmanager/WM_keymap.h | 5 +- source/blender/windowmanager/intern/wm.c | 10 ++-- source/blender/windowmanager/intern/wm_files.c | 7 --- source/blender/windowmanager/intern/wm_keymap.c | 63 +++++++++++++++--------- 6 files changed, 76 insertions(+), 62 deletions(-) diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py index b76050395da..835cbe6c110 100644 --- a/release/scripts/modules/bpy/utils/__init__.py +++ b/release/scripts/modules/bpy/utils/__init__.py @@ -26,6 +26,7 @@ not associated with blenders internal data. __all__ = ( "blend_paths", "escape_identifier", + "keyconfig_init", "keyconfig_set", "load_scripts", "modules_from_path", @@ -262,21 +263,6 @@ def load_scripts(reload_scripts=False, refresh_scripts=False): _addon_utils.reset_all(reload_scripts=reload_scripts) del _initialize - if not is_background: - # Load the default key configuration. - filepath = preset_find("blender", "keyconfig") - if filepath: - keyconfig_set(filepath) - - # run the active integration preset - filepath = preset_find( - _user_preferences.inputs.active_keyconfig, - "keyconfig", - ) - - if filepath: - keyconfig_set(filepath) - if reload_scripts: import gc print("gc.collect() -> %d" % gc.collect()) @@ -570,6 +556,22 @@ def preset_find(name, preset_path, display_name=False, ext=".py"): return filepath +def keyconfig_init(): + # Key configuration initialization and refresh, called from the Blender + # window manager on startup and refresh. + active_config = _user_preferences.inputs.active_keyconfig + + # Load the default key configuration. + default_filepath = preset_find("blender", "keyconfig") + keyconfig_set(default_filepath) + + # Set the active key configuration if different + filepath = preset_find(active_config, "keyconfig") + + if filepath and filepath != default_filepath: + keyconfig_set(filepath) + + def keyconfig_set(filepath, report=None): from os.path import basename, splitext from itertools import chain @@ -602,23 +604,18 @@ def keyconfig_set(filepath, report=None): kc_new = next(chain(iter(kc for kc in keyconfigs if kc not in keyconfigs_old), (None,))) + + # Get name, exception for default keymap to keep backwards compatibility. + name = splitext(basename(filepath))[0] + if name == 'blender': + name = 'Blender' + + kc_new = keyconfigs.get(name) if kc_new is None: if report is not None: report({'ERROR'}, "Failed to load keymap %r" % filepath) return False else: - kc_new.name = "" - - # remove duplicates - name = splitext(basename(filepath))[0] - while True: - kc_dupe = keyconfigs.get(name) - if kc_dupe: - keyconfigs.remove(kc_dupe) - else: - break - - kc_new.name = name keyconfigs.active = kc_new return True diff --git a/release/scripts/presets/keyconfig/blender_27x.py b/release/scripts/presets/keyconfig/blender_27x.py index 2d9ea9d8f44..69d84639a86 100644 --- a/release/scripts/presets/keyconfig/blender_27x.py +++ b/release/scripts/presets/keyconfig/blender_27x.py @@ -8,4 +8,4 @@ _mod = keyconfig_module_from_preset(os.path.join("keymap_data", "blender_default keyconfig_data = _mod.generate_keymaps(_mod.KeymapParams(legacy=True)) if __name__ == "__main__": - keyconfig_import_from_data("Blender 27X", keyconfig_data) + keyconfig_import_from_data("blender_27x", keyconfig_data) diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h index b27d6b44ab0..71037ab162e 100644 --- a/source/blender/windowmanager/WM_keymap.h +++ b/source/blender/windowmanager/WM_keymap.h @@ -42,9 +42,10 @@ struct EnumPropertyItem; /* Key Configuration */ -wmKeyConfig *WM_keyconfig_new (struct wmWindowManager *wm, const char *idname); +wmKeyConfig *WM_keyconfig_new (struct wmWindowManager *wm, const char *idname, bool user_defined); wmKeyConfig *WM_keyconfig_new_user(struct wmWindowManager *wm, const char *idname); bool WM_keyconfig_remove (struct wmWindowManager *wm, struct wmKeyConfig *keyconf); +void WM_keyconfig_clear (struct wmKeyConfig *keyconf); void WM_keyconfig_free (struct wmKeyConfig *keyconf); void WM_keyconfig_set_active(struct wmWindowManager *wm, const char *idname); @@ -56,7 +57,7 @@ void WM_keyconfig_update_operatortype(void); /* Keymap */ void WM_keymap_init (struct bContext *C); -void WM_keymap_free (struct wmKeyMap *keymap); +void WM_keymap_clear (struct wmKeyMap *keymap); wmKeyMapItem *WM_keymap_verify_item( struct wmKeyMap *keymap, const char *idname, int type, diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index cf7c43ff5c0..bc9c1e263cb 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -231,11 +231,11 @@ void WM_keymap_init(bContext *C) /* create standard key configs */ if (!wm->defaultconf) - wm->defaultconf = WM_keyconfig_new(wm, "Blender"); + wm->defaultconf = WM_keyconfig_new(wm, "Blender", false); if (!wm->addonconf) - wm->addonconf = WM_keyconfig_new(wm, "Blender Addon"); + wm->addonconf = WM_keyconfig_new(wm, "Blender Addon", false); if (!wm->userconf) - wm->userconf = WM_keyconfig_new(wm, "Blender User"); + wm->userconf = WM_keyconfig_new(wm, "Blender User", false); /* initialize only after python init is done, for keymaps that * use python operators */ @@ -246,6 +246,10 @@ void WM_keymap_init(bContext *C) wm_window_keymap(wm->defaultconf); ED_spacetypes_keymap(wm->defaultconf); + BPY_execute_string( + C, (const char *[]){"bpy", NULL}, + "bpy.utils.keyconfig_init()"); + wm->defaultconf->flag |= KEYCONF_INIT_DEFAULT; } diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index f7971ed1b64..318147e8c25 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -511,13 +511,6 @@ static void wm_file_read_post(bContext *C, const bool is_startup_file, const boo } BPY_python_reset(C); addons_loaded = true; - - if (!G.background) { - /* Load the keymap from Python, otherwise we get an empty keymap. */ - BPY_execute_string( - C, (const char *[]){"bpy", NULL}, - "bpy.utils.keyconfig_set(bpy.utils.preset_find('blender', 'keyconfig'))"); - } } } else { diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 6078f0b92ce..4032f47eec2 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -259,24 +259,40 @@ static void wm_keymap_diff_item_free(wmKeyMapDiffItem *kmdi) * List of keymaps for all editors, modes, ... . There is a builtin default key * configuration, a user key configuration, and other preset configurations. */ -wmKeyConfig *WM_keyconfig_new(wmWindowManager *wm, const char *idname) -{ - wmKeyConfig *keyconf; +wmKeyConfig *WM_keyconfig_new(wmWindowManager *wm, const char *idname, bool user_defined) +{ + wmKeyConfig *keyconf = BLI_findstring(&wm->keyconfigs, idname, offsetof(wmKeyConfig, idname)); + if (keyconf) { + if (keyconf == wm->defaultconf) { + /* For default configuration, we need to keep keymap + * modal items and poll functions intact. */ + for (wmKeyMap *km = keyconf->keymaps.first; km; km = km->next) { + WM_keymap_clear(km); + } + } + else { + /* For user defined key configuration, clear all keymaps. */ + WM_keyconfig_clear(keyconf); + } + return keyconf; + } + + /* Create new configuration. */ keyconf = MEM_callocN(sizeof(wmKeyConfig), "wmKeyConfig"); BLI_strncpy(keyconf->idname, idname, sizeof(keyconf->idname)); BLI_addtail(&wm->keyconfigs, keyconf); + if (user_defined) { + keyconf->flag |= KEYCONF_USER; + } + return keyconf; } wmKeyConfig *WM_keyconfig_new_user(wmWindowManager *wm, const char *idname) { - wmKeyConfig *keyconf = WM_keyconfig_new(wm, idname); - - keyconf->flag |= KEYCONF_USER; - - return keyconf; + return WM_keyconfig_new(wm, idname, true); } bool WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf) @@ -297,15 +313,18 @@ bool WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf) } } -void WM_keyconfig_free(wmKeyConfig *keyconf) +void WM_keyconfig_clear(wmKeyConfig *keyconf) { - wmKeyMap *km; - - while ((km = keyconf->keymaps.first)) { - WM_keymap_free(km); - BLI_freelinkN(&keyconf->keymaps, km); + for (wmKeyMap *km = keyconf->keymaps.first; km; km = km->next) { + WM_keymap_clear(km); } + BLI_freelistN(&keyconf->keymaps); +} + +void WM_keyconfig_free(wmKeyConfig *keyconf) +{ + WM_keyconfig_clear(keyconf); MEM_freeN(keyconf); } @@ -379,7 +398,7 @@ static wmKeyMap *wm_keymap_copy(wmKeyMap *keymap) return keymapn; } -void WM_keymap_free(wmKeyMap *keymap) +void WM_keymap_clear(wmKeyMap *keymap) { wmKeyMapItem *kmi; wmKeyMapDiffItem *kmdi; @@ -398,7 +417,7 @@ bool WM_keymap_remove(wmKeyConfig *keyconf, wmKeyMap *keymap) { if (BLI_findindex(&keyconf->keymaps, keymap) != -1) { - WM_keymap_free(keymap); + WM_keymap_clear(keymap); BLI_remlink(&keyconf->keymaps, keymap); MEM_freeN(keymap); @@ -665,7 +684,7 @@ static wmKeyMap *wm_keymap_patch_update(ListBase *lb, wmKeyMap *defaultmap, wmKe km = WM_keymap_list_find(lb, defaultmap->idname, defaultmap->spaceid, defaultmap->regionid); if (km) { expanded = (km->flag & (KEYMAP_EXPANDED | KEYMAP_CHILDREN_EXPANDED)); - WM_keymap_free(km); + WM_keymap_clear(km); BLI_freelinkN(lb, km); } @@ -728,7 +747,7 @@ static void wm_keymap_diff_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap * /* remove previous diff keymap in list, we will replace it */ prevmap = WM_keymap_list_find(lb, km->idname, km->spaceid, km->regionid); if (prevmap) { - WM_keymap_free(prevmap); + WM_keymap_clear(prevmap); BLI_freelinkN(lb, prevmap); } @@ -744,13 +763,13 @@ static void wm_keymap_diff_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap * BLI_addtail(lb, diffmap); } else { - WM_keymap_free(diffmap); + WM_keymap_clear(diffmap); MEM_freeN(diffmap); } /* free temporary default map */ if (addonmap) { - WM_keymap_free(defaultmap); + WM_keymap_clear(defaultmap); MEM_freeN(defaultmap); } } @@ -1630,7 +1649,7 @@ void WM_keymap_restore_item_to_default(bContext *C, wmKeyMap *keymap, wmKeyMapIt /* free temporary keymap */ if (addonmap) { - WM_keymap_free(defaultmap); + WM_keymap_clear(defaultmap); MEM_freeN(defaultmap); } } @@ -1644,7 +1663,7 @@ void WM_keymap_restore_to_default(wmKeyMap *keymap, bContext *C) usermap = WM_keymap_list_find(&U.user_keymaps, keymap->idname, keymap->spaceid, keymap->regionid); if (usermap) { - WM_keymap_free(usermap); + WM_keymap_clear(usermap); BLI_freelinkN(&U.user_keymaps, usermap); WM_keyconfig_update_tag(NULL, NULL); -- cgit v1.2.3