diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64879bc..185c038 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: sudo apt-get install -y software-properties-common sudo add-apt-repository -y ppa:pipewire-debian/pipewire-upstream sudo apt-get update -y - sudo apt-get install -y libudev-dev libgbm-dev libxkbcommon-dev libegl1-mesa-dev libwayland-dev libinput-dev libdbus-1-dev libsystemd-dev libseat-dev libpipewire-0.3-dev + sudo apt-get install -y libudev-dev libgbm-dev libxkbcommon-dev libegl1-mesa-dev libwayland-dev libinput-dev libdbus-1-dev libsystemd-dev libseat-dev libpipewire-0.3-dev libpango1.0-dev - name: Install Rust run: | @@ -78,7 +78,7 @@ jobs: sudo apt-get install -y software-properties-common sudo add-apt-repository -y ppa:pipewire-debian/pipewire-upstream sudo apt-get update -y - sudo apt-get install -y libudev-dev libgbm-dev libxkbcommon-dev libegl1-mesa-dev libwayland-dev libinput-dev libdbus-1-dev libsystemd-dev libseat-dev libpipewire-0.3-dev + sudo apt-get install -y libudev-dev libgbm-dev libxkbcommon-dev libegl1-mesa-dev libwayland-dev libinput-dev libdbus-1-dev libsystemd-dev libseat-dev libpipewire-0.3-dev libpango1.0-dev - name: Install Rust run: | diff --git a/Cargo.lock b/Cargo.lock index ae135e4..67d18af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -468,6 +468,31 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +[[package]] +name = "cairo-rs" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" +dependencies = [ + "bitflags 2.4.1", + "cairo-sys-rs", + "glib", + "libc", + "once_cell", + "thiserror", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + [[package]] name = "calloop" version = "0.12.3" @@ -1025,12 +1050,32 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", +] + [[package]] name = "futures-core" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.30" @@ -1065,6 +1110,17 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "futures-sink" version = "0.3.30" @@ -1085,6 +1141,7 @@ checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", "futures-io", + "futures-macro", "futures-sink", "futures-task", "memchr", @@ -1161,6 +1218,38 @@ dependencies = [ "wasi", ] +[[package]] +name = "gio" +version = "0.18.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "libc", + "once_cell", + "pin-project-lite", + "smallvec", + "thiserror", +] + +[[package]] +name = "gio-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "winapi", +] + [[package]] name = "git-version" version = "0.3.9" @@ -1192,12 +1281,70 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "glib" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" +dependencies = [ + "bitflags 2.4.1", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "memchr", + "once_cell", + "smallvec", + "thiserror", +] + +[[package]] +name = "glib-macros" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" +dependencies = [ + "heck", + "proc-macro-crate 2.0.1", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "glib-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" +dependencies = [ + "libc", + "system-deps", +] + [[package]] name = "glob" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "gobject-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + [[package]] name = "hashbrown" version = "0.14.3" @@ -1720,6 +1867,7 @@ dependencies = [ "niri-config", "niri-ipc", "notify-rust", + "pangocairo", "pipewire", "png", "portable-atomic", @@ -1829,7 +1977,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 2.0.1", "proc-macro2", "quote", "syn 2.0.48", @@ -1923,6 +2071,57 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "pango" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" +dependencies = [ + "gio", + "glib", + "libc", + "once_cell", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "pangocairo" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57036589a9cfcacf83f9e606d15813fc6bf03f0e9e69aa2b5e3bb85af86b38a5" +dependencies = [ + "cairo-rs", + "glib", + "libc", + "pango", + "pangocairo-sys", +] + +[[package]] +name = "pangocairo-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc3c8ff676a37e7a72ec1d5fc029f91c407278083d2752784ff9f5188c108833" +dependencies = [ + "cairo-sys-rs", + "glib-sys", + "libc", + "pango-sys", + "system-deps", +] + [[package]] name = "parking" version = "2.2.0" @@ -2069,6 +2268,16 @@ dependencies = [ "toml_edit 0.19.15", ] +[[package]] +name = "proc-macro-crate" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +dependencies = [ + "toml_datetime", + "toml_edit 0.20.2", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -2726,21 +2935,21 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" -version = "0.8.8" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.21.0", + "toml_edit 0.20.2", ] [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" dependencies = [ "serde", ] @@ -2758,9 +2967,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.21.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ "indexmap", "serde", @@ -3675,7 +3884,7 @@ version = "3.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d1794a946878c0e807f55a397187c11fc7a038ba5d868e7db4f3bd7760bc9d" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "regex", @@ -3734,7 +3943,7 @@ version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "934d7a7dfc310d6ee06c87ffe88ef4eca7d3e37bb251dece2ef93da8f17d8ecd" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", diff --git a/Cargo.toml b/Cargo.toml index 8a52e63..a701ad1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,6 +52,7 @@ logind-zbus = { version = "3.1.2", optional = true } niri-config = { version = "0.1.0-alpha.3", path = "niri-config" } niri-ipc = { version = "0.1.0-alpha.3", path = "niri-ipc" } notify-rust = { version = "4.10.0", optional = true } +pangocairo = "0.18.0" pipewire = { version = "0.7.2", optional = true } png = "0.17.10" portable-atomic = { version = "1.6.0", default-features = false, features = ["float"] } diff --git a/README.md b/README.md index 1b87488..e9609ae 100644 --- a/README.md +++ b/README.md @@ -62,13 +62,13 @@ First, install the dependencies for your distribution. sudo apt-get install -y software-properties-common sudo add-apt-repository -y ppa:pipewire-debian/pipewire-upstream sudo apt-get update -y - sudo apt-get install -y libudev-dev libgbm-dev libxkbcommon-dev libegl1-mesa-dev libwayland-dev libinput-dev libdbus-1-dev libsystemd-dev libseat-dev libpipewire-0.3-dev + sudo apt-get install -y libudev-dev libgbm-dev libxkbcommon-dev libegl1-mesa-dev libwayland-dev libinput-dev libdbus-1-dev libsystemd-dev libseat-dev libpipewire-0.3-dev libpango1.0-dev ``` - Fedora: ```sh - sudo dnf install gcc libudev-devel libgbm-devel libxkbcommon-devel wayland-devel libinput-devel dbus-devel systemd-devel libseat-devel pipewire-devel clang + sudo dnf install gcc libudev-devel libgbm-devel libxkbcommon-devel wayland-devel libinput-devel dbus-devel systemd-devel libseat-devel pipewire-devel pango-devel clang ``` Next, build niri with `cargo build --release`. diff --git a/flake.nix b/flake.nix index c97c2d9..74e3885 100644 --- a/flake.nix +++ b/flake.nix @@ -67,6 +67,7 @@ fontconfig stdenv.cc.cc.lib pipewire + pango ]; runtimeDependencies = with pkgs; [ diff --git a/src/config_error_notification.rs b/src/config_error_notification.rs new file mode 100644 index 0000000..6e54ead --- /dev/null +++ b/src/config_error_notification.rs @@ -0,0 +1,197 @@ +use std::cell::RefCell; +use std::collections::HashMap; +use std::time::Duration; + +use pangocairo::cairo::{self, ImageSurface}; +use pangocairo::pango::FontDescription; +use smithay::backend::renderer::element::memory::{ + MemoryRenderBuffer, MemoryRenderBufferRenderElement, +}; +use smithay::backend::renderer::element::utils::{Relocate, RelocateRenderElement}; +use smithay::backend::renderer::element::{Element, Kind}; +use smithay::output::Output; +use smithay::reexports::gbm::Format as Fourcc; +use smithay::utils::Transform; + +use crate::animation::Animation; +use crate::render_helpers::NiriRenderer; + +const TEXT: &str = "Failed to parse the config file. \ + Please run niri validate \ + to see the errors."; +const PADDING: i32 = 8; +const FONT: &str = "sans 14px"; +const BORDER: i32 = 4; + +pub struct ConfigErrorNotification { + state: State, + buffers: RefCell>>, +} + +enum State { + Hidden, + Showing(Animation), + Shown(Duration), + Hiding(Animation), +} + +pub type ConfigErrorNotificationRenderElement = + RelocateRenderElement>; + +impl ConfigErrorNotification { + pub fn new() -> Self { + Self { + state: State::Hidden, + buffers: RefCell::new(HashMap::new()), + } + } + + pub fn show(&mut self) { + // Show from scratch even if already showing to bring attention. + self.state = State::Showing(Animation::new(0., 1., Duration::from_millis(250))); + } + + pub fn hide(&mut self) { + if matches!(self.state, State::Hidden) { + return; + } + + self.state = State::Hiding(Animation::new(1., 0., Duration::from_millis(250))); + } + + pub fn advance_animations(&mut self, target_presentation_time: Duration) { + match &mut self.state { + State::Hidden => (), + State::Showing(anim) => { + anim.set_current_time(target_presentation_time); + if anim.is_done() { + self.state = State::Shown(target_presentation_time + Duration::from_secs(4)); + } + } + State::Shown(deadline) => { + if target_presentation_time >= *deadline { + self.hide(); + } + } + State::Hiding(anim) => { + anim.set_current_time(target_presentation_time); + if anim.is_done() { + self.state = State::Hidden; + } + } + } + } + + pub fn are_animations_ongoing(&self) -> bool { + !matches!(self.state, State::Hidden) + } + + pub fn render( + &self, + renderer: &mut R, + output: &Output, + ) -> Option> { + if matches!(self.state, State::Hidden) { + return None; + } + + let scale = output.current_scale().integer_scale(); + + let mut buffers = self.buffers.borrow_mut(); + let buffer = buffers + .entry(scale) + .or_insert_with_key(move |&scale| render(scale).ok()); + let buffer = buffer.as_ref()?; + + let elem = MemoryRenderBufferRenderElement::from_buffer( + renderer, + (0., 0.), + buffer, + Some(0.9), + None, + None, + Kind::Unspecified, + ) + .ok()?; + + let output_transform = output.current_transform(); + let output_mode = output.current_mode().unwrap(); + let output_size = output_transform.transform_size(output_mode.size); + + let buffer_size = elem + .geometry(output.current_scale().fractional_scale().into()) + .size; + + let y_range = buffer_size.h + PADDING * 2 * scale; + + let x = (output_size.w / 2 - buffer_size.w / 2).max(0); + let y = match &self.state { + State::Hidden => unreachable!(), + State::Showing(anim) | State::Hiding(anim) => { + (-buffer_size.h as f64 + anim.value() * y_range as f64).round() as i32 + } + State::Shown(_) => PADDING * 2 * scale, + }; + let elem = RelocateRenderElement::from_element(elem, (x, y), Relocate::Absolute); + + Some(elem) + } +} + +fn render(scale: i32) -> anyhow::Result { + let _span = tracy_client::span!("config_error_notification::render"); + + let padding = PADDING * scale; + + let mut font = FontDescription::from_string(FONT); + font.set_absolute_size((font.size() * scale).into()); + + let surface = ImageSurface::create(cairo::Format::ARgb32, 0, 0)?; + let cr = cairo::Context::new(&surface)?; + let layout = pangocairo::create_layout(&cr); + layout.set_font_description(Some(&font)); + layout.set_markup(TEXT); + + let (mut width, mut height) = layout.pixel_size(); + width += padding * 2; + height += padding * 2; + + // FIXME: fix bug in Smithay that rounds pixel sizes down to scale. + width = (width + scale - 1) / scale * scale; + height = (height + scale - 1) / scale * scale; + + let surface = ImageSurface::create(cairo::Format::ARgb32, width, height)?; + let cr = cairo::Context::new(&surface)?; + cr.set_source_rgb(0.1, 0.1, 0.1); + cr.paint()?; + + cr.move_to(padding.into(), padding.into()); + let layout = pangocairo::create_layout(&cr); + layout.set_font_description(Some(&font)); + layout.set_markup(TEXT); + + cr.set_source_rgb(1., 1., 1.); + pangocairo::show_layout(&cr, &layout); + + cr.move_to(0., 0.); + cr.line_to(width.into(), 0.); + cr.line_to(width.into(), height.into()); + cr.line_to(0., height.into()); + cr.line_to(0., 0.); + cr.set_source_rgb(1., 0.3, 0.3); + cr.set_line_width((BORDER * scale).into()); + cr.stroke()?; + drop(cr); + + let data = surface.take_data().unwrap(); + let buffer = MemoryRenderBuffer::from_memory( + &data, + Fourcc::Argb8888, + (width, height), + scale, + Transform::Normal, + None, + ); + + Ok(buffer) +} diff --git a/src/main.rs b/src/main.rs index 8a8096b..9fe1394 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ extern crate tracing; mod animation; mod backend; +mod config_error_notification; mod cursor; #[cfg(feature = "dbus")] mod dbus; @@ -157,12 +158,14 @@ fn main() -> Result<(), Box> { // Load the config. let path = cli.config.or_else(default_config_path); + let mut config_errored = false; let mut config = path .as_deref() .and_then(|path| match Config::load(path) { Ok(config) => Some(config), Err(err) => { warn!("{err:?}"); + config_errored = true; None } }) @@ -239,6 +242,11 @@ fn main() -> Result<(), Box> { spawn(elem.command); } + // Show the config error notification right away if needed. + if config_errored { + state.niri.config_error_notification.show(); + } + // Run the compositor. event_loop .run(None, &mut state, |state| state.refresh_and_flush_clients()) diff --git a/src/niri.rs b/src/niri.rs index e0762ae..8109f2e 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -90,6 +90,9 @@ use smithay::wayland::virtual_keyboard::VirtualKeyboardManagerState; use crate::animation; use crate::backend::tty::{SurfaceDmabufFeedback, TtyFrame, TtyRenderer, TtyRendererError}; use crate::backend::{Backend, RenderResult, Tty, Winit}; +use crate::config_error_notification::{ + ConfigErrorNotification, ConfigErrorNotificationRenderElement, +}; use crate::cursor::{CursorManager, CursorTextureCache, RenderCursor, XCursor}; #[cfg(feature = "dbus")] use crate::dbus::gnome_shell_screenshot::{NiriToScreenshot, ScreenshotToNiri}; @@ -185,6 +188,7 @@ pub struct Niri { pub lock_state: LockState, pub screenshot_ui: ScreenshotUi, + pub config_error_notification: ConfigErrorNotification, #[cfg(feature = "dbus")] pub dbus: Option, @@ -540,10 +544,14 @@ impl State { Ok(config) => config, Err(err) => { warn!("{:?}", err.context("error loading config")); + self.niri.config_error_notification.show(); + self.niri.queue_redraw_all(); return; } }; + self.niri.config_error_notification.hide(); + self.niri.layout.update_config(&config); animation::ANIMATION_SLOWDOWN.store(config.debug.animation_slowdown, Ordering::Relaxed); @@ -850,6 +858,7 @@ impl Niri { }); let screenshot_ui = ScreenshotUi::new(); + let config_error_notification = ConfigErrorNotification::new(); let socket_source = ListeningSocketSource::new_auto().unwrap(); let socket_name = socket_source.socket_name().to_os_string(); @@ -954,6 +963,7 @@ impl Niri { lock_state: LockState::Unlocked, screenshot_ui, + config_error_notification, #[cfg(feature = "dbus")] dbus: None, @@ -1788,6 +1798,11 @@ impl Niri { elements = self.pointer_element(renderer, output); } + // The config error notification too. + if let Some(element) = self.config_error_notification.render(renderer, output) { + elements.push(element.into()); + } + // If the session is locked, draw the lock surface. if self.is_locked() { let state = self.output_state.get(output).unwrap(); @@ -1915,6 +1930,11 @@ impl Niri { .unwrap() .are_animations_ongoing(); + self.config_error_notification + .advance_animations(target_presentation_time); + state.unfinished_animations_remain |= + self.config_error_notification.are_animations_ongoing(); + // Also keep redrawing if the current cursor is animated. state.unfinished_animations_remain |= self .cursor_manager @@ -2828,6 +2848,7 @@ pub enum OutputRenderElements { NamedPointer(PrimaryGpuTextureRenderElement), SolidColor(SolidColorRenderElement), ScreenshotUi(ScreenshotUiRenderElement), + ConfigErrorNotification(ConfigErrorNotificationRenderElement), } impl Element for OutputRenderElements { @@ -2838,6 +2859,7 @@ impl Element for OutputRenderElements { Self::NamedPointer(elem) => elem.id(), Self::SolidColor(elem) => elem.id(), Self::ScreenshotUi(elem) => elem.id(), + Self::ConfigErrorNotification(elem) => elem.id(), } } @@ -2848,6 +2870,7 @@ impl Element for OutputRenderElements { Self::NamedPointer(elem) => elem.current_commit(), Self::SolidColor(elem) => elem.current_commit(), Self::ScreenshotUi(elem) => elem.current_commit(), + Self::ConfigErrorNotification(elem) => elem.current_commit(), } } @@ -2858,6 +2881,7 @@ impl Element for OutputRenderElements { Self::NamedPointer(elem) => elem.geometry(scale), Self::SolidColor(elem) => elem.geometry(scale), Self::ScreenshotUi(elem) => elem.geometry(scale), + Self::ConfigErrorNotification(elem) => elem.geometry(scale), } } @@ -2868,6 +2892,7 @@ impl Element for OutputRenderElements { Self::NamedPointer(elem) => elem.transform(), Self::SolidColor(elem) => elem.transform(), Self::ScreenshotUi(elem) => elem.transform(), + Self::ConfigErrorNotification(elem) => elem.transform(), } } @@ -2878,6 +2903,7 @@ impl Element for OutputRenderElements { Self::NamedPointer(elem) => elem.src(), Self::SolidColor(elem) => elem.src(), Self::ScreenshotUi(elem) => elem.src(), + Self::ConfigErrorNotification(elem) => elem.src(), } } @@ -2892,6 +2918,7 @@ impl Element for OutputRenderElements { Self::NamedPointer(elem) => elem.damage_since(scale, commit), Self::SolidColor(elem) => elem.damage_since(scale, commit), Self::ScreenshotUi(elem) => elem.damage_since(scale, commit), + Self::ConfigErrorNotification(elem) => elem.damage_since(scale, commit), } } @@ -2902,6 +2929,7 @@ impl Element for OutputRenderElements { Self::NamedPointer(elem) => elem.opaque_regions(scale), Self::SolidColor(elem) => elem.opaque_regions(scale), Self::ScreenshotUi(elem) => elem.opaque_regions(scale), + Self::ConfigErrorNotification(elem) => elem.opaque_regions(scale), } } @@ -2912,6 +2940,7 @@ impl Element for OutputRenderElements { Self::NamedPointer(elem) => elem.alpha(), Self::SolidColor(elem) => elem.alpha(), Self::ScreenshotUi(elem) => elem.alpha(), + Self::ConfigErrorNotification(elem) => elem.alpha(), } } @@ -2922,6 +2951,7 @@ impl Element for OutputRenderElements { Self::NamedPointer(elem) => elem.kind(), Self::SolidColor(elem) => elem.kind(), Self::ScreenshotUi(elem) => elem.kind(), + Self::ConfigErrorNotification(elem) => elem.kind(), } } } @@ -2946,6 +2976,7 @@ impl RenderElement for OutputRenderElements { Self::ScreenshotUi(elem) => { RenderElement::::draw(&elem, frame, src, dst, damage) } + Self::ConfigErrorNotification(elem) => elem.draw(frame, src, dst, damage), } } @@ -2956,6 +2987,7 @@ impl RenderElement for OutputRenderElements { Self::NamedPointer(elem) => elem.underlying_storage(renderer), Self::SolidColor(elem) => elem.underlying_storage(renderer), Self::ScreenshotUi(elem) => elem.underlying_storage(renderer), + Self::ConfigErrorNotification(elem) => elem.underlying_storage(renderer), } } } @@ -2982,6 +3014,7 @@ impl<'render, 'alloc> RenderElement> Self::ScreenshotUi(elem) => { RenderElement::>::draw(&elem, frame, src, dst, damage) } + Self::ConfigErrorNotification(elem) => elem.draw(frame, src, dst, damage), } } @@ -2995,6 +3028,7 @@ impl<'render, 'alloc> RenderElement> Self::NamedPointer(elem) => elem.underlying_storage(renderer), Self::SolidColor(elem) => elem.underlying_storage(renderer), Self::ScreenshotUi(elem) => elem.underlying_storage(renderer), + Self::ConfigErrorNotification(elem) => elem.underlying_storage(renderer), } } } @@ -3028,3 +3062,9 @@ impl From for OutputRenderElements From> for OutputRenderElements { + fn from(x: ConfigErrorNotificationRenderElement) -> Self { + Self::ConfigErrorNotification(x) + } +} diff --git a/src/render_helpers.rs b/src/render_helpers.rs index 6cdc9fc..5402cba 100644 --- a/src/render_helpers.rs +++ b/src/render_helpers.rs @@ -3,7 +3,9 @@ use smithay::backend::renderer::element::texture::TextureRenderElement; use smithay::backend::renderer::element::{Element, Id, Kind, RenderElement, UnderlyingStorage}; use smithay::backend::renderer::gles::{GlesError, GlesFrame, GlesRenderer, GlesTexture}; use smithay::backend::renderer::utils::CommitCounter; -use smithay::backend::renderer::{Bind, ExportMem, ImportAll, Offscreen, Renderer, Texture}; +use smithay::backend::renderer::{ + Bind, ExportMem, ImportAll, ImportMem, Offscreen, Renderer, Texture, +}; use smithay::utils::{Buffer, Physical, Rectangle, Scale, Transform}; use crate::backend::tty::{TtyFrame, TtyRenderer, TtyRendererError}; @@ -11,6 +13,7 @@ use crate::backend::tty::{TtyFrame, TtyRenderer, TtyRendererError}; /// Trait with our main renderer requirements to save on the typing. pub trait NiriRenderer: ImportAll + + ImportMem + ExportMem + Bind + Offscreen @@ -28,7 +31,7 @@ pub trait NiriRenderer: impl NiriRenderer for R where - R: ImportAll + ExportMem + Bind + Offscreen + AsGlesRenderer, + R: ImportAll + ImportMem + ExportMem + Bind + Offscreen + AsGlesRenderer, R::TextureId: Texture + Clone + 'static, R::Error: std::error::Error + Send + Sync + From<::Error> + 'static, {