Keymaps: refactor loading of default keymap, fix bugs.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Mon, 12 Nov 2018 13:53:08 +0000 (14:53 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Tue, 13 Nov 2018 17:22:07 +0000 (18:22 +0100)
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
release/scripts/presets/keyconfig/blender_27x.py
source/blender/windowmanager/WM_keymap.h
source/blender/windowmanager/intern/wm.c
source/blender/windowmanager/intern/wm_files.c
source/blender/windowmanager/intern/wm_keymap.c

index b76050395da6b68a594af725bcf14a8d0d10977e..835cbe6c110a9c461743e4021213db315cbdb76c 100644 (file)
@@ -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
 
index 2d9ea9d8f441611d018fbb1e329ec6b57b5d8840..69d84639a867cd04ceafe12c4846c00737dd7552 100644 (file)
@@ -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)
index b27d6b44ab07cf48e7cdc5e4b2d8883ea8600fe1..71037ab162e3934d7849e8a9a4f92843dd7ebfc1 100644 (file)
@@ -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,
index cf7c43ff5c0726513b0a69d62150f44dada198a0..bc9c1e263cbc23db050bccb3c441e19c0029aa11 100644 (file)
@@ -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;
                }
 
index f7971ed1b643192928993a163fc2f1b3cb4ff291..318147e8c250ba1520d931ed2787334013b4c059 100644 (file)
@@ -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 {
index 6078f0b92ce6ea5565c0a65d9f50285cef26f9fc..4032f47eec2a6be4a27d091359165aa64a9dec29 100644 (file)
@@ -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);