gtk4/auto/
uri_launcher.rs
1use crate::{ffi, Window};
6use glib::{
7 prelude::*,
8 signal::{connect_raw, SignalHandlerId},
9 translate::*,
10};
11use std::{boxed::Box as Box_, pin::Pin};
12
13glib::wrapper! {
14 #[doc(alias = "GtkUriLauncher")]
36 pub struct UriLauncher(Object<ffi::GtkUriLauncher, ffi::GtkUriLauncherClass>);
37
38 match fn {
39 type_ => || ffi::gtk_uri_launcher_get_type(),
40 }
41}
42
43impl UriLauncher {
44 #[doc(alias = "gtk_uri_launcher_new")]
52 pub fn new(uri: &str) -> UriLauncher {
53 assert_initialized_main_thread!();
54 unsafe { from_glib_full(ffi::gtk_uri_launcher_new(uri.to_glib_none().0)) }
55 }
56
57 pub fn builder() -> UriLauncherBuilder {
62 UriLauncherBuilder::new()
63 }
64
65 #[doc(alias = "gtk_uri_launcher_get_uri")]
71 #[doc(alias = "get_uri")]
72 pub fn uri(&self) -> Option<glib::GString> {
73 unsafe { from_glib_none(ffi::gtk_uri_launcher_get_uri(self.to_glib_none().0)) }
74 }
75
76 #[doc(alias = "gtk_uri_launcher_launch")]
87 pub fn launch<P: FnOnce(Result<(), glib::Error>) + 'static>(
88 &self,
89 parent: Option<&impl IsA<Window>>,
90 cancellable: Option<&impl IsA<gio::Cancellable>>,
91 callback: P,
92 ) {
93 let main_context = glib::MainContext::ref_thread_default();
94 let is_main_context_owner = main_context.is_owner();
95 let has_acquired_main_context = (!is_main_context_owner)
96 .then(|| main_context.acquire().ok())
97 .flatten();
98 assert!(
99 is_main_context_owner || has_acquired_main_context.is_some(),
100 "Async operations only allowed if the thread is owning the MainContext"
101 );
102
103 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
104 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
105 unsafe extern "C" fn launch_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
106 _source_object: *mut glib::gobject_ffi::GObject,
107 res: *mut gio::ffi::GAsyncResult,
108 user_data: glib::ffi::gpointer,
109 ) {
110 let mut error = std::ptr::null_mut();
111 let _ = ffi::gtk_uri_launcher_launch_finish(_source_object as *mut _, res, &mut error);
112 let result = if error.is_null() {
113 Ok(())
114 } else {
115 Err(from_glib_full(error))
116 };
117 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
118 Box_::from_raw(user_data as *mut _);
119 let callback: P = callback.into_inner();
120 callback(result);
121 }
122 let callback = launch_trampoline::<P>;
123 unsafe {
124 ffi::gtk_uri_launcher_launch(
125 self.to_glib_none().0,
126 parent.map(|p| p.as_ref()).to_glib_none().0,
127 cancellable.map(|p| p.as_ref()).to_glib_none().0,
128 Some(callback),
129 Box_::into_raw(user_data) as *mut _,
130 );
131 }
132 }
133
134 pub fn launch_future(
135 &self,
136 parent: Option<&(impl IsA<Window> + Clone + 'static)>,
137 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
138 let parent = parent.map(ToOwned::to_owned);
139 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
140 obj.launch(
141 parent.as_ref().map(::std::borrow::Borrow::borrow),
142 Some(cancellable),
143 move |res| {
144 send.resolve(res);
145 },
146 );
147 }))
148 }
149
150 #[doc(alias = "gtk_uri_launcher_set_uri")]
154 #[doc(alias = "uri")]
155 pub fn set_uri(&self, uri: Option<&str>) {
156 unsafe {
157 ffi::gtk_uri_launcher_set_uri(self.to_glib_none().0, uri.to_glib_none().0);
158 }
159 }
160
161 #[cfg(feature = "v4_10")]
162 #[cfg_attr(docsrs, doc(cfg(feature = "v4_10")))]
163 #[doc(alias = "uri")]
164 pub fn connect_uri_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
165 unsafe extern "C" fn notify_uri_trampoline<F: Fn(&UriLauncher) + 'static>(
166 this: *mut ffi::GtkUriLauncher,
167 _param_spec: glib::ffi::gpointer,
168 f: glib::ffi::gpointer,
169 ) {
170 let f: &F = &*(f as *const F);
171 f(&from_glib_borrow(this))
172 }
173 unsafe {
174 let f: Box_<F> = Box_::new(f);
175 connect_raw(
176 self.as_ptr() as *mut _,
177 b"notify::uri\0".as_ptr() as *const _,
178 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
179 notify_uri_trampoline::<F> as *const (),
180 )),
181 Box_::into_raw(f),
182 )
183 }
184 }
185}
186
187#[cfg(feature = "v4_10")]
188#[cfg_attr(docsrs, doc(cfg(feature = "v4_10")))]
189impl Default for UriLauncher {
190 fn default() -> Self {
191 glib::object::Object::new::<Self>()
192 }
193}
194
195#[must_use = "The builder must be built to be used"]
200pub struct UriLauncherBuilder {
201 builder: glib::object::ObjectBuilder<'static, UriLauncher>,
202}
203
204impl UriLauncherBuilder {
205 fn new() -> Self {
206 Self {
207 builder: glib::object::Object::builder(),
208 }
209 }
210
211 #[cfg(feature = "v4_10")]
213 #[cfg_attr(docsrs, doc(cfg(feature = "v4_10")))]
214 pub fn uri(self, uri: impl Into<glib::GString>) -> Self {
215 Self {
216 builder: self.builder.property("uri", uri.into()),
217 }
218 }
219
220 #[must_use = "Building the object from the builder is usually expensive and is not expected to have side effects"]
223 pub fn build(self) -> UriLauncher {
224 assert_initialized_main_thread!();
225 self.builder.build()
226 }
227}