examples: Add sctk_subsurface_img
Test scrolling. Single color buffers in `sctk_subsurface` aren't good for comparing it, and `sctk_subsurface_gst` isn't working on latest gst with explicit sync (and AppSync isn't accepting the dmabuf when I try to modify it.)
This commit is contained in:
parent
5865264964
commit
d0b4d0e9c9
2 changed files with 156 additions and 0 deletions
21
examples/sctk_subsurface_img/Cargo.toml
Normal file
21
examples/sctk_subsurface_img/Cargo.toml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
[package]
|
||||
name = "sctk_subsurface_img"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
iced = { path = "../..", default-features = false, features = [
|
||||
"tokio",
|
||||
"wayland",
|
||||
"winit",
|
||||
"debug",
|
||||
"tiny-skia",
|
||||
"image",
|
||||
] }
|
||||
iced_runtime = { path = "../../runtime" }
|
||||
env_logger = "0.10"
|
||||
futures-channel = "0.3.29"
|
||||
calloop = "0.13"
|
||||
rustix = { version = "0.38.30", features = ["fs", "shm"] }
|
||||
cctk.workspace = true
|
||||
image = { workspace = true, features = ["png"] }
|
||||
135
examples/sctk_subsurface_img/src/main.rs
Normal file
135
examples/sctk_subsurface_img/src/main.rs
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
use cctk::sctk::reexports::client::protocol::wl_shm;
|
||||
use iced::{
|
||||
platform_specific::shell::subsurface_widget::{
|
||||
self, Shmbuf, SubsurfaceBuffer,
|
||||
},
|
||||
window::{self, Id, Settings},
|
||||
Element, Length, Subscription, Task,
|
||||
};
|
||||
use image::{ImageReader, Pixel};
|
||||
use rustix::{io::Errno, shm::ShmOFlags};
|
||||
use std::{
|
||||
env,
|
||||
os::fd::OwnedFd,
|
||||
path::Path,
|
||||
sync::Arc,
|
||||
time::{SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
fn main() -> iced::Result {
|
||||
let args = env::args();
|
||||
if args.len() != 2 {
|
||||
eprintln!("usage: sctk_subsurface_img [image path]");
|
||||
return Ok(());
|
||||
}
|
||||
let path = args.skip(1).next().unwrap();
|
||||
if !Path::new(&path).exists() {
|
||||
eprintln!("File `{path}` not found.");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
iced::daemon(
|
||||
SubsurfaceApp::title,
|
||||
SubsurfaceApp::update,
|
||||
SubsurfaceApp::view,
|
||||
)
|
||||
.subscription(SubsurfaceApp::subscription)
|
||||
.run_with(|| SubsurfaceApp::new(path))
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct SubsurfaceApp {
|
||||
path: String,
|
||||
buffer: SubsurfaceBuffer,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Message {
|
||||
Id(Id),
|
||||
}
|
||||
|
||||
impl SubsurfaceApp {
|
||||
fn new(path: String) -> (SubsurfaceApp, Task<Message>) {
|
||||
let img = ImageReader::open(&path)
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap()
|
||||
.to_rgba8();
|
||||
let fd = create_memfile().unwrap();
|
||||
for pixel in img.pixels() {
|
||||
let [r, g, b, a] = <[u8; 4]>::try_from(pixel.channels()).unwrap();
|
||||
rustix::io::write(&fd, &[b, g, r, a]).unwrap();
|
||||
}
|
||||
let shmbuf = Shmbuf {
|
||||
fd,
|
||||
offset: 0,
|
||||
width: img.width() as i32,
|
||||
height: img.height() as i32,
|
||||
stride: img.width() as i32 * 4,
|
||||
format: wl_shm::Format::Xrgb8888,
|
||||
};
|
||||
let buffer = SubsurfaceBuffer::new(Arc::new(shmbuf.into())).0;
|
||||
|
||||
(
|
||||
SubsurfaceApp { path, buffer },
|
||||
iced::window::open(Settings {
|
||||
..Default::default()
|
||||
})
|
||||
.1
|
||||
.map(Message::Id),
|
||||
)
|
||||
}
|
||||
|
||||
fn title(&self, _id: window::Id) -> String {
|
||||
String::from("SubsurfaceApp")
|
||||
}
|
||||
|
||||
fn update(&mut self, message: Message) -> Task<Message> {
|
||||
match message {
|
||||
Message::Id(_) => {}
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
fn view(&self, _id: window::Id) -> Element<Message> {
|
||||
// TODO compare side-by-side with image widget; key bind to toggle?
|
||||
let image = subsurface_widget::Subsurface::new(self.buffer.clone())
|
||||
.content_fit(iced::ContentFit::None);
|
||||
/*
|
||||
let image = iced::widget::image::Image::new(&self.path)
|
||||
.content_fit(iced::ContentFit::None);
|
||||
*/
|
||||
iced::widget::scrollable(image).into()
|
||||
}
|
||||
|
||||
fn subscription(&self) -> Subscription<Message> {
|
||||
Subscription::none()
|
||||
}
|
||||
}
|
||||
|
||||
fn create_memfile() -> rustix::io::Result<OwnedFd> {
|
||||
loop {
|
||||
let flags = ShmOFlags::CREATE | ShmOFlags::EXCL | ShmOFlags::RDWR;
|
||||
|
||||
let time = SystemTime::now();
|
||||
let name = format!(
|
||||
"/iced-sctk-{}",
|
||||
time.duration_since(UNIX_EPOCH).unwrap().subsec_nanos()
|
||||
);
|
||||
|
||||
match rustix::io::retry_on_intr(|| {
|
||||
rustix::shm::shm_open(&name, flags, 0600.into())
|
||||
}) {
|
||||
Ok(fd) => match rustix::shm::shm_unlink(&name) {
|
||||
Ok(_) => return Ok(fd),
|
||||
Err(errno) => {
|
||||
return Err(errno.into());
|
||||
}
|
||||
},
|
||||
Err(Errno::EXIST) => {
|
||||
continue;
|
||||
}
|
||||
Err(err) => return Err(err.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue