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.
This commit is contained in:
Leonardo Gibrowski Faé
2024-12-05 11:33:42 -03:00
parent 31996fb43c
commit e0d2e8436e
9 changed files with 462 additions and 356 deletions

View File

@@ -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<Rc<RefCell<Wallpaper>>>,
transition: &ipc::Transition,
pixel_format: PixelFormat,
img_req: ImgReq,
animation: Option<Animation>,
) -> Option<Self> {
@@ -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}");

View File

@@ -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<RefCell<Wallpaper>>], img: &[u8]) -> bool {
fn run(
&mut self,
objman: &mut ObjectManager,
pixel_format: PixelFormat,
wallpapers: &mut [Rc<RefCell<Wallpaper>>],
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<RefCell<Wallpaper>>], img: &[u8]) -> bool {
pub fn execute(
&mut self,
objman: &mut ObjectManager,
pixel_format: PixelFormat,
wallpapers: &mut [Rc<RefCell<Wallpaper>>],
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<RefCell<Wallpaper>>], img: &[u8]) -> bool {
fn run(
&mut self,
objman: &mut ObjectManager,
pixel_format: PixelFormat,
wallpapers: &mut [Rc<RefCell<Wallpaper>>],
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<RefCell<Wallpaper>>], img: &[u8]) -> bool {
fn run(
&mut self,
objman: &mut ObjectManager,
pixel_format: PixelFormat,
wallpapers: &mut [Rc<RefCell<Wallpaper>>],
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<RefCell<Wallpaper>>], img: &[u8]) -> bool {
fn run(
&mut self,
objman: &mut ObjectManager,
pixel_format: PixelFormat,
wallpapers: &mut [Rc<RefCell<Wallpaper>>],
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<RefCell<Wallpaper>>], img: &[u8]) -> bool {
fn run(
&mut self,
objman: &mut ObjectManager,
pixel_format: PixelFormat,
wallpapers: &mut [Rc<RefCell<Wallpaper>>],
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<RefCell<Wallpaper>>], img: &[u8]) -> bool {
fn run(
&mut self,
objman: &mut ObjectManager,
pixel_format: PixelFormat,
wallpapers: &mut [Rc<RefCell<Wallpaper>>],
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);
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);
// 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<RefCell<Wallpaper>>], img: &[u8]) -> bool {
fn run(
&mut self,
objman: &mut ObjectManager,
pixel_format: PixelFormat,
wallpapers: &mut [Rc<RefCell<Wallpaper>>],
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);
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);
}
}
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());

View File

@@ -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<Rc<RefCell<Wallpaper>>>,
transition_animators: Vec<TransitionAnimator>,
image_animators: Vec<ImageAnimator>,
use_cache: bool,
fractional_scale_manager: Option<FractionalScaleManager>,
fractional_scale_manager: Option<ObjectId>,
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<Server>) {
@@ -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),

View File

@@ -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<ObjectId>,
output_name: u32,
wl_surface: ObjectId,
wp_viewport: ObjectId,
wp_fractional: Option<ObjectId>,
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<F, T>(&mut self, f: F) -> T
pub(super) fn canvas_change<F, T>(
&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<RefCell<Wallpaper>>]) {
pub(crate) fn attach_buffers_and_damage_surfaces(
objman: &mut ObjectManager,
wallpapers: &[Rc<RefCell<Wallpaper>>],
) {
#[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<RefCell<Wallpa
msg[40..44].copy_from_slice(&height.to_ne_bytes());
// frame callback
let callback = globals::object_create(WlDynObj::Callback);
let callback = objman.create(WlDynObj::Callback);
wallpaper.frame_callback_handler.callback = callback;
msg[44..48].copy_from_slice(&wallpaper.wl_surface.get().to_ne_bytes());
msg[52..56].copy_from_slice(&callback.get().to_ne_bytes());

View File

@@ -1,6 +1,6 @@
use common::mmap::Mmap;
use common::{ipc::PixelFormat, mmap::Mmap};
use super::{globals, ObjectId};
use super::{ObjectId, ObjectManager};
#[derive(Debug)]
struct Buffer {
@@ -10,6 +10,7 @@ struct Buffer {
impl Buffer {
fn new(
objman: &mut ObjectManager,
pool_id: ObjectId,
offset: i32,
width: i32,
@@ -18,7 +19,7 @@ impl Buffer {
format: u32,
) -> 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);

View File

@@ -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<WlDynObj> {
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<PixelFormat>) -> Initializer {
pub fn init(pixel_format: Option<PixelFormat>) -> 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<PixelFormat>) -> 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<PixelFormat>) -> 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<u32>,
fractional_scale: Option<FractionalScaleManager>,
@@ -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<u32>,
pub fractional_scale: Option<FractionalScaleManager>,
pub objman: ObjectManager,
pub pixel_format: PixelFormat,
}
impl Initializer {
fn new(cli_format: Option<PixelFormat>) -> 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");
}
}

View File

@@ -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",

View File

@@ -67,6 +67,7 @@ pub struct ObjectManager {
objects: Vec<Option<WlDynObj>>,
/// 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<WlDynObj> {
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)]

View File

@@ -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