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")]
25pub fn accelerator_valid(keyval: gdk::Key, modifiers: gdk::ModifierType) -> bool {
26 assert_initialized_main_thread!();
27 unsafe {
28 from_glib(ffi::gtk_accelerator_valid(
29 keyval.into_glib(),
30 modifiers.into_glib(),
31 ))
32 }
33}
34
35#[doc(alias = "gtk_accelerator_get_label")]
46pub fn accelerator_get_label(
47 accelerator_key: gdk::Key,
48 accelerator_mods: gdk::ModifierType,
49) -> glib::GString {
50 assert_initialized_main_thread!();
51 unsafe {
52 from_glib_full(ffi::gtk_accelerator_get_label(
53 accelerator_key.into_glib(),
54 accelerator_mods.into_glib(),
55 ))
56 }
57}
58
59#[doc(alias = "gtk_accelerator_get_label_with_keycode")]
81pub fn accelerator_get_label_with_keycode(
82 display: Option<&impl IsA<gdk::Display>>,
83 accelerator_key: gdk::Key,
84 keycode: u32,
85 accelerator_mods: gdk::ModifierType,
86) -> glib::GString {
87 assert_initialized_main_thread!();
88 unsafe {
89 from_glib_full(ffi::gtk_accelerator_get_label_with_keycode(
90 display.map(|p| p.as_ref()).to_glib_none().0,
91 accelerator_key.into_glib(),
92 keycode,
93 accelerator_mods.into_glib(),
94 ))
95 }
96}
97
98#[doc(alias = "gtk_accelerator_name")]
115pub fn accelerator_name(
116 accelerator_key: gdk::Key,
117 accelerator_mods: gdk::ModifierType,
118) -> glib::GString {
119 assert_initialized_main_thread!();
120 unsafe {
121 from_glib_full(ffi::gtk_accelerator_name(
122 accelerator_key.into_glib(),
123 accelerator_mods.into_glib(),
124 ))
125 }
126}
127
128#[doc(alias = "gtk_accelerator_name_with_keycode")]
147pub fn accelerator_name_with_keycode(
148 display: Option<&impl IsA<gdk::Display>>,
149 accelerator_key: gdk::Key,
150 keycode: u32,
151 accelerator_mods: gdk::ModifierType,
152) -> glib::GString {
153 assert_initialized_main_thread!();
154 unsafe {
155 from_glib_full(ffi::gtk_accelerator_name_with_keycode(
156 display.map(|p| p.as_ref()).to_glib_none().0,
157 accelerator_key.into_glib(),
158 keycode,
159 accelerator_mods.into_glib(),
160 ))
161 }
162}
163
164#[doc(alias = "gtk_accelerator_parse")]
201pub fn accelerator_parse(accelerator: impl IntoGStr) -> Option<(gdk::Key, gdk::ModifierType)> {
202 assert_initialized_main_thread!();
203 unsafe {
204 accelerator.run_with_gstr(|accelerator| {
205 let mut accelerator_key = std::mem::MaybeUninit::uninit();
206 let mut accelerator_mods = std::mem::MaybeUninit::uninit();
207 let ret = from_glib(ffi::gtk_accelerator_parse(
208 accelerator.as_ptr(),
209 accelerator_key.as_mut_ptr(),
210 accelerator_mods.as_mut_ptr(),
211 ));
212 if ret {
213 Some((
214 gdk::Key::from_glib(accelerator_key.assume_init()),
215 from_glib(accelerator_mods.assume_init()),
216 ))
217 } else {
218 None
219 }
220 })
221 }
222}
223
224#[doc(alias = "gtk_accelerator_parse_with_keycode")]
258pub fn accelerator_parse_with_keycode(
259 accelerator: impl IntoGStr,
260 display: Option<&impl IsA<gdk::Display>>,
261) -> Option<(gdk::Key, Slice<u32>, gdk::ModifierType)> {
262 assert_initialized_main_thread!();
263 unsafe {
264 accelerator.run_with_gstr(|accelerator| {
265 let mut accelerator_key = std::mem::MaybeUninit::uninit();
266 let mut accelerator_codes_ptr = std::ptr::null_mut();
267 let mut accelerator_mods = std::mem::MaybeUninit::uninit();
268 let success = from_glib(ffi::gtk_accelerator_parse_with_keycode(
269 accelerator.as_ptr(),
270 display.map(|p| p.as_ref()).to_glib_none().0,
271 accelerator_key.as_mut_ptr(),
272 &mut accelerator_codes_ptr,
273 accelerator_mods.as_mut_ptr(),
274 ));
275 if success {
276 let mut len = 0;
277 if !accelerator_codes_ptr.is_null() {
278 while std::ptr::read(accelerator_codes_ptr.add(len)) != 0 {
279 len += 1;
280 }
281 }
282 let accelerator_codes = Slice::from_glib_full_num(accelerator_codes_ptr, len);
283 Some((
284 gdk::Key::from_glib(accelerator_key.assume_init()),
285 accelerator_codes,
286 from_glib(accelerator_mods.assume_init()),
287 ))
288 } else {
289 None
290 }
291 })
292 }
293}
294
295#[doc(alias = "gtk_show_uri_full")]
318#[doc(alias = "gtk_show_uri_full_finish")]
319#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
320#[allow(deprecated)]
321pub fn show_uri_full<P: FnOnce(Result<(), glib::Error>) + 'static>(
322 parent: Option<&impl IsA<Window>>,
323 uri: &str,
324 timestamp: u32,
325 cancellable: Option<&impl IsA<gio::Cancellable>>,
326 callback: P,
327) {
328 assert_initialized_main_thread!();
329 let main_context = glib::MainContext::ref_thread_default();
330 let is_main_context_owner = main_context.is_owner();
331 let has_acquired_main_context = (!is_main_context_owner)
332 .then(|| main_context.acquire().ok())
333 .flatten();
334 assert!(
335 is_main_context_owner || has_acquired_main_context.is_some(),
336 "Async operations only allowed if the thread is owning the MainContext"
337 );
338
339 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
340 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
341 unsafe extern "C" fn show_uri_full_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
342 parent_ptr: *mut glib::gobject_ffi::GObject,
343 res: *mut gio::ffi::GAsyncResult,
344 user_data: glib::ffi::gpointer,
345 ) {
346 let mut error = std::ptr::null_mut();
347 let _ = ffi::gtk_show_uri_full_finish(parent_ptr as *mut ffi::GtkWindow, res, &mut error);
348 let result = if error.is_null() {
349 Ok(())
350 } else {
351 Err(from_glib_full(error))
352 };
353 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
354 Box_::from_raw(user_data as *mut _);
355 let callback = callback.into_inner();
356 callback(result);
357 }
358 let callback = show_uri_full_trampoline::<P>;
359 unsafe {
360 ffi::gtk_show_uri_full(
361 parent.map(|p| p.as_ref()).to_glib_none().0,
362 uri.to_glib_none().0,
363 timestamp,
364 cancellable.map(|p| p.as_ref()).to_glib_none().0,
365 Some(callback),
366 Box_::into_raw(user_data) as *mut _,
367 );
368 }
369}
370
371#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
372#[allow(deprecated)]
373pub fn show_uri_full_future(
374 parent: Option<&(impl IsA<Window> + Clone + 'static)>,
375 uri: &str,
376 timestamp: u32,
377) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
378 skip_assert_initialized!();
379 let parent = parent.map(ToOwned::to_owned);
380 let uri = String::from(uri);
381 Box_::pin(gio::GioFuture::new(&(), move |_obj, cancellable, send| {
382 show_uri_full(
383 parent.as_ref().map(::std::borrow::Borrow::borrow),
384 &uri,
385 timestamp,
386 Some(cancellable),
387 move |res| {
388 send.resolve(res);
389 },
390 );
391 }))
392}
393
394#[doc(alias = "gtk_show_about_dialog")]
403pub fn show_about_dialog<P: IsA<Window>>(parent: Option<&P>, properties: &[(&str, &dyn ToValue)]) {
404 assert_initialized_main_thread!();
405 static QUARK: OnceLock<Quark> = OnceLock::new();
406 let quark = *QUARK.get_or_init(|| Quark::from_str("gtk-rs-about-dialog"));
407
408 unsafe {
409 if let Some(d) = parent.and_then(|p| p.qdata::<AboutDialog>(quark)) {
410 d.as_ref().show();
411 } else {
412 let mut builder = glib::Object::builder::<AboutDialog>();
413 for (key, value) in properties {
414 builder = builder.property(key, *value);
415 }
416 let about_dialog = builder.build();
417 about_dialog.set_hide_on_close(true);
418
419 if let Some(dialog_parent) = parent {
421 about_dialog.set_modal(true);
422 about_dialog.set_transient_for(parent);
423 about_dialog.set_destroy_with_parent(true);
424 dialog_parent.set_qdata(quark, about_dialog.clone());
425 }
426
427 about_dialog.show();
428 };
429 }
430}
431
432#[doc(alias = "gtk_test_list_all_types")]
440pub fn test_list_all_types() -> Slice<glib::Type> {
441 unsafe {
442 let mut n_types = std::mem::MaybeUninit::uninit();
443 let types = ffi::gtk_test_list_all_types(n_types.as_mut_ptr());
444 Slice::from_glib_container_num(types as *mut _, n_types.assume_init() as usize)
445 }
446}
447
448#[doc(alias = "gtk_style_context_add_provider_for_display")]
449#[doc(alias = "add_provider_for_display")]
450pub fn style_context_add_provider_for_display(
451 display: &impl IsA<gdk::Display>,
452 provider: &impl IsA<StyleProvider>,
453 priority: u32,
454) {
455 skip_assert_initialized!();
456 unsafe {
457 ffi::gtk_style_context_add_provider_for_display(
458 display.as_ref().to_glib_none().0,
459 provider.as_ref().to_glib_none().0,
460 priority,
461 );
462 }
463}
464
465#[doc(alias = "gtk_style_context_remove_provider_for_display")]
466#[doc(alias = "remove_provider_for_display")]
467pub fn style_context_remove_provider_for_display(
468 display: &impl IsA<gdk::Display>,
469 provider: &impl IsA<StyleProvider>,
470) {
471 skip_assert_initialized!();
472 unsafe {
473 ffi::gtk_style_context_remove_provider_for_display(
474 display.as_ref().to_glib_none().0,
475 provider.as_ref().to_glib_none().0,
476 );
477 }
478}