cosmic-comp/src/debug.rs

428 lines
18 KiB
Rust
Raw Normal View History

// SPDX-License-Identifier: GPL-3.0-only
use crate::state::{Common, Fps};
use smithay::{
backend::drm::DrmNode,
desktop::layer_map_for_output,
reexports::wayland_server::Resource,
2022-08-30 13:28:36 +02:00
utils::{IsAlive, Physical, Rectangle},
};
2022-03-16 20:05:24 +01:00
pub use smithay_egui::EguiFrame;
2022-02-04 21:08:11 +01:00
pub fn fps_ui(
gpu: Option<&DrmNode>,
2022-02-04 21:08:11 +01:00
state: &Common,
fps: &mut Fps,
2022-07-04 16:00:03 +02:00
area: Rectangle<f64, Physical>,
2022-01-18 19:42:56 +01:00
scale: f64,
) -> EguiFrame {
2022-02-04 21:08:11 +01:00
use egui::widgets::plot::{Bar, BarChart, HLine, Legend, Plot};
let (max, min, avg, avg_fps) = (
fps.max_frametime().as_secs_f64(),
fps.min_frametime().as_secs_f64(),
fps.avg_frametime().as_secs_f64(),
fps.avg_fps(),
);
let bars = fps
.frames
.iter()
.rev()
.take(30)
.rev()
.enumerate()
.map(|(i, (_, d))| {
let value = d.as_secs_f64();
let transformed = ((value - min) / (max - min) * 255.0).round() as u8;
Bar::new(i as f64, transformed as f64).fill(egui::Color32::from_rgb(
transformed,
255 - transformed,
0,
))
})
.collect();
fps.state.run(
|ctx| {
egui::Area::new("main")
.anchor(egui::Align2::LEFT_TOP, (10.0, 10.0))
.show(ctx, |ui| {
let label_res = ui.label(format!(
"cosmic-comp version {}",
std::env!("CARGO_PKG_VERSION")
));
if let Some(hash) = std::option_env!("GIT_HASH").and_then(|x| x.get(0..8)) {
ui.label(hash);
}
if !state.egui.active {
ui.label("Press Mod+Escape for debug menu");
} else {
2022-02-04 21:08:11 +01:00
ui.set_max_width(label_res.rect.min.x + label_res.rect.width());
ui.separator();
if let Some(gpu) = gpu {
ui.label(egui::RichText::new(format!("renderD{}", gpu.minor())).code());
}
ui.label(egui::RichText::new(format!("FPS: {:>7.3}", avg_fps)).heading());
ui.label("Frame Times:");
ui.label(egui::RichText::new(format!("avg: {:>7.6}", avg)).code());
ui.label(egui::RichText::new(format!("min: {:>7.6}", min)).code());
ui.label(egui::RichText::new(format!("max: {:>7.6}", max)).code());
2022-02-04 21:08:11 +01:00
let fps_chart = BarChart::new(bars).vertical();
Plot::new("FPS")
.legend(Legend::default())
.view_aspect(33.0)
.include_x(0.0)
.include_x(30.0)
.include_y(0.0)
2022-02-04 21:08:11 +01:00
.include_y(300.0)
.show_x(false)
.show(ui, |plot_ui| {
plot_ui.bar_chart(fps_chart);
plot_ui.hline(
2022-07-04 16:00:29 +02:00
HLine::new(avg)
.highlight(true)
.color(egui::Color32::LIGHT_BLUE),
);
});
}
});
2022-02-04 21:08:11 +01:00
},
area,
scale,
1.0,
&state.start_time,
fps.modifiers.clone(),
)
}
2022-01-18 19:42:56 +01:00
2022-02-04 21:08:11 +01:00
pub fn debug_ui(
state: &mut Common,
2022-07-04 16:00:03 +02:00
area: Rectangle<f64, Physical>,
2022-02-04 21:08:11 +01:00
scale: f64,
) -> Option<EguiFrame> {
if !state.egui.active {
return None;
}
2022-02-05 00:40:17 +01:00
Some(state.egui.debug_state.run(
2022-02-04 21:08:11 +01:00
|ctx| {
2022-07-04 16:00:03 +02:00
use crate::utils::prelude::*;
2022-02-04 21:08:11 +01:00
egui::Window::new("Workspaces")
.default_pos([0.0, 300.0])
.vscroll(true)
.collapsible(true)
.show(ctx, |ui| {
2022-07-04 16:00:03 +02:00
use crate::{
config::WorkspaceMode as ConfigMode,
shell::{OutputBoundState, WorkspaceMode, MAX_WORKSPACES},
};
2022-02-04 21:08:11 +01:00
ui.set_min_width(250.0);
2022-02-04 21:08:11 +01:00
// Mode
2022-02-04 21:08:11 +01:00
ui.label(egui::RichText::new("Mode").heading());
2022-07-04 16:00:03 +02:00
let mut mode = match &state.shell.workspace_mode {
WorkspaceMode::Global { .. } => ConfigMode::Global,
WorkspaceMode::OutputBound => ConfigMode::OutputBound,
2022-02-04 21:08:11 +01:00
};
2022-07-04 16:00:03 +02:00
ui.radio_value(&mut mode, ConfigMode::OutputBound, "Output bound");
ui.radio_value(&mut mode, ConfigMode::Global, "Global");
2022-03-24 20:32:31 +01:00
state.shell.set_mode(mode);
2022-02-04 21:08:11 +01:00
2022-07-04 16:00:03 +02:00
let mode = match &state.shell.workspace_mode {
2022-07-04 16:00:29 +02:00
WorkspaceMode::OutputBound => (ConfigMode::OutputBound, None),
WorkspaceMode::Global { ref active, .. } => {
(ConfigMode::Global, Some(*active))
}
2022-07-04 16:00:03 +02:00
};
match mode {
(ConfigMode::OutputBound, _) => {
2022-02-04 21:08:11 +01:00
ui.label("Workspaces:");
2022-03-24 20:32:31 +01:00
for output in state.shell.outputs().cloned().collect::<Vec<_>>() {
ui.horizontal(|ui| {
2022-02-04 21:08:11 +01:00
let active = output
.user_data()
2022-07-04 16:00:03 +02:00
.get::<OutputBoundState>()
2022-02-04 21:08:11 +01:00
.unwrap()
2022-07-04 16:00:03 +02:00
.active
.get();
let mut active_val = active as f64;
2022-02-04 21:08:11 +01:00
ui.label(output.name());
2022-01-18 19:42:56 +01:00
ui.add(
egui::DragValue::new(&mut active_val)
.clamp_range(0..=(MAX_WORKSPACES - 1))
.speed(1.0),
);
if active != active_val as usize {
state.shell.activate(
&state.seats[0],
&output,
active_val as usize,
);
}
});
}
}
2022-07-04 16:00:03 +02:00
(ConfigMode::Global, Some(active)) => {
2022-02-04 21:08:11 +01:00
ui.horizontal(|ui| {
let mut active_val = active as f64;
ui.label("Workspace:");
ui.add(
egui::DragValue::new(&mut active_val)
.clamp_range(0..=(MAX_WORKSPACES - 1))
.speed(1.0),
);
if active != active_val as usize {
2022-03-24 20:32:31 +01:00
let output = state.shell.outputs().next().cloned().unwrap();
state.shell.activate(
&state.seats[0],
&output,
active_val as usize,
);
2022-02-04 21:08:11 +01:00
}
});
2022-07-04 16:00:29 +02:00
}
2022-07-04 16:00:03 +02:00
_ => unreachable!(),
2022-02-04 21:08:11 +01:00
}
2022-01-18 19:42:56 +01:00
2022-02-04 21:08:11 +01:00
// Spaces
2022-03-24 20:32:31 +01:00
for (i, workspace) in state.shell.spaces.iter().enumerate() {
2022-02-04 21:08:11 +01:00
ui.collapsing(format!("Space: {}", i), |ui| {
ui.collapsing(format!("Windows"), |ui| {
2022-03-24 20:32:31 +01:00
for window in workspace.space.windows() {
2022-02-04 21:08:11 +01:00
ui.collapsing(format!("{:?}", window.toplevel()), |ui| {
2022-03-16 20:05:24 +01:00
ui.label(format!("Rect: {:?}", {
let mut geo = window.geometry();
2022-03-24 20:32:31 +01:00
geo.loc += workspace
.space
2022-03-16 20:05:24 +01:00
.window_location(window)
.unwrap_or((0, 0).into());
geo
}));
2022-02-04 21:08:11 +01:00
ui.label(format!(
"Bounding box: {:?}",
2022-03-24 20:32:31 +01:00
workspace.space.window_bbox(window)
2022-02-04 21:08:11 +01:00
));
});
}
})
});
}
});
egui::Window::new("Outputs")
.collapsible(true)
.hscroll(true)
.default_pos([300.0, 300.0])
.show(ctx, |ui| {
2022-03-24 20:32:31 +01:00
ui.label(format!("Global Space: {:?}", state.shell.global_space()));
2022-03-16 20:01:34 +01:00
for output in state
2022-03-24 20:32:31 +01:00
.shell
2022-03-16 20:01:34 +01:00
.outputs()
.cloned()
.collect::<Vec<_>>()
.into_iter()
{
2022-02-04 21:08:11 +01:00
ui.separator();
ui.collapsing(output.name(), |ui| {
ui.label(format!("Mode: {:#?}", output.current_mode()));
ui.label(format!("Scale: {:#?}", output.current_scale()));
ui.label(format!("Transform: {:#?}", output.current_transform()));
2022-07-04 16:00:29 +02:00
ui.label(format!("Geometry: {:?}", output.geometry()));
2022-03-16 20:01:34 +01:00
ui.label(format!(
"Local Geometry: {:?}",
2022-03-24 20:32:31 +01:00
state
.shell
.active_space(&output)
.space
.output_geometry(&output)
2022-03-16 20:01:34 +01:00
));
ui.label(format!(
"Relative Geometry: {:?}",
2022-07-04 16:00:29 +02:00
state
.shell
.space_relative_output_geometry((0i32, 0i32), &output)
2022-03-16 20:01:34 +01:00
));
ui.separator();
ui.collapsing("Layers:", |ui| {
let map = layer_map_for_output(&output);
for layer in map.layers() {
2022-08-30 13:28:36 +02:00
ui.collapsing(
format!(
"{}/{:?}",
layer.wl_surface().id(),
layer.wl_surface().client_id()
),
|ui| {
ui.label(format!(
"Alive: {:?} {:?} {:?}",
layer.alive(),
layer.layer_surface().alive(),
layer.wl_surface().alive()
));
ui.label(format!("Layer: {:?}", layer.layer()));
ui.label(format!("Namespace: {:?}", layer.namespace()));
ui.label(format!("Geometry: {:?}", layer.bbox()));
ui.label(format!(
"Anchor: {:?}",
layer.cached_state().anchor
));
ui.label(format!(
"Margin: {:?}",
layer.cached_state().margin
));
ui.label(format!(
"Exclusive: {:?}",
layer.cached_state().exclusive_zone
));
},
);
}
ui.label(format!("{:?}", map));
});
2022-02-04 21:08:11 +01:00
});
}
});
},
area,
scale,
2022-02-04 21:08:11 +01:00
state.egui.alpha,
&state.start_time,
state.egui.modifiers.clone(),
2022-02-04 21:08:11 +01:00
))
}
2022-02-05 00:40:17 +01:00
pub fn log_ui(
state: &mut Common,
2022-07-04 16:00:03 +02:00
area: Rectangle<f64, Physical>,
2022-02-05 00:40:17 +01:00
scale: f64,
default_width: f32,
) -> Option<EguiFrame> {
if !state.egui.active {
return None;
}
Some(state.egui.log_state.run(
|ctx| {
egui::SidePanel::right("Log")
2022-03-16 20:01:34 +01:00
.frame(egui::Frame {
2022-07-04 16:00:03 +02:00
inner_margin: egui::Vec2::new(10.0, 10.0).into(),
outer_margin: egui::Vec2::new(0.0, 0.0).into(),
rounding: 5.0.into(),
2022-03-16 20:01:34 +01:00
shadow: egui::epaint::Shadow {
extrusion: 0.0,
color: egui::Color32::TRANSPARENT,
},
fill: egui::Color32::from_black_alpha(100),
stroke: egui::Stroke::none(),
})
.default_width(default_width)
.show(ctx, |ui| {
egui::ScrollArea::vertical()
.always_show_scroll(true)
.stick_to_bottom()
.show(ui, |ui| {
for (_i, record) in state
.log
.debug_buffer
.lock()
.unwrap()
.iter()
.rev()
.enumerate()
{
let mut message = egui::text::LayoutJob::single_section(
record.level.as_short_str().to_string(),
egui::TextFormat::simple(
2022-07-04 16:00:03 +02:00
egui::FontId::monospace(16.0),
2022-03-16 20:01:34 +01:00
match record.level {
slog::Level::Critical => egui::Color32::RED,
slog::Level::Error => egui::Color32::LIGHT_RED,
slog::Level::Warning => egui::Color32::LIGHT_YELLOW,
slog::Level::Info => egui::Color32::LIGHT_BLUE,
slog::Level::Debug => egui::Color32::LIGHT_GREEN,
slog::Level::Trace => egui::Color32::GRAY,
},
),
);
message.append(
&record.message,
6.0,
egui::TextFormat::simple(
2022-07-04 16:00:03 +02:00
egui::FontId::default(),
2022-03-16 20:01:34 +01:00
egui::Color32::WHITE,
),
);
ui.vertical(|ui| {
ui.add(egui::Label::new(message));
ui.add_space(4.0);
for (k, v) in &record.kv {
ui.horizontal(|ui| {
ui.add(
egui::Label::new(egui::RichText::new(k).code())
.sense(egui::Sense::click()),
)
.on_hover_cursor(egui::CursorIcon::PointingHand);
render_value(ui, v);
});
}
2022-02-05 00:40:17 +01:00
});
}
2022-03-16 20:01:34 +01:00
})
});
2022-02-05 00:40:17 +01:00
},
area,
scale,
state.egui.alpha,
&state.start_time,
state.egui.modifiers.clone(),
))
}
fn render_value(ui: &mut egui::Ui, value: &serde_json::Value) {
use serde_json::Value::*;
match value {
2022-03-16 20:01:34 +01:00
Null => {
ui.label(egui::RichText::new("null").code());
}
Bool(val) => {
ui.label(egui::RichText::new(format!("{}", val)).code());
}
Number(val) => {
ui.label(egui::RichText::new(format!("{}", val)).code());
}
String(val) => {
ui.label(val);
}
2022-02-05 00:40:17 +01:00
Array(list) => {
ui.vertical(|ui| {
ui.label("[");
for val in list {
ui.horizontal(|ui| {
ui.add_space(4.0);
render_value(ui, val);
});
}
ui.label("]");
});
2022-03-16 20:01:34 +01:00
}
2022-02-05 00:40:17 +01:00
Object(map) => {
ui.vertical(|ui| {
for (k, val) in map {
ui.horizontal(|ui| {
ui.add_space(4.0);
ui.add(egui::Label::new(egui::RichText::new(k).code()));
render_value(ui, val);
});
}
});
2022-03-16 20:01:34 +01:00
}
2022-02-05 00:40:17 +01:00
};
}