mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
XR: Decouple XR action operator handlers from main window handlers
This commit fixes a long standing issue within the Blender XR event handling where having any sort of modal handler running in the main Blender window (text editing, opened popup, modal operator, etc..) would block XR actions from occuring or completing. To reproduce the original issue, open a VR session in Blender, execute an action (such as teleportation), and observe that the operator will fail to execute or complete if a modal operation is currently occuring in the main window. This issue was fixed by: - Tagging XR operator handlers with a new `is_xr` boolean, set on creation by checking if the current context area corresponds to the XR surface. - During XR event handling, only process said tagged XR operator handlers instead of all main window modal handlers to prevent interferences between the main window and the XR surface. Pull Request: https://projects.blender.org/blender/blender/pulls/150308
This commit is contained in:
parent
ada8dd2d29
commit
334b4efb66
4 changed files with 40 additions and 9 deletions
|
|
@ -126,6 +126,7 @@ static int rna_Operator_ui_popup(bContext *C, wmOperator *op, int width)
|
|||
|
||||
static bool rna_event_modal_handler_add(bContext *C, ReportList *reports, wmOperator *op)
|
||||
{
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
if (win == nullptr) {
|
||||
BKE_report(reports, RPT_ERROR, "No active window in context!");
|
||||
|
|
@ -133,7 +134,7 @@ static bool rna_event_modal_handler_add(bContext *C, ReportList *reports, wmOper
|
|||
}
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
return WM_event_add_modal_handler_ex(win, area, region, op) != nullptr;
|
||||
return WM_event_add_modal_handler_ex(wm, win, area, region, op) != nullptr;
|
||||
}
|
||||
|
||||
static wmTimer *rna_event_timer_add(wmWindowManager *wm, float time_step, wmWindow *win)
|
||||
|
|
|
|||
|
|
@ -723,7 +723,8 @@ void WM_event_free_ui_handler_all(bContext *C,
|
|||
/**
|
||||
* Add a modal handler to `win`, `area` and `region` may optionally be NULL.
|
||||
*/
|
||||
wmEventHandler_Op *WM_event_add_modal_handler_ex(wmWindow *win,
|
||||
wmEventHandler_Op *WM_event_add_modal_handler_ex(wmWindowManager *wm,
|
||||
wmWindow *win,
|
||||
ScrArea *area,
|
||||
ARegion *region,
|
||||
wmOperator *op) ATTR_NONNULL(1, 4);
|
||||
|
|
|
|||
|
|
@ -4021,7 +4021,29 @@ static void wm_event_handle_xrevent(bContext *C,
|
|||
CTX_wm_area_set(C, area);
|
||||
CTX_wm_region_set(C, region);
|
||||
|
||||
eHandlerActionFlag action = wm_handlers_do(C, event, &win->modalhandlers);
|
||||
ListBase *modalhandlers = &win->modalhandlers;
|
||||
|
||||
/* Only process XR operator handlers to prevent interferences with main window handlers.
|
||||
* NOTE: This is a stripped-down XR specific version of #wm_handlers_do_intern. Changes made
|
||||
* in that function might also need to be reproduced here. */
|
||||
eHandlerActionFlag action = WM_HANDLER_CONTINUE;
|
||||
LISTBASE_FOREACH (wmEventHandler *, handler_base, modalhandlers) {
|
||||
if (handler_base->type == WM_HANDLER_TYPE_OP) {
|
||||
BLI_assert((handler_base->flag & WM_HANDLER_DO_FREE) == 0);
|
||||
|
||||
if (handler_base->poll != nullptr && !handler_base->poll(win, area, region, event)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
wmEventHandler_Op *op_handler = (wmEventHandler_Op *)handler_base;
|
||||
if (op_handler->is_xr) {
|
||||
action = wm_handler_operator_call(C, modalhandlers, handler_base, event, nullptr, nullptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wm_event_handler_return_value_check(C, event, action);
|
||||
|
||||
if ((action & WM_HANDLER_BREAK) == 0) {
|
||||
wmXrActionData *actiondata = static_cast<wmXrActionData *>(event->customdata);
|
||||
|
|
@ -4644,10 +4666,8 @@ static void WM_event_set_handler_flag(wmEventHandler *handler, const int flag)
|
|||
}
|
||||
#endif
|
||||
|
||||
wmEventHandler_Op *WM_event_add_modal_handler_ex(wmWindow *win,
|
||||
ScrArea *area,
|
||||
ARegion *region,
|
||||
wmOperator *op)
|
||||
wmEventHandler_Op *WM_event_add_modal_handler_ex(
|
||||
wmWindowManager *wm, wmWindow *win, ScrArea *area, ARegion *region, wmOperator *op)
|
||||
{
|
||||
wmEventHandler_Op *handler = MEM_callocN<wmEventHandler_Op>(__func__);
|
||||
handler->head.type = WM_HANDLER_TYPE_OP;
|
||||
|
|
@ -4667,6 +4687,11 @@ wmEventHandler_Op *WM_event_add_modal_handler_ex(wmWindow *win,
|
|||
handler->context.region = region;
|
||||
handler->context.region_type = handler->context.region ? handler->context.region->regiontype :
|
||||
-1;
|
||||
#ifdef WITH_XR_OPENXR
|
||||
handler->is_xr = (area == WM_xr_session_area_get(&wm->xr));
|
||||
#else
|
||||
UNUSED_VARS(wm);
|
||||
#endif
|
||||
|
||||
wm_handler_operator_insert(win, handler);
|
||||
|
||||
|
|
@ -4679,10 +4704,11 @@ wmEventHandler_Op *WM_event_add_modal_handler_ex(wmWindow *win,
|
|||
|
||||
wmEventHandler_Op *WM_event_add_modal_handler(bContext *C, wmOperator *op)
|
||||
{
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
return WM_event_add_modal_handler_ex(win, area, region, op);
|
||||
return WM_event_add_modal_handler_ex(wm, win, area, region, op);
|
||||
}
|
||||
|
||||
void WM_event_remove_model_handler(ListBase *handlers, const wmOperator *op, const bool postpone)
|
||||
|
|
|
|||
|
|
@ -114,8 +114,11 @@ struct wmEventHandler_Op {
|
|||
/** Operator can be NULL. */
|
||||
wmOperator *op;
|
||||
|
||||
/** Hack, special case for file-select. */
|
||||
/** Workaround: special cases for file-select and XR. */
|
||||
bool is_fileselect;
|
||||
#ifdef WITH_XR_OPENXR
|
||||
bool is_xr;
|
||||
#endif
|
||||
|
||||
/** Store context for this handler for derived/modal handlers. */
|
||||
struct {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue