[go: up one dir, main page]

gtk4/
functions.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use 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            // cache the dialog if a parent is set
242            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}