From eb917648c132ab002a1d4a5c42227ae41483899a Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Mon, 23 Feb 2026 20:28:23 +0100 Subject: [PATCH] control-center: add compositor pane --- src/control_center.rs | 31 +++++----- src/control_center/cc_compositor.rs | 88 +++++++++++++++++++++++++++++ src/control_center/cc_sidebar.rs | 19 +++++-- src/logger.rs | 1 - src/state.rs | 5 +- 5 files changed, 122 insertions(+), 22 deletions(-) create mode 100644 src/control_center/cc_compositor.rs diff --git a/src/control_center.rs b/src/control_center.rs index c49dfbad..9ca3ca01 100644 --- a/src/control_center.rs +++ b/src/control_center.rs @@ -1,5 +1,6 @@ use { crate::{ + control_center::cc_compositor::CompositorPane, egui_adapter::egui_platform::{ EggError, EggWindow, EggWindowOwner, icons::{ICON_CLOSE, ICON_DRAG_INDICATOR, ICON_INFO}, @@ -29,6 +30,7 @@ use { thiserror::Error, }; +mod cc_compositor; mod cc_sidebar; #[derive(Debug, Error)] @@ -62,7 +64,7 @@ pub struct ControlCenters { bitflags! { ControlCenterInterest: u32; - _UNUSED, + CCI_COMPOSITOR, } pub struct ControlCenter { @@ -102,7 +104,9 @@ struct PaneState { errors: Vec, } -enum PaneType {} +enum PaneType { + Compositor(CompositorPane), +} struct CcBehavior<'a> { #[expect(dead_code)] @@ -118,18 +122,24 @@ impl ControlCenters { } impl Pane { - fn title(&self, _res: &mut String) { - match self.ty {} + fn title(&self, res: &mut String) { + match &self.ty { + PaneType::Compositor(v) => v.title(res), + } } - fn show(&mut self, _behavior: &mut CcBehavior<'_>, _ui: &mut Ui) { - match self.ty {} + fn show(&mut self, _behavior: &mut CcBehavior<'_>, ui: &mut Ui) { + match &mut self.ty { + PaneType::Compositor(p) => p.show(ui), + } } } impl PaneType { fn interest(&self) -> ControlCenterInterest { - match *self {} + match self { + PaneType::Compositor(_) => CCI_COMPOSITOR, + } } } @@ -305,7 +315,6 @@ impl State { Ok(cc) } - #[expect(dead_code)] pub fn trigger_cci(&self, cci: ControlCenterInterest) { self.control_centers.change.or_assign(cci); self.control_centers.redraw.trigger(); @@ -348,8 +357,6 @@ impl ControlCenterInner { } fn open(&self, tree: &mut Tree, ty: PaneType) { - let _ = tree; - #[expect(unused_variables, unreachable_code)] let pane = self.create_pane(ty); let id = tree.tiles.insert_pane(pane); if let Some(root) = tree.root @@ -438,7 +445,6 @@ fn show_errors(ui: &mut Ui, pane: &mut PaneState) { ui.separator(); } -#[expect(dead_code)] fn grid( ui: &mut Ui, id_salt: impl Hash, @@ -467,7 +473,6 @@ fn row_ui( add_contents(ui) } -#[expect(dead_code)] fn bool(ui: &mut Ui, name: &str, old: bool, set: impl FnOnce(bool)) { bool_ui(ui, name, |_| (), old, set); } @@ -497,7 +502,6 @@ fn read_only_bool_ui(ui: &mut Ui, name: &str, label: impl FnOnce(&mut Ui) -> }); } -#[expect(dead_code)] fn combo_box(ui: &mut Ui, name: &str, old: T, set: impl FnOnce(T)) where T: StaticText + Linearize + PartialEq + Copy, @@ -566,7 +570,6 @@ fn drag_value_ui( }); } -#[expect(dead_code)] fn label(ui: &mut Ui, name: &str, text: impl Into) { row(ui, name, |ui| ui.label(text)); } diff --git a/src/control_center/cc_compositor.rs b/src/control_center/cc_compositor.rs new file mode 100644 index 00000000..e1bce419 --- /dev/null +++ b/src/control_center/cc_compositor.rs @@ -0,0 +1,88 @@ +use { + crate::{ + compositor::{LIBEI_SOCKET, WAYLAND_DISPLAY}, + control_center::{ControlCenterInner, bool, combo_box, grid, label, row}, + state::State, + version::VERSION, + }, + egui::{DragValue, OpenUrl, Ui, Widget}, + std::rc::Rc, +}; + +pub struct CompositorPane { + state: Rc, + switch_to_vt: u32, +} + +impl ControlCenterInner { + pub fn create_compositor_pane(self: &Rc) -> CompositorPane { + CompositorPane { + state: self.state.clone(), + switch_to_vt: 1, + } + } +} + +impl CompositorPane { + pub fn title(&self, res: &mut String) { + res.push_str("Compositor"); + } + + pub fn show(&mut self, ui: &mut Ui) { + let s = &self.state; + grid(ui, "compositor", |ui| { + row(ui, "Repository", |ui| { + let url = "https://github.com/mahkoh/jay"; + if ui.link(url).clicked() { + ui.ctx().open_url(OpenUrl::new_tab(url)); + } + }); + label(ui, "Version", VERSION); + label(ui, "PID", s.pid.to_string()); + if let Some(acceptor) = s.acceptor.get() { + label(ui, WAYLAND_DISPLAY, acceptor.socket_name()); + } + if let Some(dir) = &s.config_dir { + label(ui, "Config DIR", dir); + } + bool(ui, "Libei Socket", s.enable_ei_acceptor.get(), |v| { + s.set_ei_socket_enabled(v); + }); + if let Some(a) = s.ei_acceptor.get() { + label(ui, LIBEI_SOCKET, a.socket_name()); + } + combo_box( + ui, + "Workspace Display Order", + s.workspace_display_order.get(), + |o| s.set_workspace_display_order(o), + ); + if let Some(logger) = &s.logger { + combo_box(ui, "Log Level", logger.level(), |l| s.set_log_level(l)); + row(ui, "Log File", |ui| { + let path = logger.path().to_string(); + if ui + .link(&path) + .on_hover_text_at_pointer("Copy to clipboard") + .clicked() + { + ui.ctx().copy_text(path); + } + }); + } + }); + if ui.button("Quit").clicked() { + s.quit(); + } + if ui.button("Reload Config").clicked() { + s.reload_config(); + } + ui.horizontal(|ui| { + let button = ui.button("Switch to VT"); + DragValue::new(&mut self.switch_to_vt).ui(ui); + if button.clicked() { + s.backend.get().switch_to(self.switch_to_vt); + } + }); + } +} diff --git a/src/control_center/cc_sidebar.rs b/src/control_center/cc_sidebar.rs index 2b76420b..f1a484d1 100644 --- a/src/control_center/cc_sidebar.rs +++ b/src/control_center/cc_sidebar.rs @@ -1,5 +1,5 @@ use { - crate::control_center::{ControlCenterInner, Pane}, + crate::control_center::{ControlCenterInner, Pane, PaneType}, egui::{Align, Layout, ScrollArea, Ui, ViewportCommand}, egui_tiles::Tree, linearize::{Linearize, LinearizeExt}, @@ -7,11 +7,15 @@ use { }; #[derive(Copy, Clone, Linearize)] -enum PaneName {} +enum PaneName { + Compositor, +} impl PaneName { fn name(self) -> &'static str { - match self {} + match self { + PaneName::Compositor => "Compositor", + } } } @@ -34,9 +38,12 @@ impl ControlCenterInner { ScrollArea::vertical().show(ui, |ui| { for &ty in &*TYPES { if ui.button(ty.name()).clicked() { - let _ty = match ty {}; - #[expect(unreachable_code)] - self.open(tree, _ty); + let ty = match ty { + PaneName::Compositor => { + PaneType::Compositor(self.create_compositor_pane()) + } + }; + self.open(tree, ty); ui.ctx().request_repaint(); } } diff --git a/src/logger.rs b/src/logger.rs index 22c4118a..a344abbd 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -80,7 +80,6 @@ impl Logger { log::set_max_level(filter); } - #[expect(dead_code)] pub fn level(&self) -> LogLevel { self.level.load(Relaxed) } diff --git a/src/state.rs b/src/state.rs index 92e4daa6..a6c6cfaa 100644 --- a/src/state.rs +++ b/src/state.rs @@ -16,7 +16,7 @@ use { cmm::{cmm_description::ColorDescription, cmm_manager::ColorManager}, compositor::{LIBEI_SOCKET, LogLevel}, config::ConfigProxy, - control_center::ControlCenters, + control_center::{CCI_COMPOSITOR, ControlCenters}, copy_device::CopyDeviceRegistry, cpu_worker::CpuWorker, criteria::{clm::ClMatcherManager, tlm::TlMatcherManager}, @@ -1729,6 +1729,7 @@ impl State { pub fn set_log_level(&self, level: LogLevel) { if let Some(logger) = &self.logger { logger.set_level(level); + self.trigger_cci(CCI_COMPOSITOR); } } @@ -1787,6 +1788,7 @@ impl State { pub fn set_ei_socket_enabled(self: &Rc, enabled: bool) { self.enable_ei_acceptor.set(enabled); self.update_ei_acceptor(); + self.trigger_cci(CCI_COMPOSITOR); } pub fn set_workspace_display_order(&self, order: WorkspaceDisplayOrder) { @@ -1794,6 +1796,7 @@ impl State { for output in self.root.outputs.lock().values() { output.handle_workspace_display_order_update(); } + self.trigger_cci(CCI_COMPOSITOR); } fn spaces_changed(&self) {