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