UI: support for custom keymaps for popovers
This commit is contained in:
@@ -144,14 +144,14 @@ class WindowManager(bpy_types.ID):
|
|||||||
finally:
|
finally:
|
||||||
self.popmenu_end__internal(popup)
|
self.popmenu_end__internal(popup)
|
||||||
|
|
||||||
def popover(self, draw_func):
|
def popover(self, draw_func, keymap=None):
|
||||||
import bpy
|
import bpy
|
||||||
popup = self.popover_begin__internal()
|
popup = self.popover_begin__internal()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
draw_func(popup, bpy.context)
|
draw_func(popup, bpy.context)
|
||||||
finally:
|
finally:
|
||||||
self.popover_end__internal(popup)
|
self.popover_end__internal(popup, keymap)
|
||||||
|
|
||||||
def popup_menu_pie(self, event, draw_func, title="", icon='NONE'):
|
def popup_menu_pie(self, event, draw_func, title="", icon='NONE'):
|
||||||
import bpy
|
import bpy
|
||||||
|
@@ -74,6 +74,7 @@ struct wmDrag;
|
|||||||
struct wmEvent;
|
struct wmEvent;
|
||||||
struct wmManipulator;
|
struct wmManipulator;
|
||||||
struct wmMsgBus;
|
struct wmMsgBus;
|
||||||
|
struct wmKeyMap;
|
||||||
|
|
||||||
typedef struct uiBut uiBut;
|
typedef struct uiBut uiBut;
|
||||||
typedef struct uiBlock uiBlock;
|
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;
|
typedef struct uiPopover uiPopover;
|
||||||
|
|
||||||
uiPopover *UI_popover_begin(struct bContext *C) ATTR_NONNULL();
|
uiPopover *UI_popover_begin(struct bContext *C) ATTR_NONNULL(1);
|
||||||
void UI_popover_end(struct bContext *C, struct uiPopover *head);
|
void UI_popover_end(struct bContext *C, struct uiPopover *head, struct wmKeyMap *keymap);
|
||||||
struct uiLayout *UI_popover_layout(uiPopover *head);
|
struct uiLayout *UI_popover_layout(uiPopover *head);
|
||||||
void UI_popover_once_clear(uiPopover *pup);
|
void UI_popover_once_clear(uiPopover *pup);
|
||||||
|
|
||||||
|
@@ -77,6 +77,11 @@ struct uiPopover {
|
|||||||
uiLayout *layout;
|
uiLayout *layout;
|
||||||
uiBut *but;
|
uiBut *but;
|
||||||
|
|
||||||
|
/* Needed for keymap removal. */
|
||||||
|
wmWindow *window;
|
||||||
|
wmKeyMap *keymap;
|
||||||
|
struct wmEventHandler *keymap_handler;
|
||||||
|
|
||||||
uiMenuCreateFunc menu_func;
|
uiMenuCreateFunc menu_func;
|
||||||
void *menu_arg;
|
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)
|
static void ui_block_free_func_POPOVER(uiPopupBlockHandle *UNUSED(handle), void *arg_pup)
|
||||||
{
|
{
|
||||||
uiPopover *pup = 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);
|
MEM_freeN(pup);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,22 +270,44 @@ uiPopover *UI_popover_begin(bContext *C)
|
|||||||
return pup;
|
return pup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the whole structure to work */
|
static void popover_keymap_fn(wmKeyMap *UNUSED(keymap), wmKeyMapItem *UNUSEDF(kmi), void *user_data)
|
||||||
void UI_popover_end(bContext *C, uiPopover *pup)
|
|
||||||
{
|
{
|
||||||
|
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, wmKeyMap *keymap)
|
||||||
|
{
|
||||||
|
wmWindow *window = CTX_wm_window(C);
|
||||||
/* Create popup block. No refresh support since the buttons were created
|
/* Create popup block. No refresh support since the buttons were created
|
||||||
* between begin/end and we have no callback to recreate them. */
|
* between begin/end and we have no callback to recreate them. */
|
||||||
uiPopupBlockHandle *handle;
|
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 = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPOVER, pup);
|
||||||
handle->popup_create_vars.free_func = ui_block_free_func_POPOVER;
|
handle->popup_create_vars.free_func = ui_block_free_func_POPOVER;
|
||||||
|
|
||||||
/* Add handlers. */
|
/* Add handlers. */
|
||||||
wmWindow *window = CTX_wm_window(C);
|
|
||||||
UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
|
UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
|
||||||
WM_event_add_mousemove(C);
|
WM_event_add_mousemove(C);
|
||||||
handle->popup = true;
|
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.
|
/* 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.
|
* 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. */
|
* For now close this style of popvers when accessed. */
|
||||||
|
@@ -361,9 +361,9 @@ static PointerRNA rna_PopoverBegin(bContext *C)
|
|||||||
return r_ptr;
|
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 */
|
/* pie menu wrapper */
|
||||||
@@ -585,6 +585,7 @@ void RNA_api_wm(StructRNA *srna)
|
|||||||
RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
|
RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
|
||||||
parm = RNA_def_pointer(func, "menu", "UIPopover", "", "");
|
parm = RNA_def_pointer(func, "menu", "UIPopover", "", "");
|
||||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_RNAPTR);
|
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_RNAPTR);
|
||||||
|
RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Active key map");
|
||||||
|
|
||||||
|
|
||||||
/* wrap uiPieMenuBegin */
|
/* wrap uiPieMenuBegin */
|
||||||
|
@@ -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_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 int (*wmUIHandlerFunc)(struct bContext *C, const struct wmEvent *event, void *userdata);
|
||||||
typedef void (*wmUIHandlerRemoveFunc)(struct bContext *C, void *userdata);
|
typedef void (*wmUIHandlerRemoveFunc)(struct bContext *C, void *userdata);
|
||||||
|
|
||||||
|
@@ -2262,6 +2262,9 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
|
|||||||
if (action & WM_HANDLER_BREAK) {
|
if (action & WM_HANDLER_BREAK) {
|
||||||
/* not always_pass here, it denotes removed handler */
|
/* not always_pass here, it denotes removed handler */
|
||||||
CLOG_INFO(WM_LOG_HANDLERS, 2, "handled! '%s'", kmi->idname);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
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(
|
wmEventHandler *WM_event_add_ui_handler(
|
||||||
const bContext *C, ListBase *handlers,
|
const bContext *C, ListBase *handlers,
|
||||||
wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove,
|
wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove,
|
||||||
|
@@ -1214,8 +1214,12 @@ static wmKeyMapItem *wm_keymap_item_find_props(
|
|||||||
wmKeyMapItem *found = NULL;
|
wmKeyMapItem *found = NULL;
|
||||||
|
|
||||||
/* look into multiple handler lists to find the item */
|
/* look into multiple handler lists to find the item */
|
||||||
if (win)
|
if (win) {
|
||||||
found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
|
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)
|
if (sa && found == NULL)
|
||||||
found = wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
|
found = wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap);
|
||||||
|
@@ -51,6 +51,9 @@ typedef struct wmEventHandler {
|
|||||||
/* keymap handler */
|
/* keymap handler */
|
||||||
wmKeyMap *keymap; /* pointer to builtin/custom keymaps */
|
wmKeyMap *keymap; /* pointer to builtin/custom keymaps */
|
||||||
const rcti *bblocal, *bbwin; /* optional local and windowspace bb */
|
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 */
|
/* modal operator handler */
|
||||||
wmOperator *op; /* for derived/modal handlers */
|
wmOperator *op; /* for derived/modal handlers */
|
||||||
|
Reference in New Issue
Block a user