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")]
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")]
111pub fn accelerator_name(
112 accelerator_key: gdk::Key,
113 accelerator_mods: gdk::ModifierType,
114) -> glib::GString {
115 assert_initialized_main_thread!();
116 unsafe {
117 from_glib_full(ffi::gtk_accelerator_name(
118 accelerator_key.into_glib(),
119 accelerator_mods.into_glib(),
120 ))
121 }
122}
123
124#[doc(alias = "gtk_accelerator_name_with_keycode")]
143pub fn accelerator_name_with_keycode(
144 display: Option<&impl IsA<gdk::Display>>,
145 accelerator_key: gdk::Key,
146 keycode: u32,
147 accelerator_mods: gdk::ModifierType,
148) -> glib::GString {
149 assert_initialized_main_thread!();
150 unsafe {
151 from_glib_full(ffi::gtk_accelerator_name_with_keycode(
152 display.map(|p| p.as_ref()).to_glib_none().0,
153 accelerator_key.into_glib(),
154 keycode,
155 accelerator_mods.into_glib(),
156 ))
157 }
158}
159
160#[doc(alias = "gtk_accelerator_parse")]
178pub fn accelerator_parse(accelerator: impl IntoGStr) -> Option<(gdk::Key, gdk::ModifierType)> {
179 assert_initialized_main_thread!();
180 unsafe {
181 accelerator.run_with_gstr(|accelerator| {
182 let mut accelerator_key = std::mem::MaybeUninit::uninit();
183 let mut accelerator_mods = std::mem::MaybeUninit::uninit();
184 let ret = from_glib(ffi::gtk_accelerator_parse(
185 accelerator.as_ptr(),
186 accelerator_key.as_mut_ptr(),
187 accelerator_mods.as_mut_ptr(),
188 ));
189 if ret {
190 Some((
191 gdk::Key::from_glib(accelerator_key.assume_init()),
192 from_glib(accelerator_mods.assume_init()),
193 ))
194 } else {
195 None
196 }
197 })
198 }
199}
200
201#[doc(alias = "gtk_accelerator_parse_with_keycode")]
235pub fn accelerator_parse_with_keycode(
236 accelerator: impl IntoGStr,
237 display: Option<&impl IsA<gdk::Display>>,
238) -> Option<(gdk::Key, Slice<u32>, gdk::ModifierType)> {
239 assert_initialized_main_thread!();
240 unsafe {
241 accelerator.run_with_gstr(|accelerator| {
242 let mut accelerator_key = std::mem::MaybeUninit::uninit();
243 let mut accelerator_codes_ptr = std::ptr::null_mut();
244 let mut accelerator_mods = std::mem::MaybeUninit::uninit();
245 let success = from_glib(ffi::gtk_accelerator_parse_with_keycode(
246 accelerator.as_ptr(),
247 display.map(|p| p.as_ref()).to_glib_none().0,
248 accelerator_key.as_mut_ptr(),
249 &mut accelerator_codes_ptr,
250 accelerator_mods.as_mut_ptr(),
251 ));
252 if success {
253 let mut len = 0;
254 if !accelerator_codes_ptr.is_null() {
255 while std::ptr::read(accelerator_codes_ptr.add(len)) != 0 {
256 len += 1;
257 }
258 }
259 let accelerator_codes = Slice::from_glib_full_num(accelerator_codes_ptr, len);
260 Some((
261 gdk::Key::from_glib(accelerator_key.assume_init()),
262 accelerator_codes,
263 from_glib(accelerator_mods.assume_init()),
264 ))
265 } else {
266 None
267 }
268 })
269 }
270}
271
272#[doc(alias = "gtk_show_uri_full")]
295#[doc(alias = "gtk_show_uri_full_finish")]
296#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
297#[allow(deprecated)]
298pub fn show_uri_full<P: FnOnce(Result<(), glib::Error>) + 'static>(
299 parent: Option<&impl IsA<Window>>,
300 uri: &str,
301 timestamp: u32,
302 cancellable: Option<&impl IsA<gio::Cancellable>>,
303 callback: P,
304) {
305 assert_initialized_main_thread!();
306 let main_context = glib::MainContext::ref_thread_default();
307 let is_main_context_owner = main_context.is_owner();
308 let has_acquired_main_context = (!is_main_context_owner)
309 .then(|| main_context.acquire().ok())
310 .flatten();
311 assert!(
312 is_main_context_owner || has_acquired_main_context.is_some(),
313 "Async operations only allowed if the thread is owning the MainContext"
314 );
315
316 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
317 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
318 unsafe extern "C" fn show_uri_full_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
319 parent_ptr: *mut glib::gobject_ffi::GObject,
320 res: *mut gio::ffi::GAsyncResult,
321 user_data: glib::ffi::gpointer,
322 ) {
323 unsafe {
324 let mut error = std::ptr::null_mut();
325 let _ =
326 ffi::gtk_show_uri_full_finish(parent_ptr as *mut ffi::GtkWindow, res, &mut error);
327 let result = if error.is_null() {
328 Ok(())
329 } else {
330 Err(from_glib_full(error))
331 };
332 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
333 Box_::from_raw(user_data as *mut _);
334 let callback = callback.into_inner();
335 callback(result);
336 }
337 }
338 let callback = show_uri_full_trampoline::<P>;
339 unsafe {
340 ffi::gtk_show_uri_full(
341 parent.map(|p| p.as_ref()).to_glib_none().0,
342 uri.to_glib_none().0,
343 timestamp,
344 cancellable.map(|p| p.as_ref()).to_glib_none().0,
345 Some(callback),
346 Box_::into_raw(user_data) as *mut _,
347 );
348 }
349}
350
351#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
352#[allow(deprecated)]
353pub fn show_uri_full_future(
354 parent: Option<&(impl IsA<Window> + Clone + 'static)>,
355 uri: &str,
356 timestamp: u32,
357) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
358 skip_assert_initialized!();
359 let parent = parent.map(ToOwned::to_owned);
360 let uri = String::from(uri);
361 Box_::pin(gio::GioFuture::new(&(), move |_obj, cancellable, send| {
362 show_uri_full(
363 parent.as_ref().map(::std::borrow::Borrow::borrow),
364 &uri,
365 timestamp,
366 Some(cancellable),
367 move |res| {
368 send.resolve(res);
369 },
370 );
371 }))
372}
373
374#[doc(alias = "gtk_show_about_dialog")]
383pub fn show_about_dialog<P: IsA<Window>>(parent: Option<&P>, properties: &[(&str, &dyn ToValue)]) {
384 assert_initialized_main_thread!();
385 static QUARK: OnceLock<Quark> = OnceLock::new();
386 let quark = *QUARK.get_or_init(|| Quark::from_str("gtk-rs-about-dialog"));
387
388 unsafe {
389 if let Some(d) = parent.and_then(|p| p.qdata::<AboutDialog>(quark)) {
390 d.as_ref().show();
391 } else {
392 let mut builder = glib::Object::builder::<AboutDialog>();
393 for (key, value) in properties {
394 builder = builder.property(key, *value);
395 }
396 let about_dialog = builder.build();
397 about_dialog.set_hide_on_close(true);
398
399 if let Some(dialog_parent) = parent {
401 about_dialog.set_modal(true);
402 about_dialog.set_transient_for(parent);
403 about_dialog.set_destroy_with_parent(true);
404 dialog_parent.set_qdata(quark, about_dialog.clone());
405 }
406
407 about_dialog.show();
408 };
409 }
410}
411
412#[doc(alias = "gtk_test_list_all_types")]
420pub fn test_list_all_types() -> Slice<glib::Type> {
421 unsafe {
422 let mut n_types = std::mem::MaybeUninit::uninit();
423 let types = ffi::gtk_test_list_all_types(n_types.as_mut_ptr());
424 Slice::from_glib_container_num(types as *mut _, n_types.assume_init() as usize)
425 }
426}
427
428#[doc(alias = "gtk_style_context_add_provider_for_display")]
429#[doc(alias = "add_provider_for_display")]
430pub fn style_context_add_provider_for_display(
431 display: &impl IsA<gdk::Display>,
432 provider: &impl IsA<StyleProvider>,
433 priority: u32,
434) {
435 skip_assert_initialized!();
436 unsafe {
437 ffi::gtk_style_context_add_provider_for_display(
438 display.as_ref().to_glib_none().0,
439 provider.as_ref().to_glib_none().0,
440 priority,
441 );
442 }
443}
444
445#[doc(alias = "gtk_style_context_remove_provider_for_display")]
446#[doc(alias = "remove_provider_for_display")]
447pub fn style_context_remove_provider_for_display(
448 display: &impl IsA<gdk::Display>,
449 provider: &impl IsA<StyleProvider>,
450) {
451 skip_assert_initialized!();
452 unsafe {
453 ffi::gtk_style_context_remove_provider_for_display(
454 display.as_ref().to_glib_none().0,
455 provider.as_ref().to_glib_none().0,
456 );
457 }
458}