bar functionality
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Copy, Default)]
|
||||
@@ -7,3 +9,33 @@ pub enum LeftRight {
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
pub trait LogErr {
|
||||
fn log_err(self) -> Self;
|
||||
fn log_warn(self) -> Self;
|
||||
}
|
||||
|
||||
impl<T, E> LogErr for Result<T, E>
|
||||
where
|
||||
E: Debug + Send + Sync + 'static,
|
||||
{
|
||||
fn log_warn(self) -> Result<T, E> {
|
||||
match self {
|
||||
Ok(ok) => Ok(ok),
|
||||
Err(error) => {
|
||||
log::warn!("{error:?}");
|
||||
Err(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn log_err(self) -> Result<T, E> {
|
||||
match self {
|
||||
Ok(ok) => Ok(ok),
|
||||
Err(error) => {
|
||||
log::error!("{error:?}");
|
||||
Err(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,14 +88,14 @@
|
||||
|
||||
<!-- An app with a single icon. -->
|
||||
<template name="App">
|
||||
<Button macro="button_style" _press="" tooltip="${tooltip}" tooltip_side="bottom">
|
||||
<Button macro="button_style" id="overlay_${idx}" _press="::OverlayToggle ${name}" tooltip="${name}" tooltip_side="bottom">
|
||||
<sprite width="56" height="56" color="~text_color" src_ext="${src}" />
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
<!-- A screen with a shortened connector name, e.g. "H1" for HDMI-A-1 or "D2" for DP-2 -->
|
||||
<template name="Screen">
|
||||
<Button macro="button_style" tooltip="${tooltip}" tooltip_side="bottom">
|
||||
<Button macro="button_style" id="overlay_${idx}" _press="::OverlayToggle ${name}" tooltip="${name}" tooltip_side="bottom">
|
||||
<sprite width="56" height="56" color="~text_color" src_builtin="edit/screen.svg" />
|
||||
<div position="absolute" margin_top="-10">
|
||||
<label text="${display}" size="26" color="~color_faded_20" weight="bold" />
|
||||
@@ -104,13 +104,13 @@
|
||||
</template>
|
||||
|
||||
<template name="Panel">
|
||||
<Button macro="button_style" tooltip="${tooltip}" tooltip_side="bottom">
|
||||
<Button macro="button_style" id="overlay_${idx}" _press="::OverlayToggle ${name}" tooltip="${name}" tooltip_side="bottom">
|
||||
<sprite width="56" height="56" color="~text_color" src_builtin="edit/panel.svg" />
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
<template name="Mirror">
|
||||
<Button macro="button_style" _press="" tooltip="${tooltip}" tooltip_side="bottom">
|
||||
<Button macro="button_style" id="overlay_${idx}" _press="::OverlayToggle ${name}" tooltip="${name}" tooltip_side="bottom">
|
||||
<sprite width="56" height="56" color="~text_color" src_builtin="edit/mirror.svg" />
|
||||
<div position="absolute" margin_top="7" margin_left="20">
|
||||
<label text="${display}" size="26" color="~color_faded_20" weight="bold" />
|
||||
@@ -131,17 +131,17 @@
|
||||
<div flex_direction="column" interactable="0">
|
||||
<rectangle macro="bg_rect" padding="16" align_items="center" justify_content="space_between">
|
||||
<div gap="16">
|
||||
<div id="panels_root_TODO" gap="8">
|
||||
<Screen idx="0" display="H1" tooltip="Screen: HDMI-A-1" />
|
||||
<Screen idx="1" display="D2" tooltip="Screen: DP-2" />
|
||||
<Mirror idx="1" display="1" tooltip="Mirror: M-1" />
|
||||
<Panel idx="1" display="Test" tooltip="Panel: Test" />
|
||||
<div id="panels_root" gap="8">
|
||||
<Screen idx="0" display="H1" name="HDMI-A-1" />
|
||||
<Screen idx="1" display="D2" name="Screen: DP-2" />
|
||||
<Mirror idx="1" display="1" name="M1" />
|
||||
<Panel idx="1" display="Test" name="Test" />
|
||||
</div>
|
||||
<VerticalSeparator />
|
||||
<div id="apps_root_TODO" gap="8">
|
||||
<App id="test1" src="/usr/share/icons/hicolor/scalable/apps/blender-5.0.svg" tooltip="App: Blender" />
|
||||
<App id="test2" src="/usr/share/icons/hicolor/scalable/apps/org.inkscape.Inkscape.svg" tooltip="App: Inkscape" />
|
||||
<App id="test3" src="/usr/share/icons/hicolor/scalable/apps/gimp.svg" tooltip="App: GIMP" />
|
||||
<div id="apps_root" gap="8">
|
||||
<App id="test1" name="Blender" src="/usr/share/icons/hicolor/scalable/apps/blender-5.0.svg" />
|
||||
<App id="test2" name="Inkscape" src="/usr/share/icons/hicolor/scalable/apps/org.inkscape.Inkscape.svg" />
|
||||
<App id="test3" name="GIMP" src="/usr/share/icons/hicolor/scalable/apps/gimp.svg" />
|
||||
</div>
|
||||
</div>
|
||||
<div id="tray_root" flex_direction="row" gap="16">
|
||||
@@ -165,4 +165,4 @@
|
||||
</div>
|
||||
</elements>
|
||||
|
||||
</layout>
|
||||
</layout>
|
||||
|
||||
@@ -248,7 +248,8 @@ pub(super) fn setup_custom_button<S: 'static>(
|
||||
})
|
||||
}
|
||||
"::OverlayToggle" => {
|
||||
let Some(arg): Option<Arc<str>> = args.next().map(Into::into) else {
|
||||
let arg: Arc<str> = args.collect::<Vec<_>>().join(" ").into();
|
||||
if arg.len() < 1 {
|
||||
log::error!("{command} has missing arguments");
|
||||
return;
|
||||
};
|
||||
@@ -271,6 +272,24 @@ pub(super) fn setup_custom_button<S: 'static>(
|
||||
Ok(EventResult::Consumed)
|
||||
})
|
||||
}
|
||||
"::OverlaySoftToggle" => {
|
||||
let arg: Arc<str> = args.collect::<Vec<_>>().join(" ").into();
|
||||
if arg.len() < 1 {
|
||||
log::error!("{command} has missing arguments");
|
||||
return;
|
||||
};
|
||||
|
||||
Box::new(move |_common, data, app, _| {
|
||||
if !test_button(data) || !test_duration(&button, app) {
|
||||
return Ok(EventResult::Pass);
|
||||
}
|
||||
|
||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::SoftToggleOverlay(
|
||||
OverlaySelector::Name(arg.clone()),
|
||||
)));
|
||||
Ok(EventResult::Consumed)
|
||||
})
|
||||
}
|
||||
"::EditToggle" => Box::new(move |_common, data, app, _| {
|
||||
if !test_button(data) || !test_duration(&button, app) {
|
||||
return Ok(EventResult::Pass);
|
||||
|
||||
@@ -14,7 +14,7 @@ use wgui::{
|
||||
},
|
||||
gfx::cmd::WGfxClearMode,
|
||||
layout::{Layout, LayoutParams, LayoutUpdateParams, WidgetID},
|
||||
parser::{CustomAttribsInfoOwned, Fetchable, ParserState},
|
||||
parser::{CustomAttribsInfoOwned, Fetchable, ParseDocumentExtra, ParserState},
|
||||
renderer_vk::context::Context as WguiContext,
|
||||
widget::{EventResult, label::WidgetLabel},
|
||||
};
|
||||
@@ -52,11 +52,14 @@ pub struct GuiPanel<S> {
|
||||
pub gui_scale: f32,
|
||||
pub on_notify: Option<OnNotifyFunc<S>>,
|
||||
pub initialized: bool,
|
||||
pub doc_extra: Option<ParseDocumentExtra>,
|
||||
interaction_transform: Option<Affine2>,
|
||||
context: WguiContext,
|
||||
timestep: Timestep,
|
||||
has_focus: [bool; 2],
|
||||
last_content_size: Vec2,
|
||||
custom_elems: Rc<RefCell<Vec<CustomAttribsInfoOwned>>>,
|
||||
on_custom_attrib: Option<OnCustomAttribFunc>,
|
||||
}
|
||||
|
||||
pub type OnCustomIdFunc<S> = Box<
|
||||
@@ -142,29 +145,10 @@ impl<S: 'static> GuiPanel<S> {
|
||||
}
|
||||
}
|
||||
|
||||
for elem in custom_elems.borrow().iter() {
|
||||
if layout
|
||||
.state
|
||||
.widgets
|
||||
.get_as::<WidgetLabel>(elem.widget_id)
|
||||
.is_some()
|
||||
{
|
||||
setup_custom_label::<S>(&mut layout, elem, app);
|
||||
} else if let Ok(button) =
|
||||
parser_state.fetch_component_from_widget_id_as::<ComponentButton>(elem.widget_id)
|
||||
{
|
||||
setup_custom_button::<S>(&mut layout, elem, app, button);
|
||||
}
|
||||
|
||||
if let Some(on_custom_attrib) = ¶ms.on_custom_attrib {
|
||||
on_custom_attrib(&mut layout, &parser_state, elem, app);
|
||||
}
|
||||
}
|
||||
|
||||
let context = WguiContext::new(&mut app.wgui_shared, 1.0)?;
|
||||
let timestep = Timestep::new(60.0);
|
||||
|
||||
Ok(Self {
|
||||
let mut me = Self {
|
||||
layout,
|
||||
context,
|
||||
timestep,
|
||||
@@ -178,38 +162,38 @@ impl<S: 'static> GuiPanel<S> {
|
||||
initialized: false,
|
||||
has_focus: [false, false],
|
||||
last_content_size: Vec2::ZERO,
|
||||
})
|
||||
doc_extra: Some(doc_params.extra),
|
||||
custom_elems,
|
||||
on_custom_attrib: params.on_custom_attrib,
|
||||
};
|
||||
me.process_custom_elems(app);
|
||||
|
||||
Ok(me)
|
||||
}
|
||||
|
||||
pub fn new_blank(
|
||||
app: &mut AppState,
|
||||
state: S,
|
||||
params: NewGuiPanelParams<S>,
|
||||
) -> anyhow::Result<Self> {
|
||||
let layout = Layout::new(
|
||||
app.wgui_globals.clone(),
|
||||
&LayoutParams {
|
||||
resize_to_parent: params.resize_to_parent,
|
||||
},
|
||||
)?;
|
||||
let context = WguiContext::new(&mut app.wgui_shared, 1.0)?;
|
||||
let timestep = Timestep::new(60.0);
|
||||
pub fn process_custom_elems(&mut self, app: &mut AppState) {
|
||||
let mut elems = self.custom_elems.borrow_mut();
|
||||
for elem in elems.iter() {
|
||||
if self
|
||||
.layout
|
||||
.state
|
||||
.widgets
|
||||
.get_as::<WidgetLabel>(elem.widget_id)
|
||||
.is_some()
|
||||
{
|
||||
setup_custom_label::<S>(&mut self.layout, elem, app);
|
||||
} else if let Ok(button) = self
|
||||
.parser_state
|
||||
.fetch_component_from_widget_id_as::<ComponentButton>(elem.widget_id)
|
||||
{
|
||||
setup_custom_button::<S>(&mut self.layout, elem, app, button);
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
layout,
|
||||
context,
|
||||
timestep,
|
||||
state,
|
||||
parser_state: ParserState::default(),
|
||||
max_size: vec2(DEFAULT_MAX_SIZE as _, DEFAULT_MAX_SIZE as _),
|
||||
timers: vec![],
|
||||
on_notify: None,
|
||||
interaction_transform: None,
|
||||
gui_scale: params.gui_scale,
|
||||
initialized: false,
|
||||
has_focus: [false, false],
|
||||
last_content_size: Vec2::ZERO,
|
||||
})
|
||||
if let Some(on_custom_attrib) = &self.on_custom_attrib {
|
||||
on_custom_attrib(&mut self.layout, &self.parser_state, elem, app);
|
||||
}
|
||||
}
|
||||
elems.clear();
|
||||
}
|
||||
|
||||
pub fn update_layout(&mut self, app: &mut AppState) -> anyhow::Result<()> {
|
||||
|
||||
@@ -1,28 +1,15 @@
|
||||
use std::{collections::HashMap, rc::Rc};
|
||||
use std::{collections::{HashMap}, rc::Rc, time::Duration};
|
||||
|
||||
use crate::{
|
||||
app_misc,
|
||||
gui::panel::{GuiPanel, NewGuiPanelParams},
|
||||
gui::{panel::{GuiPanel, NewGuiPanelParams}, timer::GuiTimer},
|
||||
state::AppState,
|
||||
subsystem::hid::XkbKeymap,
|
||||
subsystem::hid::XkbKeymap, windowing::{backend::OverlayEventData, window::OverlayCategory},
|
||||
};
|
||||
use anyhow::Context;
|
||||
use glam::{FloatExt, Mat4, Vec2, vec2, vec3};
|
||||
use wgui::{
|
||||
animation::{Animation, AnimationEasing},
|
||||
assets::AssetPath,
|
||||
drawing::{self, Color},
|
||||
event::{self, CallbackMetadata, EventListenerKind},
|
||||
layout::{LayoutParams, LayoutUpdateParams},
|
||||
parser::{Fetchable, ParseDocumentExtra, ParseDocumentParams},
|
||||
renderer_vk::util,
|
||||
taffy::{self, prelude::length},
|
||||
widget::{
|
||||
EventResult,
|
||||
div::WidgetDiv,
|
||||
rectangle::{WidgetRectangle, WidgetRectangleParams},
|
||||
util::WLength,
|
||||
},
|
||||
animation::{Animation, AnimationEasing}, assets::AssetPath, components::button::ComponentButton, drawing::{self, Color}, event::{self, CallbackDataCommon, CallbackMetadata, EventAlterables, EventListenerKind}, layout::LayoutUpdateParams, parser::{Fetchable, ParseDocumentExtra, ParseDocumentParams}, renderer_vk::util, taffy::{self, prelude::length}, widget::{div::WidgetDiv, rectangle::WidgetRectangle, EventResult}
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -32,6 +19,14 @@ use super::{
|
||||
|
||||
const PIXELS_PER_UNIT: f32 = 80.;
|
||||
|
||||
fn new_doc_params(panel: &mut GuiPanel<KeyboardState>) -> ParseDocumentParams<'static> {
|
||||
ParseDocumentParams {
|
||||
globals: panel.layout.state.globals.clone(),
|
||||
path: AssetPath::FileOrBuiltIn("gui/keyboard.xml"),
|
||||
extra: panel.doc_extra.take().unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines, clippy::significant_drop_tightening)]
|
||||
pub(super) fn create_keyboard_panel(
|
||||
app: &mut AppState,
|
||||
@@ -42,11 +37,7 @@ pub(super) fn create_keyboard_panel(
|
||||
let mut panel =
|
||||
GuiPanel::new_from_template(app, "gui/keyboard.xml", state, NewGuiPanelParams::default())?;
|
||||
|
||||
let doc_params = ParseDocumentParams {
|
||||
globals: app.wgui_globals.clone(),
|
||||
path: AssetPath::FileOrBuiltIn("gui/keyboard.xml"),
|
||||
extra: ParseDocumentExtra::default(),
|
||||
};
|
||||
let doc_params = new_doc_params(&mut panel);
|
||||
|
||||
let globals = app.wgui_globals.clone();
|
||||
let accent_color = globals.get().defaults.accent_color;
|
||||
@@ -256,6 +247,133 @@ pub(super) fn create_keyboard_panel(
|
||||
}
|
||||
}
|
||||
|
||||
panel.on_notify = Some(Box::new(move |panel, app, event_data| {
|
||||
let mut alterables = EventAlterables::default();
|
||||
|
||||
match event_data {
|
||||
OverlayEventData::ActiveSetChanged(current_set) => {
|
||||
let mut com = CallbackDataCommon {
|
||||
alterables: &mut alterables,
|
||||
state: &panel.layout.state,
|
||||
};
|
||||
if let Some(old_set) = panel.state.current_set.take()
|
||||
&& let Some(old_set) = panel.state.set_buttons.get_mut(old_set)
|
||||
{
|
||||
old_set.set_sticky_state(&mut com, false);
|
||||
}
|
||||
if let Some(new_set) = current_set
|
||||
&& let Some(new_set) = panel.state.set_buttons.get_mut(new_set)
|
||||
{
|
||||
new_set.set_sticky_state(&mut com, true);
|
||||
}
|
||||
panel.state.current_set = current_set;
|
||||
}
|
||||
OverlayEventData::NumSetsChanged(num_sets) => {
|
||||
let sets_root = panel.parser_state.get_widget_id("sets_root")?;
|
||||
panel.layout.remove_children(sets_root);
|
||||
panel.state.set_buttons.clear();
|
||||
|
||||
for i in 0..num_sets {
|
||||
let mut params = HashMap::new();
|
||||
params.insert("idx".into(), i.to_string().into());
|
||||
params.insert("display".into(), (i+1).to_string().into());
|
||||
panel.parser_state.instantiate_template(
|
||||
&doc_params,
|
||||
"Set",
|
||||
&mut panel.layout,
|
||||
sets_root,
|
||||
params,
|
||||
)?;
|
||||
let set_button = panel.parser_state.fetch_component_as::<ComponentButton>(&format!("set_{i}"))?;
|
||||
if panel.state.current_set == Some(i) {
|
||||
let mut com = CallbackDataCommon {
|
||||
alterables: &mut alterables,
|
||||
state: &panel.layout.state,
|
||||
};
|
||||
set_button.set_sticky_state(&mut com, true);
|
||||
}
|
||||
panel.state.set_buttons.push(set_button);
|
||||
}
|
||||
panel.process_custom_elems(app);
|
||||
}
|
||||
OverlayEventData::OverlaysChanged(metas) => {
|
||||
let panels_root = panel.parser_state.get_widget_id("panels_root")?;
|
||||
let apps_root = panel.parser_state.get_widget_id("apps_root")?;
|
||||
panel.layout.remove_children(panels_root);
|
||||
panel.layout.remove_children(apps_root);
|
||||
panel.state.overlay_buttons.clear();
|
||||
|
||||
for (i, meta) in metas.iter().enumerate() {
|
||||
let mut params = HashMap::new();
|
||||
|
||||
let (template, root) = match meta.category {
|
||||
OverlayCategory::Screen => {
|
||||
params.insert("display".into(), format!("{}{}", (*meta.name).chars().next().unwrap_or_default(), (*meta.name).chars().last().unwrap_or_default()).into());
|
||||
("Screen", panels_root)
|
||||
},
|
||||
OverlayCategory::Mirror => {
|
||||
params.insert("display".into(), meta.name.as_ref().into());
|
||||
("Mirror", panels_root)
|
||||
},
|
||||
OverlayCategory::Panel => {
|
||||
("Panel", panels_root)
|
||||
},
|
||||
OverlayCategory::WayVR => {
|
||||
("App", apps_root)
|
||||
},
|
||||
_ => continue
|
||||
};
|
||||
|
||||
params.insert("idx".into(), i.to_string().into());
|
||||
params.insert("name".into(), meta.name.as_ref().into());
|
||||
panel.parser_state.instantiate_template(
|
||||
&doc_params,
|
||||
template,
|
||||
&mut panel.layout,
|
||||
root,
|
||||
params,
|
||||
)?;
|
||||
let overlay_buttons = panel.parser_state.fetch_component_as::<ComponentButton>(&format!("overlay_{i}"))?;
|
||||
if meta.visible {
|
||||
let mut com = CallbackDataCommon {
|
||||
alterables: &mut alterables,
|
||||
state: &panel.layout.state,
|
||||
};
|
||||
overlay_buttons.set_sticky_state(&mut com, true);
|
||||
}
|
||||
panel.state.overlay_buttons.insert(meta.id, overlay_buttons);
|
||||
}
|
||||
panel.process_custom_elems(app);
|
||||
}
|
||||
OverlayEventData::VisibleOverlaysChanged(overlays) => {
|
||||
let mut com = CallbackDataCommon {
|
||||
alterables: &mut alterables,
|
||||
state: &panel.layout.state,
|
||||
};
|
||||
let mut overlay_buttons = panel.state.overlay_buttons.clone();
|
||||
|
||||
for visible in &*overlays {
|
||||
if let Some(btn) = overlay_buttons.remove(*visible)
|
||||
{
|
||||
btn.set_sticky_state(&mut com, true);
|
||||
}
|
||||
}
|
||||
|
||||
for btn in overlay_buttons.values() {
|
||||
btn.set_sticky_state(&mut com, false);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
panel.layout.process_alterables(alterables)?;
|
||||
Ok(())
|
||||
}));
|
||||
|
||||
panel
|
||||
.timers
|
||||
.push(GuiTimer::new(Duration::from_millis(100), 0));
|
||||
|
||||
app_misc::process_layout_result(
|
||||
app,
|
||||
panel.layout.update(&mut LayoutUpdateParams {
|
||||
|
||||
@@ -1,35 +1,24 @@
|
||||
use std::{
|
||||
cell::Cell,
|
||||
collections::HashMap,
|
||||
process::{Child, Command},
|
||||
sync::atomic::Ordering,
|
||||
cell::Cell, collections::HashMap, process::{Child, Command}, rc::Rc, sync::atomic::Ordering
|
||||
};
|
||||
|
||||
use crate::{
|
||||
KEYMAP_CHANGE,
|
||||
backend::input::{HoverResult, PointerHit},
|
||||
gui::panel::GuiPanel,
|
||||
overlays::keyboard::{builder::create_keyboard_panel, layout::AltModifier},
|
||||
state::AppState,
|
||||
subsystem::{
|
||||
backend::input::{HoverResult, PointerHit}, gui::panel::GuiPanel, overlays::keyboard::{builder::create_keyboard_panel, layout::AltModifier}, state::AppState, subsystem::{
|
||||
dbus::DbusConnector,
|
||||
hid::{
|
||||
ALT, CTRL, KeyModifier, META, SHIFT, SUPER, VirtualKey, WheelDelta, XkbKeymap,
|
||||
get_keymap_wl, get_keymap_x11,
|
||||
get_keymap_wl, get_keymap_x11, KeyModifier, VirtualKey, WheelDelta, XkbKeymap, ALT, CTRL, META, SHIFT, SUPER
|
||||
},
|
||||
},
|
||||
windowing::{
|
||||
backend::{FrameMeta, OverlayBackend, OverlayEventData, RenderResources, ShouldRender},
|
||||
window::{OverlayCategory, OverlayWindowConfig},
|
||||
},
|
||||
}, windowing::{
|
||||
backend::{FrameMeta, OverlayBackend, OverlayEventData, OverlayMeta, RenderResources, ShouldRender},
|
||||
window::{OverlayCategory, OverlayWindowConfig}, OverlayID,
|
||||
}, KEYMAP_CHANGE
|
||||
};
|
||||
use anyhow::Context;
|
||||
use glam::{Affine3A, Quat, Vec3, vec3};
|
||||
use regex::Regex;
|
||||
use slotmap::{SlotMap, new_key_type};
|
||||
use slotmap::{new_key_type, SecondaryMap, SlotMap};
|
||||
use wgui::{
|
||||
drawing,
|
||||
event::{InternalStateChangeEvent, MouseButton, MouseButtonIndex},
|
||||
components::button::ComponentButton, drawing, event::{InternalStateChangeEvent, MouseButton, MouseButtonIndex}
|
||||
};
|
||||
use wlx_common::overlays::{BackendAttrib, BackendAttribValue};
|
||||
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
||||
@@ -54,6 +43,10 @@ pub fn create_keyboard(app: &mut AppState, wayland: bool) -> anyhow::Result<Over
|
||||
_ => 0,
|
||||
},
|
||||
processes: vec![],
|
||||
set_buttons: vec![],
|
||||
overlay_buttons: SecondaryMap::new(),
|
||||
overlay_metas: SecondaryMap::new(),
|
||||
current_set: None,
|
||||
};
|
||||
|
||||
let auto_labels = layout.auto_labels.unwrap_or(true);
|
||||
@@ -309,10 +302,14 @@ struct KeyboardState {
|
||||
modifiers: KeyModifier,
|
||||
alt_modifier: KeyModifier,
|
||||
processes: Vec<Child>,
|
||||
set_buttons: Vec<Rc<ComponentButton>>,
|
||||
overlay_buttons: SecondaryMap<OverlayID, Rc<ComponentButton>>,
|
||||
overlay_metas: SecondaryMap<OverlayID, OverlayMeta>,
|
||||
current_set: Option<usize>,
|
||||
}
|
||||
|
||||
impl KeyboardState {
|
||||
const fn take(&mut self) -> Self {
|
||||
fn take(&mut self) -> Self {
|
||||
Self {
|
||||
modifiers: self.modifiers,
|
||||
alt_modifier: self.alt_modifier,
|
||||
@@ -321,6 +318,22 @@ impl KeyboardState {
|
||||
std::mem::swap(&mut processes, &mut self.processes);
|
||||
processes
|
||||
},
|
||||
set_buttons: {
|
||||
let mut set_buttons = vec![];
|
||||
std::mem::swap(&mut set_buttons, &mut self.set_buttons);
|
||||
set_buttons
|
||||
},
|
||||
overlay_buttons: {
|
||||
let mut overlay_buttons = SecondaryMap::new();
|
||||
std::mem::swap(&mut overlay_buttons, &mut self.overlay_buttons);
|
||||
overlay_buttons
|
||||
},
|
||||
overlay_metas: {
|
||||
let mut overlay_metas= SecondaryMap::new();
|
||||
std::mem::swap(&mut overlay_metas, &mut self.overlay_metas);
|
||||
overlay_metas
|
||||
},
|
||||
current_set: self.current_set.take(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,7 +425,7 @@ pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
||||
}
|
||||
OverlayEventData::OverlaysChanged(metas) => {
|
||||
panel.state.overlay_metas.clear();
|
||||
for meta in metas {
|
||||
for meta in &*metas {
|
||||
match meta.category {
|
||||
OverlayCategory::Keyboard => {
|
||||
panel.state.keyboard_oid = meta.id;
|
||||
@@ -440,7 +440,7 @@ pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
||||
panel.state.dashboard_oid = meta.id;
|
||||
}
|
||||
OverlayCategory::Internal => {}
|
||||
_ => panel.state.overlay_metas.push(meta),
|
||||
_ => panel.state.overlay_metas.push(meta.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,7 +494,7 @@ pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
||||
let mut keyboard_visible = false;
|
||||
let mut dashboard_visible = false;
|
||||
|
||||
for visible in &overlays {
|
||||
for visible in &*overlays {
|
||||
if let Some(idx) = panel.state.overlay_indices.get(*visible)
|
||||
&& let Some(o) = panel.state.overlay_metas.get_mut(*idx)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use glam::{Affine2, Affine3A, Vec2};
|
||||
use smallvec::SmallVec;
|
||||
use std::{any::Any, sync::Arc};
|
||||
use std::{any::Any, rc::Rc, sync::Arc};
|
||||
use vulkano::{command_buffer::CommandBufferUsage, format::Format, image::view::ImageView};
|
||||
use wgui::gfx::{
|
||||
WGfx,
|
||||
@@ -106,6 +106,7 @@ macro_rules! attrib_value {
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct OverlayMeta {
|
||||
pub id: OverlayID,
|
||||
pub name: Arc<str>,
|
||||
@@ -120,8 +121,8 @@ pub enum OverlayEventData {
|
||||
ActiveSetChanged(Option<usize>),
|
||||
NumSetsChanged(usize),
|
||||
EditModeChanged(bool),
|
||||
OverlaysChanged(Vec<OverlayMeta>),
|
||||
VisibleOverlaysChanged(Vec<OverlayID>),
|
||||
OverlaysChanged(Rc<[OverlayMeta]>),
|
||||
VisibleOverlaysChanged(Rc<[OverlayID]>),
|
||||
DevicesChanged,
|
||||
OverlayGrabbed {
|
||||
name: Arc<str>,
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
sync::atomic::Ordering,
|
||||
collections::{HashMap, VecDeque}, rc::Rc, sync::atomic::Ordering
|
||||
};
|
||||
|
||||
use anyhow::Context;
|
||||
use glam::{Affine3A, Vec3, Vec3A};
|
||||
use slotmap::{HopSlotMap, Key, SecondaryMap};
|
||||
use wlx_common::{
|
||||
astr_containers::{AStrMap, AStrMapExt},
|
||||
config::SerializedWindowSet,
|
||||
overlays::{BackendAttrib, ToastTopic},
|
||||
astr_containers::{AStrMap, AStrMapExt}, common::LogErr, config::SerializedWindowSet, overlays::{BackendAttrib, ToastTopic}
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -48,6 +46,7 @@ pub struct OverlayWindowManager<T> {
|
||||
restore_set: usize,
|
||||
anchor_local: Affine3A,
|
||||
watch_id: OverlayID,
|
||||
keyboard_id: OverlayID,
|
||||
edit_mode: bool,
|
||||
dropped_overlays: VecDeque<OverlayWindowData<T>>,
|
||||
initialized: bool,
|
||||
@@ -66,6 +65,7 @@ where
|
||||
sets: vec![OverlayWindowSet::default()],
|
||||
anchor_local: Affine3A::from_translation(Vec3::NEG_Z),
|
||||
watch_id: OverlayID::null(), // set down below
|
||||
keyboard_id: OverlayID::null(), // set down below
|
||||
edit_mode: false,
|
||||
dropped_overlays: VecDeque::with_capacity(8),
|
||||
initialized: false,
|
||||
@@ -101,7 +101,7 @@ where
|
||||
|
||||
let mut keyboard = OverlayWindowData::from_config(create_keyboard(app, wayland)?);
|
||||
keyboard.config.show_on_spawn = true;
|
||||
let keyboard_id = me.add(keyboard, app);
|
||||
me.keyboard_id = me.add(keyboard, app);
|
||||
|
||||
// is this needed?
|
||||
me.switch_to_set(app, None, false);
|
||||
@@ -110,11 +110,11 @@ where
|
||||
let kbd_state = me
|
||||
.sets
|
||||
.last()
|
||||
.and_then(|s| s.overlays.get(keyboard_id))
|
||||
.and_then(|s| s.overlays.get(me.keyboard_id))
|
||||
.unwrap()
|
||||
.clone();
|
||||
for set in &mut me.sets {
|
||||
set.overlays.insert(keyboard_id, kbd_state.clone());
|
||||
set.overlays.insert(me.keyboard_id, kbd_state.clone());
|
||||
}
|
||||
|
||||
let anchor = OverlayWindowData::from_config(create_anchor(app)?);
|
||||
@@ -142,16 +142,18 @@ where
|
||||
me.restore_layout(app);
|
||||
me.overlays_changed(app)?;
|
||||
|
||||
for ev in [
|
||||
OverlayEventData::NumSetsChanged(me.sets.len()),
|
||||
OverlayEventData::EditModeChanged(false),
|
||||
OverlayEventData::DevicesChanged,
|
||||
] {
|
||||
me.mut_by_id(me.watch_id)
|
||||
.unwrap()
|
||||
.config
|
||||
.backend
|
||||
.notify(app, ev)?;
|
||||
for id in [me.watch_id, me.keyboard_id] {
|
||||
for ev in [
|
||||
OverlayEventData::NumSetsChanged(me.sets.len()),
|
||||
OverlayEventData::EditModeChanged(false),
|
||||
OverlayEventData::DevicesChanged,
|
||||
] {
|
||||
me.mut_by_id(id)
|
||||
.unwrap()
|
||||
.config
|
||||
.backend
|
||||
.notify(app, ev)?;
|
||||
}
|
||||
}
|
||||
|
||||
me.initialized = true;
|
||||
@@ -191,6 +193,7 @@ where
|
||||
// no saved state
|
||||
o.config.activate(app);
|
||||
}
|
||||
self.visible_overlays_changed(app)?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
@@ -200,11 +203,12 @@ where
|
||||
OverlayTask::AddSet => {
|
||||
self.sets.push(OverlayWindowSet::default());
|
||||
let len = self.sets.len();
|
||||
if let Some(watch) = self.mut_by_id(self.watch_id) {
|
||||
watch
|
||||
for id in [self.watch_id, self.keyboard_id] {
|
||||
self.mut_by_id(id).and_then(|o| o
|
||||
.config
|
||||
.backend
|
||||
.notify(app, OverlayEventData::NumSetsChanged(len))?;
|
||||
.notify(app, OverlayEventData::NumSetsChanged(len)).log_err().ok())
|
||||
.context("Could not notify NumSetsChanged")?;
|
||||
}
|
||||
}
|
||||
OverlayTask::DeleteActiveSet => {
|
||||
@@ -235,11 +239,12 @@ where
|
||||
self.switch_to_set(app, None, false);
|
||||
self.sets.remove(set);
|
||||
let len = self.sets.len();
|
||||
if let Some(watch) = self.mut_by_id(self.watch_id) {
|
||||
watch
|
||||
for id in [self.watch_id, self.keyboard_id] {
|
||||
self.mut_by_id(id).and_then(|o| o
|
||||
.config
|
||||
.backend
|
||||
.notify(app, OverlayEventData::NumSetsChanged(len))?;
|
||||
.notify(app, OverlayEventData::NumSetsChanged(len)).log_err().ok())
|
||||
.context("Could not notify NumSetsChanged")?;
|
||||
}
|
||||
}
|
||||
OverlayTask::CleanupMirrors => {
|
||||
@@ -733,12 +738,13 @@ impl<T> OverlayWindowManager<T> {
|
||||
}
|
||||
self.current_set = new_set;
|
||||
|
||||
if let Some(watch) = self.mut_by_id(self.watch_id) {
|
||||
watch
|
||||
.config
|
||||
for id in [self.watch_id, self.keyboard_id] {
|
||||
let _ = self.mut_by_id(id)
|
||||
.context("Missing overlay")
|
||||
.and_then(|o|
|
||||
o.config
|
||||
.backend
|
||||
.notify(app, OverlayEventData::ActiveSetChanged(new_set))
|
||||
.unwrap(); // TODO: handle this
|
||||
.notify(app, OverlayEventData::ActiveSetChanged(new_set)));
|
||||
|
||||
let _ = self
|
||||
.visible_overlays_changed(app)
|
||||
@@ -775,11 +781,14 @@ impl<T> OverlayWindowManager<T> {
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(watch) = self.mut_by_id(self.watch_id) {
|
||||
watch
|
||||
let meta: Rc<[OverlayMeta]> = meta.into();
|
||||
for id in [self.watch_id, self.keyboard_id] {
|
||||
let _ = self.mut_by_id(id)
|
||||
.context("Missing overlay")
|
||||
.and_then(|o| o
|
||||
.config
|
||||
.backend
|
||||
.notify(app, OverlayEventData::OverlaysChanged(meta))?;
|
||||
.notify(app, OverlayEventData::OverlaysChanged(meta.clone())));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -797,11 +806,14 @@ impl<T> OverlayWindowManager<T> {
|
||||
vis.push(id);
|
||||
}
|
||||
|
||||
if let Some(watch) = self.mut_by_id(self.watch_id) {
|
||||
watch
|
||||
let vis: Rc<[OverlayID]> = vis.into();
|
||||
for id in [self.watch_id, self.keyboard_id] {
|
||||
let _ = self.mut_by_id(id)
|
||||
.context("Missing overlay")
|
||||
.and_then(|o| o
|
||||
.config
|
||||
.backend
|
||||
.notify(app, OverlayEventData::VisibleOverlaysChanged(vis))?;
|
||||
.notify(app, OverlayEventData::VisibleOverlaysChanged(vis.clone())));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -809,10 +821,10 @@ impl<T> OverlayWindowManager<T> {
|
||||
|
||||
pub fn devices_changed(&mut self, app: &mut AppState) -> anyhow::Result<()> {
|
||||
if let Some(watch) = self.mut_by_id(self.watch_id) {
|
||||
watch
|
||||
let _ = watch
|
||||
.config
|
||||
.backend
|
||||
.notify(app, OverlayEventData::DevicesChanged)?;
|
||||
.notify(app, OverlayEventData::DevicesChanged);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user