From e0d2e8436ea35f13f645884715079e0130f6e654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Gibrowski=20Fa=C3=A9?= Date: Thu, 5 Dec 2024 11:33:42 -0300 Subject: [PATCH] remote most static muts from globals The only remaining `static mut` is the wayland file descriptor, because it would be incredibly incovenient to change it. The wayland `static mut` is also the least concerning one, since it always creates immutable references to it. --- daemon/src/animations/mod.rs | 21 +- daemon/src/animations/transitions.rs | 342 ++++++++++++++++----------- daemon/src/main.rs | 151 ++++++------ daemon/src/wallpaper.rs | 98 ++++++-- daemon/src/wayland/bump_pool.rs | 60 +++-- daemon/src/wayland/globals.rs | 114 ++++----- daemon/src/wayland/interfaces.rs | 12 +- daemon/src/wayland/mod.rs | 16 +- daemon/src/wayland/wire.rs | 6 +- 9 files changed, 463 insertions(+), 357 deletions(-) diff --git a/daemon/src/animations/mod.rs b/daemon/src/animations/mod.rs index 1096c4d..d853183 100644 --- a/daemon/src/animations/mod.rs +++ b/daemon/src/animations/mod.rs @@ -8,11 +8,11 @@ use std::{ use common::{ compression::Decompressor, - ipc::{self, Animation, BgImg, ImgReq}, + ipc::{self, Animation, BgImg, ImgReq, PixelFormat}, mmap::MmappedBytes, }; -use crate::{wallpaper::Wallpaper, wayland::globals}; +use crate::{wallpaper::Wallpaper, wayland::ObjectManager}; mod transitions; use transitions::Effect; @@ -31,6 +31,7 @@ impl TransitionAnimator { pub fn new( mut wallpapers: Vec>>, transition: &ipc::Transition, + pixel_format: PixelFormat, img_req: ImgReq, animation: Option, ) -> Option { @@ -49,7 +50,7 @@ impl TransitionAnimator { return None; } let fps = Duration::from_nanos(1_000_000_000 / transition.fps as u64); - let effect = Effect::new(transition, dim); + let effect = Effect::new(transition, pixel_format, dim); Some(Self { wallpapers, effect, @@ -69,7 +70,7 @@ impl TransitionAnimator { self.now = Instant::now(); } - pub fn frame(&mut self) -> bool { + pub fn frame(&mut self, objman: &mut ObjectManager, pixel_format: PixelFormat) -> bool { let Self { wallpapers, effect, @@ -78,7 +79,7 @@ impl TransitionAnimator { .. } = self; if !*over { - *over = effect.execute(wallpapers, img.bytes()); + *over = effect.execute(objman, pixel_format, wallpapers, img.bytes()); false } else { true @@ -121,7 +122,7 @@ impl ImageAnimator { self.now = Instant::now(); } - pub fn frame(&mut self) { + pub fn frame(&mut self, objman: &mut ObjectManager, pixel_format: PixelFormat) { let Self { wallpapers, animation, @@ -134,9 +135,11 @@ impl ImageAnimator { let mut j = 0; while j < wallpapers.len() { - let result = wallpapers[j].borrow_mut().canvas_change(|canvas| { - decompressor.decompress(frame, canvas, globals::pixel_format()) - }); + let result = wallpapers[j] + .borrow_mut() + .canvas_change(objman, pixel_format, |canvas| { + decompressor.decompress(frame, canvas, pixel_format) + }); if let Err(e) = result { error!("failed to unpack frame: {e}"); diff --git a/daemon/src/animations/transitions.rs b/daemon/src/animations/transitions.rs index debaeed..e47498d 100644 --- a/daemon/src/animations/transitions.rs +++ b/daemon/src/animations/transitions.rs @@ -1,7 +1,7 @@ use std::{cell::RefCell, rc::Rc, time::Instant}; -use crate::{wallpaper::Wallpaper, wayland::globals}; -use common::ipc::{Transition, TransitionType}; +use crate::{wallpaper::Wallpaper, wayland::ObjectManager}; +use common::ipc::{PixelFormat, Transition, TransitionType}; use keyframe::{ functions::BezierCurve, keyframes, mint::Vector2, num_traits::Pow, AnimationSequence, @@ -41,10 +41,17 @@ impl None { fn new() -> Self { Self } - fn run(&mut self, wallpapers: &mut [Rc>], img: &[u8]) -> bool { + + fn run( + &mut self, + objman: &mut ObjectManager, + pixel_format: PixelFormat, + wallpapers: &mut [Rc>], + img: &[u8], + ) -> bool { wallpapers.iter().for_each(|w| { w.borrow_mut() - .canvas_change(|canvas| canvas.copy_from_slice(img)) + .canvas_change(objman, pixel_format, |canvas| canvas.copy_from_slice(img)) }); true } @@ -62,27 +69,33 @@ pub enum Effect { } impl Effect { - pub fn new(transition: &Transition, dimensions: (u32, u32)) -> Self { + pub fn new(transition: &Transition, pixel_format: PixelFormat, dimensions: (u32, u32)) -> Self { match transition.transition_type { TransitionType::Simple => Self::Simple(Simple::new(transition.step.get())), TransitionType::Fade => Self::Fade(Fade::new(transition)), - TransitionType::Outer => Self::Outer(Outer::new(transition, dimensions)), - TransitionType::Wipe => Self::Wipe(Wipe::new(transition, dimensions)), - TransitionType::Grow => Self::Grow(Grow::new(transition, dimensions)), - TransitionType::Wave => Self::Wave(Wave::new(transition, dimensions)), + TransitionType::Outer => Self::Outer(Outer::new(transition, pixel_format, dimensions)), + TransitionType::Wipe => Self::Wipe(Wipe::new(transition, pixel_format, dimensions)), + TransitionType::Grow => Self::Grow(Grow::new(transition, pixel_format, dimensions)), + TransitionType::Wave => Self::Wave(Wave::new(transition, pixel_format, dimensions)), TransitionType::None => Self::None(None::new()), } } - pub fn execute(&mut self, wallpapers: &mut [Rc>], img: &[u8]) -> bool { + pub fn execute( + &mut self, + objman: &mut ObjectManager, + pixel_format: PixelFormat, + wallpapers: &mut [Rc>], + img: &[u8], + ) -> bool { let done = match self { - Effect::None(effect) => effect.run(wallpapers, img), - Effect::Simple(effect) => effect.run(wallpapers, img), - Effect::Fade(effect) => effect.run(wallpapers, img), - Effect::Wave(effect) => effect.run(wallpapers, img), - Effect::Wipe(effect) => effect.run(wallpapers, img), - Effect::Grow(effect) => effect.run(wallpapers, img), - Effect::Outer(effect) => effect.run(wallpapers, img), + Effect::None(effect) => effect.run(objman, pixel_format, wallpapers, img), + Effect::Simple(effect) => effect.run(objman, pixel_format, wallpapers, img), + Effect::Fade(effect) => effect.run(objman, pixel_format, wallpapers, img), + Effect::Wave(effect) => effect.run(objman, pixel_format, wallpapers, img), + Effect::Wipe(effect) => effect.run(objman, pixel_format, wallpapers, img), + Effect::Grow(effect) => effect.run(objman, pixel_format, wallpapers, img), + Effect::Outer(effect) => effect.run(objman, pixel_format, wallpapers, img), }; // we only finish for real if we are doing a None or a Simple transition if done { @@ -108,16 +121,24 @@ impl Simple { fn new(step: u8) -> Self { Self { step } } - fn run(&mut self, wallpapers: &mut [Rc>], img: &[u8]) -> bool { + fn run( + &mut self, + objman: &mut ObjectManager, + pixel_format: PixelFormat, + wallpapers: &mut [Rc>], + img: &[u8], + ) -> bool { let step = self.step; let mut done = true; for wallpaper in wallpapers.iter() { - wallpaper.borrow_mut().canvas_change(|canvas| { - for (old, new) in canvas.iter_mut().zip(img) { - change_byte(step, old, new); - } - done = done && canvas == img; - }); + wallpaper + .borrow_mut() + .canvas_change(objman, pixel_format, |canvas| { + for (old, new) in canvas.iter_mut().zip(img) { + change_byte(step, old, new); + } + done = done && canvas == img; + }); } done } @@ -135,15 +156,23 @@ impl Fade { let step = 0; Self { start, seq, step } } - fn run(&mut self, wallpapers: &mut [Rc>], img: &[u8]) -> bool { + fn run( + &mut self, + objman: &mut ObjectManager, + pixel_format: PixelFormat, + wallpapers: &mut [Rc>], + img: &[u8], + ) -> bool { for wallpaper in wallpapers.iter() { - wallpaper.borrow_mut().canvas_change(|canvas| { - for (old, new) in canvas.iter_mut().zip(img) { - let x = *old as u16 * (256 - self.step); - let y = *new as u16 * self.step; - *old = ((x + y) >> 8) as u8; - } - }); + wallpaper + .borrow_mut() + .canvas_change(objman, pixel_format, |canvas| { + for (old, new) in canvas.iter_mut().zip(img) { + let x = *old as u16 * (256 - self.step); + let y = *new as u16 * self.step; + *old = ((x + y) >> 8) as u8; + } + }); } self.step = (256.0 * self.seq.now() as f64).trunc() as u16; self.seq.advance_to(self.start.elapsed().as_secs_f64()); @@ -169,7 +198,7 @@ struct Wave { } impl Wave { - fn new(transition: &Transition, dimensions: (u32, u32)) -> Self { + fn new(transition: &Transition, pixel_format: PixelFormat, dimensions: (u32, u32)) -> Self { let width = dimensions.0; let height = dimensions.1; let center = (width / 2, height / 2); @@ -190,7 +219,7 @@ impl Wave { let (seq, start) = bezier_seq(transition, offset as f32, max_offset as f32); let step = transition.step.get(); - let channels = globals::pixel_format().channels() as usize; + let channels = pixel_format.channels() as usize; let stride = width * channels; Self { start, @@ -209,7 +238,13 @@ impl Wave { step, } } - fn run(&mut self, wallpapers: &mut [Rc>], img: &[u8]) -> bool { + fn run( + &mut self, + objman: &mut ObjectManager, + pixel_format: PixelFormat, + wallpapers: &mut [Rc>], + img: &[u8], + ) -> bool { let Self { width, height, @@ -239,54 +274,57 @@ impl Wave { lhs <= rhs }; - let channels = globals::pixel_format().channels() as usize; + let channels = pixel_format.channels() as usize; let offset = self.seq.now() as f64; self.seq.advance_to(self.start.elapsed().as_secs_f64()); for wallpaper in wallpapers.iter() { - wallpaper.borrow_mut().canvas_change(|canvas| { - // divide in 3 sections: the one we know will not be drawn to, the one we know - // WILL be drawn to, and the one we need to do a more expensive check on. - // We do this by creating 2 lines: the first tangential to the wave's peaks, - // the second to its valeys. In-between is where we have to do the more - // expensive checks - for line in 0..height { - let y = ((height - line) as f64 - center.1 as f64 - scale_y * sin) * b; - let x = - (circle_radius.powi(2) - y - offset) / a + center.0 as f64 + scale_y * cos; - let x = x.min(width as f64); - let (col_begin, col_end) = if a.is_sign_negative() { - (0usize, x as usize * channels) - } else { - (x as usize * channels, stride) - }; - for col in col_begin..col_end { - let old = unsafe { canvas.get_unchecked_mut(line * stride + col) }; - let new = unsafe { img.get_unchecked(line * stride + col) }; - change_byte(step, old, new); - } - let old_x = x; - let y = ((height - line) as f64 - center.1 as f64 + scale_y * sin) * b; - let x = - (circle_radius.powi(2) - y - offset) / a + center.0 as f64 - scale_y * cos; - let x = x.min(width as f64); - let (col_begin, col_end) = if old_x < x { - (old_x as usize, x as usize) - } else { - (x as usize, old_x as usize) - }; - for col in col_begin..col_end { - if is_low(col as f64, line as f64, offset) { - let i = line * stride + col * channels; - for j in 0..channels { - let old = unsafe { canvas.get_unchecked_mut(i + j) }; - let new = unsafe { img.get_unchecked(i + j) }; - change_byte(step, old, new); + wallpaper + .borrow_mut() + .canvas_change(objman, pixel_format, |canvas| { + // divide in 3 sections: the one we know will not be drawn to, the one we know + // WILL be drawn to, and the one we need to do a more expensive check on. + // We do this by creating 2 lines: the first tangential to the wave's peaks, + // the second to its valeys. In-between is where we have to do the more + // expensive checks + for line in 0..height { + let y = ((height - line) as f64 - center.1 as f64 - scale_y * sin) * b; + let x = (circle_radius.powi(2) - y - offset) / a + + center.0 as f64 + + scale_y * cos; + let x = x.min(width as f64); + let (col_begin, col_end) = if a.is_sign_negative() { + (0usize, x as usize * channels) + } else { + (x as usize * channels, stride) + }; + for col in col_begin..col_end { + let old = unsafe { canvas.get_unchecked_mut(line * stride + col) }; + let new = unsafe { img.get_unchecked(line * stride + col) }; + change_byte(step, old, new); + } + let old_x = x; + let y = ((height - line) as f64 - center.1 as f64 + scale_y * sin) * b; + let x = (circle_radius.powi(2) - y - offset) / a + center.0 as f64 + - scale_y * cos; + let x = x.min(width as f64); + let (col_begin, col_end) = if old_x < x { + (old_x as usize, x as usize) + } else { + (x as usize, old_x as usize) + }; + for col in col_begin..col_end { + if is_low(col as f64, line as f64, offset) { + let i = line * stride + col * channels; + for j in 0..channels { + let old = unsafe { canvas.get_unchecked_mut(i + j) }; + let new = unsafe { img.get_unchecked(i + j) }; + change_byte(step, old, new); + } } } } - } - }); + }); } self.start.elapsed().as_secs_f64() > self.seq.duration() @@ -307,7 +345,7 @@ struct Wipe { } impl Wipe { - fn new(transition: &Transition, dimensions: (u32, u32)) -> Self { + fn new(transition: &Transition, pixel_format: PixelFormat, dimensions: (u32, u32)) -> Self { let width = dimensions.0; let height = dimensions.1; let center = (width / 2, height / 2); @@ -330,7 +368,7 @@ impl Wipe { let (seq, start) = bezier_seq(transition, offset as f32, max_offset as f32); let step = transition.step.get(); - let channels = globals::pixel_format().channels() as usize; + let channels = pixel_format.channels() as usize; let stride = width * channels; Self { start, @@ -345,7 +383,13 @@ impl Wipe { step, } } - fn run(&mut self, wallpapers: &mut [Rc>], img: &[u8]) -> bool { + fn run( + &mut self, + objman: &mut ObjectManager, + pixel_format: PixelFormat, + wallpapers: &mut [Rc>], + img: &[u8], + ) -> bool { let Self { width, height, @@ -357,29 +401,31 @@ impl Wipe { step, .. } = *self; - let channels = globals::pixel_format().channels() as usize; + let channels = pixel_format.channels() as usize; let offset = self.seq.now() as f64; self.seq.advance_to(self.start.elapsed().as_secs_f64()); for wallpaper in wallpapers.iter() { - wallpaper.borrow_mut().canvas_change(|canvas| { - // line formula: (x-h)*a + (y-k)*b + C = r^2 - // https://www.desmos.com/calculator/vpvzk12yar - for line in 0..height { - let y = ((height - line) as f64 - center.1 as f64) * b; - let x = (circle_radius.powi(2) - y - offset) / a + center.0 as f64; - let x = x.min(width as f64); - let (col_begin, col_end) = if a.is_sign_negative() { - (0usize, x as usize * channels) - } else { - (x as usize * channels, stride) - }; - for col in col_begin..col_end { - let old = unsafe { canvas.get_unchecked_mut(line * stride + col) }; - let new = unsafe { img.get_unchecked(line * stride + col) }; - change_byte(step, old, new); + wallpaper + .borrow_mut() + .canvas_change(objman, pixel_format, |canvas| { + // line formula: (x-h)*a + (y-k)*b + C = r^2 + // https://www.desmos.com/calculator/vpvzk12yar + for line in 0..height { + let y = ((height - line) as f64 - center.1 as f64) * b; + let x = (circle_radius.powi(2) - y - offset) / a + center.0 as f64; + let x = x.min(width as f64); + let (col_begin, col_end) = if a.is_sign_negative() { + (0usize, x as usize * channels) + } else { + (x as usize * channels, stride) + }; + for col in col_begin..col_end { + let old = unsafe { canvas.get_unchecked_mut(line * stride + col) }; + let new = unsafe { img.get_unchecked(line * stride + col) }; + change_byte(step, old, new); + } } - } - }); + }); } self.start.elapsed().as_secs_f64() > self.seq.duration() } @@ -398,7 +444,7 @@ struct Grow { } impl Grow { - fn new(transition: &Transition, dimensions: (u32, u32)) -> Self { + fn new(transition: &Transition, pixel_format: PixelFormat, dimensions: (u32, u32)) -> Self { let (width, height) = (dimensions.0 as f32, dimensions.1 as f32); let (center_x, center_y) = transition.pos.to_pixel(dimensions, transition.invert_y); let dist_center: f32 = 0.0; @@ -418,7 +464,7 @@ impl Grow { let (center_x, center_y) = (center_x as usize, center_y as usize); let step = transition.step.get(); - let channels = globals::pixel_format().channels() as usize; + let channels = pixel_format.channels() as usize; let stride = width * channels; let (seq, start) = bezier_seq(transition, 0.0, dist_end); Self { @@ -433,7 +479,13 @@ impl Grow { step, } } - fn run(&mut self, wallpapers: &mut [Rc>], img: &[u8]) -> bool { + fn run( + &mut self, + objman: &mut ObjectManager, + pixel_format: PixelFormat, + wallpapers: &mut [Rc>], + img: &[u8], + ) -> bool { let Self { width, height, @@ -444,26 +496,28 @@ impl Grow { step, .. } = *self; - let channels = globals::pixel_format().channels() as usize; + let channels = pixel_format.channels() as usize; for wallpaper in wallpapers.iter() { - wallpaper.borrow_mut().canvas_change(|canvas| { - let line_begin = center_y.saturating_sub(dist_center as usize); - let line_end = height.min(center_y + dist_center as usize); - - // to plot half a circle with radius r, we do sqrt(r^2 - x^2) - for line in line_begin..line_end { - let offset = (dist_center.powi(2) - (center_y as f32 - line as f32).powi(2)) - .sqrt() as usize; - let col_begin = center_x.saturating_sub(offset) * channels; - let col_end = width.min(center_x + offset) * channels; - for col in col_begin..col_end { - let old = unsafe { canvas.get_unchecked_mut(line * stride + col) }; - let new = unsafe { img.get_unchecked(line * stride + col) }; - change_byte(step, old, new); + wallpaper + .borrow_mut() + .canvas_change(objman, pixel_format, |canvas| { + let line_begin = center_y.saturating_sub(dist_center as usize); + let line_end = height.min(center_y + dist_center as usize); + + // to plot half a circle with radius r, we do sqrt(r^2 - x^2) + for line in line_begin..line_end { + let offset = (dist_center.powi(2) - (center_y as f32 - line as f32).powi(2)) + .sqrt() as usize; + let col_begin = center_x.saturating_sub(offset) * channels; + let col_end = width.min(center_x + offset) * channels; + for col in col_begin..col_end { + let old = unsafe { canvas.get_unchecked_mut(line * stride + col) }; + let new = unsafe { img.get_unchecked(line * stride + col) }; + change_byte(step, old, new); + } } - } - }); + }); } self.dist_center = self.seq.now(); @@ -485,7 +539,7 @@ struct Outer { } impl Outer { - fn new(transition: &Transition, dimensions: (u32, u32)) -> Self { + fn new(transition: &Transition, pixel_format: PixelFormat, dimensions: (u32, u32)) -> Self { let (width, height) = (dimensions.0 as f32, dimensions.1 as f32); let (center_x, center_y) = transition.pos.to_pixel(dimensions, transition.invert_y); let dist_center = { @@ -503,7 +557,7 @@ impl Outer { let (center_x, center_y) = (center_x as usize, center_y as usize); let step = transition.step.get(); - let channels = globals::pixel_format().channels() as usize; + let channels = pixel_format.channels() as usize; let stride = width * channels; let (seq, start) = bezier_seq(transition, dist_center, 0.0); Self { @@ -518,7 +572,13 @@ impl Outer { dist_center, } } - fn run(&mut self, wallpapers: &mut [Rc>], img: &[u8]) -> bool { + fn run( + &mut self, + objman: &mut ObjectManager, + pixel_format: PixelFormat, + wallpapers: &mut [Rc>], + img: &[u8], + ) -> bool { let Self { width, height, @@ -529,27 +589,29 @@ impl Outer { step, .. } = *self; - let channels = globals::pixel_format().channels() as usize; + let channels = pixel_format.channels() as usize; for wallpaper in wallpapers.iter() { - wallpaper.borrow_mut().canvas_change(|canvas| { - // to plot half a circle with radius r, we do sqrt(r^2 - x^2) - for line in 0..height { - let offset = (dist_center.powi(2) - (center_y as f32 - line as f32).powi(2)) - .sqrt() as usize; - let col_begin = center_x.saturating_sub(offset) * channels; - let col_end = width.min(center_x + offset) * channels; - for col in 0..col_begin { - let old = unsafe { canvas.get_unchecked_mut(line * stride + col) }; - let new = unsafe { img.get_unchecked(line * stride + col) }; - change_byte(step, old, new); - } - for col in col_end..stride { - let old = unsafe { canvas.get_unchecked_mut(line * stride + col) }; - let new = unsafe { img.get_unchecked(line * stride + col) }; - change_byte(step, old, new); + wallpaper + .borrow_mut() + .canvas_change(objman, pixel_format, |canvas| { + // to plot half a circle with radius r, we do sqrt(r^2 - x^2) + for line in 0..height { + let offset = (dist_center.powi(2) - (center_y as f32 - line as f32).powi(2)) + .sqrt() as usize; + let col_begin = center_x.saturating_sub(offset) * channels; + let col_end = width.min(center_x + offset) * channels; + for col in 0..col_begin { + let old = unsafe { canvas.get_unchecked_mut(line * stride + col) }; + let new = unsafe { img.get_unchecked(line * stride + col) }; + change_byte(step, old, new); + } + for col in col_end..stride { + let old = unsafe { canvas.get_unchecked_mut(line * stride + col) }; + let new = unsafe { img.get_unchecked(line * stride + col) }; + change_byte(step, old, new); + } } - } - }); + }); } self.dist_center = self.seq.now(); self.seq.advance_to(self.start.elapsed().as_secs_f64()); diff --git a/daemon/src/main.rs b/daemon/src/main.rs index 7d9cfb3..94d70dc 100644 --- a/daemon/src/main.rs +++ b/daemon/src/main.rs @@ -15,8 +15,8 @@ use rustix::{ use wallpaper::Wallpaper; use wayland::{ - globals::{self, FractionalScaleManager, Initializer}, - ObjectId, + globals::{self, InitState}, + ObjectId, ObjectManager, }; use std::{ @@ -31,7 +31,9 @@ use std::{ }; use animations::{ImageAnimator, TransitionAnimator}; -use common::ipc::{Answer, BgInfo, ImageReq, IpcSocket, RequestRecv, RequestSend, Scale, Server}; +use common::ipc::{ + Answer, BgInfo, ImageReq, IpcSocket, PixelFormat, RequestRecv, RequestSend, Scale, Server, +}; use common::mmap::MmappedStr; // We need this because this might be set by signals, so we can't keep it in the daemon @@ -50,83 +52,58 @@ extern "C" fn signal_handler(_s: libc::c_int) { } struct Daemon { + objman: ObjectManager, + pixel_format: PixelFormat, wallpapers: Vec>>, transition_animators: Vec, image_animators: Vec, use_cache: bool, - fractional_scale_manager: Option, + fractional_scale_manager: Option, poll_time: PollTime, } impl Daemon { - fn new(initializer: &Initializer, no_cache: bool) -> Self { - log::info!( - "Selected wl_shm format: {:?}", - wayland::globals::pixel_format() + fn new(init_state: InitState, no_cache: bool) -> Self { + let InitState { + output_names, + fractional_scale, + objman, + pixel_format, + } = init_state; + + assert_eq!( + fractional_scale.is_some(), + objman.fractional_scale_support() ); - let fractional_scale_manager = initializer.fractional_scale().cloned(); - let wallpapers = Vec::new(); + log::info!("Selected wl_shm format: {pixel_format:?}"); - Self { - wallpapers, + let mut daemon = Self { + objman, + pixel_format, + wallpapers: Vec::new(), transition_animators: Vec::new(), image_animators: Vec::new(), use_cache: !no_cache, - fractional_scale_manager, + fractional_scale_manager: fractional_scale.map(|x| x.id()), poll_time: PollTime::Never, + }; + + for output_name in output_names { + daemon.new_output(output_name); } + + daemon } fn new_output(&mut self, output_name: u32) { - use wayland::interfaces::*; - let output = globals::object_create(wayland::WlDynObj::Output); - wl_registry::req::bind(output_name, output, "wl_output", 4).unwrap(); - - let surface = globals::object_create(wayland::WlDynObj::Surface); - wl_compositor::req::create_surface(surface).unwrap(); - - let region = globals::object_create(wayland::WlDynObj::Region); - wl_compositor::req::create_region(region).unwrap(); - - wl_surface::req::set_input_region(surface, Some(region)).unwrap(); - wl_region::req::destroy(region).unwrap(); - - let layer_surface = globals::object_create(wayland::WlDynObj::LayerSurface); - zwlr_layer_shell_v1::req::get_layer_surface( - layer_surface, - surface, - Some(output), - zwlr_layer_shell_v1::layer::BACKGROUND, - "swww-daemon", - ) - .unwrap(); - - let viewport = globals::object_create(wayland::WlDynObj::Viewport); - wp_viewporter::req::get_viewport(viewport, surface).unwrap(); - - let wp_fractional = if let Some(fract_man) = self.fractional_scale_manager.as_ref() { - let fractional = globals::object_create(wayland::WlDynObj::FractionalScale); - wp_fractional_scale_manager_v1::req::get_fractional_scale( - fract_man.id(), - fractional, - surface, - ) - .unwrap(); - Some(fractional) - } else { - None - }; - - debug!("New output: {output_name}"); - self.wallpapers.push(Rc::new(RefCell::new(Wallpaper::new( - output, + let wallpaper = Rc::new(RefCell::new(Wallpaper::new( + &mut self.objman, + self.pixel_format, + self.fractional_scale_manager, output_name, - surface, - viewport, - wp_fractional, - layer_surface, - )))); + ))); + self.wallpapers.push(wallpaper); } fn recv_socket_msg(&mut self, stream: IpcSocket) { @@ -146,9 +123,9 @@ impl Daemon { for wallpaper in &wallpapers { let mut wallpaper = wallpaper.borrow_mut(); wallpaper.set_img_info(common::ipc::BgImg::Color(clear.color)); - wallpaper.clear(clear.color); + wallpaper.clear(&mut self.objman, self.pixel_format, clear.color); } - crate::wallpaper::attach_buffers_and_damage_surfaces(&wallpapers); + crate::wallpaper::attach_buffers_and_damage_surfaces(&mut self.objman, &wallpapers); crate::wallpaper::commit_wallpapers(&wallpapers); Answer::Ok } @@ -178,10 +155,14 @@ impl Daemon { }; let wallpapers = self.find_wallpapers_by_names(&names); self.stop_animations(&wallpapers); - if let Some(mut transition) = - TransitionAnimator::new(wallpapers, &transition, img, animation) - { - transition.frame(); + if let Some(mut transition) = TransitionAnimator::new( + wallpapers, + &transition, + self.pixel_format, + img, + animation, + ) { + transition.frame(&mut self.objman, self.pixel_format); self.transition_animators.push(transition); } } @@ -197,7 +178,7 @@ impl Daemon { fn wallpapers_info(&self) -> Box<[BgInfo]> { self.wallpapers .iter() - .map(|wallpaper| wallpaper.borrow().get_bg_info()) + .map(|wallpaper| wallpaper.borrow().get_bg_info(self.pixel_format)) .collect() } @@ -235,10 +216,13 @@ impl Daemon { spin_sleep(time); } - wallpaper::attach_buffers_and_damage_surfaces(&animator.wallpapers); + wallpaper::attach_buffers_and_damage_surfaces( + &mut self.objman, + &animator.wallpapers, + ); wallpaper::commit_wallpapers(&animator.wallpapers); animator.updt_time(); - if animator.frame() { + if animator.frame(&mut self.objman, self.pixel_format) { let animator = self.transition_animators.swap_remove(i); if let Some(anim) = animator.into_image_animator() { self.image_animators.push(anim); @@ -266,10 +250,13 @@ impl Daemon { spin_sleep(time); } - wallpaper::attach_buffers_and_damage_surfaces(&animator.wallpapers); + wallpaper::attach_buffers_and_damage_surfaces( + &mut self.objman, + &animator.wallpapers, + ); wallpaper::commit_wallpapers(&animator.wallpapers); animator.updt_time(); - animator.frame(); + animator.frame(&mut self.objman, self.pixel_format); } } } @@ -294,10 +281,16 @@ impl Daemon { } } +impl wayland::interfaces::wl_display::HasObjman for Daemon { + fn objman(&mut self) -> &mut ObjectManager { + &mut self.objman + } +} + impl wayland::interfaces::wl_display::EvHandler for Daemon { fn delete_id(&mut self, id: u32) { if let Some(id) = NonZeroU32::new(id) { - globals::object_remove(ObjectId::new(id)); + self.objman.remove(ObjectId::new(id)); } } } @@ -374,7 +367,7 @@ impl wayland::interfaces::wl_output::EvHandler for Daemon { if wallpaper.borrow().has_output(sender_id) { if wallpaper .borrow_mut() - .commit_surface_changes(self.use_cache) + .commit_surface_changes(&mut self.objman, self.use_cache) { self.stop_animations(&[wallpaper.clone()]); } @@ -502,7 +495,7 @@ impl wayland::interfaces::wp_fractional_scale_v1::EvHandler for Daemon { wallpaper.borrow_mut().set_scale(Scale::Fractional(factor)); if wallpaper .borrow_mut() - .commit_surface_changes(self.use_cache) + .commit_surface_changes(&mut self.objman, self.use_cache) { self.stop_animations(&[wallpaper.clone()]); } @@ -521,7 +514,7 @@ fn main() -> Result<(), String> { make_logger(cli.quiet); // initialize the wayland connection, getting all the necessary globals - let initializer = wayland::globals::init(cli.format); + let init_state = wayland::globals::init(cli.format); // create the socket listener and setup the signal handlers // this will also return an error if there is an `swww-daemon` instance already @@ -530,11 +523,7 @@ fn main() -> Result<(), String> { setup_signals(); // use the initializer to create the Daemon, then drop it to free up the memory - let mut daemon = Daemon::new(&initializer, cli.no_cache); - for &output_name in initializer.output_names() { - daemon.new_output(output_name); - } - drop(initializer); + let mut daemon = Daemon::new(init_state, cli.no_cache); if let Ok(true) = sd_notify::booted() { if let Err(e) = sd_notify::notify(true, &[sd_notify::NotifyState::Ready]) { @@ -574,7 +563,7 @@ fn main() -> Result<(), String> { globals::WP_VIEWPORTER => error!("wp_viewporter has no events"), globals::ZWLR_LAYER_SHELL_V1 => error!("zwlr_layer_shell_v1 has no events"), other => { - let obj_id = globals::object_type_get(other); + let obj_id = daemon.objman.get(other); match obj_id { Some(WlDynObj::Output) => wl_output::event(&mut daemon, msg, payload), Some(WlDynObj::Surface) => wl_surface::event(&mut daemon, msg, payload), diff --git a/daemon/src/wallpaper.rs b/daemon/src/wallpaper.rs index 67ab413..75f2c97 100644 --- a/daemon/src/wallpaper.rs +++ b/daemon/src/wallpaper.rs @@ -1,15 +1,14 @@ -use common::ipc::{BgImg, BgInfo, Scale}; +use common::ipc::{BgImg, BgInfo, PixelFormat, Scale}; use log::{debug, error, warn}; use std::{cell::RefCell, num::NonZeroI32, rc::Rc, sync::atomic::AtomicBool}; use crate::wayland::{ bump_pool::BumpPool, - globals, interfaces::{ wl_output, wl_surface, wp_fractional_scale_v1, wp_viewport, zwlr_layer_surface_v1, }, - ObjectId, WlDynObj, + ObjectId, ObjectManager, WlDynObj, }; struct FrameCallbackHandler { @@ -18,8 +17,8 @@ struct FrameCallbackHandler { } impl FrameCallbackHandler { - fn new(surface: ObjectId) -> Self { - let callback = globals::object_create(WlDynObj::Callback); + fn new(objman: &mut ObjectManager, surface: ObjectId) -> Self { + let callback = objman.create(WlDynObj::Callback); wl_surface::req::frame(surface, callback).unwrap(); FrameCallbackHandler { done: true, // we do not have to wait for the first frame @@ -27,8 +26,8 @@ impl FrameCallbackHandler { } } - fn request_frame_callback(&mut self, surface: ObjectId) { - let callback = globals::object_create(WlDynObj::Callback); + fn request_frame_callback(&mut self, objman: &mut ObjectManager, surface: ObjectId) { + let callback = objman.create(WlDynObj::Callback); wl_surface::req::frame(surface, callback).unwrap(); self.callback = callback; } @@ -85,13 +84,48 @@ impl std::cmp::PartialEq for Wallpaper { impl Wallpaper { pub(crate) fn new( - output: ObjectId, + objman: &mut ObjectManager, + pixel_format: PixelFormat, + fractional_scale_manager: Option, output_name: u32, - wl_surface: ObjectId, - wp_viewport: ObjectId, - wp_fractional: Option, - layer_surface: ObjectId, ) -> Self { + use crate::wayland::{self, interfaces::*}; + let output = objman.create(wayland::WlDynObj::Output); + wl_registry::req::bind(output_name, output, "wl_output", 4).unwrap(); + + let wl_surface = objman.create(wayland::WlDynObj::Surface); + wl_compositor::req::create_surface(wl_surface).unwrap(); + + let region = objman.create(wayland::WlDynObj::Region); + wl_compositor::req::create_region(region).unwrap(); + + wl_surface::req::set_input_region(wl_surface, Some(region)).unwrap(); + wl_region::req::destroy(region).unwrap(); + + let layer_surface = objman.create(wayland::WlDynObj::LayerSurface); + zwlr_layer_shell_v1::req::get_layer_surface( + layer_surface, + wl_surface, + Some(output), + zwlr_layer_shell_v1::layer::BACKGROUND, + "swww-daemon", + ) + .unwrap(); + + let wp_viewport = objman.create(wayland::WlDynObj::Viewport); + wp_viewporter::req::get_viewport(wp_viewport, wl_surface).unwrap(); + + let wp_fractional = if let Some(fract_man) = fractional_scale_manager { + let fractional = objman.create(wayland::WlDynObj::FractionalScale); + wp_fractional_scale_manager_v1::req::get_fractional_scale( + fract_man, fractional, wl_surface, + ) + .unwrap(); + Some(fractional) + } else { + None + }; + let inner = WallpaperInner::default(); let inner_staging = WallpaperInner::default(); @@ -106,12 +140,13 @@ impl Wallpaper { .unwrap(); wl_surface::req::set_buffer_scale(wl_surface, 1).unwrap(); - let frame_callback_handler = FrameCallbackHandler::new(wl_surface); + let frame_callback_handler = FrameCallbackHandler::new(objman, wl_surface); // commit so that the compositor send the initial configuration wl_surface::req::commit(wl_surface).unwrap(); - let pool = BumpPool::new(256, 256); + let pool = BumpPool::new(256, 256, objman, pixel_format); + debug!("New output: {output_name}"); Self { output, output_name, @@ -128,7 +163,7 @@ impl Wallpaper { } } - pub fn get_bg_info(&self) -> BgInfo { + pub fn get_bg_info(&self, pixel_format: PixelFormat) -> BgInfo { BgInfo { name: self.inner.name.clone().unwrap_or("?".to_string()), dim: ( @@ -137,7 +172,7 @@ impl Wallpaper { ), scale_factor: self.inner.scale_factor, img: self.img.clone(), - pixel_format: globals::pixel_format(), + pixel_format, } } @@ -213,7 +248,7 @@ impl Wallpaper { } } - pub fn commit_surface_changes(&mut self, use_cache: bool) -> bool { + pub fn commit_surface_changes(&mut self, objman: &mut ObjectManager, use_cache: bool) -> bool { use wl_output::transform; let inner = &mut self.inner; let staging = &self.inner_staging; @@ -283,7 +318,7 @@ impl Wallpaper { self.pool.resize(w, h); self.frame_callback_handler - .request_frame_callback(self.wl_surface); + .request_frame_callback(objman, self.wl_surface); wl_surface::req::commit(self.wl_surface).unwrap(); self.configured .store(true, std::sync::atomic::Ordering::Release); @@ -342,20 +377,30 @@ impl Wallpaper { (dim.0 as u32, dim.1 as u32) } - pub(super) fn canvas_change(&mut self, f: F) -> T + pub(super) fn canvas_change( + &mut self, + objman: &mut ObjectManager, + pixel_format: PixelFormat, + f: F, + ) -> T where F: FnOnce(&mut [u8]) -> T, { - f(self.pool.get_drawable()) + f(self.pool.get_drawable(objman, pixel_format)) } pub(super) fn frame_callback_completed(&mut self) { self.frame_callback_handler.done = true; } - pub(super) fn clear(&mut self, color: [u8; 3]) { - self.canvas_change(|canvas| { - for pixel in canvas.chunks_exact_mut(globals::pixel_format().channels().into()) { + pub(super) fn clear( + &mut self, + objman: &mut ObjectManager, + pixel_format: PixelFormat, + color: [u8; 3], + ) { + self.canvas_change(objman, pixel_format, |canvas| { + for pixel in canvas.chunks_exact_mut(pixel_format.channels().into()) { pixel[0..3].copy_from_slice(&color); } }) @@ -368,7 +413,10 @@ impl Wallpaper { } /// attaches all pending buffers and damages all surfaces with one single request -pub(crate) fn attach_buffers_and_damage_surfaces(wallpapers: &[Rc>]) { +pub(crate) fn attach_buffers_and_damage_surfaces( + objman: &mut ObjectManager, + wallpapers: &[Rc>], +) { #[rustfmt::skip] // Note this is little-endian specific const MSG: [u8; 56] = [ @@ -409,7 +457,7 @@ pub(crate) fn attach_buffers_and_damage_surfaces(wallpapers: &[Rc Self { let released = true; - let object_id = globals::object_create(super::WlDynObj::Buffer); + let object_id = objman.create(super::WlDynObj::Buffer); super::interfaces::wl_shm_pool::req::create_buffer( pool_id, object_id, offset, width, height, stride, format, ) @@ -66,11 +67,15 @@ pub(crate) struct BumpPool { impl BumpPool { /// We assume `width` and `height` have already been multiplied by their scale factor - pub(crate) fn new(width: i32, height: i32) -> Self { - let len = - width as usize * height as usize * super::globals::pixel_format().channels() as usize; + pub(crate) fn new( + width: i32, + height: i32, + objman: &mut ObjectManager, + pixel_format: PixelFormat, + ) -> Self { + let len = width as usize * height as usize * pixel_format.channels() as usize; let mmap = Mmap::create(len); - let pool_id = globals::object_create(super::WlDynObj::ShmPool); + let pool_id = objman.create(super::WlDynObj::ShmPool); super::interfaces::wl_shm::req::create_pool(pool_id, &mmap.fd(), len as i32) .expect("failed to create WlShmPool object"); let buffers = Vec::with_capacity(2); @@ -108,24 +113,22 @@ impl BumpPool { } } - fn buffer_len(&self) -> usize { - self.width as usize - * self.height as usize - * super::globals::pixel_format().channels() as usize + const fn buffer_len(&self, pixel_format: PixelFormat) -> usize { + self.width as usize * self.height as usize * pixel_format.channels() as usize } - fn buffer_offset(&self, buffer_index: usize) -> usize { - self.buffer_len() * buffer_index + const fn buffer_offset(&self, buffer_index: usize, pixel_format: PixelFormat) -> usize { + self.buffer_len(pixel_format) * buffer_index } - fn occupied_bytes(&self) -> usize { - self.buffer_offset(self.buffers.len()) + fn occupied_bytes(&self, pixel_format: PixelFormat) -> usize { + self.buffer_offset(self.buffers.len(), pixel_format) } /// resizes the pool and creates a new WlBuffer at the next free offset - fn grow(&mut self) { - let len = self.buffer_len(); - let new_len = self.occupied_bytes() + len; + fn grow(&mut self, objman: &mut ObjectManager, pixel_format: PixelFormat) { + let len = self.buffer_len(pixel_format); + let new_len = self.occupied_bytes(pixel_format) + len; // we unmap the shared memory file descriptor when animations are done, so here we must // ensure the bytes are actually mmaped @@ -141,12 +144,13 @@ impl BumpPool { let new_buffer_index = self.buffers.len(); self.buffers.push(Buffer::new( + objman, self.pool_id, - self.buffer_offset(new_buffer_index) as i32, + self.buffer_offset(new_buffer_index, pixel_format) as i32, self.width, self.height, - self.width * super::globals::pixel_format().channels() as i32, - super::globals::wl_shm_format(), + self.width * pixel_format.channels() as i32, + super::globals::wl_shm_format(pixel_format), )); log::info!( @@ -159,7 +163,11 @@ impl BumpPool { /// Returns a drawable surface. If we can't find a free buffer, we request more memory /// /// This function automatically handles copying the previous buffer over onto the new one - pub(crate) fn get_drawable(&mut self) -> &mut [u8] { + pub(crate) fn get_drawable( + &mut self, + objman: &mut ObjectManager, + pixel_format: PixelFormat, + ) -> &mut [u8] { let (i, buf) = match self .buffers .iter_mut() @@ -168,17 +176,17 @@ impl BumpPool { { Some((i, buf)) => (i, buf), None => { - self.grow(); + self.grow(objman, pixel_format); (self.buffers.len() - 1, self.buffers.last_mut().unwrap()) } }; buf.unset_released(); - let len = self.buffer_len(); - let offset = self.buffer_offset(i); + let len = self.buffer_len(pixel_format); + let offset = self.buffer_offset(i, pixel_format); if self.last_used_buffer != i { - let last_offset = self.buffer_offset(self.last_used_buffer); + let last_offset = self.buffer_offset(self.last_used_buffer, pixel_format); self.mmap .slice_mut() .copy_within(last_offset..last_offset + len, offset); diff --git a/daemon/src/wayland/globals.rs b/daemon/src/wayland/globals.rs index 26e2642..2b1d432 100644 --- a/daemon/src/wayland/globals.rs +++ b/daemon/src/wayland/globals.rs @@ -18,9 +18,9 @@ use rustix::{ }; use common::ipc::PixelFormat; -use log::{debug, error, info}; +use log::{debug, error}; -use super::{ObjectId, ObjectManager, WlDynObj}; +use super::{ObjectId, ObjectManager}; use std::{num::NonZeroU32, path::PathBuf, sync::atomic::AtomicBool}; // all of these objects must always exist for `swww-daemon` to work correctly, so we turn them into @@ -42,13 +42,14 @@ const REQUIRED_GLOBALS: [&str; 4] = [ "wp_viewporter", "zwlr_layer_shell_v1", ]; + /// Minimal version necessary for `REQUIRED_GLOBALS` const VERSIONS: [u32; 4] = [4, 1, 1, 3]; +/// This is an unsafe static mut that we only ever write to once, during the `init` function call. +/// Any other function in this program can only access this variable through the `wayland_fd` +/// function, which always creates an immutable reference, which should be safe. static mut WAYLAND_FD: OwnedFd = unsafe { std::mem::zeroed() }; -static mut FRACTIONAL_SCALE_SUPPORT: bool = false; -static mut PIXEL_FORMAT: PixelFormat = PixelFormat::Xrgb; -static mut OBJECT_MANAGER: ObjectManager = ObjectManager::new(); static INITIALIZED: AtomicBool = AtomicBool::new(false); @@ -60,43 +61,8 @@ pub fn wayland_fd() -> BorrowedFd<'static> { } #[must_use] -pub fn fractional_scale_support() -> bool { - unsafe { FRACTIONAL_SCALE_SUPPORT } -} - -#[must_use] -/// Safe because this is a single threaded application, so no race conditions can occur -pub fn object_type_get(object_id: ObjectId) -> Option { - debug_assert!(INITIALIZED.load(std::sync::atomic::Ordering::Relaxed)); - let ptr = &raw const OBJECT_MANAGER; - unsafe { &*ptr }.get(object_id) -} - -#[must_use] -/// Safe because this is a single threaded application, so no race conditions can occur -pub fn object_create(object_type: WlDynObj) -> ObjectId { - debug_assert!(INITIALIZED.load(std::sync::atomic::Ordering::Relaxed)); - let ptr = &raw mut OBJECT_MANAGER; - unsafe { &mut *ptr }.create(object_type) -} - -/// Safe because this is a single threaded application, so no race conditions can occur -pub fn object_remove(object_id: ObjectId) { - debug_assert!(INITIALIZED.load(std::sync::atomic::Ordering::Relaxed)); - let ptr = &raw mut OBJECT_MANAGER; - unsafe { &mut *ptr }.remove(object_id) -} - -#[must_use] -pub fn pixel_format() -> PixelFormat { - debug_assert!(INITIALIZED.load(std::sync::atomic::Ordering::Relaxed)); - unsafe { PIXEL_FORMAT } -} - -#[must_use] -pub fn wl_shm_format() -> u32 { - debug_assert!(INITIALIZED.load(std::sync::atomic::Ordering::Relaxed)); - match unsafe { PIXEL_FORMAT } { +pub fn wl_shm_format(pixel_format: PixelFormat) -> u32 { + match pixel_format { PixelFormat::Xrgb => super::interfaces::wl_shm::format::XRGB8888, PixelFormat::Xbgr => super::interfaces::wl_shm::format::XBGR8888, PixelFormat::Rgb => super::interfaces::wl_shm::format::RGB888, @@ -105,24 +71,16 @@ pub fn wl_shm_format() -> u32 { } /// Note that this function assumes the logger has already been set up -pub fn init(pixel_format: Option) -> Initializer { +pub fn init(pixel_format: Option) -> InitState { if INITIALIZED.load(std::sync::atomic::Ordering::Relaxed) { panic!("trying to run initialization code twice"); } - let mut initializer = Initializer::new(pixel_format); - - // initialize the two most important globals: - // * the wayland file descriptor; and - // * the object manager - // we optionally initialize the pixel_format, if necessary unsafe { WAYLAND_FD = connect(); - if let Some(format) = pixel_format { - info!("Forced usage of wl_shm format: {:?}", format); - PIXEL_FORMAT = format; - } } + let mut initializer = Initializer::new(pixel_format); + // the only globals that can break catastrophically are WAYLAND_FD and OBJECT_MANAGER, that we // have just initialized above. So this is safe INITIALIZED.store(true, std::sync::atomic::Ordering::SeqCst); @@ -169,7 +127,6 @@ pub fn init(pixel_format: Option) -> Initializer { // bind fractional scale, if it is supported if let Some(fractional_scale_manager) = initializer.fractional_scale.as_ref() { - unsafe { FRACTIONAL_SCALE_SUPPORT = true }; super::interfaces::wl_registry::req::bind( fractional_scale_manager.name.get(), fractional_scale_manager.id, @@ -201,7 +158,7 @@ pub fn init(pixel_format: Option) -> Initializer { } } - initializer + initializer.into_init_state() } /// mostly copy-pasted from `wayland-client.rs` @@ -263,7 +220,9 @@ impl FractionalScaleManager { } /// Helper struct to do all the initialization in this file -pub struct Initializer { +struct Initializer { + objman: ObjectManager, + pixel_format: PixelFormat, global_names: [u32; REQUIRED_GLOBALS.len()], output_names: Vec, fractional_scale: Option, @@ -271,14 +230,24 @@ pub struct Initializer { should_exit: bool, } +/// Helper struct to expose all of the initialized state +pub struct InitState { + pub output_names: Vec, + pub fractional_scale: Option, + pub objman: ObjectManager, + pub pixel_format: PixelFormat, +} + impl Initializer { fn new(cli_format: Option) -> Self { Self { + objman: ObjectManager::new(), global_names: [0; REQUIRED_GLOBALS.len()], output_names: Vec::new(), fractional_scale: None, forced_shm_format: cli_format.is_some(), should_exit: false, + pixel_format: cli_format.unwrap_or(PixelFormat::Xrgb), } } @@ -290,6 +259,16 @@ impl Initializer { } } + fn into_init_state(self) -> InitState { + debug!("Initialization Over"); + InitState { + output_names: self.output_names, + fractional_scale: self.fractional_scale, + objman: self.objman, + pixel_format: self.pixel_format, + } + } + pub fn output_names(&self) -> &[u32] { &self.output_names } @@ -299,6 +278,12 @@ impl Initializer { } } +impl super::interfaces::wl_display::HasObjman for Initializer { + fn objman(&mut self) -> &mut ObjectManager { + &mut self.objman + } +} + impl super::interfaces::wl_display::EvHandler for Initializer { fn delete_id(&mut self, id: u32) { if id == 3 // initial callback for the roundtrip @@ -333,6 +318,7 @@ impl super::interfaces::wl_registry::EvHandler for Initializer { id: ObjectId(unsafe { NonZeroU32::new_unchecked(7) }), name: name.try_into().unwrap(), }); + self.objman.set_fractional_scale_support(true); } "wl_output" => { if version < 4 { @@ -371,29 +357,23 @@ impl super::interfaces::wl_shm::EvHandler for Initializer { } super::interfaces::wl_shm::format::XBGR8888 => { debug!("available shm format: Xbgr"); - if !self.forced_shm_format && pixel_format() == PixelFormat::Xrgb { - unsafe { PIXEL_FORMAT = PixelFormat::Xbgr } + if !self.forced_shm_format && self.pixel_format == PixelFormat::Xrgb { + self.pixel_format = PixelFormat::Xbgr; } } super::interfaces::wl_shm::format::RGB888 => { debug!("available shm format: Rbg"); - if !self.forced_shm_format && pixel_format() != PixelFormat::Bgr { - unsafe { PIXEL_FORMAT = PixelFormat::Rgb } + if !self.forced_shm_format && self.pixel_format != PixelFormat::Bgr { + self.pixel_format = PixelFormat::Rgb } } super::interfaces::wl_shm::format::BGR888 => { debug!("available shm format: Bgr"); if !self.forced_shm_format { - unsafe { PIXEL_FORMAT = PixelFormat::Bgr } + self.pixel_format = PixelFormat::Bgr } } _ => (), } } } - -impl Drop for Initializer { - fn drop(&mut self) { - debug!("Initialization Over"); - } -} diff --git a/daemon/src/wayland/interfaces.rs b/daemon/src/wayland/interfaces.rs index f5a2a0f..209634a 100644 --- a/daemon/src/wayland/interfaces.rs +++ b/daemon/src/wayland/interfaces.rs @@ -8,7 +8,7 @@ use super::{ globals, wire::{WaylandPayload, WireMsg, WireMsgBuilder, WlFixed}, - ObjectId, + ObjectId, ObjectManager, }; ///core global object @@ -18,7 +18,13 @@ use super::{ pub mod wl_display { use super::*; - pub trait EvHandler { + /// This is a special interface to make it possible to have a generic implementation for this + /// interface + pub trait HasObjman { + fn objman(&mut self) -> &mut ObjectManager; + } + + pub trait EvHandler: HasObjman { ///fatal error event /// ///The error event is sent out when a fatal (non-recoverable) @@ -36,7 +42,7 @@ pub mod wl_display { globals::WL_SHM => "wl_shm", globals::WP_VIEWPORTER => "wp_viewporter", globals::ZWLR_LAYER_SHELL_V1 => "zwlr_layer_shell_v1", - other => match super::super::globals::object_type_get(other) { + other => match self.objman().get(other) { Some(super::super::WlDynObj::Output) => "wl_output", Some(super::super::WlDynObj::Surface) => "wl_surface", Some(super::super::WlDynObj::Region) => "wl_region", diff --git a/daemon/src/wayland/mod.rs b/daemon/src/wayland/mod.rs index e1c0a1b..237cc0a 100644 --- a/daemon/src/wayland/mod.rs +++ b/daemon/src/wayland/mod.rs @@ -67,6 +67,7 @@ pub struct ObjectManager { objects: Vec>, /// the next id we ought to generate next: u32, + fractional_scale_support: bool, } impl ObjectManager { @@ -77,6 +78,7 @@ impl ObjectManager { Self { objects: Vec::new(), next: 0, + fractional_scale_support: false, } } @@ -87,7 +89,7 @@ impl ObjectManager { /// * 'None' if the object was already deleted #[must_use] pub fn get(&self, object_id: ObjectId) -> Option { - let offset = Self::BASE_OFFSET + globals::fractional_scale_support() as u32; + let offset = Self::BASE_OFFSET + self.fractional_scale_support as u32; let pos = object_id.get() - offset; self.objects[pos as usize] } @@ -95,7 +97,7 @@ impl ObjectManager { /// creates a new Id to use in requests #[must_use] pub fn create(&mut self, object: WlDynObj) -> ObjectId { - let offset = Self::BASE_OFFSET + globals::fractional_scale_support() as u32; + let offset = Self::BASE_OFFSET + self.fractional_scale_support as u32; if self.next as usize == self.objects.len() { self.next += 1; self.objects.push(Some(object)); @@ -122,13 +124,21 @@ impl ObjectManager { /// Removing the same element twice currently works just fine and does not panic, /// but that may change in the future pub fn remove(&mut self, object_id: ObjectId) { - let offset = Self::BASE_OFFSET + globals::fractional_scale_support() as u32; + let offset = Self::BASE_OFFSET + self.fractional_scale_support as u32; let pos = object_id.get() - offset; self.objects[pos as usize] = None; if pos < self.next { self.next = pos; } } + + pub fn set_fractional_scale_support(&mut self, fractional_scale_support: bool) { + self.fractional_scale_support = fractional_scale_support; + } + + pub fn fractional_scale_support(&self) -> bool { + self.fractional_scale_support + } } #[cfg(test)] diff --git a/daemon/src/wayland/wire.rs b/daemon/src/wayland/wire.rs index 7f2bfcd..e915440 100644 --- a/daemon/src/wayland/wire.rs +++ b/daemon/src/wayland/wire.rs @@ -263,7 +263,7 @@ pub unsafe fn send_unchecked(msg: &[u8], fds: &[BorrowedFd]) -> rustix::io::Resu net::sendmsg(wayland_fd(), &[iov], &mut control, net::SendFlags::NOSIGNAL).map(|_| ()) } -impl<'a> WlSlice<'a> { +impl WlSlice<'_> { #[must_use] pub const fn get(&self) -> &[u8] { self.0 @@ -302,7 +302,7 @@ where } } -impl<'a> WlStr<'a> { +impl WlStr<'_> { #[must_use] pub const fn get(&self) -> &str { self.0 @@ -381,7 +381,7 @@ impl From<&WlFixed> for f64 { } } -impl<'a> NewId<'a> { +impl NewId<'_> { #[must_use] pub const fn id(&self) -> &ObjectId { &self.id