1use std::{boxed::Box as Box_, pin::Pin, sync::OnceLock};
4
5use glib::{translate::*, Quark, Slice};
6
7pub use crate::auto::functions::*;
8use crate::{ffi, prelude::*, AboutDialog, StyleProvider, Window};
9
10#[doc(alias = "gtk_accelerator_valid")]
11pub fn accelerator_valid(keyval: gdk::Key, modifiers: gdk::ModifierType) -> bool {
12 assert_initialized_main_thread!();
13 unsafe {
14 from_glib(ffi::gtk_accelerator_valid(
15 keyval.into_glib(),
16 modifiers.into_glib(),
17 ))
18 }
19}
20
21#[doc(alias = "gtk_accelerator_get_label")]
22pub fn accelerator_get_label(
23 accelerator_key: gdk::Key,
24 accelerator_mods: gdk::ModifierType,
25) -> glib::GString {
26 assert_initialized_main_thread!();
27 unsafe {
28 from_glib_full(ffi::gtk_accelerator_get_label(
29 accelerator_key.into_glib(),
30 accelerator_mods.into_glib(),
31 ))
32 }
33}
34
35#[doc(alias = "gtk_accelerator_get_label_with_keycode")]
36pub fn accelerator_get_label_with_keycode(
37 display: Option<&impl IsA<gdk::Display>>,
38 accelerator_key: gdk::Key,
39 keycode: u32,
40 accelerator_mods: gdk::ModifierType,
41) -> glib::GString {
42 assert_initialized_main_thread!();
43 unsafe {
44 from_glib_full(ffi::gtk_accelerator_get_label_with_keycode(
45 display.map(|p| p.as_ref()).to_glib_none().0,
46 accelerator_key.into_glib(),
47 keycode,
48 accelerator_mods.into_glib(),
49 ))
50 }
51}
52
53#[doc(alias = "gtk_accelerator_name")]
54pub fn accelerator_name(
55 accelerator_key: gdk::Key,
56 accelerator_mods: gdk::ModifierType,
57) -> glib::GString {
58 assert_initialized_main_thread!();
59 unsafe {
60 from_glib_full(ffi::gtk_accelerator_name(
61 accelerator_key.into_glib(),
62 accelerator_mods.into_glib(),
63 ))
64 }
65}
66
67#[doc(alias = "gtk_accelerator_name_with_keycode")]
68pub fn accelerator_name_with_keycode(
69 display: Option<&impl IsA<gdk::Display>>,
70 accelerator_key: gdk::Key,
71 keycode: u32,
72 accelerator_mods: gdk::ModifierType,
73) -> glib::GString {
74 assert_initialized_main_thread!();
75 unsafe {
76 from_glib_full(ffi::gtk_accelerator_name_with_keycode(
77 display.map(|p| p.as_ref()).to_glib_none().0,
78 accelerator_key.into_glib(),
79 keycode,
80 accelerator_mods.into_glib(),
81 ))
82 }
83}
84
85#[doc(alias = "gtk_accelerator_parse")]
86pub fn accelerator_parse(accelerator: impl IntoGStr) -> Option<(gdk::Key, gdk::ModifierType)> {
87 assert_initialized_main_thread!();
88 unsafe {
89 accelerator.run_with_gstr(|accelerator| {
90 let mut accelerator_key = std::mem::MaybeUninit::uninit();
91 let mut accelerator_mods = std::mem::MaybeUninit::uninit();
92 let ret = from_glib(ffi::gtk_accelerator_parse(
93 accelerator.as_ptr(),
94 accelerator_key.as_mut_ptr(),
95 accelerator_mods.as_mut_ptr(),
96 ));
97 if ret {
98 Some((
99 gdk::Key::from_glib(accelerator_key.assume_init()),
100 from_glib(accelerator_mods.assume_init()),
101 ))
102 } else {
103 None
104 }
105 })
106 }
107}
108
109#[doc(alias = "gtk_accelerator_parse_with_keycode")]
110pub fn accelerator_parse_with_keycode(
111 accelerator: impl IntoGStr,
112 display: Option<&impl IsA<gdk::Display>>,
113) -> Option<(gdk::Key, Slice<u32>, gdk::ModifierType)> {
114 assert_initialized_main_thread!();
115 unsafe {
116 accelerator.run_with_gstr(|accelerator| {
117 let mut accelerator_key = std::mem::MaybeUninit::uninit();
118 let mut accelerator_codes_ptr = std::ptr::null_mut();
119 let mut accelerator_mods = std::mem::MaybeUninit::uninit();
120 let success = from_glib(ffi::gtk_accelerator_parse_with_keycode(
121 accelerator.as_ptr(),
122 display.map(|p| p.as_ref()).to_glib_none().0,
123 accelerator_key.as_mut_ptr(),
124 &mut accelerator_codes_ptr,
125 accelerator_mods.as_mut_ptr(),
126 ));
127 if success {
128 let mut len = 0;
129 if !accelerator_codes_ptr.is_null() {
130 while std::ptr::read(accelerator_codes_ptr.add(len)) != 0 {
131 len += 1;
132 }
133 }
134 let accelerator_codes = Slice::from_glib_full_num(accelerator_codes_ptr, len);
135 Some((
136 gdk::Key::from_glib(accelerator_key.assume_init()),
137 accelerator_codes,
138 from_glib(accelerator_mods.assume_init()),
139 ))
140 } else {
141 None
142 }
143 })
144 }
145}
146
147#[doc(alias = "gtk_show_uri_full")]
148#[doc(alias = "gtk_show_uri_full_finish")]
149#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
150#[allow(deprecated)]
151pub fn show_uri_full<P: FnOnce(Result<(), glib::Error>) + 'static>(
152 parent: Option<&impl IsA<Window>>,
153 uri: &str,
154 timestamp: u32,
155 cancellable: Option<&impl IsA<gio::Cancellable>>,
156 callback: P,
157) {
158 assert_initialized_main_thread!();
159 let main_context = glib::MainContext::ref_thread_default();
160 let is_main_context_owner = main_context.is_owner();
161 let has_acquired_main_context = (!is_main_context_owner)
162 .then(|| main_context.acquire().ok())
163 .flatten();
164 assert!(
165 is_main_context_owner || has_acquired_main_context.is_some(),
166 "Async operations only allowed if the thread is owning the MainContext"
167 );
168
169 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
170 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
171 unsafe extern "C" fn show_uri_full_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
172 parent_ptr: *mut glib::gobject_ffi::GObject,
173 res: *mut gio::ffi::GAsyncResult,
174 user_data: glib::ffi::gpointer,
175 ) {
176 let mut error = std::ptr::null_mut();
177 let _ = ffi::gtk_show_uri_full_finish(parent_ptr as *mut ffi::GtkWindow, res, &mut error);
178 let result = if error.is_null() {
179 Ok(())
180 } else {
181 Err(from_glib_full(error))
182 };
183 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
184 Box_::from_raw(user_data as *mut _);
185 let callback = callback.into_inner();
186 callback(result);
187 }
188 let callback = show_uri_full_trampoline::<P>;
189 unsafe {
190 ffi::gtk_show_uri_full(
191 parent.map(|p| p.as_ref()).to_glib_none().0,
192 uri.to_glib_none().0,
193 timestamp,
194 cancellable.map(|p| p.as_ref()).to_glib_none().0,
195 Some(callback),
196 Box_::into_raw(user_data) as *mut _,
197 );
198 }
199}
200
201#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
202#[allow(deprecated)]
203pub fn show_uri_full_future(
204 parent: Option<&(impl IsA<Window> + Clone + 'static)>,
205 uri: &str,
206 timestamp: u32,
207) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
208 skip_assert_initialized!();
209 let parent = parent.map(ToOwned::to_owned);
210 let uri = String::from(uri);
211 Box_::pin(gio::GioFuture::new(&(), move |_obj, cancellable, send| {
212 show_uri_full(
213 parent.as_ref().map(::std::borrow::Borrow::borrow),
214 &uri,
215 timestamp,
216 Some(cancellable),
217 move |res| {
218 send.resolve(res);
219 },
220 );
221 }))
222}
223
224#[doc(alias = "gtk_show_about_dialog")]
225pub fn show_about_dialog<P: IsA<Window>>(parent: Option<&P>, properties: &[(&str, &dyn ToValue)]) {
226 assert_initialized_main_thread!();
227 static QUARK: OnceLock<Quark> = OnceLock::new();
228 let quark = *QUARK.get_or_init(|| Quark::from_str("gtk-rs-about-dialog"));
229
230 unsafe {
231 if let Some(d) = parent.and_then(|p| p.qdata::<AboutDialog>(quark)) {
232 d.as_ref().show();
233 } else {
234 let mut builder = glib::Object::builder::<AboutDialog>();
235 for (key, value) in properties {
236 builder = builder.property(key, *value);
237 }
238 let about_dialog = builder.build();
239 about_dialog.set_hide_on_close(true);
240
241 if let Some(dialog_parent) = parent {
243 about_dialog.set_modal(true);
244 about_dialog.set_transient_for(parent);
245 about_dialog.set_destroy_with_parent(true);
246 dialog_parent.set_qdata(quark, about_dialog.clone());
247 }
248
249 about_dialog.show();
250 };
251 }
252}
253
254#[doc(alias = "gtk_test_list_all_types")]
255pub fn test_list_all_types() -> Slice<glib::Type> {
256 unsafe {
257 let mut n_types = std::mem::MaybeUninit::uninit();
258 let types = ffi::gtk_test_list_all_types(n_types.as_mut_ptr());
259 Slice::from_glib_container_num(types as *mut _, n_types.assume_init() as usize)
260 }
261}
262
263#[doc(alias = "gtk_style_context_add_provider_for_display")]
264#[doc(alias = "add_provider_for_display")]
265pub fn style_context_add_provider_for_display(
266 display: &impl IsA<gdk::Display>,
267 provider: &impl IsA<StyleProvider>,
268 priority: u32,
269) {
270 skip_assert_initialized!();
271 unsafe {
272 ffi::gtk_style_context_add_provider_for_display(
273 display.as_ref().to_glib_none().0,
274 provider.as_ref().to_glib_none().0,
275 priority,
276 );
277 }
278}
279
280#[doc(alias = "gtk_style_context_remove_provider_for_display")]
281#[doc(alias = "remove_provider_for_display")]
282pub fn style_context_remove_provider_for_display(
283 display: &impl IsA<gdk::Display>,
284 provider: &impl IsA<StyleProvider>,
285) {
286 skip_assert_initialized!();
287 unsafe {
288 ffi::gtk_style_context_remove_provider_for_display(
289 display.as_ref().to_glib_none().0,
290 provider.as_ref().to_glib_none().0,
291 );
292 }
293}