diff --git a/Cargo.lock b/Cargo.lock
index 79e09859..2e8f4b67 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6930,6 +6930,7 @@ dependencies = [
"serde",
"serde_json",
"smol",
+ "strum",
"walkdir",
"wayvr-ipc",
"wgui",
diff --git a/dash-frontend/assets/dashboard/down.svg b/dash-frontend/assets/dashboard/down.svg
new file mode 120000
index 00000000..5ab12e3e
--- /dev/null
+++ b/dash-frontend/assets/dashboard/down.svg
@@ -0,0 +1 @@
+../../../wlx-overlay-s/src/assets/keyboard/down.svg
\ No newline at end of file
diff --git a/dash-frontend/assets/gui/t_dropdown_button.xml b/dash-frontend/assets/gui/t_dropdown_button.xml
new file mode 100644
index 00000000..d9604071
--- /dev/null
+++ b/dash-frontend/assets/gui/t_dropdown_button.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dash-frontend/assets/gui/tab/settings.xml b/dash-frontend/assets/gui/tab/settings.xml
index cb29c7e9..b2b635f7 100644
--- a/dash-frontend/assets/gui/tab/settings.xml
+++ b/dash-frontend/assets/gui/tab/settings.xml
@@ -1,6 +1,7 @@
+
@@ -27,7 +28,10 @@
-
+
diff --git a/dash-frontend/assets/lang/en.json b/dash-frontend/assets/lang/en.json
index 0516089d..77e1bb57 100644
--- a/dash-frontend/assets/lang/en.json
+++ b/dash-frontend/assets/lang/en.json
@@ -69,7 +69,16 @@
"CLEAR_SAVED_STATE_HELP": "Reset sets & overlay positions",
"CLEAR_PIPEWIRE_TOKENS_HELP": "Prompt for screen selection on next start",
"DELETE_ALL_CONFIGS_HELP": "Remove all configuration files from conf.d",
- "RESTART_SOFTWARE_HELP": "Apply settings that require a restart"
+ "RESTART_SOFTWARE_HELP": "Apply settings that require a restart",
+
+ "CAPTURE_METHOD": "Wayland screen capture",
+ "CAPTURE_METHOD_HELP": "Try changing this if experiencing\nblack or glitchy screens",
+
+ "OPTION": {
+ "PIPEWIRE_HELP": "Fast GPU capture. Recommended",
+ "PW_FALLBACK_HELP": "Slow. Try in case PipeWire GPU doesn't work",
+ "SCREENCOPY_HELP": "Slow. Works on: Hyprland, Niri, River, Sway"
+ }
},
"APPLICATION_LAUNCHER": "Application launcher",
"APPLICATION_STARTED": "Application started",
diff --git a/dash-frontend/src/tab/settings.rs b/dash-frontend/src/tab/settings.rs
index f50375c2..d26bd9c2 100644
--- a/dash-frontend/src/tab/settings.rs
+++ b/dash-frontend/src/tab/settings.rs
@@ -1,13 +1,18 @@
-use std::{collections::HashMap, marker::PhantomData, rc::Rc};
+use std::{collections::HashMap, marker::PhantomData, rc::Rc, str::FromStr};
-use strum::AsRefStr;
+use glam::Vec2;
+use strum::{AsRefStr, EnumProperty, EnumString, VariantArray};
use wgui::{
assets::AssetPath,
components::{button::ComponentButton, checkbox::ComponentCheckbox, slider::ComponentSlider},
+ event::{CallbackDataCommon, EventAlterables},
+ i18n::Translation,
layout::{Layout, WidgetID},
log::LogErr,
parser::{Fetchable, ParseDocumentParams, ParserState},
task::Tasks,
+ widget::label::WidgetLabel,
+ windowing::context_menu::{self, Blueprint, ContextMenu, TickResult},
};
use wlx_common::{config::GeneralConfig, config_io::ConfigRoot};
@@ -20,6 +25,7 @@ enum Task {
UpdateBool(SettingType, bool),
UpdateFloat(SettingType, f32),
UpdateInt(SettingType, i32),
+ OpenContextMenu(Vec2, Vec),
ClearPipewireTokens,
ClearSavedState,
DeleteAllConfigs,
@@ -30,6 +36,8 @@ pub struct TabSettings {
#[allow(dead_code)]
pub state: ParserState,
+ context_menu: ContextMenu,
+
tasks: Tasks,
marker: PhantomData,
}
@@ -76,17 +84,56 @@ impl Tab for TabSettings {
frontend.interface.restart(data);
return Ok(());
}
+ Task::OpenContextMenu(position, cells) => {
+ self.context_menu.open(context_menu::OpenParams {
+ on_custom_attribs: None,
+ position,
+ blueprint: Blueprint::Cells(cells),
+ });
+ }
}
}
+
+ // Dropdown handling
+ if let TickResult::Action(name) = self.context_menu.tick(&mut frontend.layout, &mut self.state)? {
+ if let (Some(setting), Some(id), Some(value), Some(text), Some(translated)) = {
+ let mut s = name.splitn(5, ';');
+ (s.next(), s.next(), s.next(), s.next(), s.next())
+ } {
+ let mut label = self
+ .state
+ .fetch_widget_as::(&frontend.layout.state, &format!("{id}_value"))?;
+
+ let mut alterables = EventAlterables::default();
+ let mut common = CallbackDataCommon {
+ alterables: &mut alterables,
+ state: &frontend.layout.state,
+ };
+
+ let translation = Translation {
+ text: text.into(),
+ translated: translated == "1",
+ };
+
+ label.set_text(&mut common, translation);
+
+ let setting = SettingType::from_str(setting).expect("Invalid Enum string");
+ setting.set_enum(config, value);
+ changed = true;
+ }
+ }
+
+ // Notify overlays of the change
if changed {
frontend.interface.config_changed(data);
}
+
Ok(())
}
}
#[allow(clippy::enum_variant_names)]
-#[derive(Clone, Copy, AsRefStr)]
+#[derive(Clone, Copy, AsRefStr, EnumString)]
enum SettingType {
AnimationSpeed,
RoundMultiplier,
@@ -120,6 +167,7 @@ enum SettingType {
HideUsername,
OpaqueBackground,
XwaylandByDefault,
+ CaptureMethod,
}
impl SettingType {
@@ -173,6 +221,40 @@ impl SettingType {
}
}
+ pub fn set_enum<'a>(self, config: &'a mut GeneralConfig, value: &str) {
+ match self {
+ Self::CaptureMethod => {
+ config.capture_method = wlx_common::config::CaptureMethod::from_str(value).expect("Invalid enum value!")
+ }
+ _ => panic!("Requested enum for non-enum SettingType"),
+ }
+ }
+
+ fn get_enum_title<'a>(self, config: &'a mut GeneralConfig) -> Translation {
+ match self {
+ Self::CaptureMethod => Self::get_enum_title_inner(config.capture_method),
+ _ => panic!("Requested enum for non-enum SettingType"),
+ }
+ }
+
+ fn get_enum_title_inner(value: E) -> Translation
+ where
+ E: EnumProperty + AsRef,
+ {
+ value
+ .get_str("Translation")
+ .map(|x| Translation::from_translation_key(x))
+ .or_else(|| value.get_str("Text").map(|x| Translation::from_raw_text(x)))
+ .unwrap_or_else(|| Translation::from_raw_text(value.as_ref()))
+ }
+
+ fn get_enum_tooltip_inner(value: E) -> Option
+ where
+ E: EnumProperty + AsRef,
+ {
+ value.get_str("Tooltip").map(|x| Translation::from_translation_key(x))
+ }
+
/// Ok is translation, Err is raw text
fn get_translation(self) -> Result<&'static str, &'static str> {
match self {
@@ -208,6 +290,7 @@ impl SettingType {
Self::HideUsername => Ok("APP_SETTINGS.HIDE_USERNAME"),
Self::OpaqueBackground => Ok("APP_SETTINGS.OPAQUE_BACKGROUND"),
Self::XwaylandByDefault => Ok("APP_SETTINGS.XWAYLAND_BY_DEFAULT"),
+ Self::CaptureMethod => Ok("APP_SETTINGS.CAPTURE_METHOD"),
}
}
@@ -224,6 +307,7 @@ impl SettingType {
Self::UseSkybox => Some("APP_SETTINGS.USE_SKYBOX_HELP"),
Self::UsePassthrough => Some("APP_SETTINGS.USE_PASSTHROUGH_HELP"),
Self::ScreenRenderDown => Some("APP_SETTINGS.SCREEN_RENDER_DOWN_HELP"),
+ Self::CaptureMethod => Some("APP_SETTINGS.CAPTURE_METHOD_HELP"),
_ => None,
}
}
@@ -381,6 +465,72 @@ macro_rules! slider_i32 {
};
}
+macro_rules! dropdown {
+ ($mp:expr, $root:expr, $setting:expr, $options:expr) => {
+ let id = $mp.idx.to_string();
+ $mp.idx += 1;
+
+ let mut params: HashMap, Rc> = HashMap::new();
+ params.insert(Rc::from("id"), Rc::from(id.as_ref()));
+
+ match $setting.get_translation() {
+ Ok(translation) => params.insert(Rc::from("translation"), translation.into()),
+ Err(raw_text) => params.insert(Rc::from("text"), raw_text.into()),
+ };
+
+ if let Some(tooltip) = $setting.get_tooltip() {
+ params.insert(Rc::from("tooltip"), Rc::from(tooltip));
+ }
+
+ $mp
+ .parser_state
+ .instantiate_template($mp.doc_params, "DropdownButton", $mp.layout, $root, params)?;
+
+ let setting_str = $setting.as_ref();
+ let title = $setting.get_enum_title($mp.config);
+
+ {
+ let mut label = $mp
+ .parser_state
+ .fetch_widget_as::(&$mp.layout.state, &format!("{id}_value"))?;
+ label.set_text_simple(&mut $mp.layout.state.globals.get(), title);
+ }
+
+ let btn = $mp.parser_state.fetch_component_as::(&id)?;
+ btn.on_click(Box::new({
+ let tasks = $mp.tasks.clone();
+ move |_common, e| {
+ tasks.push(Task::OpenContextMenu(
+ e.mouse_pos_absolute.unwrap_or_default(),
+ $options
+ .iter()
+ .filter_map(|item| {
+ if item.get_bool("Hidden").unwrap_or(false) {
+ return None;
+ }
+
+ let value = item.as_ref();
+ let title = SettingType::get_enum_title_inner(*item);
+ let tooltip = SettingType::get_enum_tooltip_inner(*item);
+
+ let text = &title.text;
+ let translated = if title.translated { "1" } else { "0" };
+
+ Some(context_menu::Cell {
+ action_name: Some(format!("{setting_str};{id};{value};{text};{translated}").into()),
+ title,
+ tooltip,
+ attribs: vec![],
+ })
+ })
+ .collect(),
+ ));
+ Ok(())
+ }
+ }));
+ };
+}
+
macro_rules! button {
($mp:expr, $root:expr, $translation:expr, $icon:expr, $task:expr) => {
let id = $mp.idx.to_string();
@@ -474,27 +624,33 @@ impl TabSettings {
checkbox!(mp, c, SettingType::UprightScreenFix);
checkbox!(mp, c, SettingType::DoubleCursorFix);
checkbox!(mp, c, SettingType::ScreenRenderDown);
+ dropdown!(
+ mp,
+ c,
+ SettingType::CaptureMethod,
+ wlx_common::config::CaptureMethod::VARIANTS
+ );
let c = category!(mp, root, "APP_SETTINGS.TROUBLESHOOTING", "dashboard/blocks.svg")?;
- button!(
- mp,
- c,
- "APP_SETTINGS.CLEAR_SAVED_STATE",
- "dashboard/remove_circle.svg",
- Task::ClearSavedState
- );
button!(
mp,
c,
"APP_SETTINGS.CLEAR_PIPEWIRE_TOKENS",
- "dashboard/remove_circle.svg",
+ "dashboard/display.svg",
Task::ClearPipewireTokens
);
+ button!(
+ mp,
+ c,
+ "APP_SETTINGS.CLEAR_SAVED_STATE",
+ "dashboard/binary.svg",
+ Task::ClearSavedState
+ );
button!(
mp,
c,
"APP_SETTINGS.DELETE_ALL_CONFIGS",
- "dashboard/remove_circle.svg",
+ "dashboard/circle.svg",
Task::DeleteAllConfigs
);
button!(
@@ -509,6 +665,7 @@ impl TabSettings {
tasks: mp.tasks,
state: parser_state,
marker: PhantomData,
+ context_menu: ContextMenu::default(),
})
}
}
diff --git a/uidev/src/testbed/testbed_generic.rs b/uidev/src/testbed/testbed_generic.rs
index 68168aa3..334619b0 100644
--- a/uidev/src/testbed/testbed_generic.rs
+++ b/uidev/src/testbed/testbed_generic.rs
@@ -259,8 +259,10 @@ impl TestbedGeneric {
on_custom_attribs: Some(Rc::new(move |custom_attribs| {
log::info!("custom attribs {:?}", custom_attribs.pairs);
})),
- template_name: "my_context_menu".into(),
- template_params: Default::default(),
+ blueprint: context_menu::Blueprint::Template {
+ template_name: "my_context_menu".into(),
+ template_params: Default::default(),
+ },
position,
});
}
diff --git a/wgui/assets/wgui/context_menu.xml b/wgui/assets/wgui/context_menu.xml
index 4768639c..0e0cd222 100644
--- a/wgui/assets/wgui/context_menu.xml
+++ b/wgui/assets/wgui/context_menu.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/wgui/src/components/radio_group.rs b/wgui/src/components/radio_group.rs
index 1a3b3b59..4c047a9f 100644
--- a/wgui/src/components/radio_group.rs
+++ b/wgui/src/components/radio_group.rs
@@ -1,10 +1,10 @@
use std::{cell::RefCell, rc::Rc};
use crate::{
- components::{Component, ComponentBase, ComponentTrait, RefreshData, checkbox::ComponentCheckbox},
+ components::{checkbox::ComponentCheckbox, Component, ComponentBase, ComponentTrait, RefreshData},
event::CallbackDataCommon,
layout::WidgetPair,
- widget::{ConstructEssentials, div::WidgetDiv},
+ widget::{div::WidgetDiv, ConstructEssentials},
};
pub struct RadioValueChangeEvent {
diff --git a/wgui/src/components/tooltip.rs b/wgui/src/components/tooltip.rs
index ec8e0167..8c3d1c94 100644
--- a/wgui/src/components/tooltip.rs
+++ b/wgui/src/components/tooltip.rs
@@ -9,11 +9,11 @@ use crate::{
layout::{self, LayoutTask, LayoutTasks, WidgetID, WidgetPair},
renderer_vk::text::{FontWeight, TextStyle},
widget::{
- ConstructEssentials,
div::WidgetDiv,
label::{WidgetLabel, WidgetLabelParams},
rectangle::{WidgetRectangle, WidgetRectangleParams},
util::WLength,
+ ConstructEssentials,
},
};
diff --git a/wgui/src/parser/mod.rs b/wgui/src/parser/mod.rs
index eab1da8f..7f1c1444 100644
--- a/wgui/src/parser/mod.rs
+++ b/wgui/src/parser/mod.rs
@@ -259,11 +259,11 @@ impl ParserState {
Ok(())
}
- pub(crate) fn context_menu_create_blueprint(
+ pub(crate) fn context_menu_parse_cells(
&mut self,
template_name: &str,
template_params: &HashMap, Rc>,
- ) -> anyhow::Result {
+ ) -> anyhow::Result> {
let Some(template) = self.data.templates.get(template_name) else {
anyhow::bail!("no template named \"{template_name}\" found");
};
@@ -283,6 +283,7 @@ impl ParserState {
"" => {}
"cell" => {
let mut title: Option = None;
+ let mut tooltip: Option = None;
let mut action_name: Option> = None;
let mut attribs = Vec::::new();
@@ -292,6 +293,8 @@ impl ParserState {
match key {
"text" => title = Some(Translation::from_raw_text(value)),
"translation" => title = Some(Translation::from_translation_key(value)),
+ "tooltip" => tooltip = Some(Translation::from_translation_key(value)),
+ "tooltip_str" => tooltip = Some(Translation::from_raw_text(value)),
"action" => action_name = Some(value.into()),
other => {
if !other.starts_with('_') {
@@ -305,6 +308,7 @@ impl ParserState {
let title = title.context("No text/translation provided")?;
cells.push(context_menu::Cell {
title,
+ tooltip,
action_name,
attribs,
});
@@ -316,9 +320,7 @@ impl ParserState {
}
Ok(
- context_menu::Blueprint {
cells,
- }
)
}
}
diff --git a/wgui/src/windowing/context_menu.rs b/wgui/src/windowing/context_menu.rs
index 20f30d52..5bf560bf 100644
--- a/wgui/src/windowing/context_menu.rs
+++ b/wgui/src/windowing/context_menu.rs
@@ -15,19 +15,23 @@ use crate::{
pub struct Cell {
pub title: Translation,
+ pub tooltip: Option,
pub action_name: Option>,
pub attribs: Vec,
}
-pub(crate) struct Blueprint {
- pub cells: Vec,
+pub enum Blueprint {
+ Cells(Vec| ),
+ Template {
+ template_name: Rc,
+ template_params: HashMap, Rc>,
+ },
}
pub struct OpenParams {
pub on_custom_attribs: Option,
- pub template_name: Rc,
- pub template_params: HashMap, Rc>,
pub position: Vec2,
+ pub blueprint: Blueprint,
}
#[derive(Clone)]
@@ -74,11 +78,17 @@ impl ContextMenu {
fn open_process(
&mut self,
- params: &mut OpenParams,
+ params: OpenParams,
layout: &mut Layout,
parser_state: &mut ParserState,
) -> anyhow::Result<()> {
- let blueprint = parser_state.context_menu_create_blueprint(¶ms.template_name, ¶ms.template_params)?;
+ let cells = match params.blueprint {
+ Blueprint::Template {
+ template_name,
+ template_params,
+ } => parser_state.context_menu_parse_cells(&template_name, &template_params)?,
+ Blueprint::Cells(cells) => cells,
+ };
let globals = layout.state.globals.clone();
@@ -100,9 +110,13 @@ impl ContextMenu {
let id_buttons = inner_parser.get_widget_id("buttons")?;
- for (idx, cell) in blueprint.cells.iter().enumerate() {
+ for (idx, cell) in cells.iter().enumerate() {
let mut par = HashMap::new();
par.insert(Rc::from("text"), cell.title.generate(&mut globals.i18n()));
+ if let Some(tooltip) = cell.tooltip.as_ref() {
+ par.insert(Rc::from("tooltip_str"), tooltip.generate(&mut globals.i18n()));
+ }
+
let mut data_cell = inner_parser.parse_template(&doc_params, "Cell", layout, id_buttons, par)?;
let button = data_cell.fetch_component_as::("button")?;
@@ -112,7 +126,7 @@ impl ContextMenu {
.tasks
.handle_button(&button, Task::ActionClicked(cell.action_name.clone()));
- if let Some(c) = &mut params.on_custom_attribs {
+ if let Some(c) = params.on_custom_attribs.as_ref() {
(*c)(parser::CustomAttribsInfo {
pairs: &cell.attribs,
parent_id: id_buttons,
@@ -121,7 +135,7 @@ impl ContextMenu {
});
}
- if idx < blueprint.cells.len() - 1 {
+ if idx < cells.len() - 1 {
inner_parser.parse_template(&doc_params, "Separator", layout, id_buttons, Default::default())?;
}
}
@@ -129,8 +143,8 @@ impl ContextMenu {
}
pub fn tick(&mut self, layout: &mut Layout, parser_state: &mut ParserState) -> anyhow::Result {
- if let Some(mut p) = self.pending_open.take() {
- self.open_process(&mut p, layout, parser_state)?;
+ if let Some(p) = self.pending_open.take() {
+ self.open_process(p, layout, parser_state)?;
let _ = self.tasks.drain();
return Ok(TickResult::Opened);
}
diff --git a/wlx-common/Cargo.toml b/wlx-common/Cargo.toml
index 83de42e4..fe2d64e7 100644
--- a/wlx-common/Cargo.toml
+++ b/wlx-common/Cargo.toml
@@ -14,7 +14,9 @@ idmap-derive.workspace = true
log.workspace = true
serde = { workspace = true, features = ["rc"] }
serde_json.workspace = true
+strum.workspace = true
xdg.workspace = true
+
chrono = "0.4.42"
smol = "2.0.2"
wgui = { path = "../wgui/" }
diff --git a/wlx-common/src/config.rs b/wlx-common/src/config.rs
index d897d2a8..f25e9532 100644
--- a/wlx-common/src/config.rs
+++ b/wlx-common/src/config.rs
@@ -3,6 +3,7 @@ use std::{collections::HashMap, sync::Arc};
use chrono::Offset;
use idmap::IdMap;
use serde::{Deserialize, Serialize};
+use strum::{AsRefStr, EnumProperty, EnumString, VariantArray};
use crate::{
astr_containers::{AStrMap, AStrSet},
@@ -13,6 +14,22 @@ use crate::{
pub type PwTokenMap = AStrMap;
pub type SerializedWindowStates = HashMap, OverlayWindowState>;
+#[derive(Default, Clone, Copy, Serialize, Deserialize, AsRefStr, EnumString, EnumProperty, VariantArray)]
+pub enum CaptureMethod {
+ #[default]
+ #[serde(alias = "pipewire", alias = "auto")]
+ #[strum(props(Text = "PipeWire GPU", Tooltip = "APP_SETTINGS.OPTION.PIPEWIRE_HELP"))]
+ PipeWire,
+
+ #[serde(alias = "pw-fallback")]
+ #[strum(props(Text = "PipeWire CPU", Tooltip = "APP_SETTINGS.OPTION.PW_FALLBACK_HELP"))]
+ PwFallback,
+
+ #[serde(alias = "screencopy")]
+ #[strum(props(Text = "ScreenCopy CPU", Tooltip = "APP_SETTINGS.OPTION.SCREENCOPY_HELP"))]
+ ScreenCopy,
+}
+
#[derive(Clone, Serialize, Deserialize)]
pub struct SerializedWindowSet {
pub name: Arc,
@@ -76,10 +93,6 @@ fn def_timezones() -> Vec {
}
}
-fn def_auto() -> Arc {
- "auto".into()
-}
-
fn def_empty() -> Arc {
"".into()
}
@@ -174,8 +187,8 @@ pub struct GeneralConfig {
#[serde(default)]
pub custom_panels: AStrSet,
- #[serde(default = "def_auto")]
- pub capture_method: Arc,
+ #[serde(default)]
+ pub capture_method: CaptureMethod,
#[serde(default = "def_point7")]
pub xr_click_sensitivity: f32,
diff --git a/wlx-overlay-s/src/config.rs b/wlx-overlay-s/src/config.rs
index 1158ff49..72bdf98d 100644
--- a/wlx-overlay-s/src/config.rs
+++ b/wlx-overlay-s/src/config.rs
@@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use wlx_common::{
astr_containers::AStrMap,
- config::{GeneralConfig, SerializedWindowSet, SerializedWindowStates},
+ config::{CaptureMethod, GeneralConfig, SerializedWindowSet, SerializedWindowStates},
config_io,
overlays::BackendAttribValue,
};
@@ -138,6 +138,7 @@ pub struct AutoSettings {
pub opaque_background: bool,
pub xwayland_by_default: bool,
pub context_menu_hold_and_release: bool,
+ pub capture_method: CaptureMethod,
}
fn get_settings_path() -> PathBuf {
@@ -181,6 +182,7 @@ pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> {
opaque_background: config.opaque_background,
xwayland_by_default: config.xwayland_by_default,
context_menu_hold_and_release: config.context_menu_hold_and_release,
+ capture_method: config.capture_method,
};
let json = serde_json::to_string_pretty(&conf).unwrap(); // want panic
diff --git a/wlx-overlay-s/src/gui/panel/button.rs b/wlx-overlay-s/src/gui/panel/button.rs
index c5b501c0..69f8e90c 100644
--- a/wlx-overlay-s/src/gui/panel/button.rs
+++ b/wlx-overlay-s/src/gui/panel/button.rs
@@ -20,7 +20,7 @@ use wgui::{
parser::{self, AttribPair, CustomAttribsInfoOwned, Fetchable, ParserState},
taffy,
widget::EventResult,
- windowing::context_menu::{ContextMenu, OpenParams},
+ windowing::context_menu::{Blueprint, ContextMenu, OpenParams},
};
use wlx_common::overlays::ToastTopic;
@@ -207,8 +207,9 @@ pub(super) fn setup_custom_button(
let callback: EventCallback = match command {
"::ContextMenuOpen" => {
let Some(template_name) = args.next() else {
- log::warn!(
- "{command} has incorrect arguments. Should be: {command} "
+ log::error!(
+ "{:?}: {command} has invalid arguments",
+ parser_state.path.get_path_buf()
);
return;
};
@@ -230,8 +231,10 @@ pub(super) fn setup_custom_button(
move |_common, data, _app, _| {
context_menu.borrow_mut().open(OpenParams {
on_custom_attribs: Some(on_custom_attribs.clone()),
- template_name: template_name.clone(),
- template_params: template_params.clone(),
+ blueprint: Blueprint::Template {
+ template_name: template_name.clone(),
+ template_params: template_params.clone(),
+ },
position: data.metadata.get_mouse_pos_absolute().unwrap(), //want panic
});
Ok(EventResult::Consumed)
@@ -249,14 +252,18 @@ pub(super) fn setup_custom_button(
}
"::ElementSetDisplay" => {
let (Some(id), Some(value)) = (args.next(), args.next()) else {
- log::warn!(
- "{command} has incorrect arguments. Should be: {command} "
+ log::error!(
+ "{:?}: {command} has invalid arguments",
+ parser_state.path.get_path_buf()
);
return;
};
let Ok(widget_id) = parser_state.data.get_widget_id(id) else {
- log::warn!("{command}: no element exists with ID '{id}'");
+ log::warn!(
+ "{:?}: {command}: no element exists with ID '{id}'",
+ parser_state.path.get_path_buf()
+ );
return;
};
@@ -290,7 +297,10 @@ pub(super) fn setup_custom_button(
"::SetToggle" => {
let arg = args.next().unwrap_or_default();
let Ok(set_idx) = arg.parse() else {
- log::error!("{command} has invalid argument: \"{arg}\"");
+ log::error!(
+ "{:?}: {command} has invalid argument: \"{arg}\"",
+ parser_state.path.get_path_buf()
+ );
return;
};
Box::new(move |_common, data, app, _| {
@@ -306,7 +316,10 @@ pub(super) fn setup_custom_button(
"::SetSwitch" => {
let arg = args.next().unwrap_or_default();
let Ok(set_idx) = arg.parse::() else {
- log::error!("{command} has invalid argument: \"{arg}\"");
+ log::error!(
+ "{:?}: {command} has invalid argument: \"{arg}\"",
+ parser_state.path.get_path_buf()
+ );
return;
};
let maybe_set = if set_idx < 0 {
@@ -327,7 +340,10 @@ pub(super) fn setup_custom_button(
"::OverlayReset" => {
let arg: Arc = args.collect::>().join(" ").into();
if arg.len() < 1 {
- log::error!("{command} has missing arguments");
+ log::error!(
+ "{:?}: {command} has missing arguments",
+ parser_state.path.get_path_buf()
+ );
return;
};
@@ -346,7 +362,10 @@ pub(super) fn setup_custom_button(
"::OverlayToggle" => {
let arg: Arc = args.collect::>().join(" ").into();
if arg.len() < 1 {
- log::error!("{command} has missing arguments");
+ log::error!(
+ "{:?}: {command} has missing arguments",
+ parser_state.path.get_path_buf()
+ );
return;
};
@@ -366,7 +385,10 @@ pub(super) fn setup_custom_button(
"::OverlayDrop" => {
let arg: Arc = args.collect::>().join(" ").into();
if arg.len() < 1 {
- log::error!("{command} has missing arguments");
+ log::error!(
+ "{:?}: {command} has missing arguments",
+ parser_state.path.get_path_buf()
+ );
return;
};
@@ -402,7 +424,10 @@ pub(super) fn setup_custom_button(
"::CustomOverlayReload" => {
let arg: Arc = args.collect::>().join(" ").into();
if arg.len() < 1 {
- log::error!("{command} has missing arguments");
+ log::error!(
+ "{:?}: {command} has missing arguments",
+ parser_state.path.get_path_buf()
+ );
return;
};
@@ -440,7 +465,10 @@ pub(super) fn setup_custom_button(
"::WvrOverlayCloseWindow" => {
let arg: Arc = args.collect::>().join(" ").into();
if arg.len() < 1 {
- log::error!("{command} has missing arguments");
+ log::error!(
+ "{:?}: {command} has missing arguments",
+ parser_state.path.get_path_buf()
+ );
return;
};
Box::new(move |_common, data, app, _| {
@@ -463,7 +491,10 @@ pub(super) fn setup_custom_button(
"::WvrOverlayKillProcess" | "::WvrOverlayTermProcess" => {
let arg: Arc = args.collect::>().join(" ").into();
if arg.len() < 1 {
- log::error!("{command} has missing arguments");
+ log::error!(
+ "{:?}: {command} has missing arguments",
+ parser_state.path.get_path_buf()
+ );
return;
};
@@ -585,7 +616,10 @@ pub(super) fn setup_custom_button(
}),
"::SendKey" => {
let Some(key) = args.next().and_then(|s| VirtualKey::from_str(s).ok()) else {
- log::error!("{command} has bad/missing arguments");
+ log::error!(
+ "{:?}: {command} has bad/missing arguments",
+ parser_state.path.get_path_buf()
+ );
return;
};
let Some(down) = args.next().and_then(|s| match s.to_lowercase().as_str() {
@@ -593,7 +627,10 @@ pub(super) fn setup_custom_button(
"up" => Some(false),
_ => None,
}) else {
- log::error!("{command} has bad/missing arguments");
+ log::error!(
+ "{:?}: {command} has bad/missing arguments",
+ parser_state.path.get_path_buf()
+ );
return;
};
Box::new(move |_common, data, app, _| {
@@ -640,7 +677,10 @@ pub(super) fn setup_custom_button(
use crate::subsystem::osc::parse_osc_value;
let Some(address) = args.next().map(std::string::ToString::to_string) else {
- log::error!("{command} has missing arguments");
+ log::error!(
+ "{:?}: {command} has bad/missing arguments",
+ parser_state.path.get_path_buf()
+ );
return;
};
diff --git a/wlx-overlay-s/src/gui/panel/mod.rs b/wlx-overlay-s/src/gui/panel/mod.rs
index a8b649fe..cd96d9b6 100644
--- a/wlx-overlay-s/src/gui/panel/mod.rs
+++ b/wlx-overlay-s/src/gui/panel/mod.rs
@@ -1,4 +1,4 @@
-use std::{cell::RefCell, rc::Rc};
+use std::{any, cell::RefCell, rc::Rc};
use button::setup_custom_button;
use glam::{Affine2, Vec2, vec2};
diff --git a/wlx-overlay-s/src/overlays/screen/backend.rs b/wlx-overlay-s/src/overlays/screen/backend.rs
index c84de439..84c23dbc 100644
--- a/wlx-overlay-s/src/overlays/screen/backend.rs
+++ b/wlx-overlay-s/src/overlays/screen/backend.rs
@@ -18,7 +18,10 @@ use crate::{
FrameMeta, OverlayBackend, OverlayEventData, RenderResources, ShouldRender, ui_transform,
},
};
-use wlx_common::overlays::{BackendAttrib, BackendAttribValue, MouseTransform, StereoMode};
+use wlx_common::{
+ config::CaptureMethod,
+ overlays::{BackendAttrib, BackendAttribValue, MouseTransform, StereoMode},
+};
use super::capture::{ScreenPipeline, WlxCaptureIn, WlxCaptureOut, receive_callback};
@@ -144,10 +147,12 @@ impl OverlayBackend for ScreenBackend {
.ext_external_memory_dma_buf
&& self.capture.supports_dmbuf();
- let allow_dmabuf = &*app.session.config.capture_method != "pw_fallback"
- && &*app.session.config.capture_method != "screencopy";
+ let capture_method = app.session.config.capture_method;
- let capture_method = app.session.config.capture_method.clone();
+ let allow_dmabuf = !matches!(
+ capture_method,
+ CaptureMethod::PwFallback | CaptureMethod::ScreenCopy
+ );
let dmabuf_formats = if !supports_dmabuf {
log::info!("Capture method does not support DMA-buf");
@@ -158,7 +163,10 @@ impl OverlayBackend for ScreenBackend {
}
&Vec::new()
} else if !allow_dmabuf {
- log::info!("Not using DMA-buf capture due to {capture_method}");
+ log::info!(
+ "Not using DMA-buf capture due to {}",
+ capture_method.as_ref()
+ );
if app.gfx_extras.queue_capture.is_none() {
log::warn!(
"Current GPU does not support multiple queues. Software capture will take place on the main thread. Expect degraded performance."
diff --git a/wlx-overlay-s/src/overlays/screen/wl.rs b/wlx-overlay-s/src/overlays/screen/wl.rs
index fe77b973..f2d27f6a 100644
--- a/wlx-overlay-s/src/overlays/screen/wl.rs
+++ b/wlx-overlay-s/src/overlays/screen/wl.rs
@@ -6,7 +6,10 @@ use wlx_capture::{
wlr_dmabuf::WlrDmabufCapture,
wlr_screencopy::WlrScreencopyCapture,
};
-use wlx_common::{astr_containers::AStrMapExt, config::PwTokenMap};
+use wlx_common::{
+ astr_containers::AStrMapExt,
+ config::{CaptureMethod, PwTokenMap},
+};
use crate::{
overlays::screen::create_screen_from_backend,
@@ -43,18 +46,14 @@ impl ScreenBackend {
#[allow(clippy::useless_let_if_seq)]
pub fn create_screen_renderer_wl(
output: &WlxOutput,
- has_wlr_dmabuf: bool,
has_wlr_screencopy: bool,
pw_token_store: &mut PwTokenMap,
app: &mut AppState,
) -> Option {
let mut capture: Option = None;
- if (&*app.session.config.capture_method == "wlr-dmabuf") && has_wlr_dmabuf {
- log::info!("{}: Using Wlr DMA-Buf", &output.name);
- capture = ScreenBackend::new_wlr_dmabuf(output, app);
- }
- if &*app.session.config.capture_method == "screencopy" && has_wlr_screencopy {
+ if matches!(app.session.config.capture_method, CaptureMethod::ScreenCopy) && has_wlr_screencopy
+ {
log::info!("{}: Using Wlr Screencopy Wl-SHM", &output.name);
capture = ScreenBackend::new_wlr_screencopy(output, app);
}
@@ -102,7 +101,6 @@ pub fn create_screens_wayland(wl: &mut WlxClient, app: &mut AppState) -> ScreenC
let mut pw_tokens: PwTokenMap = load_pw_token_config().unwrap_or_default();
let pw_tokens_copy = pw_tokens.clone();
- let has_wlr_dmabuf = wl.maybe_wlr_dmabuf_mgr.is_some();
let has_wlr_screencopy = wl.maybe_wlr_screencopy_mgr.is_some();
for (id, output) in &wl.outputs {
@@ -118,13 +116,9 @@ pub fn create_screens_wayland(wl: &mut WlxClient, app: &mut AppState) -> ScreenC
output.logical_pos,
);
- if let Some(mut backend) = create_screen_renderer_wl(
- output,
- has_wlr_dmabuf,
- has_wlr_screencopy,
- &mut pw_tokens,
- app,
- ) {
+ if let Some(mut backend) =
+ create_screen_renderer_wl(output, has_wlr_screencopy, &mut pw_tokens, app)
+ {
backend.logical_pos = vec2(output.logical_pos.0 as f32, output.logical_pos.1 as f32);
backend.logical_size = vec2(output.logical_size.0 as f32, output.logical_size.1 as f32);
backend.mouse_transform_original = output.transform;
| |