bar functionality

This commit is contained in:
galister
2026-01-05 03:57:56 +09:00
parent c3e04e0a89
commit 4dd7c85e79
9 changed files with 330 additions and 151 deletions

View File

@@ -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)
}
}
}
}

View File

@@ -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>

View File

@@ -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);

View File

@@ -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) = &params.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<()> {

View File

@@ -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 {

View File

@@ -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(),
}
}
}

View File

@@ -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)
{

View File

@@ -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>,

View File

@@ -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(())