1use std::{boxed::Box as Box_, pin::Pin, sync::OnceLock};
4
5use glib::{Quark, Slice, translate::*};
6
7pub use crate::auto::functions::*;
8use crate::{AboutDialog, StyleProvider, Window, ffi, prelude::*};
9
10#[doc(alias = "gtk_accelerator_valid")]
21pub fn accelerator_valid(keyval: gdk::Key, modifiers: gdk::ModifierType) -> bool {
22 assert_initialized_main_thread!();
23 unsafe {
24 from_glib(ffi::gtk_accelerator_valid(
25 keyval.into_glib(),
26 modifiers.into_glib(),
27 ))
28 }
29}
30
31#[doc(alias = "gtk_accelerator_get_label")]
42pub fn accelerator_get_label(
43 accelerator_key: gdk::Key,
44 accelerator_mods: gdk::ModifierType,
45) -> glib::GString {
46 assert_initialized_main_thread!();
47 unsafe {
48 from_glib_full(ffi::gtk_accelerator_get_label(
49 accelerator_key.into_glib(),
50 accelerator_mods.into_glib(),
51 ))
52 }
53}
54
55#[doc(alias = "gtk_accelerator_get_label_with_keycode")]
77pub fn accelerator_get_label_with_keycode(
78 display: Option<&impl IsA<gdk::Display>>,
79 accelerator_key: gdk::Key,
80 keycode: u32,
81 accelerator_mods: gdk::ModifierType,
82) -> glib::GString {
83 assert_initialized_main_thread!();
84 unsafe {
85 from_glib_full(ffi::gtk_accelerator_get_label_with_keycode(
86 display.map(|p| p.as_ref()).to_glib_none().0,
87 accelerator_key.into_glib(),
88 keycode,
89 accelerator_mods.into_glib(),
90 ))
91 }
92}
93
94#[doc(alias = "gtk_accelerator_name")]
107pub fn accelerator_name(
108 accelerator_key: gdk::Key,
109 accelerator_mods: gdk::ModifierType,
110) -> glib::GString {
111 assert_initialized_main_thread!();
112 unsafe {
113 from_glib_full(ffi::gtk_accelerator_name(
114 accelerator_key.into_glib(),
115 accelerator_mods.into_glib(),
116 ))
117 }
118}
119
120#[doc(alias = "gtk_accelerator_name_with_keycode")]
139pub fn accelerator_name_with_keycode(
140 display: Option<&impl IsA<gdk::Display>>,
141 accelerator_key: gdk::Key,
142 keycode: u32,
143 accelerator_mods: gdk::ModifierType,
144) -> glib::GString {
145 assert_initialized_main_thread!();
146 unsafe {
147 from_glib_full(ffi::gtk_accelerator_name_with_keycode(
148 display.map(|p| p.as_ref()).to_glib_none().0,
149 accelerator_key.into_glib(),
150 keycode,
151 accelerator_mods.into_glib(),
152 ))
153 }
154}
155
156#[doc(alias = "gtk_accelerator_parse")]
174pub fn accelerator_parse(accelerator: impl IntoGStr) -> Option<(gdk::Key, gdk::ModifierType)> {
175 assert_initialized_main_thread!();
176 unsafe {
177 accelerator.run_with_gstr(|accelerator| {
178 let mut accelerator_key = std::mem::MaybeUninit::uninit();
179 let mut accelerator_mods = std::mem::MaybeUninit::uninit();
180 let ret = from_glib(ffi::gtk_accelerator_parse(
181 accelerator.as_ptr(),
182 accelerator_key.as_mut_ptr(),
183 accelerator_mods.as_mut_ptr(),
184 ));
185 if ret {
186 Some((
187 gdk::Key::from_glib(accelerator_key.assume_init()),
188 from_glib(accelerator_mods.assume_init()),
189 ))
190 } else {
191 None
192 }
193 })
194 }
195}
196
197#[doc(alias = "gtk_accelerator_parse_with_keycode")]
231pub fn accelerator_parse_with_keycode(
232 accelerator: impl IntoGStr,
233 display: Option<&impl IsA<gdk::Display>>,
234) -> Option<(gdk::Key, Slice<u32>, gdk::ModifierType)> {
235 assert_initialized_main_thread!();
236 unsafe {
237 accelerator.run_with_gstr(|accelerator| {
238 let mut accelerator_key = std::mem::MaybeUninit::uninit();
239 let mut accelerator_codes_ptr = std::ptr::null_mut();
240 let mut accelerator_mods = std::mem::MaybeUninit::uninit();
241 let success = from_glib(ffi::gtk_accelerator_parse_with_keycode(
242 accelerator.as_ptr(),
243 display.map(|p| p.as_ref()).to_glib_none().0,
244 accelerator_key.as_mut_ptr(),
245 &mut accelerator_codes_ptr,
246 accelerator_mods.as_mut_ptr(),
247 ));
248 if success {
249 let mut len = 0;
250 if !accelerator_codes_ptr.is_null() {
251 while std::ptr::read(accelerator_codes_ptr.add(len)) != 0 {
252 len += 1;
253 }
254 }
255 let accelerator_codes = Slice::from_glib_full_num(accelerator_codes_ptr, len);
256 Some((
257 gdk::Key::from_glib(accelerator_key.assume_init()),
258 accelerator_codes,
259 from_glib(accelerator_mods.assume_init()),
260 ))
261 } else {
262 None
263 }
264 })
265 }
266}
267
268#[doc(alias = "gtk_show_uri_full")]
291#[doc(alias = "gtk_show_uri_full_finish")]
292#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
293#[allow(deprecated)]
294pub fn show_uri_full<P: FnOnce(Result<(), glib::Error>) + 'static>(
295 parent: Option<&impl IsA<Window>>,
296 uri: &str,
297 timestamp: u32,
298 cancellable: Option<&impl IsA<gio::Cancellable>>,
299 callback: P,
300) {
301 assert_initialized_main_thread!();
302 let main_context = glib::MainContext::ref_thread_default();
303 let is_main_context_owner = main_context.is_owner();
304 let has_acquired_main_context = (!is_main_context_owner)
305 .then(|| main_context.acquire().ok())
306 .flatten();
307 assert!(
308 is_main_context_owner || has_acquired_main_context.is_some(),
309 "Async operations only allowed if the thread is owning the MainContext"
310 );
311
312 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
313 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
314 unsafe extern "C" fn show_uri_full_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
315 parent_ptr: *mut glib::gobject_ffi::GObject,
316 res: *mut gio::ffi::GAsyncResult,
317 user_data: glib::ffi::gpointer,
318 ) {
319 unsafe {
320 let mut error = std::ptr::null_mut();
321 let _ =
322 ffi::gtk_show_uri_full_finish(parent_ptr as *mut ffi::GtkWindow, res, &mut error);
323 let result = if error.is_null() {
324 Ok(())
325 } else {
326 Err(from_glib_full(error))
327 };
328 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
329 Box_::from_raw(user_data as *mut _);
330 let callback = callback.into_inner();
331 callback(result);
332 }
333 }
334 let callback = show_uri_full_trampoline::<P>;
335 unsafe {
336 ffi::gtk_show_uri_full(
337 parent.map(|p| p.as_ref()).to_glib_none().0,
338 uri.to_glib_none().0,
339 timestamp,
340 cancellable.map(|p| p.as_ref()).to_glib_none().0,
341 Some(callback),
342 Box_::into_raw(user_data) as *mut _,
343 );
344 }
345}
346
347#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
348#[allow(deprecated)]
349pub fn show_uri_full_future(
350 parent: Option<&(impl IsA<Window> + Clone + 'static)>,
351 uri: &str,
352 timestamp: u32,
353) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
354 skip_assert_initialized!();
355 let parent = parent.map(ToOwned::to_owned);
356 let uri = String::from(uri);
357 Box_::pin(gio::GioFuture::new(&(), move |_obj, cancellable, send| {
358 show_uri_full(
359 parent.as_ref().map(::std::borrow::Borrow::borrow),
360 &uri,
361 timestamp,
362 Some(cancellable),
363 move |res| {
364 send.resolve(res);
365 },
366 );
367 }))
368}
369
370#[doc(alias = "gtk_show_about_dialog")]
379pub fn show_about_dialog<P: IsA<Window>>(parent: Option<&P>, properties: &[(&str, &dyn ToValue)]) {
380 assert_initialized_main_thread!();
381 static QUARK: OnceLock<Quark> = OnceLock::new();
382 let quark = *QUARK.get_or_init(|| Quark::from_str("gtk-rs-about-dialog"));
383
384 unsafe {
385 if let Some(d) = parent.and_then(|p| p.qdata::<AboutDialog>(quark)) {
386 d.as_ref().show();
387 } else {
388 let mut builder = glib::Object::builder::<AboutDialog>();
389 for (key, value) in properties {
390 builder = builder.property(key, *value);
391 }
392 let about_dialog = builder.build();
393 about_dialog.set_hide_on_close(true);
394
395 if let Some(dialog_parent) = parent {
397 about_dialog.set_modal(true);
398 about_dialog.set_transient_for(parent);
399 about_dialog.set_destroy_with_parent(true);
400 dialog_parent.set_qdata(quark, about_dialog.clone());
401 }
402
403 about_dialog.show();
404 };
405 }
406}
407
408#[doc(alias = "gtk_test_list_all_types")]
416pub fn test_list_all_types() -> Slice<glib::Type> {
417 unsafe {
418 let mut n_types = std::mem::MaybeUninit::uninit();
419 let types = ffi::gtk_test_list_all_types(n_types.as_mut_ptr());
420 Slice::from_glib_container_num(types as *mut _, n_types.assume_init() as usize)
421 }
422}
423
424#[doc(alias = "gtk_style_context_add_provider_for_display")]
425#[doc(alias = "add_provider_for_display")]
426pub fn style_context_add_provider_for_display(
427 display: &impl IsA<gdk::Display>,
428 provider: &impl IsA<StyleProvider>,
429 priority: u32,
430) {
431 skip_assert_initialized!();
432 unsafe {
433 ffi::gtk_style_context_add_provider_for_display(
434 display.as_ref().to_glib_none().0,
435 provider.as_ref().to_glib_none().0,
436 priority,
437 );
438 }
439}
440
441#[doc(alias = "gtk_style_context_remove_provider_for_display")]
442#[doc(alias = "remove_provider_for_display")]
443pub fn style_context_remove_provider_for_display(
444 display: &impl IsA<gdk::Display>,
445 provider: &impl IsA<StyleProvider>,
446) {
447 skip_assert_initialized!();
448 unsafe {
449 ffi::gtk_style_context_remove_provider_for_display(
450 display.as_ref().to_glib_none().0,
451 provider.as_ref().to_glib_none().0,
452 );
453 }
454}