summaryrefslogtreecommitdiff
path: root/src/gtk.rs
diff options
context:
space:
mode:
authordyknon dyknonr5fjp2025-02-24 18:58:32 +0900
committerdyknon dyknonr5fjp2025-02-24 18:58:32 +0900
commit6ecbf0d55695335f52d6fcf2b6a22ed45f5e4d99 (patch)
treee17bfc8a9b55d5afbfe2f884322a96a54340f25d /src/gtk.rs
parent31b60ae28e6aff6d23b378cd77e288c96c7db148 (diff)
Remote camera capability.
Diffstat (limited to 'src/gtk.rs')
-rw-r--r--src/gtk.rs78
1 files changed, 59 insertions, 19 deletions
diff --git a/src/gtk.rs b/src/gtk.rs
index 94fb5f1..c72b524 100644
--- a/src/gtk.rs
+++ b/src/gtk.rs
@@ -1,9 +1,11 @@
use anyhow::{anyhow, Result};
-use gtk4::{self as gtk, glib, cairo};
+use gtk4::{self as gtk, glib, cairo, gio};
use gtk4::prelude::*;
use glib::{clone, spawn_future_local};
use std::thread;
use std::sync::{Arc, Mutex};
+use std::rc::Rc;
+use std::cell::RefCell;
use crate::sync::Signal;
use std::future::poll_fn;
use std::task::Poll;
@@ -49,12 +51,30 @@ pub struct Packet<T>{
pub image: cairo::ImageSurfaceDataOwned,
pub attr: T,
}
-pub trait Overray: Send + 'static{}
+pub trait Overlay: Send + 'static{
+ type Widget: glib::object::IsA<gtk::Widget>;
+ fn empty() -> Result<Self::Widget>;
+ fn activate(_widget: &Self::Widget) -> Result<()>{
+ Ok(())
+ }
+ fn update(&self, _widget: &Self::Widget) -> Result<()>{
+ Ok(())
+ }
+}
pub trait Source: Send + 'static{
- type Attr: Overray;
+ type Attr: Overlay;
fn next(&mut self, fbpool: impl FbSourceOnce) -> Result<Packet<Self::Attr>>;
}
-impl Overray for (){}
+impl Overlay for (){
+ type Widget = gtk::Box;
+ fn empty() -> Result<gtk::Box>{
+ Ok(gtk::Box::builder()
+ .halign(gtk::Align::Start)
+ .valign(gtk::Align::Start)
+ .visible(false)
+ .build())
+ }
+}
struct AppState<T>{
next: Mutex<Option<Packet<T>>>,
@@ -63,7 +83,7 @@ struct AppState<T>{
fbpool: Mutex<FbPool>,
}
-fn sourcing_loop<Attr: Overray>(
+fn sourcing_loop<Attr: Overlay>(
apps: &AppState<Attr>,
src: &mut impl Source<Attr=Attr>
) -> Result<()>{
@@ -81,23 +101,19 @@ fn sourcing_loop<Attr: Overray>(
}
}
-fn activate<Attr: Overray>(app: &gtk::Application, apps: Arc<AppState<Attr>>){
+fn activate<Attr: Overlay>(app: &gtk::Application, apps: Arc<AppState<Attr>>){
let draw = gtk::DrawingArea::new();
- let mut frame_cache: Option<cairo::ImageSurface> = None;
+ let overlay = Attr::empty().unwrap();
+
+ let frame_cache: Rc<RefCell<Option<cairo::ImageSurface>>>
+ = Rc::new(RefCell::new(None));
draw.set_draw_func(clone!{
- #[strong] apps,
+ #[strong] frame_cache,
move |_draw, ctx, canvas_w, canvas_h|{
ctx.set_source_rgb(0., 0., 0.);
ctx.paint().unwrap();
- if let Some(newfb) = apps.next.lock().unwrap().take(){
- if let Some(lastframe) = frame_cache.take(){
- apps.fbpool.lock().unwrap()
- .put(lastframe.take_data().unwrap());
- }
- frame_cache = Some(newfb.image.into_inner());
- }
- if let Some(image) = frame_cache.clone(){
+ if let Some(image) = frame_cache.borrow_mut().clone(){
let ipat = cairo::SurfacePattern::create(&image);
let scale = ((canvas_w as f64) / (image.width() as f64)).min(
(canvas_h as f64) / (image.height() as f64));
@@ -110,10 +126,21 @@ fn activate<Attr: Overray>(app: &gtk::Application, apps: Arc<AppState<Attr>>){
spawn_future_local(poll_fn(clone!{
#[strong] apps,
#[strong] draw,
+ #[strong] frame_cache,
+ #[strong] overlay,
move |ctx|{
loop{
match apps.update.lock().unwrap().poll(ctx){
Poll::Ready(_) => {
+ if let Some(newfb) = apps.next.lock().unwrap().take(){
+ let mut frame_cache = frame_cache.borrow_mut();
+ if let Some(lastframe) = frame_cache.take(){
+ apps.fbpool.lock().unwrap()
+ .put(lastframe.take_data().unwrap());
+ }
+ *frame_cache = Some(newfb.image.into_inner());
+ newfb.attr.update(&overlay).unwrap();
+ }
draw.queue_draw();
},
pending => return pending,
@@ -136,11 +163,16 @@ fn activate<Attr: Overray>(app: &gtk::Application, apps: Arc<AppState<Attr>>){
}
}));
+ let olcontainer = gtk::Overlay::builder()
+ .child(&draw)
+ .build();
+ olcontainer.add_overlay(&overlay);
let win = gtk::ApplicationWindow::builder()
.application(app)
- .child(&draw)
+ .child(&olcontainer)
.build();
win.present();
+ Attr::activate(&overlay).unwrap();
}
pub fn main(src: impl Source + 'static) -> Result<glib::ExitCode>{
@@ -162,10 +194,18 @@ pub fn main(src: impl Source + 'static) -> Result<glib::ExitCode>{
});
let app = gtk::Application::builder()
+ .flags(gio::ApplicationFlags::HANDLES_COMMAND_LINE)
.build();
- app.connect_activate(clone!{
+ app.connect_command_line(clone!{
#[strong] apps,
- move |app| activate(app, apps.clone())
+ move |app, _| {
+ activate(app, apps.clone());
+ 0
+ }
});
+ //app.connect_activate(clone!{
+ // #[strong] apps,
+ // move |app| activate(app, apps.clone())
+ //});
Ok(app.run())
}