From 689c33b8ce60b0590c20a28cfbdc55d1aa319872 Mon Sep 17 00:00:00 2001 From: Maximiliano Sandoval Date: Thu, 27 Nov 2025 17:17:24 +0100 Subject: [PATCH 1/2] Add gsk::RenderReplay bindings manually Generated by temporarily adding glib:get-type to the gir file, moving the generated file to src and then - Replace the glib::wrapper macro with `struct` and `impl Drop`. - Replace from_glib_borrow with Self(ptr) - Replace to_glib_none_mut with self.0.as_mut --- gsk4/Gir.toml | 4 + gsk4/src/lib.rs | 6 + gsk4/src/render_replay.rs | 265 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 275 insertions(+) create mode 100644 gsk4/src/render_replay.rs diff --git a/gsk4/Gir.toml b/gsk4/Gir.toml index 7bc9b9ed7ceb..1db7df244f74 100644 --- a/gsk4/Gir.toml +++ b/gsk4/Gir.toml @@ -230,6 +230,10 @@ status = "generate" name = "cr" const = true +[[object]] +name = "Gsk.RenderReplay" +status = "manual" + [[object]] name = "Gsk.RoundedRect" status = "manual" diff --git a/gsk4/src/lib.rs b/gsk4/src/lib.rs index 406a0a7229c6..7cd7f8f06938 100644 --- a/gsk4/src/lib.rs +++ b/gsk4/src/lib.rs @@ -84,6 +84,9 @@ mod path_builder; #[cfg_attr(docsrs, doc(cfg(feature = "v4_14")))] mod path_point; mod radial_gradient_node; +#[cfg(feature = "v4_22")] +#[cfg_attr(docsrs, doc(cfg(feature = "v4_22")))] +mod render_replay; mod repeat_node; mod repeating_linear_gradient_node; mod repeating_radial_gradient_node; @@ -109,5 +112,8 @@ pub use color_stop::ColorStop; #[cfg_attr(feature = "v4_4", deprecated = "Since 4.4")] pub use ngl_renderer::NglRenderer; pub use parse_location::ParseLocation; +#[cfg(feature = "v4_22")] +#[cfg_attr(docsrs, doc(cfg(feature = "v4_22")))] +pub use render_replay::RenderReplay; pub use rounded_rect::RoundedRect; pub use shadow::Shadow; diff --git a/gsk4/src/render_replay.rs b/gsk4/src/render_replay.rs new file mode 100644 index 000000000000..baf2cd6b3831 --- /dev/null +++ b/gsk4/src/render_replay.rs @@ -0,0 +1,265 @@ +// Take a look at the license at the top of the repository in the LICENSE file. + +use crate::{ffi, RenderNode}; +use glib::{prelude::*, translate::*}; +use std::boxed::Box as Box_; + +#[repr(C)] +#[doc(alias = "GskRenderReplay")] +pub struct RenderReplay(std::ptr::NonNull); + +impl Drop for RenderReplay { + fn drop(&mut self) { + unsafe { + ffi::gsk_render_replay_free(self.0.as_ptr()); + } + } +} + +impl RenderReplay { + #[doc(alias = "gsk_render_replay_default")] + #[allow(clippy::should_implement_trait)] + pub fn default(&self, node: impl AsRef) -> Option { + unsafe { + from_glib_full(ffi::gsk_render_replay_default( + self.0.as_ptr(), + node.as_ref().to_glib_none().0, + )) + } + } + + #[doc(alias = "gsk_render_replay_filter_font")] + pub fn filter_font(&self, font: &impl IsA) -> pango::Font { + unsafe { + from_glib_full(ffi::gsk_render_replay_filter_font( + self.0.as_ptr(), + font.as_ref().to_glib_none().0, + )) + } + } + + #[doc(alias = "gsk_render_replay_filter_node")] + pub fn filter_node(&self, node: impl AsRef) -> Option { + unsafe { + from_glib_full(ffi::gsk_render_replay_filter_node( + self.0.as_ptr(), + node.as_ref().to_glib_none().0, + )) + } + } + + #[doc(alias = "gsk_render_replay_filter_texture")] + pub fn filter_texture(&self, texture: &impl IsA) -> gdk::Texture { + unsafe { + from_glib_full(ffi::gsk_render_replay_filter_texture( + self.0.as_ptr(), + texture.as_ref().to_glib_none().0, + )) + } + } + + #[doc(alias = "gsk_render_replay_foreach_node")] + pub fn foreach_node(&self, node: impl AsRef) { + unsafe { + ffi::gsk_render_replay_foreach_node(self.0.as_ptr(), node.as_ref().to_glib_none().0); + } + } + + #[allow(clippy::type_complexity)] + #[doc(alias = "gsk_render_replay_set_font_filter")] + pub fn set_font_filter( + &mut self, + filter: Option pango::Font + 'static>>, + ) { + let filter_data: Box_< + Option pango::Font + 'static>>, + > = Box_::new(filter); + unsafe extern "C" fn filter_func( + replay: *mut ffi::GskRenderReplay, + font: *mut pango::ffi::PangoFont, + user_data: glib::ffi::gpointer, + ) -> *mut pango::ffi::PangoFont { + let replay = RenderReplay(std::ptr::NonNull::new_unchecked(replay)); + let font = from_glib_borrow(font); + let callback = &*(user_data + as *mut Option pango::Font + 'static>>); + if let Some(ref callback) = *callback { + callback(&replay, &font) + } else { + panic!("cannot get closure...") + } + .into_glib_ptr() + } + let filter = if filter_data.is_some() { + Some(filter_func as _) + } else { + None + }; + unsafe extern "C" fn user_destroy_func(data: glib::ffi::gpointer) { + let _callback = Box_::from_raw( + data as *mut Option< + Box_ pango::Font + 'static>, + >, + ); + } + let destroy_call3 = Some(user_destroy_func as _); + let super_callback0: Box_< + Option pango::Font + 'static>>, + > = filter_data; + unsafe { + ffi::gsk_render_replay_set_font_filter( + self.0.as_mut(), + filter, + Box_::into_raw(super_callback0) as *mut _, + destroy_call3, + ); + } + } + + #[doc(alias = "gsk_render_replay_set_node_filter")] + pub fn set_node_filter Option + 'static>( + &mut self, + filter: P, + ) { + let filter_data: Box_

= Box_::new(filter); + unsafe extern "C" fn filter_func< + P: Fn(&RenderReplay, &RenderNode) -> Option + 'static, + >( + replay: *mut ffi::GskRenderReplay, + node: *mut ffi::GskRenderNode, + user_data: glib::ffi::gpointer, + ) -> *mut ffi::GskRenderNode { + let replay = RenderReplay(std::ptr::NonNull::new_unchecked(replay)); + let node = from_glib_borrow(node); + let callback = &*(user_data as *mut P); + (*callback)(&replay, &node).into_glib_ptr() + } + let filter = Some(filter_func::

as _); + unsafe extern "C" fn user_destroy_func< + P: Fn(&RenderReplay, &RenderNode) -> Option + 'static, + >( + data: glib::ffi::gpointer, + ) { + let _callback = Box_::from_raw(data as *mut P); + } + let destroy_call3 = Some(user_destroy_func::

as _); + let super_callback0: Box_

= filter_data; + unsafe { + ffi::gsk_render_replay_set_node_filter( + self.0.as_mut(), + filter, + Box_::into_raw(super_callback0) as *mut _, + destroy_call3, + ); + } + } + + #[doc(alias = "gsk_render_replay_set_node_foreach")] + pub fn set_node_foreach glib::ControlFlow + 'static>( + &mut self, + foreach: P, + ) { + let foreach_data: Box_

= Box_::new(foreach); + unsafe extern "C" fn foreach_func< + P: Fn(&RenderReplay, &RenderNode) -> glib::ControlFlow + 'static, + >( + replay: *mut ffi::GskRenderReplay, + node: *mut ffi::GskRenderNode, + user_data: glib::ffi::gpointer, + ) -> glib::ffi::gboolean { + let replay = RenderReplay(std::ptr::NonNull::new_unchecked(replay)); + let node = from_glib_borrow(node); + let callback = &*(user_data as *mut P); + (*callback)(&replay, &node).into_glib() + } + let foreach = Some(foreach_func::

as _); + unsafe extern "C" fn user_destroy_func< + P: Fn(&RenderReplay, &RenderNode) -> glib::ControlFlow + 'static, + >( + data: glib::ffi::gpointer, + ) { + let _callback = Box_::from_raw(data as *mut P); + } + let destroy_call3 = Some(user_destroy_func::

as _); + let super_callback0: Box_

= foreach_data; + unsafe { + ffi::gsk_render_replay_set_node_foreach( + self.0.as_mut(), + foreach, + Box_::into_raw(super_callback0) as *mut _, + destroy_call3, + ); + } + } + + #[allow(clippy::type_complexity)] + #[doc(alias = "gsk_render_replay_set_texture_filter")] + pub fn set_texture_filter( + &mut self, + filter: Option gdk::Texture + 'static>>, + ) { + let filter_data: Box_< + Option gdk::Texture + 'static>>, + > = Box_::new(filter); + unsafe extern "C" fn filter_func( + replay: *mut ffi::GskRenderReplay, + texture: *mut gdk::ffi::GdkTexture, + user_data: glib::ffi::gpointer, + ) -> *mut gdk::ffi::GdkTexture { + let replay = RenderReplay(std::ptr::NonNull::new_unchecked(replay)); + let texture = from_glib_borrow(texture); + let callback = &*(user_data + as *mut Option< + Box_ gdk::Texture + 'static>, + >); + if let Some(ref callback) = *callback { + callback(&replay, &texture) + } else { + panic!("cannot get closure...") + } + .into_glib_ptr() + } + let filter = if filter_data.is_some() { + Some(filter_func as _) + } else { + None + }; + unsafe extern "C" fn user_destroy_func(data: glib::ffi::gpointer) { + let _callback = Box_::from_raw( + data as *mut Option< + Box_ gdk::Texture + 'static>, + >, + ); + } + let destroy_call3 = Some(user_destroy_func as _); + let super_callback0: Box_< + Option gdk::Texture + 'static>>, + > = filter_data; + unsafe { + ffi::gsk_render_replay_set_texture_filter( + self.0.as_mut(), + filter, + Box_::into_raw(super_callback0) as *mut _, + destroy_call3, + ); + } + } + + #[doc(alias = "gsk_render_replay_new")] + pub fn new() -> RenderReplay { + assert_initialized_main_thread!(); + unsafe { + RenderReplay(std::ptr::NonNull::new_unchecked( + ffi::gsk_render_replay_new(), + )) + } + } +} + +#[cfg(feature = "v4_22")] +#[cfg_attr(docsrs, doc(cfg(feature = "v4_22")))] +impl Default for RenderReplay { + fn default() -> Self { + Self::new() + } +} From e32fbaa715a4bf4c95b1200fee1eff7265a078ca Mon Sep 17 00:00:00 2001 From: Maximiliano Sandoval Date: Fri, 28 Nov 2025 10:23:53 +0100 Subject: [PATCH 2/2] render_replay: Add unset for optional parameters --- gsk4/src/render_replay.rs | 148 ++++++++++++++++++++++---------------- 1 file changed, 86 insertions(+), 62 deletions(-) diff --git a/gsk4/src/render_replay.rs b/gsk4/src/render_replay.rs index baf2cd6b3831..ad8e74a372a0 100644 --- a/gsk4/src/render_replay.rs +++ b/gsk4/src/render_replay.rs @@ -65,47 +65,34 @@ impl RenderReplay { } } - #[allow(clippy::type_complexity)] #[doc(alias = "gsk_render_replay_set_font_filter")] - pub fn set_font_filter( + pub fn set_font_filter pango::Font + 'static>( &mut self, - filter: Option pango::Font + 'static>>, + filter: P, ) { - let filter_data: Box_< - Option pango::Font + 'static>>, - > = Box_::new(filter); - unsafe extern "C" fn filter_func( + let filter_data: Box_

= Box_::new(filter); + unsafe extern "C" fn filter_func< + P: Fn(&RenderReplay, &pango::Font) -> pango::Font + 'static, + >( replay: *mut ffi::GskRenderReplay, font: *mut pango::ffi::PangoFont, user_data: glib::ffi::gpointer, ) -> *mut pango::ffi::PangoFont { let replay = RenderReplay(std::ptr::NonNull::new_unchecked(replay)); let font = from_glib_borrow(font); - let callback = &*(user_data - as *mut Option pango::Font + 'static>>); - if let Some(ref callback) = *callback { - callback(&replay, &font) - } else { - panic!("cannot get closure...") - } - .into_glib_ptr() + let callback = &*(user_data as *mut P); + (*callback)(&replay, &font).into_glib_ptr() } - let filter = if filter_data.is_some() { - Some(filter_func as _) - } else { - None - }; - unsafe extern "C" fn user_destroy_func(data: glib::ffi::gpointer) { - let _callback = Box_::from_raw( - data as *mut Option< - Box_ pango::Font + 'static>, - >, - ); + let filter = Some(filter_func::

as _); + unsafe extern "C" fn user_destroy_func< + P: Fn(&RenderReplay, &pango::Font) -> pango::Font + 'static, + >( + data: glib::ffi::gpointer, + ) { + let _callback = Box_::from_raw(data as *mut P); } - let destroy_call3 = Some(user_destroy_func as _); - let super_callback0: Box_< - Option pango::Font + 'static>>, - > = filter_data; + let destroy_call3 = Some(user_destroy_func::

as _); + let super_callback0: Box_

= filter_data; unsafe { ffi::gsk_render_replay_set_font_filter( self.0.as_mut(), @@ -116,6 +103,19 @@ impl RenderReplay { } } + #[doc(alias = "gsk_render_replay_set_font_filter")] + #[doc(alias = "set_font_filter")] + pub fn unset_font_filter(&mut self) { + unsafe { + ffi::gsk_render_replay_set_font_filter( + self.0.as_mut(), + None, + std::ptr::null_mut(), + None, + ) + } + } + #[doc(alias = "gsk_render_replay_set_node_filter")] pub fn set_node_filter Option + 'static>( &mut self, @@ -154,6 +154,19 @@ impl RenderReplay { } } + #[doc(alias = "gsk_render_replay_set_node_filter")] + #[doc(alias = "set_node_filter")] + pub fn unset_node_filter(&mut self) { + unsafe { + ffi::gsk_render_replay_set_node_filter( + self.0.as_mut(), + None, + std::ptr::null_mut(), + None, + ) + } + } + #[doc(alias = "gsk_render_replay_set_node_foreach")] pub fn set_node_foreach glib::ControlFlow + 'static>( &mut self, @@ -192,49 +205,47 @@ impl RenderReplay { } } - #[allow(clippy::type_complexity)] + #[doc(alias = "gsk_render_replay_set_node_foreach")] + #[doc(alias = "set_node_foreach")] + pub fn unset_foreach_node(&mut self) { + unsafe { + ffi::gsk_render_replay_set_node_foreach( + self.0.as_mut(), + None, + std::ptr::null_mut(), + None, + ) + } + } + #[doc(alias = "gsk_render_replay_set_texture_filter")] - pub fn set_texture_filter( + pub fn set_texture_filter gdk::Texture + 'static>( &mut self, - filter: Option gdk::Texture + 'static>>, + filter: P, ) { - let filter_data: Box_< - Option gdk::Texture + 'static>>, - > = Box_::new(filter); - unsafe extern "C" fn filter_func( + let filter_data: Box_

= Box_::new(filter); + unsafe extern "C" fn filter_func< + P: Fn(&RenderReplay, &gdk::Texture) -> gdk::Texture + 'static, + >( replay: *mut ffi::GskRenderReplay, texture: *mut gdk::ffi::GdkTexture, user_data: glib::ffi::gpointer, ) -> *mut gdk::ffi::GdkTexture { let replay = RenderReplay(std::ptr::NonNull::new_unchecked(replay)); let texture = from_glib_borrow(texture); - let callback = &*(user_data - as *mut Option< - Box_ gdk::Texture + 'static>, - >); - if let Some(ref callback) = *callback { - callback(&replay, &texture) - } else { - panic!("cannot get closure...") - } - .into_glib_ptr() + let callback = &*(user_data as *mut P); + (*callback)(&replay, &texture).into_glib_ptr() } - let filter = if filter_data.is_some() { - Some(filter_func as _) - } else { - None - }; - unsafe extern "C" fn user_destroy_func(data: glib::ffi::gpointer) { - let _callback = Box_::from_raw( - data as *mut Option< - Box_ gdk::Texture + 'static>, - >, - ); + let filter = Some(filter_func::

as _); + unsafe extern "C" fn user_destroy_func< + P: Fn(&RenderReplay, &gdk::Texture) -> gdk::Texture + 'static, + >( + data: glib::ffi::gpointer, + ) { + let _callback = Box_::from_raw(data as *mut P); } - let destroy_call3 = Some(user_destroy_func as _); - let super_callback0: Box_< - Option gdk::Texture + 'static>>, - > = filter_data; + let destroy_call3 = Some(user_destroy_func::

as _); + let super_callback0: Box_

= filter_data; unsafe { ffi::gsk_render_replay_set_texture_filter( self.0.as_mut(), @@ -245,6 +256,19 @@ impl RenderReplay { } } + #[doc(alias = "gsk_render_replay_set_texture_filter")] + #[doc(alias = "set_texture_filter")] + pub fn unset_texture_filter(&mut self) { + unsafe { + ffi::gsk_render_replay_set_texture_filter( + self.0.as_mut(), + None, + std::ptr::null_mut(), + None, + ) + } + } + #[doc(alias = "gsk_render_replay_new")] pub fn new() -> RenderReplay { assert_initialized_main_thread!();