1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 */
16
17 /** \file
18 * \ingroup bke
19 */
20
21 #include <stddef.h>
22 #include <stdlib.h>
23
24 #include "RNA_types.h"
25
26 #include "BLI_ghash.h"
27 #include "BLI_listbase.h"
28 #include "BLI_string.h"
29 #include "BLI_utildefines.h"
30
31 #include "DNA_listBase.h"
32 #include "DNA_userdef_types.h"
33 #include "DNA_windowmanager_types.h"
34
35 #include "BKE_idprop.h"
36 #include "BKE_keyconfig.h" /* own include */
37
38 #include "MEM_guardedalloc.h"
39
40 /* -------------------------------------------------------------------- */
41 /** \name Key-Config Preference (UserDef) API
42 *
43 * \see #BKE_addon_pref_type_init for logic this is bases on.
44 * \{ */
45
BKE_keyconfig_pref_ensure(UserDef * userdef,const char * kc_idname)46 wmKeyConfigPref *BKE_keyconfig_pref_ensure(UserDef *userdef, const char *kc_idname)
47 {
48 wmKeyConfigPref *kpt = BLI_findstring(
49 &userdef->user_keyconfig_prefs, kc_idname, offsetof(wmKeyConfigPref, idname));
50 if (kpt == NULL) {
51 kpt = MEM_callocN(sizeof(*kpt), __func__);
52 STRNCPY(kpt->idname, kc_idname);
53 BLI_addtail(&userdef->user_keyconfig_prefs, kpt);
54 }
55 if (kpt->prop == NULL) {
56 IDPropertyTemplate val = {0};
57 kpt->prop = IDP_New(IDP_GROUP, &val, kc_idname); /* name is unimportant */
58 }
59 return kpt;
60 }
61
62 /** \} */
63
64 /* -------------------------------------------------------------------- */
65 /** \name Key-Config Preference (RNA Type) API
66 *
67 * \see #BKE_addon_pref_type_init for logic this is bases on.
68 * \{ */
69
70 static GHash *global_keyconfigpreftype_hash = NULL;
71
BKE_keyconfig_pref_type_find(const char * idname,bool quiet)72 wmKeyConfigPrefType_Runtime *BKE_keyconfig_pref_type_find(const char *idname, bool quiet)
73 {
74 if (idname[0]) {
75 wmKeyConfigPrefType_Runtime *kpt_rt;
76
77 kpt_rt = BLI_ghash_lookup(global_keyconfigpreftype_hash, idname);
78 if (kpt_rt) {
79 return kpt_rt;
80 }
81
82 if (!quiet) {
83 printf("search for unknown keyconfig-pref '%s'\n", idname);
84 }
85 }
86 else {
87 if (!quiet) {
88 printf("search for empty keyconfig-pref\n");
89 }
90 }
91
92 return NULL;
93 }
94
BKE_keyconfig_pref_type_add(wmKeyConfigPrefType_Runtime * kpt_rt)95 void BKE_keyconfig_pref_type_add(wmKeyConfigPrefType_Runtime *kpt_rt)
96 {
97 BLI_ghash_insert(global_keyconfigpreftype_hash, kpt_rt->idname, kpt_rt);
98 }
99
BKE_keyconfig_pref_type_remove(const wmKeyConfigPrefType_Runtime * kpt_rt)100 void BKE_keyconfig_pref_type_remove(const wmKeyConfigPrefType_Runtime *kpt_rt)
101 {
102 BLI_ghash_remove(global_keyconfigpreftype_hash, kpt_rt->idname, NULL, MEM_freeN);
103 }
104
BKE_keyconfig_pref_type_init(void)105 void BKE_keyconfig_pref_type_init(void)
106 {
107 BLI_assert(global_keyconfigpreftype_hash == NULL);
108 global_keyconfigpreftype_hash = BLI_ghash_str_new(__func__);
109 }
110
BKE_keyconfig_pref_type_free(void)111 void BKE_keyconfig_pref_type_free(void)
112 {
113 BLI_ghash_free(global_keyconfigpreftype_hash, NULL, MEM_freeN);
114 global_keyconfigpreftype_hash = NULL;
115 }
116
117 /** \} */
118
119 /* -------------------------------------------------------------------- */
120 /** \name Key-Config Versioning
121 * \{ */
122
123 /* Set select mouse, for versioning code. */
BKE_keyconfig_pref_set_select_mouse(UserDef * userdef,int value,bool override)124 void BKE_keyconfig_pref_set_select_mouse(UserDef *userdef, int value, bool override)
125 {
126 wmKeyConfigPref *kpt = BKE_keyconfig_pref_ensure(userdef, WM_KEYCONFIG_STR_DEFAULT);
127 IDProperty *idprop = IDP_GetPropertyFromGroup(kpt->prop, "select_mouse");
128 if (!idprop) {
129 IDPropertyTemplate tmp = {
130 .i = value,
131 };
132 IDP_AddToGroup(kpt->prop, IDP_New(IDP_INT, &tmp, "select_mouse"));
133 }
134 else if (override) {
135 IDP_Int(idprop) = value;
136 }
137 }
138
keymap_item_free(wmKeyMapItem * kmi)139 static void keymap_item_free(wmKeyMapItem *kmi)
140 {
141 IDP_FreeProperty(kmi->properties);
142 if (kmi->ptr) {
143 MEM_freeN(kmi->ptr);
144 }
145 MEM_freeN(kmi);
146 }
147
keymap_diff_item_free(wmKeyMapDiffItem * kmdi)148 static void keymap_diff_item_free(wmKeyMapDiffItem *kmdi)
149 {
150 if (kmdi->add_item) {
151 keymap_item_free(kmdi->add_item);
152 }
153 if (kmdi->remove_item) {
154 keymap_item_free(kmdi->remove_item);
155 }
156 MEM_freeN(kmdi);
157 }
158
BKE_keyconfig_keymap_filter_item(wmKeyMap * keymap,const struct wmKeyConfigFilterItemParams * params,bool (* filter_fn)(wmKeyMapItem * kmi,void * user_data),void * user_data)159 void BKE_keyconfig_keymap_filter_item(wmKeyMap *keymap,
160 const struct wmKeyConfigFilterItemParams *params,
161 bool (*filter_fn)(wmKeyMapItem *kmi, void *user_data),
162 void *user_data)
163 {
164 if (params->check_diff_item_add || params->check_diff_item_remove) {
165 for (wmKeyMapDiffItem *kmdi = keymap->diff_items.first, *kmdi_next; kmdi; kmdi = kmdi_next) {
166 kmdi_next = kmdi->next;
167 bool remove = false;
168
169 if (params->check_diff_item_add) {
170 if (kmdi->add_item) {
171 if (filter_fn(kmdi->add_item, user_data)) {
172 remove = true;
173 }
174 }
175 }
176
177 if (!remove && params->check_diff_item_remove) {
178 if (kmdi->remove_item) {
179 if (filter_fn(kmdi->remove_item, user_data)) {
180 remove = true;
181 }
182 }
183 }
184
185 if (remove) {
186 BLI_remlink(&keymap->diff_items, kmdi);
187 keymap_diff_item_free(kmdi);
188 }
189 }
190 }
191
192 if (params->check_item) {
193 for (wmKeyMapItem *kmi = keymap->items.first, *kmi_next; kmi; kmi = kmi_next) {
194 kmi_next = kmi->next;
195 if (filter_fn(kmi, user_data)) {
196 BLI_remlink(&keymap->items, kmi);
197 keymap_item_free(kmi);
198 }
199 }
200 }
201 }
202
203 /**
204 * Filter & optionally remove key-map items,
205 * intended for versioning, but may be used in other situations too.
206 */
BKE_keyconfig_pref_filter_items(struct UserDef * userdef,const struct wmKeyConfigFilterItemParams * params,bool (* filter_fn)(wmKeyMapItem * kmi,void * user_data),void * user_data)207 void BKE_keyconfig_pref_filter_items(struct UserDef *userdef,
208 const struct wmKeyConfigFilterItemParams *params,
209 bool (*filter_fn)(wmKeyMapItem *kmi, void *user_data),
210 void *user_data)
211 {
212 LISTBASE_FOREACH (wmKeyMap *, keymap, &userdef->user_keymaps) {
213 BKE_keyconfig_keymap_filter_item(keymap, params, filter_fn, user_data);
214 }
215 }
216
217 /** \} */
218