diff --git a/examples/counter/src/main.rs b/examples/counter/src/main.rs index 5aad0987..762a0a92 100644 --- a/examples/counter/src/main.rs +++ b/examples/counter/src/main.rs @@ -1,4 +1,6 @@ use floem::{ + event::{Event, EventListener}, + keyboard::{Key, NamedKey}, peniko::Color, reactive::create_signal, unit::UnitExt, @@ -8,7 +10,7 @@ use floem::{ fn app_view() -> impl View { let (counter, set_counter) = create_signal(0); - stack(( + let view = stack(( label(move || format!("Value: {}", counter.get())).style(|s| s.padding(10.0)), stack(( text("Increment") @@ -72,6 +74,16 @@ fn app_view() -> impl View { .flex_col() .items_center() .justify_center() + }); + + let id = view.id(); + view.on_event(EventListener::KeyUp, move |e| { + if let Event::KeyUp(e) = e { + if e.key.logical_key == Key::Named(NamedKey::F11) { + id.inspect(); + } + } + true }) } diff --git a/examples/widget-gallery/src/main.rs b/examples/widget-gallery/src/main.rs index 62e6e7de..c368ca49 100644 --- a/examples/widget-gallery/src/main.rs +++ b/examples/widget-gallery/src/main.rs @@ -31,7 +31,7 @@ fn app_view() -> impl View { let (tabs, _set_tabs) = create_signal(tabs); let (active_tab, set_active_tab) = create_signal(0); - stack({ + let view = stack({ ( container({ scroll({ @@ -144,7 +144,17 @@ fn app_view() -> impl View { ) }) .style(|s| s.size(100.pct(), 100.pct())) - .window_title(|| "Widget Gallery".to_owned()) + .window_title(|| "Widget Gallery".to_owned()); + + let id = view.id(); + view.on_event(EventListener::KeyUp, move |e| { + if let Event::KeyUp(e) = e { + if e.key.logical_key == Key::Named(NamedKey::F11) { + id.inspect(); + } + } + true + }) } fn main() { diff --git a/examples/window-scale/src/main.rs b/examples/window-scale/src/main.rs index 453fe88d..791ca25f 100644 --- a/examples/window-scale/src/main.rs +++ b/examples/window-scale/src/main.rs @@ -1,4 +1,6 @@ use floem::{ + event::{Event, EventListener}, + keyboard::{Key, NamedKey}, peniko::Color, reactive::{create_rw_signal, create_signal}, unit::UnitExt, @@ -9,7 +11,7 @@ use floem::{ fn app_view() -> impl View { let (counter, set_counter) = create_signal(0); let window_scale = create_rw_signal(1.0); - stack(( + let view = stack(( label(move || format!("Value: {}", counter.get())).style(|s| s.padding(10.0)), stack({ ( @@ -121,6 +123,16 @@ fn app_view() -> impl View { .flex_col() .items_center() .justify_center() + }); + + let id = view.id(); + view.on_event(EventListener::KeyUp, move |e| { + if let Event::KeyUp(e) = e { + if e.key.logical_key == Key::Named(NamedKey::F11) { + id.inspect(); + } + } + true }) } diff --git a/renderer/src/lib.rs b/renderer/src/lib.rs index 0c7fcf09..0fe36b44 100644 --- a/renderer/src/lib.rs +++ b/renderer/src/lib.rs @@ -20,7 +20,7 @@ pub struct Img<'a> { } pub trait Renderer { - fn begin(&mut self); + fn begin(&mut self, capture: bool); fn transform(&mut self, transform: Affine); @@ -49,5 +49,5 @@ pub trait Renderer { fn draw_img(&mut self, img: Img<'_>, rect: Rect); - fn finish(&mut self); + fn finish(&mut self) -> Option; } diff --git a/src/app.rs b/src/app.rs index f9dd7aef..e121b0d8 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,5 +1,6 @@ -use std::{cell::RefCell, sync::Arc}; +use std::{cell::RefCell, rc::Rc, sync::Arc}; +use floem_reactive::WriteSignal; use once_cell::sync::Lazy; use parking_lot::Mutex; use winit::{ @@ -8,7 +9,10 @@ use winit::{ window::WindowId, }; -use crate::{action::Timer, app_handle::ApplicationHandle, view::View, window::WindowConfig}; +use crate::{ + action::Timer, app_handle::ApplicationHandle, inspector::Capture, view::View, + window::WindowConfig, +}; type AppEventCallback = dyn Fn(AppEvent); @@ -42,6 +46,10 @@ pub(crate) enum AppUpdateEvent { CloseWindow { window_id: WindowId, }, + CaptureWindow { + window_id: WindowId, + capture: WriteSignal>>, + }, RequestTimer { timer: Timer, }, diff --git a/src/app_handle.rs b/src/app_handle.rs index c0df7339..b646bc32 100644 --- a/src/app_handle.rs +++ b/src/app_handle.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, time::Instant}; +use std::{collections::HashMap, rc::Rc, time::Instant}; use kurbo::{Point, Size}; use winit::{ @@ -12,6 +12,7 @@ use crate::{ action::{Timer, TimerToken}, app::{AppUpdateEvent, UserEvent, APP_UPDATE_EVENTS}, ext_event::EXT_EVENT_HANDLER, + inspector::Capture, view::View, window::WindowConfig, window_handle::WindowHandle, @@ -64,6 +65,9 @@ impl ApplicationHandle { AppUpdateEvent::RequestTimer { timer } => { self.request_timer(timer, event_loop); } + AppUpdateEvent::CaptureWindow { window_id, capture } => { + capture.set(self.capture_window(window_id).map(Rc::new)); + } #[cfg(target_os = "linux")] AppUpdateEvent::MenuAction { window_id, @@ -235,6 +239,12 @@ impl ApplicationHandle { } } + fn capture_window(&mut self, window_id: WindowId) -> Option { + self.window_handles + .get_mut(&window_id) + .map(|handle| handle.capture()) + } + pub(crate) fn idle(&mut self) { while let Some(trigger) = { EXT_EVENT_HANDLER.queue.lock().pop_front() } { trigger.notify(); diff --git a/src/context.rs b/src/context.rs index 5a60021c..88a66d8c 100644 --- a/src/context.rs +++ b/src/context.rs @@ -9,7 +9,7 @@ use floem_renderer::{ cosmic_text::{LineHeightValue, Style as FontStyle, Weight}, Renderer as FloemRenderer, }; -use kurbo::{Affine, Point, Rect, RoundedRect, Shape, Size, Vec2}; +use kurbo::{Affine, Insets, Point, Rect, RoundedRect, Shape, Size, Vec2}; use peniko::Color; use taffy::{ prelude::{Layout, Node}, @@ -21,13 +21,15 @@ use crate::{ animate::{AnimId, AnimPropKind, Animation}, event::{Event, EventListener}, id::Id, + inspector::CaptureState, menu::Menu, pointer::PointerInputEvent, responsive::{GridBreakpoints, ScreenSize, ScreenSizeBp}, style::{ - BuiltinStyleReader, ComputedStyle, CursorStyle, DisplayProp, Style, StyleMap, StyleProp, - StyleSelector, StyleSelectors, + BuiltinStyleReader, ComputedStyle, CursorStyle, DisplayProp, LayoutProps, Style, StyleMap, + StyleProp, StyleSelector, StyleSelectors, }, + unit::PxPct, }; pub type EventCallback = dyn Fn(&Event) -> bool; @@ -52,6 +54,7 @@ pub struct ViewState { pub(crate) has_style_selectors: StyleSelectors, pub(crate) viewport: Option, pub(crate) layout_rect: Rect, + pub(crate) layout_props: LayoutProps, pub(crate) animation: Option, pub(crate) base_style: Option