1use gio;
6use glib::object::Cast;
7use glib::object::IsA;
8use glib::signal::connect_raw;
9use glib::signal::SignalHandlerId;
10use glib::translate::*;
11use glib::GString;
12use glib::StaticType;
13use glib::ToValue;
14use glib::Value;
15use glib_sys;
16use gobject_sys;
17use gtk_sys;
18use std::boxed::Box as Box_;
19use std::fmt;
20use std::mem::transmute;
21use ApplicationInhibitFlags;
22use Window;
23
24glib_wrapper! {
25 pub struct Application(Object<gtk_sys::GtkApplication, gtk_sys::GtkApplicationClass, ApplicationClass>) @extends gio::Application, @implements gio::ActionGroup, gio::ActionMap;
26
27 match fn {
28 get_type => || gtk_sys::gtk_application_get_type(),
29 }
30}
31
32pub struct ApplicationBuilder {
33 app_menu: Option<gio::MenuModel>,
34 menubar: Option<gio::MenuModel>,
35 register_session: Option<bool>,
36 action_group: Option<gio::ActionGroup>,
37 application_id: Option<String>,
38 flags: Option<gio::ApplicationFlags>,
39 inactivity_timeout: Option<u32>,
40 resource_base_path: Option<String>,
41}
42
43impl ApplicationBuilder {
44 pub fn new() -> Self {
45 Self {
46 app_menu: None,
47 menubar: None,
48 register_session: None,
49 action_group: None,
50 application_id: None,
51 flags: None,
52 inactivity_timeout: None,
53 resource_base_path: None,
54 }
55 }
56
57 pub fn build(self) -> Application {
58 let mut properties: Vec<(&str, &dyn ToValue)> = vec![];
59 if let Some(ref app_menu) = self.app_menu {
60 properties.push(("app-menu", app_menu));
61 }
62 if let Some(ref menubar) = self.menubar {
63 properties.push(("menubar", menubar));
64 }
65 if let Some(ref register_session) = self.register_session {
66 properties.push(("register-session", register_session));
67 }
68 if let Some(ref action_group) = self.action_group {
69 properties.push(("action-group", action_group));
70 }
71 if let Some(ref application_id) = self.application_id {
72 properties.push(("application-id", application_id));
73 }
74 if let Some(ref flags) = self.flags {
75 properties.push(("flags", flags));
76 }
77 if let Some(ref inactivity_timeout) = self.inactivity_timeout {
78 properties.push(("inactivity-timeout", inactivity_timeout));
79 }
80 if let Some(ref resource_base_path) = self.resource_base_path {
81 properties.push(("resource-base-path", resource_base_path));
82 }
83 glib::Object::new(Application::static_type(), &properties)
84 .expect("object new")
85 .downcast()
86 .expect("downcast")
87 }
88
89 pub fn app_menu(mut self, app_menu: &gio::MenuModel) -> Self {
90 self.app_menu = Some(app_menu.clone());
91 self
92 }
93
94 pub fn menubar(mut self, menubar: &gio::MenuModel) -> Self {
95 self.menubar = Some(menubar.clone());
96 self
97 }
98
99 pub fn register_session(mut self, register_session: bool) -> Self {
100 self.register_session = Some(register_session);
101 self
102 }
103
104 pub fn action_group(mut self, action_group: &gio::ActionGroup) -> Self {
105 self.action_group = Some(action_group.clone());
106 self
107 }
108
109 pub fn application_id(mut self, application_id: &str) -> Self {
110 self.application_id = Some(application_id.to_string());
111 self
112 }
113
114 pub fn flags(mut self, flags: gio::ApplicationFlags) -> Self {
115 self.flags = Some(flags);
116 self
117 }
118
119 pub fn inactivity_timeout(mut self, inactivity_timeout: u32) -> Self {
120 self.inactivity_timeout = Some(inactivity_timeout);
121 self
122 }
123
124 pub fn resource_base_path(mut self, resource_base_path: &str) -> Self {
125 self.resource_base_path = Some(resource_base_path.to_string());
126 self
127 }
128}
129
130pub const NONE_APPLICATION: Option<&Application> = None;
131
132pub trait GtkApplicationExt: 'static {
133 fn add_window<P: IsA<Window>>(&self, window: &P);
134
135 fn get_accels_for_action(&self, detailed_action_name: &str) -> Vec<GString>;
136
137 fn get_actions_for_accel(&self, accel: &str) -> Vec<GString>;
138
139 fn get_active_window(&self) -> Option<Window>;
140
141 fn get_app_menu(&self) -> Option<gio::MenuModel>;
142
143 fn get_menu_by_id(&self, id: &str) -> Option<gio::Menu>;
144
145 fn get_menubar(&self) -> Option<gio::MenuModel>;
146
147 fn get_window_by_id(&self, id: u32) -> Option<Window>;
148
149 fn get_windows(&self) -> Vec<Window>;
150
151 fn inhibit<P: IsA<Window>>(
152 &self,
153 window: Option<&P>,
154 flags: ApplicationInhibitFlags,
155 reason: Option<&str>,
156 ) -> u32;
157
158 fn is_inhibited(&self, flags: ApplicationInhibitFlags) -> bool;
159
160 fn list_action_descriptions(&self) -> Vec<GString>;
161
162 fn prefers_app_menu(&self) -> bool;
163
164 fn remove_window<P: IsA<Window>>(&self, window: &P);
165
166 fn set_accels_for_action(&self, detailed_action_name: &str, accels: &[&str]);
167
168 fn set_app_menu<P: IsA<gio::MenuModel>>(&self, app_menu: Option<&P>);
169
170 fn set_menubar<P: IsA<gio::MenuModel>>(&self, menubar: Option<&P>);
171
172 fn uninhibit(&self, cookie: u32);
173
174 fn get_property_register_session(&self) -> bool;
175
176 fn set_property_register_session(&self, register_session: bool);
177
178 #[cfg(any(feature = "v3_24", feature = "dox"))]
179 fn get_property_screensaver_active(&self) -> bool;
180
181 fn connect_window_added<F: Fn(&Self, &Window) + 'static>(&self, f: F) -> SignalHandlerId;
182
183 fn connect_window_removed<F: Fn(&Self, &Window) + 'static>(&self, f: F) -> SignalHandlerId;
184
185 fn connect_property_active_window_notify<F: Fn(&Self) + 'static>(
186 &self,
187 f: F,
188 ) -> SignalHandlerId;
189
190 fn connect_property_app_menu_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId;
191
192 fn connect_property_menubar_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId;
193
194 fn connect_property_register_session_notify<F: Fn(&Self) + 'static>(
195 &self,
196 f: F,
197 ) -> SignalHandlerId;
198
199 #[cfg(any(feature = "v3_24", feature = "dox"))]
200 fn connect_property_screensaver_active_notify<F: Fn(&Self) + 'static>(
201 &self,
202 f: F,
203 ) -> SignalHandlerId;
204}
205
206impl<O: IsA<Application>> GtkApplicationExt for O {
207 fn add_window<P: IsA<Window>>(&self, window: &P) {
208 unsafe {
209 gtk_sys::gtk_application_add_window(
210 self.as_ref().to_glib_none().0,
211 window.as_ref().to_glib_none().0,
212 );
213 }
214 }
215
216 fn get_accels_for_action(&self, detailed_action_name: &str) -> Vec<GString> {
217 unsafe {
218 FromGlibPtrContainer::from_glib_full(gtk_sys::gtk_application_get_accels_for_action(
219 self.as_ref().to_glib_none().0,
220 detailed_action_name.to_glib_none().0,
221 ))
222 }
223 }
224
225 fn get_actions_for_accel(&self, accel: &str) -> Vec<GString> {
226 unsafe {
227 FromGlibPtrContainer::from_glib_full(gtk_sys::gtk_application_get_actions_for_accel(
228 self.as_ref().to_glib_none().0,
229 accel.to_glib_none().0,
230 ))
231 }
232 }
233
234 fn get_active_window(&self) -> Option<Window> {
235 unsafe {
236 from_glib_none(gtk_sys::gtk_application_get_active_window(
237 self.as_ref().to_glib_none().0,
238 ))
239 }
240 }
241
242 fn get_app_menu(&self) -> Option<gio::MenuModel> {
243 unsafe {
244 from_glib_none(gtk_sys::gtk_application_get_app_menu(
245 self.as_ref().to_glib_none().0,
246 ))
247 }
248 }
249
250 fn get_menu_by_id(&self, id: &str) -> Option<gio::Menu> {
251 unsafe {
252 from_glib_none(gtk_sys::gtk_application_get_menu_by_id(
253 self.as_ref().to_glib_none().0,
254 id.to_glib_none().0,
255 ))
256 }
257 }
258
259 fn get_menubar(&self) -> Option<gio::MenuModel> {
260 unsafe {
261 from_glib_none(gtk_sys::gtk_application_get_menubar(
262 self.as_ref().to_glib_none().0,
263 ))
264 }
265 }
266
267 fn get_window_by_id(&self, id: u32) -> Option<Window> {
268 unsafe {
269 from_glib_none(gtk_sys::gtk_application_get_window_by_id(
270 self.as_ref().to_glib_none().0,
271 id,
272 ))
273 }
274 }
275
276 fn get_windows(&self) -> Vec<Window> {
277 unsafe {
278 FromGlibPtrContainer::from_glib_none(gtk_sys::gtk_application_get_windows(
279 self.as_ref().to_glib_none().0,
280 ))
281 }
282 }
283
284 fn inhibit<P: IsA<Window>>(
285 &self,
286 window: Option<&P>,
287 flags: ApplicationInhibitFlags,
288 reason: Option<&str>,
289 ) -> u32 {
290 unsafe {
291 gtk_sys::gtk_application_inhibit(
292 self.as_ref().to_glib_none().0,
293 window.map(|p| p.as_ref()).to_glib_none().0,
294 flags.to_glib(),
295 reason.to_glib_none().0,
296 )
297 }
298 }
299
300 fn is_inhibited(&self, flags: ApplicationInhibitFlags) -> bool {
301 unsafe {
302 from_glib(gtk_sys::gtk_application_is_inhibited(
303 self.as_ref().to_glib_none().0,
304 flags.to_glib(),
305 ))
306 }
307 }
308
309 fn list_action_descriptions(&self) -> Vec<GString> {
310 unsafe {
311 FromGlibPtrContainer::from_glib_full(gtk_sys::gtk_application_list_action_descriptions(
312 self.as_ref().to_glib_none().0,
313 ))
314 }
315 }
316
317 fn prefers_app_menu(&self) -> bool {
318 unsafe {
319 from_glib(gtk_sys::gtk_application_prefers_app_menu(
320 self.as_ref().to_glib_none().0,
321 ))
322 }
323 }
324
325 fn remove_window<P: IsA<Window>>(&self, window: &P) {
326 unsafe {
327 gtk_sys::gtk_application_remove_window(
328 self.as_ref().to_glib_none().0,
329 window.as_ref().to_glib_none().0,
330 );
331 }
332 }
333
334 fn set_accels_for_action(&self, detailed_action_name: &str, accels: &[&str]) {
335 unsafe {
336 gtk_sys::gtk_application_set_accels_for_action(
337 self.as_ref().to_glib_none().0,
338 detailed_action_name.to_glib_none().0,
339 accels.to_glib_none().0,
340 );
341 }
342 }
343
344 fn set_app_menu<P: IsA<gio::MenuModel>>(&self, app_menu: Option<&P>) {
345 unsafe {
346 gtk_sys::gtk_application_set_app_menu(
347 self.as_ref().to_glib_none().0,
348 app_menu.map(|p| p.as_ref()).to_glib_none().0,
349 );
350 }
351 }
352
353 fn set_menubar<P: IsA<gio::MenuModel>>(&self, menubar: Option<&P>) {
354 unsafe {
355 gtk_sys::gtk_application_set_menubar(
356 self.as_ref().to_glib_none().0,
357 menubar.map(|p| p.as_ref()).to_glib_none().0,
358 );
359 }
360 }
361
362 fn uninhibit(&self, cookie: u32) {
363 unsafe {
364 gtk_sys::gtk_application_uninhibit(self.as_ref().to_glib_none().0, cookie);
365 }
366 }
367
368 fn get_property_register_session(&self) -> bool {
369 unsafe {
370 let mut value = Value::from_type(<bool as StaticType>::static_type());
371 gobject_sys::g_object_get_property(
372 self.to_glib_none().0 as *mut gobject_sys::GObject,
373 b"register-session\0".as_ptr() as *const _,
374 value.to_glib_none_mut().0,
375 );
376 value.get().unwrap()
377 }
378 }
379
380 fn set_property_register_session(&self, register_session: bool) {
381 unsafe {
382 gobject_sys::g_object_set_property(
383 self.to_glib_none().0 as *mut gobject_sys::GObject,
384 b"register-session\0".as_ptr() as *const _,
385 Value::from(®ister_session).to_glib_none().0,
386 );
387 }
388 }
389
390 #[cfg(any(feature = "v3_24", feature = "dox"))]
391 fn get_property_screensaver_active(&self) -> bool {
392 unsafe {
393 let mut value = Value::from_type(<bool as StaticType>::static_type());
394 gobject_sys::g_object_get_property(
395 self.to_glib_none().0 as *mut gobject_sys::GObject,
396 b"screensaver-active\0".as_ptr() as *const _,
397 value.to_glib_none_mut().0,
398 );
399 value.get().unwrap()
400 }
401 }
402
403 fn connect_window_added<F: Fn(&Self, &Window) + 'static>(&self, f: F) -> SignalHandlerId {
404 unsafe extern "C" fn window_added_trampoline<P, F: Fn(&P, &Window) + 'static>(
405 this: *mut gtk_sys::GtkApplication,
406 window: *mut gtk_sys::GtkWindow,
407 f: glib_sys::gpointer,
408 ) where
409 P: IsA<Application>,
410 {
411 let f: &F = &*(f as *const F);
412 f(
413 &Application::from_glib_borrow(this).unsafe_cast(),
414 &from_glib_borrow(window),
415 )
416 }
417 unsafe {
418 let f: Box_<F> = Box_::new(f);
419 connect_raw(
420 self.as_ptr() as *mut _,
421 b"window-added\0".as_ptr() as *const _,
422 Some(transmute(window_added_trampoline::<Self, F> as usize)),
423 Box_::into_raw(f),
424 )
425 }
426 }
427
428 fn connect_window_removed<F: Fn(&Self, &Window) + 'static>(&self, f: F) -> SignalHandlerId {
429 unsafe extern "C" fn window_removed_trampoline<P, F: Fn(&P, &Window) + 'static>(
430 this: *mut gtk_sys::GtkApplication,
431 window: *mut gtk_sys::GtkWindow,
432 f: glib_sys::gpointer,
433 ) where
434 P: IsA<Application>,
435 {
436 let f: &F = &*(f as *const F);
437 f(
438 &Application::from_glib_borrow(this).unsafe_cast(),
439 &from_glib_borrow(window),
440 )
441 }
442 unsafe {
443 let f: Box_<F> = Box_::new(f);
444 connect_raw(
445 self.as_ptr() as *mut _,
446 b"window-removed\0".as_ptr() as *const _,
447 Some(transmute(window_removed_trampoline::<Self, F> as usize)),
448 Box_::into_raw(f),
449 )
450 }
451 }
452
453 fn connect_property_active_window_notify<F: Fn(&Self) + 'static>(
454 &self,
455 f: F,
456 ) -> SignalHandlerId {
457 unsafe extern "C" fn notify_active_window_trampoline<P, F: Fn(&P) + 'static>(
458 this: *mut gtk_sys::GtkApplication,
459 _param_spec: glib_sys::gpointer,
460 f: glib_sys::gpointer,
461 ) where
462 P: IsA<Application>,
463 {
464 let f: &F = &*(f as *const F);
465 f(&Application::from_glib_borrow(this).unsafe_cast())
466 }
467 unsafe {
468 let f: Box_<F> = Box_::new(f);
469 connect_raw(
470 self.as_ptr() as *mut _,
471 b"notify::active-window\0".as_ptr() as *const _,
472 Some(transmute(
473 notify_active_window_trampoline::<Self, F> as usize,
474 )),
475 Box_::into_raw(f),
476 )
477 }
478 }
479
480 fn connect_property_app_menu_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
481 unsafe extern "C" fn notify_app_menu_trampoline<P, F: Fn(&P) + 'static>(
482 this: *mut gtk_sys::GtkApplication,
483 _param_spec: glib_sys::gpointer,
484 f: glib_sys::gpointer,
485 ) where
486 P: IsA<Application>,
487 {
488 let f: &F = &*(f as *const F);
489 f(&Application::from_glib_borrow(this).unsafe_cast())
490 }
491 unsafe {
492 let f: Box_<F> = Box_::new(f);
493 connect_raw(
494 self.as_ptr() as *mut _,
495 b"notify::app-menu\0".as_ptr() as *const _,
496 Some(transmute(notify_app_menu_trampoline::<Self, F> as usize)),
497 Box_::into_raw(f),
498 )
499 }
500 }
501
502 fn connect_property_menubar_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
503 unsafe extern "C" fn notify_menubar_trampoline<P, F: Fn(&P) + 'static>(
504 this: *mut gtk_sys::GtkApplication,
505 _param_spec: glib_sys::gpointer,
506 f: glib_sys::gpointer,
507 ) where
508 P: IsA<Application>,
509 {
510 let f: &F = &*(f as *const F);
511 f(&Application::from_glib_borrow(this).unsafe_cast())
512 }
513 unsafe {
514 let f: Box_<F> = Box_::new(f);
515 connect_raw(
516 self.as_ptr() as *mut _,
517 b"notify::menubar\0".as_ptr() as *const _,
518 Some(transmute(notify_menubar_trampoline::<Self, F> as usize)),
519 Box_::into_raw(f),
520 )
521 }
522 }
523
524 fn connect_property_register_session_notify<F: Fn(&Self) + 'static>(
525 &self,
526 f: F,
527 ) -> SignalHandlerId {
528 unsafe extern "C" fn notify_register_session_trampoline<P, F: Fn(&P) + 'static>(
529 this: *mut gtk_sys::GtkApplication,
530 _param_spec: glib_sys::gpointer,
531 f: glib_sys::gpointer,
532 ) where
533 P: IsA<Application>,
534 {
535 let f: &F = &*(f as *const F);
536 f(&Application::from_glib_borrow(this).unsafe_cast())
537 }
538 unsafe {
539 let f: Box_<F> = Box_::new(f);
540 connect_raw(
541 self.as_ptr() as *mut _,
542 b"notify::register-session\0".as_ptr() as *const _,
543 Some(transmute(
544 notify_register_session_trampoline::<Self, F> as usize,
545 )),
546 Box_::into_raw(f),
547 )
548 }
549 }
550
551 #[cfg(any(feature = "v3_24", feature = "dox"))]
552 fn connect_property_screensaver_active_notify<F: Fn(&Self) + 'static>(
553 &self,
554 f: F,
555 ) -> SignalHandlerId {
556 unsafe extern "C" fn notify_screensaver_active_trampoline<P, F: Fn(&P) + 'static>(
557 this: *mut gtk_sys::GtkApplication,
558 _param_spec: glib_sys::gpointer,
559 f: glib_sys::gpointer,
560 ) where
561 P: IsA<Application>,
562 {
563 let f: &F = &*(f as *const F);
564 f(&Application::from_glib_borrow(this).unsafe_cast())
565 }
566 unsafe {
567 let f: Box_<F> = Box_::new(f);
568 connect_raw(
569 self.as_ptr() as *mut _,
570 b"notify::screensaver-active\0".as_ptr() as *const _,
571 Some(transmute(
572 notify_screensaver_active_trampoline::<Self, F> as usize,
573 )),
574 Box_::into_raw(f),
575 )
576 }
577 }
578}
579
580impl fmt::Display for Application {
581 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
582 write!(f, "Application")
583 }
584}