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