[Bf-blender-cvs] [e7895bac07f] blender2.8: UI: support for custom keymaps for popovers

Campbell Barton noreply at git.blender.org
Sun May 20 22:39:50 CEST 2018


Commit: e7895bac07f32d4f66184aff2ed2c08956daaac7
Author: Campbell Barton
Date:   Sun May 20 22:34:18 2018 +0200
Branches: blender2.8
https://developer.blender.org/rBe7895bac07f32d4f66184aff2ed2c08956daaac7

UI: support for custom keymaps for popovers

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

M	release/scripts/modules/bpy_types.py
M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/interface_region_popover.c
M	source/blender/makesrna/intern/rna_wm_api.c
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/intern/wm_event_system.c
M	source/blender/windowmanager/intern/wm_keymap.c
M	source/blender/windowmanager/wm_event_system.h

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

diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 04bb6495ece..3a9704b12e9 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -144,14 +144,14 @@ class WindowManager(bpy_types.ID):
         finally:
             self.popmenu_end__internal(popup)
 
-    def popover(self, draw_func):
+    def popover(self, draw_func, keymap=None):
         import bpy
         popup = self.popover_begin__internal()
 
         try:
             draw_func(popup, bpy.context)
         finally:
-            self.popover_end__internal(popup)
+            self.popover_end__internal(popup, keymap)
 
     def popup_menu_pie(self, event, draw_func, title="", icon='NONE'):
         import bpy
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 417aca1210e..47ecbca227b 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -74,6 +74,7 @@ struct wmDrag;
 struct wmEvent;
 struct wmManipulator;
 struct wmMsgBus;
+struct wmKeyMap;
 
 typedef struct uiBut uiBut;
 typedef struct uiBlock uiBlock;
@@ -427,8 +428,8 @@ void UI_popup_menu_but_set(uiPopupMenu *pup, struct ARegion *butregion, uiBut *b
 
 typedef struct uiPopover uiPopover;
 
-uiPopover *UI_popover_begin(struct bContext *C) ATTR_NONNULL();
-void UI_popover_end(struct bContext *C, struct uiPopover *head);
+uiPopover *UI_popover_begin(struct bContext *C) ATTR_NONNULL(1);
+void UI_popover_end(struct bContext *C, struct uiPopover *head, struct wmKeyMap *keymap);
 struct uiLayout *UI_popover_layout(uiPopover *head);
 void UI_popover_once_clear(uiPopover *pup);
 
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c
index 2f654b4f7cd..4aeb9a6d00b 100644
--- a/source/blender/editors/interface/interface_region_popover.c
+++ b/source/blender/editors/interface/interface_region_popover.c
@@ -77,6 +77,11 @@ struct uiPopover {
 	uiLayout *layout;
 	uiBut *but;
 
+	/* Needed for keymap removal. */
+	wmWindow *window;
+	wmKeyMap *keymap;
+	struct wmEventHandler *keymap_handler;
+
 	uiMenuCreateFunc menu_func;
 	void *menu_arg;
 
@@ -204,6 +209,10 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
 static void ui_block_free_func_POPOVER(uiPopupBlockHandle *UNUSED(handle), void *arg_pup)
 {
 	uiPopover *pup = arg_pup;
+	if (pup->keymap != NULL) {
+		wmWindow *window = pup->window;
+		WM_event_remove_keymap_handler(&window->modalhandlers, pup->keymap);
+	}
 	MEM_freeN(pup);
 }
 
@@ -261,22 +270,44 @@ uiPopover *UI_popover_begin(bContext *C)
 	return pup;
 }
 
+static void popover_keymap_fn(wmKeyMap *UNUSED(keymap), wmKeyMapItem *UNUSEDF(kmi), void *user_data)
+{
+	uiPopover *pup = user_data;
+	pup->block->handle->menuretval = UI_RETURN_OK;
+}
+
 /* set the whole structure to work */
-void UI_popover_end(bContext *C, uiPopover *pup)
+void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap)
 {
+	wmWindow *window = CTX_wm_window(C);
 	/* Create popup block. No refresh support since the buttons were created
 	 * between begin/end and we have no callback to recreate them. */
 	uiPopupBlockHandle *handle;
 
+	if (keymap) {
+		/* Add so we get keymaps shown in the buttons. */
+		UI_block_flag_enable(pup->block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS);
+		pup->keymap = keymap;
+		pup->keymap_handler = WM_event_add_keymap_handler_priority(&window->modalhandlers, keymap, 0);
+		WM_event_set_keymap_handler_callback(pup->keymap_handler, popover_keymap_fn, pup);
+	}
+
 	handle = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPOVER, pup);
 	handle->popup_create_vars.free_func = ui_block_free_func_POPOVER;
 
 	/* Add handlers. */
-	wmWindow *window = CTX_wm_window(C);
 	UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
 	WM_event_add_mousemove(C);
 	handle->popup = true;
 
+	/* Re-add so it gets priority. */
+	if (keymap) {
+		BLI_remlink(&window->modalhandlers, pup->keymap_handler);
+		BLI_addhead(&window->modalhandlers, pup->keymap_handler);
+	}
+
+	pup->window = window;
+
 	/* TODO(campbell): we may want to make this configurable.
 	 * The begin/end stype of calling popups doesn't allow to 'can_refresh' to be set.
 	 * For now close this style of popvers when accessed. */
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index a08a1846c5b..dc9c0223f6b 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -361,9 +361,9 @@ static PointerRNA rna_PopoverBegin(bContext *C)
 	return r_ptr;
 }
 
-static void rna_PopoverEnd(bContext *C, PointerRNA *handle)
+static void rna_PopoverEnd(bContext *C, PointerRNA *handle, wmKeyMap *keymap)
 {
-	UI_popover_end(C, handle->data);
+	UI_popover_end(C, handle->data, keymap);
 }
 
 /* pie menu wrapper */
@@ -585,6 +585,7 @@ void RNA_api_wm(StructRNA *srna)
 	RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
 	parm = RNA_def_pointer(func, "menu", "UIPopover", "", "");
 	RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_RNAPTR);
+	RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Active key map");
 
 
 	/* wrap uiPieMenuBegin */
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index e6b045bc249..050edb980e9 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -191,6 +191,11 @@ struct wmEventHandler *WM_event_add_keymap_handler_priority(ListBase *handlers,
 
 void		WM_event_remove_keymap_handler(ListBase *handlers, wmKeyMap *keymap);
 
+void WM_event_set_keymap_handler_callback(
+        struct wmEventHandler *handler,
+        void (keymap_tag)(wmKeyMap *keymap, wmKeyMapItem *kmi, void *user_data),
+        void *user_data);
+
 typedef int (*wmUIHandlerFunc)(struct bContext *C, const struct wmEvent *event, void *userdata);
 typedef void (*wmUIHandlerRemoveFunc)(struct bContext *C, void *userdata);
 
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index d38416e490d..46ea5bc137e 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -2262,6 +2262,9 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
 							if (action & WM_HANDLER_BREAK) {
 								/* not always_pass here, it denotes removed handler */
 								CLOG_INFO(WM_LOG_HANDLERS, 2, "handled! '%s'", kmi->idname);
+								if (handler->keymap_callback != NULL) {
+									handler->keymap_callback(keymap, kmi, handler->keymap_callback_user_data);
+								}
 								break;
 							}
 							else {
@@ -3166,6 +3169,15 @@ void WM_event_remove_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
 	}
 }
 
+void WM_event_set_keymap_handler_callback(
+        wmEventHandler *handler,
+        void (keymap_tag)(wmKeyMap *keymap, wmKeyMapItem *kmi, void *user_data),
+        void *user_data)
+{
+	handler->keymap_callback = keymap_tag;
+	handler->keymap_callback_user_data = user_data;
+}
+
 wmEventHandler *WM_event_add_ui_handler(
         const bContext *C, ListBase *handlers,
         wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove,
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index 63f81ca66c9..9d26c7e92d5 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -1214,8 +1214,12 @@ static wmKeyMapItem *wm_keymap_item_find_props(
 	wmKeyMapItem *found = NULL;
 
 	/* look into multiple handler lists to find the item */
-	if (win)
-		found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
+	if (win) {
+		found = wm_keymap_item_find_handlers(C, &win->modalhandlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
+		if (found == NULL) {
+			found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
+		}
+	}
 
 	if (sa && found == NULL)
 		found = wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index c14517f1662..452fe377665 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -51,6 +51,9 @@ typedef struct wmEventHandler {
 	/* keymap handler */
 	wmKeyMap *keymap;                   /* pointer to builtin/custom keymaps */
 	const rcti *bblocal, *bbwin;              /* optional local and windowspace bb */
+	/* Run after the keymap item runs. */
+	void (*keymap_callback)(wmKeyMap *keymap, wmKeyMapItem *kmi, void *user_data);
+	void  *keymap_callback_user_data;
 
 	/* modal operator handler */
 	wmOperator *op;                     /* for derived/modal handlers */



More information about the Bf-blender-cvs mailing list