Skip to main content

lightdm/
greeter.rs

1use glib::{object::IsA, translate::*};
2
3use std::{boxed::Box as Box_, pin::Pin};
4
5use super::{Greeter, GreeterError};
6
7pub trait GreeterExtManual: IsA<Greeter> + 'static {
8    /// Starts the authentication procedure for a user.
9    /// ## `username`
10    /// A username or #NULL to prompt for a username.
11    ///
12    /// # Returns
13    ///
14    /// #TRUE if authentication request sent.
15    #[doc(alias = "lightdm_greeter_authenticate")]
16    fn authenticate(&self, username: Option<&str>) -> Result<(), glib::Error> {
17        unsafe {
18            let mut error = std::ptr::null_mut();
19            let is_ok = ffi::lightdm_greeter_authenticate(
20                self.as_ref().to_glib_none().0,
21                username.to_glib_none().0,
22                &mut error,
23            );
24            if error.is_null() {
25                if is_ok == glib::ffi::GTRUE {
26                    Ok(())
27                } else {
28                    Err(glib::Error::new(
29                        GreeterError::__Unknown(5),
30                        "lightdm_greeter_authenticate() return false with null error",
31                    ))
32                }
33            } else {
34                Err(from_glib_full(error))
35            }
36        }
37    }
38
39    /// Starts the authentication procedure for the guest user.
40    ///
41    /// # Returns
42    ///
43    /// #TRUE if authentication request sent.
44    #[doc(alias = "lightdm_greeter_authenticate_as_guest")]
45    fn authenticate_as_guest(&self) -> Result<(), glib::Error> {
46        unsafe {
47            let mut error = std::ptr::null_mut();
48            let is_ok = ffi::lightdm_greeter_authenticate_as_guest(
49                self.as_ref().to_glib_none().0,
50                &mut error,
51            );
52            if error.is_null() {
53                if is_ok == glib::ffi::GTRUE {
54                    Ok(())
55                } else {
56                    Err(glib::Error::new(
57                        GreeterError::__Unknown(6),
58                        "lightdm_greeter_authenticate_as_guest() return false with null error",
59                    ))
60                }
61            } else {
62                Err(from_glib_full(error))
63            }
64        }
65    }
66
67    /// Starts the authentication procedure for the automatic login user.
68    ///
69    /// # Returns
70    ///
71    /// #TRUE if authentication request sent.
72    #[doc(alias = "lightdm_greeter_authenticate_autologin")]
73    fn authenticate_autologin(&self) -> Result<(), glib::Error> {
74        unsafe {
75            let mut error = std::ptr::null_mut();
76            let is_ok = ffi::lightdm_greeter_authenticate_autologin(
77                self.as_ref().to_glib_none().0,
78                &mut error,
79            );
80            if error.is_null() {
81                if is_ok == glib::ffi::GTRUE {
82                    Ok(())
83                } else {
84                    Err(glib::Error::new(
85                        GreeterError::__Unknown(7),
86                        "lightdm_greeter_authenticate_autologin() return false with null error",
87                    ))
88                }
89            } else {
90                Err(from_glib_full(error))
91            }
92        }
93    }
94
95    /// Start authentication for a remote session type.
96    /// ## `session`
97    /// The name of a remote session
98    /// ## `username`
99    /// A username of #NULL to prompt for a username.
100    ///
101    /// # Returns
102    ///
103    /// #TRUE if authentication request sent.
104    #[doc(alias = "lightdm_greeter_authenticate_remote")]
105    fn authenticate_remote(
106        &self,
107        session: &str,
108        username: Option<&str>,
109    ) -> Result<(), glib::Error> {
110        unsafe {
111            let mut error = std::ptr::null_mut();
112            let is_ok = ffi::lightdm_greeter_authenticate_remote(
113                self.as_ref().to_glib_none().0,
114                session.to_glib_none().0,
115                username.to_glib_none().0,
116                &mut error,
117            );
118            if error.is_null() {
119                if is_ok == glib::ffi::GTRUE {
120                    Ok(())
121                } else {
122                    Err(glib::Error::new(
123                        GreeterError::__Unknown(8),
124                        "lightdm_greeter_authenticate_remote() return false with null error",
125                    ))
126                }
127            } else {
128                Err(from_glib_full(error))
129            }
130        }
131    }
132
133    /// Cancel the current user authentication.
134    ///
135    /// # Returns
136    ///
137    /// #TRUE if cancel request sent.
138    #[doc(alias = "lightdm_greeter_cancel_authentication")]
139    fn cancel_authentication(&self) -> Result<(), glib::Error> {
140        unsafe {
141            let mut error = std::ptr::null_mut();
142            let is_ok = ffi::lightdm_greeter_cancel_authentication(
143                self.as_ref().to_glib_none().0,
144                &mut error,
145            );
146            if error.is_null() {
147                if is_ok == glib::ffi::GTRUE {
148                    Ok(())
149                } else {
150                    Err(glib::Error::new(
151                        GreeterError::__Unknown(9),
152                        "lightdm_greeter_cancel_authentication() return false with null error",
153                    ))
154                }
155            } else {
156                Err(from_glib_full(error))
157            }
158        }
159    }
160
161    /// Connects the greeter to the display manager.  Will block until connected.
162    ///
163    /// # Deprecated since 1.11.1
164    ///
165    /// Use lightdm_greeter_connect_to_daemon_sync() instead
166    ///
167    /// # Returns
168    ///
169    /// #TRUE if successfully connected
170    #[cfg_attr(feature = "v1_11_1", deprecated = "Since 1.11.1")]
171    #[allow(deprecated)]
172    #[doc(alias = "lightdm_greeter_connect_sync")]
173    fn connect_sync(&self) -> Result<(), glib::Error> {
174        unsafe {
175            let mut error = std::ptr::null_mut();
176            let is_ok =
177                ffi::lightdm_greeter_connect_sync(self.as_ref().to_glib_none().0, &mut error);
178            if error.is_null() {
179                if is_ok == glib::ffi::GTRUE {
180                    Ok(())
181                } else {
182                    Err(glib::Error::new(
183                        GreeterError::__Unknown(10),
184                        "lightdm_greeter_connect_sync() return false with null error",
185                    ))
186                }
187            } else {
188                Err(from_glib_full(error))
189            }
190        }
191    }
192
193    /// Asynchronously connects the greeter to the display manager.
194    ///
195    /// When the operation is finished, @callback will be invoked. You can then call lightdm_greeter_connect_to_daemon_finish() to get the result of the operation.
196    ///
197    /// See lightdm_greeter_connect_to_daemon_sync() for the synchronous version.
198    /// ## `cancellable`
199    /// A #GCancellable or [`None`].
200    /// ## `callback`
201    /// A #GAsyncReadyCallback to call when completed or [`None`].
202    #[doc(alias = "lightdm_greeter_connect_to_daemon")]
203    fn connect_to_daemon<P: FnOnce(Result<(), glib::Error>) + 'static>(
204        &self,
205        cancellable: Option<&impl IsA<gio::Cancellable>>,
206        callback: P,
207    ) {
208        let main_context = glib::MainContext::ref_thread_default();
209        let is_main_context_owner = main_context.is_owner();
210        let has_acquired_main_context = (!is_main_context_owner)
211            .then(|| main_context.acquire().ok())
212            .flatten();
213        assert!(
214            is_main_context_owner || has_acquired_main_context.is_some(),
215            "Async operations only allowed if the thread is owning the MainContext"
216        );
217
218        let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
219            Box_::new(glib::thread_guard::ThreadGuard::new(callback));
220        unsafe extern "C" fn connect_to_daemon_trampoline<
221            P: FnOnce(Result<(), glib::Error>) + 'static,
222        >(
223            _source_object: *mut glib::gobject_ffi::GObject,
224            res: *mut gio::ffi::GAsyncResult,
225            user_data: glib::ffi::gpointer,
226        ) {
227            let mut error = std::ptr::null_mut();
228            let is_ok = unsafe {
229                ffi::lightdm_greeter_connect_to_daemon_finish(
230                    _source_object as *mut _,
231                    res,
232                    &mut error,
233                )
234            };
235            let result = if error.is_null() {
236                if is_ok == glib::ffi::GTRUE {
237                    Ok(())
238                } else {
239                    Err(glib::Error::new(
240                        GreeterError::__Unknown(11),
241                        "lightdm_greeter_connect_to_daemon_finish() return false with null error",
242                    ))
243                }
244            } else {
245                Err(unsafe { from_glib_full(error) })
246            };
247            let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
248                unsafe { Box_::from_raw(user_data as *mut _) };
249            let callback: P = callback.into_inner();
250            callback(result);
251        }
252        let callback = connect_to_daemon_trampoline::<P>;
253        unsafe {
254            ffi::lightdm_greeter_connect_to_daemon(
255                self.as_ref().to_glib_none().0,
256                cancellable.map(|p| p.as_ref()).to_glib_none().0,
257                Some(callback),
258                Box_::into_raw(user_data) as *mut _,
259            );
260        }
261    }
262
263    fn connect_to_daemon_future(
264        &self,
265    ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
266        Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
267            obj.connect_to_daemon(Some(cancellable), move |res| {
268                send.resolve(res);
269            });
270        }))
271    }
272
273    /// Connects the greeter to the display manager.  Will block until connected.
274    ///
275    /// # Returns
276    ///
277    /// #TRUE if successfully connected
278    #[doc(alias = "lightdm_greeter_connect_to_daemon_sync")]
279    fn connect_to_daemon_sync(&self) -> Result<(), glib::Error> {
280        unsafe {
281            let mut error = std::ptr::null_mut();
282            let is_ok = ffi::lightdm_greeter_connect_to_daemon_sync(
283                self.as_ref().to_glib_none().0,
284                &mut error,
285            );
286            if error.is_null() {
287                if is_ok == glib::ffi::GTRUE {
288                    Ok(())
289                } else {
290                    Err(glib::Error::new(
291                        GreeterError::__Unknown(12),
292                        "lightdm_greeter_connect_to_daemon_sync() return false with null error",
293                    ))
294                }
295            } else {
296                Err(from_glib_full(error))
297            }
298        }
299    }
300
301    /// Ensure that a shared data dir for the given user is available.  Both the
302    /// greeter user and @username will have write access to that folder.  The
303    /// intention is that larger pieces of shared data would be stored there (files
304    /// that the greeter creates but wants to give to a user -- like camera
305    /// photos -- or files that the user creates but wants the greeter to
306    /// see -- like contact avatars).
307    ///
308    /// LightDM will automatically create these if the user actually logs in, so
309    /// greeters only need to call this method if they want to store something in
310    /// the directory themselves.
311    /// ## `username`
312    /// A username
313    /// ## `cancellable`
314    /// A #GCancellable or [`None`].
315    /// ## `callback`
316    /// A #GAsyncReadyCallback to call when completed or [`None`].
317    #[doc(alias = "lightdm_greeter_ensure_shared_data_dir")]
318    fn ensure_shared_data_dir<P: FnOnce(Result<glib::GString, glib::Error>) + 'static>(
319        &self,
320        username: &str,
321        cancellable: Option<&impl IsA<gio::Cancellable>>,
322        callback: P,
323    ) {
324        let main_context = glib::MainContext::ref_thread_default();
325        let is_main_context_owner = main_context.is_owner();
326        let has_acquired_main_context = (!is_main_context_owner)
327            .then(|| main_context.acquire().ok())
328            .flatten();
329        assert!(
330            is_main_context_owner || has_acquired_main_context.is_some(),
331            "Async operations only allowed if the thread is owning the MainContext"
332        );
333
334        let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
335            Box_::new(glib::thread_guard::ThreadGuard::new(callback));
336        unsafe extern "C" fn ensure_shared_data_dir_trampoline<
337            P: FnOnce(Result<glib::GString, glib::Error>) + 'static,
338        >(
339            _source_object: *mut glib::gobject_ffi::GObject,
340            res: *mut gio::ffi::GAsyncResult,
341            user_data: glib::ffi::gpointer,
342        ) {
343            unsafe {
344                let mut error = std::ptr::null_mut();
345                let ret = ffi::lightdm_greeter_ensure_shared_data_dir_finish(
346                    _source_object as *mut _,
347                    res,
348                    &mut error,
349                );
350                let result = if error.is_null() {
351                    if !ret.is_null() {
352                        Ok(from_glib_full(ret))
353                    } else {
354                        Err(glib::Error::new(
355                            GreeterError::__Unknown(13),
356                            "lightdm_greeter_ensure_shared_data_dir_finish() return null with null error",
357                        ))
358                    }
359                } else {
360                    Err(from_glib_full(error))
361                };
362                let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
363                    Box_::from_raw(user_data as *mut _);
364                let callback: P = callback.into_inner();
365                callback(result);
366            }
367        }
368        let callback = ensure_shared_data_dir_trampoline::<P>;
369        unsafe {
370            ffi::lightdm_greeter_ensure_shared_data_dir(
371                self.as_ref().to_glib_none().0,
372                username.to_glib_none().0,
373                cancellable.map(|p| p.as_ref()).to_glib_none().0,
374                Some(callback),
375                Box_::into_raw(user_data) as *mut _,
376            );
377        }
378    }
379
380    fn ensure_shared_data_dir_future(
381        &self,
382        username: &str,
383    ) -> Pin<Box_<dyn std::future::Future<Output = Result<glib::GString, glib::Error>> + 'static>>
384    {
385        let username = String::from(username);
386        Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
387            obj.ensure_shared_data_dir(&username, Some(cancellable), move |res| {
388                send.resolve(res);
389            });
390        }))
391    }
392
393    /// Ensure that a shared data dir for the given user is available.  Both the
394    /// greeter user and @username will have write access to that folder.  The
395    /// intention is that larger pieces of shared data would be stored there (files
396    /// that the greeter creates but wants to give to a user -- like camera
397    /// photos -- or files that the user creates but wants the greeter to
398    /// see -- like contact avatars).
399    ///
400    /// LightDM will automatically create these if the user actually logs in, so
401    /// greeters only need to call this method if they want to store something in
402    /// the directory themselves.
403    /// ## `username`
404    /// A username
405    ///
406    /// # Returns
407    ///
408    /// The path to the shared directory, free with g_free.
409    #[doc(alias = "lightdm_greeter_ensure_shared_data_dir_sync")]
410    fn ensure_shared_data_dir_sync(&self, username: &str) -> Result<glib::GString, glib::Error> {
411        unsafe {
412            let mut error = std::ptr::null_mut();
413            let ret = ffi::lightdm_greeter_ensure_shared_data_dir_sync(
414                self.as_ref().to_glib_none().0,
415                username.to_glib_none().0,
416                &mut error,
417            );
418            if error.is_null() {
419                if !ret.is_null() {
420                    Ok(from_glib_full(ret))
421                } else {
422                    Err(glib::Error::new(
423                        GreeterError::__Unknown(14),
424                        "lightdm_greeter_ensure_shared_data_dir_sync() return null with null error",
425                    ))
426                }
427            } else {
428                Err(from_glib_full(error))
429            }
430        }
431    }
432
433    /// Provide response to a prompt.  May be one in a series.
434    /// ## `response`
435    /// Response to a prompt
436    ///
437    /// # Returns
438    ///
439    /// #TRUE if response sent.
440    #[doc(alias = "lightdm_greeter_respond")]
441    fn respond(&self, response: &str) -> Result<(), glib::Error> {
442        unsafe {
443            let mut error = std::ptr::null_mut();
444            let is_ok = ffi::lightdm_greeter_respond(
445                self.as_ref().to_glib_none().0,
446                response.to_glib_none().0,
447                &mut error,
448            );
449            if error.is_null() {
450                if is_ok == glib::ffi::GTRUE {
451                    Ok(())
452                } else {
453                    Err(glib::Error::new(
454                        GreeterError::__Unknown(15),
455                        "lightdm_greeter_respond() return false with null error",
456                    ))
457                }
458            } else {
459                Err(from_glib_full(error))
460            }
461        }
462    }
463
464    /// Set the language for the currently authenticated user.
465    /// ## `language`
466    /// The language to use for this user in the form of a locale specification (e.g. "de_DE.UTF-8").
467    ///
468    /// # Returns
469    ///
470    /// #TRUE if set language request sent.
471    #[doc(alias = "lightdm_greeter_set_language")]
472    fn set_language(&self, language: &str) -> Result<(), glib::Error> {
473        unsafe {
474            let mut error = std::ptr::null_mut();
475            let is_ok = ffi::lightdm_greeter_set_language(
476                self.as_ref().to_glib_none().0,
477                language.to_glib_none().0,
478                &mut error,
479            );
480            if error.is_null() {
481                if is_ok == glib::ffi::GTRUE {
482                    Ok(())
483                } else {
484                    Err(glib::Error::new(
485                        GreeterError::__Unknown(16),
486                        "lightdm_greeter_set_language() return false with null error",
487                    ))
488                }
489            } else {
490                Err(from_glib_full(error))
491            }
492        }
493    }
494
495    /// Asynchronously start a session for the authenticated user.
496    ///
497    /// When the operation is finished, @callback will be invoked. You can then call lightdm_greeter_start_session_finish() to get the result of the operation.
498    ///
499    /// See lightdm_greeter_start_session_sync() for the synchronous version.
500    /// ## `session`
501    /// The session to log into or #NULL to use the default.
502    /// ## `cancellable`
503    /// A #GCancellable or [`None`].
504    /// ## `callback`
505    /// A #GAsyncReadyCallback to call when completed or [`None`].
506    #[doc(alias = "lightdm_greeter_start_session")]
507    fn start_session<P: FnOnce(Result<(), glib::Error>) + 'static>(
508        &self,
509        session: Option<&str>,
510        cancellable: Option<&impl IsA<gio::Cancellable>>,
511        callback: P,
512    ) {
513        let main_context = glib::MainContext::ref_thread_default();
514        let is_main_context_owner = main_context.is_owner();
515        let has_acquired_main_context = (!is_main_context_owner)
516            .then(|| main_context.acquire().ok())
517            .flatten();
518        assert!(
519            is_main_context_owner || has_acquired_main_context.is_some(),
520            "Async operations only allowed if the thread is owning the MainContext"
521        );
522
523        let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
524            Box_::new(glib::thread_guard::ThreadGuard::new(callback));
525        unsafe extern "C" fn start_session_trampoline<
526            P: FnOnce(Result<(), glib::Error>) + 'static,
527        >(
528            _source_object: *mut glib::gobject_ffi::GObject,
529            res: *mut gio::ffi::GAsyncResult,
530            user_data: glib::ffi::gpointer,
531        ) {
532            unsafe {
533                let mut error = std::ptr::null_mut();
534                let is_ok = ffi::lightdm_greeter_start_session_finish(
535                    _source_object as *mut _,
536                    res,
537                    &mut error,
538                );
539                let result = if error.is_null() {
540                    if is_ok == glib::ffi::GTRUE {
541                        Ok(())
542                    } else {
543                        Err(glib::Error::new(
544                            GreeterError::__Unknown(17),
545                            "lightdm_greeter_start_session_finish() return false with null error",
546                        ))
547                    }
548                } else {
549                    Err(from_glib_full(error))
550                };
551                let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
552                    Box_::from_raw(user_data as *mut _);
553                let callback: P = callback.into_inner();
554                callback(result);
555            }
556        }
557        let callback = start_session_trampoline::<P>;
558        unsafe {
559            ffi::lightdm_greeter_start_session(
560                self.as_ref().to_glib_none().0,
561                session.to_glib_none().0,
562                cancellable.map(|p| p.as_ref()).to_glib_none().0,
563                Some(callback),
564                Box_::into_raw(user_data) as *mut _,
565            );
566        }
567    }
568
569    fn start_session_future(
570        &self,
571        session: Option<&str>,
572    ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
573        let session = session.map(ToOwned::to_owned);
574        Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
575            obj.start_session(
576                session.as_ref().map(::std::borrow::Borrow::borrow),
577                Some(cancellable),
578                move |res| {
579                    send.resolve(res);
580                },
581            );
582        }))
583    }
584
585    /// Start a session for the authenticated user.
586    /// ## `session`
587    /// The session to log into or #NULL to use the default.
588    ///
589    /// # Returns
590    ///
591    /// TRUE if the session was started.
592    #[doc(alias = "lightdm_greeter_start_session_sync")]
593    fn start_session_sync(&self, session: Option<&str>) -> Result<(), glib::Error> {
594        unsafe {
595            let mut error = std::ptr::null_mut();
596            let is_ok = ffi::lightdm_greeter_start_session_sync(
597                self.as_ref().to_glib_none().0,
598                session.to_glib_none().0,
599                &mut error,
600            );
601            if error.is_null() {
602                if is_ok == glib::ffi::GTRUE {
603                    Ok(())
604                } else {
605                    Err(glib::Error::new(
606                        GreeterError::__Unknown(18),
607                        "lightdm_greeter_start_session_sync() return false with null error",
608                    ))
609                }
610            } else {
611                Err(from_glib_full(error))
612            }
613        }
614    }
615}
616
617impl<O: IsA<Greeter>> GreeterExtManual for O {}