fix dropdowns being stuck open; multi button events

This commit is contained in:
galister
2026-01-25 12:21:57 +09:00
parent a5146e0396
commit 554029aacf
4 changed files with 675 additions and 653 deletions

View File

@@ -165,21 +165,21 @@
<blueprint name="menu_handsfree"> <blueprint name="menu_handsfree">
<context_menu > <context_menu >
<cell translation="BAR.HANDSFREE.NONE" _press="::HandsfreeMode None" /> <cell translation="BAR.HANDSFREE.NONE" _press="::HandsfreeMode None" _press2="::ContextMenuClose" />
<cell translation="BAR.HANDSFREE.HMD" _press="::HandsfreeMode Hmd" /> <cell translation="BAR.HANDSFREE.HMD" _press="::HandsfreeMode Hmd" _press2="::ContextMenuClose" />
<cell translation="BAR.HANDSFREE.HMD_ONLY" _press="::HandsfreeMode HmdOnly" /> <cell translation="BAR.HANDSFREE.HMD_ONLY" _press="::HandsfreeMode HmdOnly" _press2="::ContextMenuClose" />
<cell translation="BAR.HANDSFREE.EYE_TRACKING" _press="::HandsfreeMode EyeTracking" /> <cell translation="BAR.HANDSFREE.EYE_TRACKING" _press="::HandsfreeMode EyeTracking" _press2="::ContextMenuClose" />
<cell translation="BAR.HANDSFREE.EYE_ONLY" _press="::HandsfreeMode EyeTrackingOnly" /> <cell translation="BAR.HANDSFREE.EYE_ONLY" _press="::HandsfreeMode EyeTrackingOnly" _press2="::ContextMenuClose" />
</context_menu> </context_menu>
</blueprint> </blueprint>
<blueprint name="menu_burger"> <blueprint name="menu_burger">
<context_menu > <context_menu >
<cell translation="BAR.EDIT_MODE_TOGGLE" _press="::EditToggle" _press2="::ContextMenuClose" />
<cell translation="BAR.HANDSFREE.TITLE" _press="::ContextMenuOpen menu_handsfree" />
<cell translation="BAR.ADD_MIRROR" _press="::NewMirror" /> <cell translation="BAR.ADD_MIRROR" _press="::NewMirror" />
<cell translation="BAR.EDIT_MODE_TOGGLE" _press="::EditToggle" />
<cell translation="BAR.ADD_NEW_SET" _press="::AddSet" /> <cell translation="BAR.ADD_NEW_SET" _press="::AddSet" />
<cell translation="BAR.DELETE_CURRENT_SET" _press="::DeleteSet" /> <cell translation="BAR.DELETE_CURRENT_SET" _press="::DeleteSet" />
<cell translation="BAR.HANDSFREE.TITLE" _press="::ContextMenuOpen menu_handsfree" />
</context_menu> </context_menu>
</blueprint> </blueprint>

File diff suppressed because it is too large Load Diff

View File

@@ -23,7 +23,10 @@ use crate::{
input::HoverResult, input::HoverResult,
task::{OverlayTask, TaskContainer, TaskType}, task::{OverlayTask, TaskContainer, TaskType},
}, },
gui::panel::{GuiPanel, NewGuiPanelParams, OnCustomAttribFunc, button::BUTTON_EVENTS}, gui::panel::{
GuiPanel, NewGuiPanelParams, OnCustomAttribFunc,
button::{BUTTON_EVENT_SUFFIX, BUTTON_EVENTS},
},
overlays::edit::{ overlays::edit::{
lock::InteractLockHandler, lock::InteractLockHandler,
mouse::new_mouse_tab_handler, mouse::new_mouse_tab_handler,
@@ -279,86 +282,32 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
}; };
for (name, kind, test_button, test_duration) in &BUTTON_EVENTS { for (name, kind, test_button, test_duration) in &BUTTON_EVENTS {
let Some(action) = attribs.get_value(name) else { for suffix in BUTTON_EVENT_SUFFIX {
continue; let name = &format!("{name}{suffix}");
}; let Some(action) = attribs.get_value(name) else {
break;
};
let mut args = action.split_whitespace(); let mut args = action.split_whitespace();
let Some(command) = args.next() else { let Some(command) = args.next() else {
continue; continue;
}; };
let button = button.clone(); let button = button.clone();
let callback: EventCallback<AppState, EditModeState> = match command { let callback: EventCallback<AppState, EditModeState> = match command {
"::EditModeToggleLock" => Box::new(move |common, data, app, state| { "::EditModeToggleLock" => Box::new(move |common, data, app, state| {
if !test_button(data) || !test_duration(&button, app) {
return Ok(EventResult::Pass);
}
let sel = OverlaySelector::Id(*state.id.borrow());
let task = state.lock.toggle(common, app, anim_mult);
app.tasks
.enqueue(TaskType::Overlay(OverlayTask::Modify(sel, task)));
Ok(EventResult::Consumed)
}),
"::EditModeToggleGrab" => Box::new(move |_common, data, app, state| {
if !test_button(data) || !test_duration(&button, app) {
return Ok(EventResult::Pass);
}
let sel = OverlaySelector::Id(*state.id.borrow());
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
sel,
Box::new(|_app, owc| {
let state = owc.active_state.as_mut().unwrap(); //want panic
state.grabbable = !state.grabbable;
}),
)));
Ok(EventResult::Consumed)
}),
"::EditModeTab" => {
let tab_name = args.next().unwrap().to_owned();
Box::new(move |common, data, app, state| {
if !test_button(data) || !test_duration(&button, app) {
return Ok(EventResult::Pass);
}
state.tabs.tab_button_clicked(common, &tab_name);
Ok(EventResult::Consumed)
})
}
"::EditModeSetPos" => {
let key = args.next().unwrap().to_owned();
Box::new(move |common, data, app, state| {
if !test_button(data) || !test_duration(&button, app) { if !test_button(data) || !test_duration(&button, app) {
return Ok(EventResult::Pass); return Ok(EventResult::Pass);
} }
let sel = OverlaySelector::Id(*state.id.borrow()); let sel = OverlaySelector::Id(*state.id.borrow());
let task = state.pos.button_clicked(common, &key); let task = state.lock.toggle(common, app, anim_mult);
app.tasks app.tasks
.enqueue(TaskType::Overlay(OverlayTask::Modify(sel, task))); .enqueue(TaskType::Overlay(OverlayTask::Modify(sel, task)));
Ok(EventResult::Consumed) Ok(EventResult::Consumed)
}) }),
} "::EditModeToggleGrab" => Box::new(move |_common, data, app, state| {
"::EditModeSetStereo" => {
let key = args.next().unwrap().to_owned();
Box::new(move |common, data, app, state| {
if !test_button(data) || !test_duration(&button, app) {
return Ok(EventResult::Pass);
}
let sel = OverlaySelector::Id(*state.id.borrow());
let task = state.stereo.button_clicked(common, &key);
app.tasks
.enqueue(TaskType::Overlay(OverlayTask::Modify(sel, task)));
Ok(EventResult::Consumed)
})
}
"::EditModeSetStereoFullFrame" => {
let full_frame = args.next().unwrap().parse::<bool>().unwrap();
Box::new(move |_common, data, app, state| {
if !test_button(data) || !test_duration(&button, app) { if !test_button(data) || !test_duration(&button, app) {
return Ok(EventResult::Pass); return Ok(EventResult::Pass);
} }
@@ -366,46 +315,103 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
let sel = OverlaySelector::Id(*state.id.borrow()); let sel = OverlaySelector::Id(*state.id.borrow());
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify( app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
sel, sel,
Box::new(move |_app, owc| { Box::new(|_app, owc| {
let attrib = BackendAttribValue::StereoFullFrame(full_frame); let state = owc.active_state.as_mut().unwrap(); //want panic
owc.backend.set_attrib(_app, attrib); state.grabbable = !state.grabbable;
}), }),
))); )));
Ok(EventResult::Consumed) Ok(EventResult::Consumed)
}) }),
} "::EditModeTab" => {
"::EditModeSetMouse" => { let tab_name = args.next().unwrap().to_owned();
let key = args.next().unwrap().to_owned(); Box::new(move |common, data, app, state| {
Box::new(move |common, data, app, state| { if !test_button(data) || !test_duration(&button, app) {
return Ok(EventResult::Pass);
}
state.tabs.tab_button_clicked(common, &tab_name);
Ok(EventResult::Consumed)
})
}
"::EditModeSetPos" => {
let key = args.next().unwrap().to_owned();
Box::new(move |common, data, app, state| {
if !test_button(data) || !test_duration(&button, app) {
return Ok(EventResult::Pass);
}
let sel = OverlaySelector::Id(*state.id.borrow());
let task = state.pos.button_clicked(common, &key);
app.tasks
.enqueue(TaskType::Overlay(OverlayTask::Modify(sel, task)));
Ok(EventResult::Consumed)
})
}
"::EditModeSetStereo" => {
let key = args.next().unwrap().to_owned();
Box::new(move |common, data, app, state| {
if !test_button(data) || !test_duration(&button, app) {
return Ok(EventResult::Pass);
}
let sel = OverlaySelector::Id(*state.id.borrow());
let task = state.stereo.button_clicked(common, &key);
app.tasks
.enqueue(TaskType::Overlay(OverlayTask::Modify(sel, task)));
Ok(EventResult::Consumed)
})
}
"::EditModeSetStereoFullFrame" => {
let full_frame = args.next().unwrap().parse::<bool>().unwrap();
Box::new(move |_common, data, app, state| {
if !test_button(data) || !test_duration(&button, app) {
return Ok(EventResult::Pass);
}
let sel = OverlaySelector::Id(*state.id.borrow());
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
sel,
Box::new(move |_app, owc| {
let attrib = BackendAttribValue::StereoFullFrame(full_frame);
owc.backend.set_attrib(_app, attrib);
}),
)));
Ok(EventResult::Consumed)
})
}
"::EditModeSetMouse" => {
let key = args.next().unwrap().to_owned();
Box::new(move |common, data, app, state| {
if !test_button(data) || !test_duration(&button, app) {
return Ok(EventResult::Pass);
}
let sel = OverlaySelector::Id(*state.id.borrow());
let task = state.mouse.button_clicked(common, &key);
app.tasks
.enqueue(TaskType::Overlay(OverlayTask::Modify(sel, task)));
Ok(EventResult::Consumed)
})
}
"::EditModeDelete" => Box::new(move |_common, data, app, state| {
if !test_button(data) || !test_duration(&button, app) { if !test_button(data) || !test_duration(&button, app) {
return Ok(EventResult::Pass); return Ok(EventResult::Pass);
} }
let sel = OverlaySelector::Id(*state.id.borrow()); app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
let task = state.mouse.button_clicked(common, &key); OverlaySelector::Id(*state.id.borrow()),
app.tasks Box::new(move |_app, owc| {
.enqueue(TaskType::Overlay(OverlayTask::Modify(sel, task))); owc.active_state = None;
}),
)));
Ok(EventResult::Consumed) Ok(EventResult::Consumed)
}) }),
} _ => return,
"::EditModeDelete" => Box::new(move |_common, data, app, state| { };
if !test_button(data) || !test_duration(&button, app) {
return Ok(EventResult::Pass);
}
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify( let id = layout.add_event_listener(attribs.widget_id, *kind, callback);
OverlaySelector::Id(*state.id.borrow()), log::debug!("Registered {action} on {:?} as {id:?}", attribs.widget_id);
Box::new(move |_app, owc| { }
owc.active_state = None;
}),
)));
Ok(EventResult::Consumed)
}),
_ => return,
};
let id = layout.add_event_listener(attribs.widget_id, *kind, callback);
log::debug!("Registered {action} on {:?} as {id:?}", attribs.widget_id);
} }
}); });

View File

@@ -32,7 +32,10 @@ use crate::{
wayvr::{self, SurfaceBufWithImage, process::KillSignal, window::WindowHandle}, wayvr::{self, SurfaceBufWithImage, process::KillSignal, window::WindowHandle},
}, },
graphics::{ExtentExt, Vert2Uv, upload_quad_vertices}, graphics::{ExtentExt, Vert2Uv, upload_quad_vertices},
gui::panel::{GuiPanel, NewGuiPanelParams, OnCustomAttribFunc, button::BUTTON_EVENTS}, gui::panel::{
GuiPanel, NewGuiPanelParams, OnCustomAttribFunc,
button::{BUTTON_EVENT_SUFFIX, BUTTON_EVENTS},
},
overlays::screen::capture::ScreenPipeline, overlays::screen::capture::ScreenPipeline,
state::{self, AppState}, state::{self, AppState},
subsystem::{hid::WheelDelta, input::KeyboardFocus}, subsystem::{hid::WheelDelta, input::KeyboardFocus},
@@ -141,32 +144,35 @@ impl WvrWindowBackend {
}; };
for (name, kind, test_button, test_duration) in &BUTTON_EVENTS { for (name, kind, test_button, test_duration) in &BUTTON_EVENTS {
let Some(action) = attribs.get_value(name) else { for suffix in BUTTON_EVENT_SUFFIX {
continue; let name = &format!("{name}{suffix}");
}; let Some(action) = attribs.get_value(name) else {
break;
};
let mut args = action.split_whitespace(); let mut args = action.split_whitespace();
let Some(command) = args.next() else { let Some(command) = args.next() else {
continue; continue;
}; };
let button = button.clone(); let button = button.clone();
let callback: EventCallback<AppState, WindowHandle> = match command { let callback: EventCallback<AppState, WindowHandle> = match command {
"::DecorCloseWindow" => Box::new(move |_common, data, app, state| { "::DecorCloseWindow" => Box::new(move |_common, data, app, state| {
if !test_button(data) || !test_duration(&button, app) { if !test_button(data) || !test_duration(&button, app) {
return Ok(EventResult::Pass); return Ok(EventResult::Pass);
} }
app.wvr_server.as_mut().unwrap().close_window(*state); app.wvr_server.as_mut().unwrap().close_window(*state);
Ok(EventResult::Consumed) Ok(EventResult::Consumed)
}), }),
_ => return, _ => return,
}; };
let id = layout.add_event_listener(attribs.widget_id, *kind, callback); let id = layout.add_event_listener(attribs.widget_id, *kind, callback);
log::debug!("Registered {action} on {:?} as {id:?}", attribs.widget_id); log::debug!("Registered {action} on {:?} as {id:?}", attribs.widget_id);
}
} }
}); });