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 wm
19 *
20 * Utilities to help define keymaps.
21 */
22
23 #include <string.h>
24
25 #include "DNA_object_types.h"
26 #include "DNA_space_types.h"
27 #include "DNA_userdef_types.h"
28 #include "DNA_windowmanager_types.h"
29
30 #include "BLI_listbase.h"
31 #include "BLI_utildefines.h"
32
33 #include "BKE_context.h"
34
35 #include "RNA_access.h"
36
37 #include "WM_api.h"
38 #include "WM_types.h"
39
40 /* menu wrapper for WM_keymap_add_item */
41
42 /* -------------------------------------------------------------------- */
43 /** \name Wrappers for #WM_keymap_add_item
44 * \{ */
45
46 /* menu wrapper for WM_keymap_add_item */
WM_keymap_add_menu(wmKeyMap * keymap,const char * idname,int type,int val,int modifier,int keymodifier)47 wmKeyMapItem *WM_keymap_add_menu(
48 wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
49 {
50 wmKeyMapItem *kmi = WM_keymap_add_item(
51 keymap, "WM_OT_call_menu", type, val, modifier, keymodifier);
52 RNA_string_set(kmi->ptr, "name", idname);
53 return kmi;
54 }
55
WM_keymap_add_menu_pie(wmKeyMap * keymap,const char * idname,int type,int val,int modifier,int keymodifier)56 wmKeyMapItem *WM_keymap_add_menu_pie(
57 wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
58 {
59 wmKeyMapItem *kmi = WM_keymap_add_item(
60 keymap, "WM_OT_call_menu_pie", type, val, modifier, keymodifier);
61 RNA_string_set(kmi->ptr, "name", idname);
62 return kmi;
63 }
64
WM_keymap_add_panel(wmKeyMap * keymap,const char * idname,int type,int val,int modifier,int keymodifier)65 wmKeyMapItem *WM_keymap_add_panel(
66 wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
67 {
68 wmKeyMapItem *kmi = WM_keymap_add_item(
69 keymap, "WM_OT_call_panel", type, val, modifier, keymodifier);
70 RNA_string_set(kmi->ptr, "name", idname);
71 /* TODO: we might want to disable this. */
72 RNA_boolean_set(kmi->ptr, "keep_open", false);
73 return kmi;
74 }
75
76 /* tool wrapper for WM_keymap_add_item */
WM_keymap_add_tool(wmKeyMap * keymap,const char * idname,int type,int val,int modifier,int keymodifier)77 wmKeyMapItem *WM_keymap_add_tool(
78 wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier)
79 {
80 wmKeyMapItem *kmi = WM_keymap_add_item(
81 keymap, "WM_OT_tool_set_by_id", type, val, modifier, keymodifier);
82 RNA_string_set(kmi->ptr, "name", idname);
83 return kmi;
84 }
85
86 /** Useful for mapping numbers to an enum. */
WM_keymap_add_context_enum_set_items(wmKeyMap * keymap,const EnumPropertyItem * items,const char * data_path,int type_start,int val,int modifier,int keymodifier)87 void WM_keymap_add_context_enum_set_items(wmKeyMap *keymap,
88 const EnumPropertyItem *items,
89 const char *data_path,
90 int type_start,
91 int val,
92 int modifier,
93 int keymodifier)
94 {
95 for (int i = 0, type_offset = 0; items[i].identifier; i++) {
96 if (items[i].identifier[0] == '\0') {
97 continue;
98 }
99 wmKeyMapItem *kmi = WM_keymap_add_item(
100 keymap, "WM_OT_context_set_enum", type_start + type_offset, val, modifier, keymodifier);
101 RNA_string_set(kmi->ptr, "data_path", data_path);
102 RNA_string_set(kmi->ptr, "value", items[i].identifier);
103 type_offset += 1;
104 }
105 }
106
107 /** \} */
108
109 /* -------------------------------------------------------------------- */
110 /** \name Introspection
111 * \{ */
112
WM_keymap_guess_from_context(const bContext * C)113 wmKeyMap *WM_keymap_guess_from_context(const bContext *C)
114 {
115 SpaceLink *sl = CTX_wm_space_data(C);
116 const char *km_id = NULL;
117 if (sl->spacetype == SPACE_VIEW3D) {
118 const enum eContextObjectMode mode = CTX_data_mode_enum(C);
119 switch (mode) {
120 case CTX_MODE_EDIT_MESH:
121 km_id = "Mesh";
122 break;
123 case CTX_MODE_EDIT_CURVE:
124 km_id = "Curve";
125 break;
126 case CTX_MODE_EDIT_SURFACE:
127 km_id = "Curve";
128 break;
129 case CTX_MODE_EDIT_TEXT:
130 km_id = "Font";
131 break;
132 case CTX_MODE_EDIT_ARMATURE:
133 km_id = "Armature";
134 break;
135 case CTX_MODE_EDIT_METABALL:
136 km_id = "Metaball";
137 break;
138 case CTX_MODE_EDIT_LATTICE:
139 km_id = "Lattice";
140 break;
141 case CTX_MODE_POSE:
142 km_id = "Pose";
143 break;
144 case CTX_MODE_SCULPT:
145 km_id = "Sculpt";
146 break;
147 case CTX_MODE_PAINT_WEIGHT:
148 km_id = "Weight Paint";
149 break;
150 case CTX_MODE_PAINT_VERTEX:
151 km_id = "Vertex Paint";
152 break;
153 case CTX_MODE_PAINT_TEXTURE:
154 km_id = "Image Paint";
155 break;
156 case CTX_MODE_PARTICLE:
157 km_id = "Particle";
158 break;
159 case CTX_MODE_OBJECT:
160 km_id = "Object Mode";
161 break;
162 case CTX_MODE_PAINT_GPENCIL:
163 km_id = "Grease Pencil Stroke Paint Mode";
164 break;
165 case CTX_MODE_EDIT_GPENCIL:
166 km_id = "Grease Pencil Stroke Edit Mode";
167 break;
168 case CTX_MODE_SCULPT_GPENCIL:
169 km_id = "Grease Pencil Stroke Sculpt Mode";
170 break;
171 case CTX_MODE_WEIGHT_GPENCIL:
172 km_id = "Grease Pencil Stroke Weight Mode";
173 break;
174 case CTX_MODE_VERTEX_GPENCIL:
175 km_id = "Grease Pencil Stroke Vertex Mode";
176 break;
177 }
178 }
179 else if (sl->spacetype == SPACE_IMAGE) {
180 const SpaceImage *sima = (SpaceImage *)sl;
181 const eSpaceImage_Mode mode = sima->mode;
182 switch (mode) {
183 case SI_MODE_VIEW:
184 km_id = "Image";
185 break;
186 case SI_MODE_PAINT:
187 km_id = "Image Paint";
188 break;
189 case SI_MODE_MASK:
190 km_id = "Mask Editing";
191 break;
192 case SI_MODE_UV:
193 km_id = "UV Editor";
194 break;
195 }
196 }
197 else {
198 return NULL;
199 }
200
201 wmKeyMap *km = WM_keymap_find_all(CTX_wm_manager(C), km_id, 0, 0);
202 BLI_assert(km);
203 return km;
204 }
205
206 /* Guess an appropriate keymap from the operator name */
207 /* Needs to be kept up to date with Keymap and Operator naming */
WM_keymap_guess_opname(const bContext * C,const char * opname)208 wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
209 {
210 /* Op types purposely skipped for now:
211 * BRUSH_OT
212 * BOID_OT
213 * BUTTONS_OT
214 * CONSTRAINT_OT
215 * PAINT_OT
216 * ED_OT
217 * FLUID_OT
218 * TEXTURE_OT
219 * UI_OT
220 * WORLD_OT
221 */
222
223 wmKeyMap *km = NULL;
224 wmWindowManager *wm = CTX_wm_manager(C);
225 SpaceLink *sl = CTX_wm_space_data(C);
226
227 /* Window */
228 if (STRPREFIX(opname, "WM_OT") || STRPREFIX(opname, "ED_OT_undo")) {
229 if (STREQ(opname, "WM_OT_tool_set_by_id")) {
230 km = WM_keymap_guess_from_context(C);
231 }
232
233 if (km == NULL) {
234 km = WM_keymap_find_all(wm, "Window", 0, 0);
235 }
236 }
237 /* Screen & Render */
238 else if (STRPREFIX(opname, "SCREEN_OT") || STRPREFIX(opname, "RENDER_OT") ||
239 STRPREFIX(opname, "SOUND_OT") || STRPREFIX(opname, "SCENE_OT")) {
240 km = WM_keymap_find_all(wm, "Screen", 0, 0);
241 }
242 /* Grease Pencil */
243 else if (STRPREFIX(opname, "GPENCIL_OT")) {
244 km = WM_keymap_find_all(wm, "Grease Pencil", 0, 0);
245 }
246 /* Markers */
247 else if (STRPREFIX(opname, "MARKER_OT")) {
248 km = WM_keymap_find_all(wm, "Markers", 0, 0);
249 }
250 /* Import/Export*/
251 else if (STRPREFIX(opname, "IMPORT_") || STRPREFIX(opname, "EXPORT_")) {
252 km = WM_keymap_find_all(wm, "Window", 0, 0);
253 }
254
255 /* 3D View */
256 else if (STRPREFIX(opname, "VIEW3D_OT")) {
257 km = WM_keymap_find_all(wm, "3D View", sl->spacetype, 0);
258 }
259 else if (STRPREFIX(opname, "OBJECT_OT")) {
260 /* exception, this needs to work outside object mode too */
261 if (STRPREFIX(opname, "OBJECT_OT_mode_set")) {
262 km = WM_keymap_find_all(wm, "Object Non-modal", 0, 0);
263 }
264 else {
265 km = WM_keymap_find_all(wm, "Object Mode", 0, 0);
266 }
267 }
268 /* Object mode related */
269 else if (STRPREFIX(opname, "GROUP_OT") || STRPREFIX(opname, "MATERIAL_OT") ||
270 STRPREFIX(opname, "PTCACHE_OT") || STRPREFIX(opname, "RIGIDBODY_OT")) {
271 km = WM_keymap_find_all(wm, "Object Mode", 0, 0);
272 }
273
274 /* Editing Modes */
275 else if (STRPREFIX(opname, "MESH_OT")) {
276 km = WM_keymap_find_all(wm, "Mesh", 0, 0);
277
278 /* some mesh operators are active in object mode too, like add-prim */
279 if (km && !WM_keymap_poll((bContext *)C, km)) {
280 km = WM_keymap_find_all(wm, "Object Mode", 0, 0);
281 }
282 }
283 else if (STRPREFIX(opname, "CURVE_OT") || STRPREFIX(opname, "SURFACE_OT")) {
284 km = WM_keymap_find_all(wm, "Curve", 0, 0);
285
286 /* some curve operators are active in object mode too, like add-prim */
287 if (km && !WM_keymap_poll((bContext *)C, km)) {
288 km = WM_keymap_find_all(wm, "Object Mode", 0, 0);
289 }
290 }
291 else if (STRPREFIX(opname, "ARMATURE_OT") || STRPREFIX(opname, "SKETCH_OT")) {
292 km = WM_keymap_find_all(wm, "Armature", 0, 0);
293 }
294 else if (STRPREFIX(opname, "POSE_OT") || STRPREFIX(opname, "POSELIB_OT")) {
295 km = WM_keymap_find_all(wm, "Pose", 0, 0);
296 }
297 else if (STRPREFIX(opname, "SCULPT_OT")) {
298 switch (CTX_data_mode_enum(C)) {
299 case CTX_MODE_SCULPT:
300 km = WM_keymap_find_all(wm, "Sculpt", 0, 0);
301 break;
302 default:
303 break;
304 }
305 }
306 else if (STRPREFIX(opname, "MBALL_OT")) {
307 km = WM_keymap_find_all(wm, "Metaball", 0, 0);
308
309 /* some mball operators are active in object mode too, like add-prim */
310 if (km && !WM_keymap_poll((bContext *)C, km)) {
311 km = WM_keymap_find_all(wm, "Object Mode", 0, 0);
312 }
313 }
314 else if (STRPREFIX(opname, "LATTICE_OT")) {
315 km = WM_keymap_find_all(wm, "Lattice", 0, 0);
316 }
317 else if (STRPREFIX(opname, "PARTICLE_OT")) {
318 km = WM_keymap_find_all(wm, "Particle", 0, 0);
319 }
320 else if (STRPREFIX(opname, "FONT_OT")) {
321 km = WM_keymap_find_all(wm, "Font", 0, 0);
322 }
323 /* Paint Face Mask */
324 else if (STRPREFIX(opname, "PAINT_OT_face_select")) {
325 km = WM_keymap_find_all(wm, "Paint Face Mask (Weight, Vertex, Texture)", 0, 0);
326 }
327 else if (STRPREFIX(opname, "PAINT_OT")) {
328 /* check for relevant mode */
329 switch (CTX_data_mode_enum(C)) {
330 case CTX_MODE_PAINT_WEIGHT:
331 km = WM_keymap_find_all(wm, "Weight Paint", 0, 0);
332 break;
333 case CTX_MODE_PAINT_VERTEX:
334 km = WM_keymap_find_all(wm, "Vertex Paint", 0, 0);
335 break;
336 case CTX_MODE_PAINT_TEXTURE:
337 km = WM_keymap_find_all(wm, "Image Paint", 0, 0);
338 break;
339 case CTX_MODE_SCULPT:
340 km = WM_keymap_find_all(wm, "Sculpt", 0, 0);
341 break;
342 default:
343 break;
344 }
345 }
346 /* General 2D View, not bound to a specific spacetype. */
347 else if (STRPREFIX(opname, "VIEW2D_OT")) {
348 km = WM_keymap_find_all(wm, "View2D", 0, 0);
349 }
350 /* Image Editor */
351 else if (STRPREFIX(opname, "IMAGE_OT")) {
352 km = WM_keymap_find_all(wm, "Image", sl->spacetype, 0);
353 }
354 /* Clip Editor */
355 else if (STRPREFIX(opname, "CLIP_OT")) {
356 km = WM_keymap_find_all(wm, "Clip", sl->spacetype, 0);
357 }
358 else if (STRPREFIX(opname, "MASK_OT")) {
359 km = WM_keymap_find_all(wm, "Mask Editing", 0, 0);
360 }
361 /* UV Editor */
362 else if (STRPREFIX(opname, "UV_OT")) {
363 /* Hack to allow using UV unwrapping ops from 3DView/editmode.
364 * Mesh keymap is probably not ideal, but best place I could find to put those. */
365 if (sl->spacetype == SPACE_VIEW3D) {
366 km = WM_keymap_find_all(wm, "Mesh", 0, 0);
367 if (km && !WM_keymap_poll((bContext *)C, km)) {
368 km = NULL;
369 }
370 }
371 if (!km) {
372 km = WM_keymap_find_all(wm, "UV Editor", 0, 0);
373 }
374 }
375 /* Node Editor */
376 else if (STRPREFIX(opname, "NODE_OT")) {
377 km = WM_keymap_find_all(wm, "Node Editor", sl->spacetype, 0);
378 }
379 /* Animation Editor Channels */
380 else if (STRPREFIX(opname, "ANIM_OT_channels")) {
381 km = WM_keymap_find_all(wm, "Animation Channels", 0, 0);
382 }
383 /* Animation Generic - after channels */
384 else if (STRPREFIX(opname, "ANIM_OT")) {
385 if (sl->spacetype == SPACE_VIEW3D) {
386 switch (CTX_data_mode_enum(C)) {
387 case CTX_MODE_OBJECT:
388 km = WM_keymap_find_all(wm, "Object Mode", 0, 0);
389 break;
390 case CTX_MODE_POSE:
391 km = WM_keymap_find_all(wm, "Pose", 0, 0);
392 break;
393 default:
394 break;
395 }
396 if (km && !WM_keymap_poll((bContext *)C, km)) {
397 km = NULL;
398 }
399 }
400
401 if (!km) {
402 km = WM_keymap_find_all(wm, "Animation", 0, 0);
403 }
404 }
405 /* Graph Editor */
406 else if (STRPREFIX(opname, "GRAPH_OT")) {
407 km = WM_keymap_find_all(wm, "Graph Editor", sl->spacetype, 0);
408 }
409 /* Dopesheet Editor */
410 else if (STRPREFIX(opname, "ACTION_OT")) {
411 km = WM_keymap_find_all(wm, "Dopesheet", sl->spacetype, 0);
412 }
413 /* NLA Editor */
414 else if (STRPREFIX(opname, "NLA_OT")) {
415 km = WM_keymap_find_all(wm, "NLA Editor", sl->spacetype, 0);
416 }
417 /* Script */
418 else if (STRPREFIX(opname, "SCRIPT_OT")) {
419 km = WM_keymap_find_all(wm, "Script", sl->spacetype, 0);
420 }
421 /* Text */
422 else if (STRPREFIX(opname, "TEXT_OT")) {
423 km = WM_keymap_find_all(wm, "Text", sl->spacetype, 0);
424 }
425 /* Sequencer */
426 else if (STRPREFIX(opname, "SEQUENCER_OT")) {
427 km = WM_keymap_find_all(wm, "Sequencer", sl->spacetype, 0);
428 }
429 /* Console */
430 else if (STRPREFIX(opname, "CONSOLE_OT")) {
431 km = WM_keymap_find_all(wm, "Console", sl->spacetype, 0);
432 }
433 /* Console */
434 else if (STRPREFIX(opname, "INFO_OT")) {
435 km = WM_keymap_find_all(wm, "Info", sl->spacetype, 0);
436 }
437 /* File browser */
438 else if (STRPREFIX(opname, "FILE_OT")) {
439 km = WM_keymap_find_all(wm, "File Browser", sl->spacetype, 0);
440 }
441 /* Logic Editor */
442 else if (STRPREFIX(opname, "LOGIC_OT")) {
443 km = WM_keymap_find_all(wm, "Logic Editor", sl->spacetype, 0);
444 }
445 /* Outliner */
446 else if (STRPREFIX(opname, "OUTLINER_OT")) {
447 km = WM_keymap_find_all(wm, "Outliner", sl->spacetype, 0);
448 }
449 /* Transform */
450 else if (STRPREFIX(opname, "TRANSFORM_OT")) {
451 /* check for relevant editor */
452 switch (sl->spacetype) {
453 case SPACE_VIEW3D:
454 km = WM_keymap_find_all(wm, "3D View", sl->spacetype, 0);
455 break;
456 case SPACE_GRAPH:
457 km = WM_keymap_find_all(wm, "Graph Editor", sl->spacetype, 0);
458 break;
459 case SPACE_ACTION:
460 km = WM_keymap_find_all(wm, "Dopesheet", sl->spacetype, 0);
461 break;
462 case SPACE_NLA:
463 km = WM_keymap_find_all(wm, "NLA Editor", sl->spacetype, 0);
464 break;
465 case SPACE_IMAGE:
466 km = WM_keymap_find_all(wm, "UV Editor", 0, 0);
467 break;
468 case SPACE_NODE:
469 km = WM_keymap_find_all(wm, "Node Editor", sl->spacetype, 0);
470 break;
471 case SPACE_SEQ:
472 km = WM_keymap_find_all(wm, "Sequencer", sl->spacetype, 0);
473 break;
474 }
475 }
476
477 return km;
478 }
479
wm_keymap_item_uses_modifier(wmKeyMapItem * kmi,const int event_modifier)480 static bool wm_keymap_item_uses_modifier(wmKeyMapItem *kmi, const int event_modifier)
481 {
482 if (kmi->ctrl != KM_ANY) {
483 if ((kmi->ctrl == KM_NOTHING) != ((event_modifier & KM_CTRL) == 0)) {
484 return false;
485 }
486 }
487
488 if (kmi->alt != KM_ANY) {
489 if ((kmi->alt == KM_NOTHING) != ((event_modifier & KM_ALT) == 0)) {
490 return false;
491 }
492 }
493
494 if (kmi->shift != KM_ANY) {
495 if ((kmi->shift == KM_NOTHING) != ((event_modifier & KM_SHIFT) == 0)) {
496 return false;
497 }
498 }
499
500 if (kmi->oskey != KM_ANY) {
501 if ((kmi->oskey == KM_NOTHING) != ((event_modifier & KM_OSKEY) == 0)) {
502 return false;
503 }
504 }
505 return true;
506 }
507
WM_keymap_uses_event_modifier(wmKeyMap * keymap,const int event_modifier)508 bool WM_keymap_uses_event_modifier(wmKeyMap *keymap, const int event_modifier)
509 {
510 LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) {
511 if ((kmi->flag & KMI_INACTIVE) == 0) {
512 if (wm_keymap_item_uses_modifier(kmi, event_modifier)) {
513 return true;
514 }
515 }
516 }
517 return false;
518 }
519
WM_keymap_fix_linking(void)520 void WM_keymap_fix_linking(void)
521 {
522 }
523
524 /** \} */
525