### Configure LightDM Display Setup Script Source: https://github.com/ubuntu/lightdm/blob/main/README.md Configure LightDM to run an external shell script for display setup by specifying the script path in the `display-setup-script` key within the `[Seat:*]` section of the LightDM configuration. ```ini [Seat:*] display-setup-script=/usr/share/example_display_setup_script.sh ``` -------------------------------- ### Start User Session with LightDM Greeter Source: https://context7.com/ubuntu/lightdm/llms.txt Call `lightdm_greeter_start_session_sync` to synchronously launch the user's session. The asynchronous variant `lightdm_greeter_start_session` requires a callback function to handle completion. ```c GError *error = NULL; /* Start the user's preferred/default session */ if (!lightdm_greeter_start_session_sync (greeter, NULL, &error)) { g_warning ("start_session failed: %s", error->message); g_clear_error (&error); } /* Start a specific session type */ if (!lightdm_greeter_start_session_sync (greeter, "plasma", &error)) { g_warning ("plasma session failed: %s", error->message); g_clear_error (&error); } /* Async variant */ lightdm_greeter_start_session (greeter, "gnome", NULL /* GCancellable */, (GAsyncReadyCallback) session_started_cb, NULL); static void session_started_cb (GObject *src, GAsyncResult *res, gpointer data) { GError *err = NULL; if (!lightdm_greeter_start_session_finish (LIGHTDM_GREETER (src), res, &err)) g_warning ("Session start failed: %s", err->message); } ``` -------------------------------- ### Initiate PAM Authentication with LightDM Greeter Source: https://context7.com/ubuntu/lightdm/llms.txt Use these functions to start a PAM authentication exchange for a user, as a guest, or for autologin. The `lightdm_greeter_respond` function is used in the PAM challenge callback to provide user input. ```c GError *error = NULL; /* Authenticate a named user */ lightdm_greeter_authenticate (greeter, "alice", &error); /* Authenticate whatever user the daemon suggests (NULL = prompt for username) */ lightdm_greeter_authenticate (greeter, NULL, &error); /* Authenticate as guest */ lightdm_greeter_authenticate_as_guest (greeter, &error); /* Trigger the configured autologin immediately */ lightdm_greeter_authenticate_autologin (greeter, &error); /* Authenticate for a remote session type */ lightdm_greeter_authenticate_remote (greeter, "vnc", NULL, &error); /* In the show-prompt callback, send the user's answer */ lightdm_greeter_respond (greeter, "s3cr3t!", &error); /* Cancel an ongoing authentication (e.g., user clicked Back) */ lightdm_greeter_cancel_authentication (greeter, &error); /* Query authentication state */ gboolean in_auth = lightdm_greeter_get_in_authentication (greeter); gboolean is_authed = lightdm_greeter_get_is_authenticated (greeter); const gchar *auth_user = lightdm_greeter_get_authentication_user (greeter); ``` -------------------------------- ### Start User Session Source: https://context7.com/ubuntu/lightdm/llms.txt Tells the daemon to start the chosen session for the currently authenticated user. ```APIDOC ## `lightdm_greeter_start_session_sync` — launch user session Tells the daemon to start the chosen session for the currently authenticated user. ```c GError *error = NULL; /* Start the user's preferred/default session */ if (!lightdm_greeter_start_session_sync (greeter, NULL, &error)) { g_warning ("start_session failed: %s", error->message); g_clear_error (&error); } /* Start a specific session type */ if (!lightdm_greeter_start_session_sync (greeter, "plasma", &error)) { g_warning ("plasma session failed: %s", error->message); g_clear_error (&error); } /* Async variant */ lightdm_greeter_start_session (greeter, "gnome", NULL /* GCancellable */, (GAsyncReadyCallback) session_started_cb, NULL); static void session_started_cb (GObject *src, GAsyncResult *res, gpointer data) { GError *err = NULL; if (!lightdm_greeter_start_session_finish (LIGHTDM_GREETER (src), res, &err)) g_warning ("Session start failed: %s", err->message); } ``` ``` -------------------------------- ### LightDM Daemon Command-Line Options Source: https://context7.com/ubuntu/lightdm/llms.txt Run the LightDM daemon with various command-line options for system start, development, custom configuration, and debugging. ```bash lightdm ``` ```bash lightdm --test-mode --debug ``` ```bash lightdm --config /etc/lightdm/my-site.conf ``` ```bash lightdm --log-dir /tmp/ldm-logs --run-dir /tmp/ldm-run ``` ```bash lightdm --version ``` -------------------------------- ### Qt5 SessionsModel for Session List Management Source: https://context7.com/ubuntu/lightdm/llms.txt Use QLightDM::SessionsModel to list available local or remote sessions. Bind to UI elements to display session names and tooltips, and retrieve session keys for starting sessions via Greeter::startSessionSync. ```cpp #include // Local sessions (X11 + Wayland) QLightDM::SessionsModel localSessions(QLightDM::SessionsModel::LocalSessions); // Remote sessions QLightDM::SessionsModel remoteSessions(QLightDM::SessionsModel::RemoteSessions); for (int i = 0; i < localSessions.rowCount(QModelIndex()); ++i) { QModelIndex idx = localSessions.index(i, 0); QString name = localSessions.data(idx, Qt::DisplayRole).toString(); QString key = localSessions.data(idx, QLightDM::SessionsModel::KeyRole).toString(); QString comment = localSessions.data(idx, Qt::ToolTipRole).toString(); QString type = localSessions.data(idx, QLightDM::SessionsModel::TypeRole).toString(); qDebug() << "Session:" << name << "key:" << key << "type:" << type; } // Use KeyRole value with Greeter::startSessionSync greeter.startSessionSync(chosenKey); ``` -------------------------------- ### lightdm_greeter_set_language Source: https://context7.com/ubuntu/lightdm/llms.txt Instructs the LightDM daemon which locale to use when starting a user session. This should be called before starting the session. ```APIDOC ## `lightdm_greeter_set_language` — set session language Instructs the daemon which locale to use when starting the session. ```c GError *error = NULL; if (!lightdm_greeter_set_language (greeter, "fr_FR.UTF-8", &error)) { g_warning ("set_language failed: %s", error->message); g_clear_error (&error); } /* Then start the session */ lightdm_greeter_start_session_sync (greeter, NULL, NULL); ``` ``` -------------------------------- ### Test LightDM in Debug Mode Source: https://github.com/ubuntu/lightdm/blob/main/README.md To test LightDM configuration, install `xserver-xephyr` and run LightDM in test mode as the 'lightdm' user with debugging enabled. ```bash sudo apt install xserver-xephyr sudo -u lightdm lightdm --test-mode --debug ``` -------------------------------- ### LightDM User List Configuration (`users.conf`) Source: https://context7.com/ubuntu/lightdm/llms.txt Configure which users are displayed in the greeter when AccountsService is not installed. This file controls user visibility based on UID and shell. ```ini [UserList] # Minimum UID to display minimum-uid=500 # Usernames never shown hidden-users=nobody nobody4 noaccess # Login shells that indicate a non-login account hidden-shells=/bin/false /usr/sbin/nologin /sbin/nologin ``` -------------------------------- ### Set Session Language Source: https://context7.com/ubuntu/lightdm/llms.txt Instructs the LightDM daemon which locale to use when starting a user's session. This should be called before starting the session. ```c GError *error = NULL; if (!lightdm_greeter_set_language (greeter, "fr_FR.UTF-8", &error)) { g_warning ("set_language failed: %s", error->message); g_clear_error (&error); } /* Then start the session */ lightdm_greeter_start_session_sync (greeter, NULL, NULL); ``` -------------------------------- ### Enumerate and Get Available Locales (C) Source: https://context7.com/ubuntu/lightdm/llms.txt Retrieves a list of all available system locales and prints their code, name, and territory. Also shows how to get the currently active language and check if a language object matches a specific code string. ```c /* All available languages */ GList *langs = lightdm_get_languages (); for (GList *l = langs; l != NULL; l = l->next) { LightDMLanguage *lang = LIGHTDM_LANGUAGE (l->data); g_print ("code=%-15s name=%-20s territory=%s\n", lightdm_language_get_code (lang), lightdm_language_get_name (lang), lightdm_language_get_territory (lang)); } /* Currently active language */ LightDMLanguage *current = lightdm_get_language (); if (current) g_print ("Current: %s\n", lightdm_language_get_code (current)); /* Check whether a language object matches a code string */ gboolean match = lightdm_language_matches (current, "en_US.UTF-8"); ``` -------------------------------- ### Get Available Session Types Source: https://context7.com/ubuntu/lightdm/llms.txt Enumerates available desktop session types by scanning configured .desktop files. Supports both local (X11/Wayland) and remote sessions. ```c /* Local sessions (X11 + Wayland) */ GList *sessions = lightdm_get_sessions (); for (GList *l = sessions; l != NULL; l = l->next) { LightDMSession *s = LIGHTDM_SESSION (l->data); g_print ("key=%-15s type=%-8s name=%s\n", lightdm_session_get_key (s), lightdm_session_get_session_type (s), lightdm_session_get_name (s)); /* lightdm_session_get_comment(s) → Description field from .desktop */ } /* Remote sessions */ GList *remote = lightdm_get_remote_sessions (); for (GList *l = remote; l != NULL; l = l->next) { LightDMSession *s = LIGHTDM_SESSION (l->data); g_print ("remote: %s\n", lightdm_session_get_key (s)); } ``` -------------------------------- ### Override System Default Session in LightDM Source: https://github.com/ubuntu/lightdm/blob/main/README.md To override the system-configured default session, create a configuration file in `/etc/lightdm/lightdm.conf.d/`. This example sets the user session to 'mysession'. ```ini [Seat:*] user-session=mysession ``` -------------------------------- ### Initialize LightDM Greeter and Connect Synchronously Source: https://context7.com/ubuntu/lightdm/llms.txt Use this for greeter initialization and synchronous connection to the LightDM daemon. It sets up signal handlers for user prompts, messages, and authentication completion, then initiates the authentication process. ```c #include #include static GMainLoop *loop; static LightDMGreeter *greeter; static void show_prompt_cb (LightDMGreeter *greeter, const gchar *text, LightDMPromptType type, gpointer user_data) { /* type == LIGHTDM_PROMPT_TYPE_SECRET → hide input */ gchar *response = collect_user_input (text, type == LIGHTDM_PROMPT_TYPE_SECRET); GError *error = NULL; if (!lightdm_greeter_respond (greeter, response, &error)) { g_warning ("respond failed: %s", error->message); g_clear_error (&error); } g_free (response); } static void show_message_cb (LightDMGreeter *greeter, const gchar *text, LightDMMessageType type, gpointer user_data) { /* LIGHTDM_MESSAGE_TYPE_ERROR → show red; INFO → show normal */ display_message (text, type); } static void authentication_complete_cb (LightDMGreeter *greeter, gpointer user_data) { GError *error = NULL; if (!lightdm_greeter_get_is_authenticated (greeter)) { /* Wrong password — restart authentication */ lightdm_greeter_authenticate (greeter, NULL, &error); return; } /* Start the default session for the authenticated user */ if (!lightdm_greeter_start_session_sync (greeter, NULL, &error)) { g_warning ("session start failed: %s", error->message); g_clear_error (&error); } } int main (int argc, char **argv) { loop = g_main_loop_new (NULL, FALSE); greeter = lightdm_greeter_new (); /* Wire up signals */ g_signal_connect (greeter, LIGHTDM_GREETER_SIGNAL_SHOW_PROMPT, G_CALLBACK (show_prompt_cb), NULL); g_signal_connect (greeter, LIGHTDM_GREETER_SIGNAL_SHOW_MESSAGE, G_CALLBACK (show_message_cb), NULL); g_signal_connect (greeter, LIGHTDM_GREETER_SIGNAL_AUTHENTICATION_COMPLETE, G_CALLBACK (authentication_complete_cb), NULL); /* Synchronous connect — blocks until the daemon responds */ GError *error = NULL; if (!lightdm_greeter_connect_to_daemon_sync (greeter, &error)) { g_error ("Cannot connect to LightDM: %s", error->message); } /* Read daemon hints */ const gchar *default_session = lightdm_greeter_get_default_session_hint (greeter); const gchar *select_user = lightdm_greeter_get_select_user_hint (greeter); gboolean has_guest = lightdm_greeter_get_has_guest_account_hint (greeter); gboolean hide_users = lightdm_greeter_get_hide_users_hint (greeter); gint autologin_to = lightdm_greeter_get_autologin_timeout_hint (greeter); g_print ("Default session: %s\n", default_session ? default_session : "(none)"); /* Begin authentication for the pre-selected user (or NULL for manual entry) */ lightdm_greeter_authenticate (greeter, select_user, &error); g_main_loop_run (loop); return 0; } ``` -------------------------------- ### Qt5 Greeter Implementation with QLightDM::Greeter Source: https://context7.com/ubuntu/lightdm/llms.txt Implement a custom greeter by subclassing QLightDM::Greeter. Connect to signals for user prompts and messages, and override slots to handle authentication and session startup. Ensure connection to the LightDM daemon is successful before proceeding. ```cpp #include #include #include #include #include class MyGreeter : public QLightDM::Greeter { Q_OBJECT public: MyGreeter() { connect(this, &Greeter::showPrompt, this, &MyGreeter::onShowPrompt); connect(this, &Greeter::showMessage, this, &MyGreeter::onShowMessage); connect(this, &Greeter::authenticationComplete, this, &MyGreeter::onAuthComplete); } private Q_SLOTS: void onShowPrompt(QString text, QLightDM::Greeter::PromptType type) { bool secret = (type == QLightDM::Greeter::PromptTypeSecret); QString response = collectInput(text, secret); respond(response); } void onShowMessage(QString text, QLightDM::Greeter::MessageType type) { if (type == QLightDM::Greeter::MessageTypeError) showErrorDialog(text); else showInfoBanner(text); } void onAuthComplete() { if (!isAuthenticated()) { authenticate(); // retry return; } startSessionSync(); // use default session } }; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); MyGreeter greeter; if (!greeter.connectSync()) { qWarning("Cannot connect to LightDM daemon"); return 1; } // Read hints qDebug() << "Hostname:" << greeter.hostname(); qDebug() << "OS:" << greeter.osPrettyName(); qDebug() << "Default session:" << greeter.defaultSessionHint(); qDebug() << "Lock hint:" << greeter.lockHint(); // Start authentication greeter.authenticate(greeter.selectUserHint()); return app.exec(); } ``` -------------------------------- ### Create Per-User Shared Data Directory (Sync/Async) Source: https://context7.com/ubuntu/lightdm/llms.txt Ensures a directory writable by both the greeter and the user's session exists. Useful for passing greeter configurations to the session. Handles synchronous and asynchronous creation. ```c GError *error = NULL; /* Synchronous */ gchar *dir = lightdm_greeter_ensure_shared_data_dir_sync (greeter, "alice", &error); if (!dir) { g_warning ("shared data dir error: %s", error->message); } else { gchar *path = g_build_filename (dir, "greeter-settings", NULL); g_file_set_contents (path, "theme=dark", -1, NULL); g_free (path); g_free (dir); } /* Async */ lightdm_greeter_ensure_shared_data_dir (greeter, "alice", NULL, (GAsyncReadyCallback) shared_dir_cb, NULL); static void shared_dir_cb (GObject *src, GAsyncResult *res, gpointer data) { GError *err = NULL; g_autofree gchar *dir = lightdm_greeter_ensure_shared_data_dir_finish (LIGHTDM_GREETER (src), res, &err); if (dir) write_settings (dir); } ``` -------------------------------- ### LightDM Daemon Configuration (`lightdm.conf`) Source: https://context7.com/ubuntu/lightdm/llms.txt Configure the LightDM daemon, seats, XDMCP, and VNC server using keyfile format. Settings are merged from multiple directories. ```ini [LightDM] # Always start one seat even if none defined in config start-default-seat=true # User that greeters run as greeter-user=lightdm # First VT to use minimum-vt=7 # Prevent memory paging to disk lock-memory=true # Directories log-directory=/var/log/lightdm run-directory=/var/run/lightdm cache-directory=/var/cache/lightdm sessions-directory=/usr/share/lightdm/sessions:/usr/share/xsessions:/usr/share/wayland-sessions greeters-directory=$XDG_DATA_DIRS/lightdm/greeters:$XDG_DATA_DIRS/xgreeters # Enable D-Bus control interface dbus-service=true # [Seat:*] applies to all seats; [Seat:seat0] overrides for seat0 only [Seat:*] # PAM services pam-service=lightdm pam-autologin-service=lightdm-autologin pam-greeter-service=lightdm-greeter # Which greeter to run greeter-session=lightdm-gtk-greeter # Which session to start for users user-session=default # Autologin (bypass greeter entirely) autologin-user=alice autologin-user-timeout=0 autologin-session=gnome # Guest sessions allow-guest=true greeter-allow-guest=true # Hide the user list in the greeter greeter-hide-users=false greeter-show-manual-login=false # Scripts run as root at key lifecycle points display-setup-script=/usr/share/setup-display.sh session-setup-script=/usr/share/setup-session.sh session-cleanup-script=/usr/share/cleanup-session.sh # X server options xserver-allow-tcp=false xserver-command=X [XDMCPServer] enabled=false port=177 # key= references a 56-bit DES key in /etc/lightdm/keys.conf [VNCServer] enabled=false command=Xvnc port=5900 width=1024 height=768 depth=24 ``` -------------------------------- ### lightdm_greeter_new / lightdm_greeter_connect_to_daemon_sync Source: https://context7.com/ubuntu/lightdm/llms.txt Initializes the LightDMGreeter GObject and synchronously connects to the LightDM daemon. This function is suitable for greeter processes that can block during initialization. ```APIDOC ## `lightdm_greeter_new` / `lightdm_greeter_connect_to_daemon_sync` — GObject greeter initialization `LightDMGreeter` is the central GObject for a greeter process. It connects to the LightDM daemon over a Unix socket, exposes daemon hints, and drives the PAM authentication conversation. ```c #include #include static GMainLoop *loop; static LightDMGreeter *greeter; static void show_prompt_cb (LightDMGreeter *greeter, const gchar *text, LightDMPromptType type, gpointer user_data) { /* type == LIGHTDM_PROMPT_TYPE_SECRET → hide input */ gchar *response = collect_user_input (text, type == LIGHTDM_PROMPT_TYPE_SECRET); GError *error = NULL; if (!lightdm_greeter_respond (greeter, response, &error)) { g_warning ("respond failed: %s", error->message); g_clear_error (&error); } g_free (response); } static void show_message_cb (LightDMGreeter *greeter, const gchar *text, LightDMMessageType type, gpointer user_data) { /* LIGHTDM_MESSAGE_TYPE_ERROR → show red; INFO → show normal */ display_message (text, type); } static void authentication_complete_cb (LightDMGreeter *greeter, gpointer user_data) { GError *error = NULL; if (!lightdm_greeter_get_is_authenticated (greeter)) { /* Wrong password — restart authentication */ lightdm_greeter_authenticate (greeter, NULL, &error); return; } /* Start the default session for the authenticated user */ if (!lightdm_greeter_start_session_sync (greeter, NULL, &error)) { g_warning ("session start failed: %s", error->message); g_clear_error (&error); } } int main (int argc, char **argv) { loop = g_main_loop_new (NULL, FALSE); greeter = lightdm_greeter_new (); /* Wire up signals */ g_signal_connect (greeter, LIGHTDM_GREETER_SIGNAL_SHOW_PROMPT, G_CALLBACK (show_prompt_cb), NULL); g_signal_connect (greeter, LIGHTDM_GREETER_SIGNAL_SHOW_MESSAGE, G_CALLBACK (show_message_cb), NULL); g_signal_connect (greeter, LIGHTDM_GREETER_SIGNAL_AUTHENTICATION_COMPLETE, G_CALLBACK (authentication_complete_cb), NULL); /* Synchronous connect — blocks until the daemon responds */ GError *error = NULL; if (!lightdm_greeter_connect_to_daemon_sync (greeter, &error)) { g_error ("Cannot connect to LightDM: %s", error->message); } /* Read daemon hints */ const gchar *default_session = lightdm_greeter_get_default_session_hint (greeter); const gchar *select_user = lightdm_greeter_get_select_user_hint (greeter); gboolean has_guest = lightdm_greeter_get_has_guest_account_hint (greeter); gboolean hide_users = lightdm_greeter_get_hide_users_hint (greeter); gint autologin_to = lightdm_greeter_get_autologin_timeout_hint (greeter); g_print ("Default session: %s\n", default_session ? default_session : "(none)"); /* Begin authentication for the pre-selected user (or NULL for manual entry) */ lightdm_greeter_authenticate (greeter, select_user, &error); g_main_loop_run (loop); return 0; } ``` ``` -------------------------------- ### Qt5 Power Management with QLightDM Source: https://context7.com/ubuntu/lightdm/llms.txt Use QLightDM::PowerInterface to check power management capabilities like suspend, hibernate, restart, and shutdown. Invoke these actions using the respective methods. Ensure the QLightDM library is included. ```cpp #include QLightDM::PowerInterface power; // Check capabilities if (power.canSuspend()) showButton("Suspend"); if (power.canHibernate()) showButton("Hibernate"); if (power.canRestart()) showButton("Restart"); if (power.canShutdown()) showButton("Shutdown"); // Invoke if (!power.restart()) qWarning("Restart failed"); if (!power.shutdown()) qWarning("Shutdown failed"); if (!power.suspend()) qWarning("Suspend failed"); if (!power.hibernate())qWarning("Hibernate failed"); ``` -------------------------------- ### Enumerate and Set Keyboard Layouts (C) Source: https://context7.com/ubuntu/lightdm/llms.txt Lists all available keyboard layouts and demonstrates how to retrieve the currently active layout and set a new layout. Requires a helper function `find_layout_by_name` which is not provided. ```c /* All layouts */ GList *layouts = lightdm_get_layouts (); for (GList *l = layouts; l != NULL; l = l->next) { LightDMLayout *layout = LIGHTDM_LAYOUT (l->data); g_print ("name=%-20s short=%-6s desc=%s\n", lightdm_layout_get_name (layout), lightdm_layout_get_short_description (layout), lightdm_layout_get_description (layout)); } /* Current layout */ LightDMLayout *current = lightdm_get_layout (); g_print ("Active layout: %s\n", lightdm_layout_get_name (current)); /* Set layout (e.g., user selected "de" from a dropdown) */ LightDMLayout *de_layout = find_layout_by_name (layouts, "de"); if (de_layout) lightdm_set_layout (de_layout); ``` -------------------------------- ### Connect to LightDM Daemon Asynchronously Source: https://context7.com/ubuntu/lightdm/llms.txt This snippet demonstrates the non-blocking, asynchronous connection to the LightDM daemon using the GIO async pattern. It's preferred for UI greeters to keep the event loop responsive. ```c static void connect_finished (GObject *source, GAsyncResult *result, gpointer user_data) { LightDMGreeter *greeter = LIGHTDM_GREETER (source); GError *error = NULL; if (!lightdm_greeter_connect_to_daemon_finish (greeter, result, &error)) { g_warning ("Connect failed: %s", error->message); g_clear_error (&error); g_main_loop_quit (loop); return; } /* Now safe to call authenticate / read hints */ lightdm_greeter_authenticate (greeter, NULL, NULL); } /* Kick off the async connect */ lightdm_greeter_connect_to_daemon (greeter, NULL /* GCancellable */, connect_finished, NULL /* user_data */); ``` -------------------------------- ### lightdm_greeter_connect_to_daemon Source: https://context7.com/ubuntu/lightdm/llms.txt Asynchronously connects to the LightDM daemon using the GIO async pattern. This non-blocking variant is preferred for UI greeters to keep the event loop responsive. ```APIDOC ## `lightdm_greeter_connect_to_daemon` — async daemon connection Non-blocking variant using GIO async pattern; preferred in UI greeters to avoid blocking the event loop. ```c static void connect_finished (GObject *source, GAsyncResult *result, gpointer user_data) { LightDMGreeter *greeter = LIGHTDM_GREETER (source); GError *error = NULL; if (!lightdm_greeter_connect_to_daemon_finish (greeter, result, &error)) { g_warning ("Connect failed: %s", error->message); g_clear_error (&error); g_main_loop_quit (loop); return; } /* Now safe to call authenticate / read hints */ lightdm_greeter_authenticate (greeter, NULL, NULL); } /* Kick off the async connect */ lightdm_greeter_connect_to_daemon (greeter, NULL /* GCancellable */, connect_finished, NULL /* user_data */); ``` ``` -------------------------------- ### dm-tool: Add and Connect Seats Source: https://context7.com/ubuntu/lightdm/llms.txt Manage display manager seats with `dm-tool`. Add dynamic seats, nested seats for testing, or connect existing X servers. ```bash # Add a dynamic seat dm-tool add-seat x11 xserver-command="X :2" ``` ```bash # Nest an X server inside an existing session (useful for testing) dm-tool add-nested-seat ``` ```bash # Connect an already-running X server to LightDM dm-tool add-local-x-seat 2 # connects :2 ``` -------------------------------- ### Power Management API (C) Source: https://context7.com/ubuntu/lightdm/llms.txt Queries system capabilities for suspend, hibernate, restart, and shutdown, and demonstrates how to invoke these power state transitions. Operations are performed via D-Bus and require error handling. ```c /* Query capabilities */ if (lightdm_get_can_suspend ()) { /* show Suspend button */ } if (lightdm_get_can_hibernate ()) { /* show Hibernate button */ } if (lightdm_get_can_restart ()) { /* show Restart button */ } if (lightdm_get_can_shutdown ()) { /* show Shutdown button */ } /* Perform actions */ GError *error = NULL; if (!lightdm_suspend (&error)) { g_warning ("Suspend failed: %s", error->message); g_clear_error (&error); } if (!lightdm_hibernate (&error)) { g_warning ("Hibernate failed: %s", error->message); g_clear_error (&error); } if (!lightdm_restart (&error)) { g_warning ("Restart failed: %s", error->message); g_clear_error (&error); } if (!lightdm_shutdown (&error)) { g_warning ("Shutdown failed: %s", error->message); g_clear_error (&error); } ``` -------------------------------- ### Python Greeter with GObject Introspection Source: https://context7.com/ubuntu/lightdm/llms.txt Develop Python greeters using `gi.repository.LightDM` for interacting with the LightDM daemon. Connect to events like 'show-prompt', 'show-message', and 'authentication-complete'. Requires Python 3 and GObject introspection bindings for LightDM. ```python #!/usr/bin/python3 from gi.repository import GLib, LightDM loop = GLib.MainLoop() def show_prompt_cb(greeter, text, prompt_type): # Collect and respond secret = (prompt_type == LightDM.PromptType.SECRET) response = collect_input(text, secret) greeter.respond(response) def show_message_cb(greeter, text, msg_type): print(f"[{'ERROR' if msg_type == LightDM.MessageType.ERROR else 'INFO'}] {text}") def authentication_complete_cb(greeter): if not greeter.get_is_authenticated(): greeter.authenticate(None) # retry return try: greeter.start_session_sync(None) # default session except GLib.Error as e: print(f"Session failed: {e.message}") greeter = LightDM.Greeter() greeter.connect('show-prompt', show_prompt_cb) greeter.connect('show-message', show_message_cb) greeter.connect('authentication-complete', authentication_complete_cb) try: greeter.connect_to_daemon_sync() except GLib.Error as e: print(f"Cannot connect: {e.message}") exit(1) # Read daemon hints default_session = greeter.get_default_session_hint() select_user = greeter.get_select_user_hint() autologin_to = greeter.get_autologin_timeout_hint() has_guest = greeter.get_has_guest_account_hint() # User list user_list = LightDM.UserList.get_instance() for user in user_list.get_users(): print(user.get_name(), user.get_display_name(), user.get_session()) # Session list for session in sorted(LightDM.get_sessions(), key=lambda s: s.get_key()): print(session.get_key(), session.get_name()) # Power if LightDM.get_can_shutdown(): LightDM.shutdown() # Language for lang in LightDM.get_languages(): print(lang.get_code(), lang.get_name()) # Layout current_layout = LightDM.get_layout() print("Layout:", current_layout.get_name()) greeter.authenticate(select_user) loop.run() ``` -------------------------------- ### Keyboard Layout Management Source: https://context7.com/ubuntu/lightdm/llms.txt Enumerates available keyboard layouts and sets the active layout for the greeter. ```APIDOC ## `lightdm_get_layouts` / `lightdm_set_layout` — keyboard layout (GObject) Enumerates keyboard layouts via libxklavier and sets the active layout for the greeter. ### Description These functions allow retrieval and setting of keyboard layouts. ### `lightdm_get_layouts` #### Method `lightdm_get_layouts` #### Parameters None #### Response - `GList*`: A list of `LightDMLayout` objects representing available keyboard layouts. ### `lightdm_set_layout` #### Method `lightdm_set_layout` #### Parameters - **layout** (`LightDMLayout*`) - The layout object to set as active. #### Response None ### Example ```c /* All layouts */ GList *layouts = lightdm_get_layouts (); for (GList *l = layouts; l != NULL; l = l->next) { LightDMLayout *layout = LIGHTDM_LAYOUT (l->data); g_print ("name=%-20s short=%-6s desc=%s\n", lightdm_layout_get_name (layout), lightdm_layout_get_short_description (layout), lightdm_layout_get_description (layout)); } /* Current layout */ LightDMLayout *current = lightdm_get_layout (); g_print ("Active layout: %s\n", lightdm_layout_get_name (current)); /* Set layout (e.g., user selected "de" from a dropdown) */ LightDMLayout *de_layout = find_layout_by_name (layouts, "de"); if (de_layout) lightdm_set_layout (de_layout); ``` ``` -------------------------------- ### Qt5 QLightDM::PowerInterface Source: https://context7.com/ubuntu/lightdm/llms.txt Provides a Qt wrapper for power management operations like suspend, hibernate, restart, and shutdown. ```APIDOC ## Qt5 `QLightDM::PowerInterface` — power management Qt wrapper around the same logind/UPower D-Bus calls as the GObject API. ```cpp #include QLightDM::PowerInterface power; // Check capabilities if (power.canSuspend()) showButton("Suspend"); if (power.canHibernate()) showButton("Hibernate"); if (power.canRestart()) showButton("Restart"); if (power.canShutdown()) showButton("Shutdown"); // Invoke if (!power.restart()) qWarning("Restart failed"); if (!power.shutdown()) qWarning("Shutdown failed"); if (!power.suspend()) qWarning("Suspend failed"); if (!power.hibernate())qWarning("Hibernate failed"); ``` ``` -------------------------------- ### PAM Authentication Conversation Source: https://context7.com/ubuntu/lightdm/llms.txt Initiates and drives a PAM authentication exchange. The daemon emits `show-prompt` for each PAM challenge; the greeter collects user input and calls `respond`. After all PAM modules finish, `authentication-complete` fires. ```APIDOC ## `lightdm_greeter_authenticate` / `lightdm_greeter_respond` — PAM authentication conversation Initiates and drives a PAM authentication exchange. The daemon emits `show-prompt` for each PAM challenge; the greeter collects user input and calls `respond`. After all PAM modules finish, `authentication-complete` fires. ```c GError *error = NULL; /* Authenticate a named user */ lightdm_greeter_authenticate (greeter, "alice", &error); /* Authenticate whatever user the daemon suggests (NULL = prompt for username) */ lightdm_greeter_authenticate (greeter, NULL, &error); /* Authenticate as guest */ lightdm_greeter_authenticate_as_guest (greeter, &error); /* Trigger the configured autologin immediately */ lightdm_greeter_authenticate_autologin (greeter, &error); /* Authenticate for a remote session type */ lightdm_greeter_authenticate_remote (greeter, "vnc", NULL, &error); /* In the show-prompt callback, send the user's answer */ lightdm_greeter_respond (greeter, "s3cr3t!", &error); /* Cancel an ongoing authentication (e.g., user clicked Back) */ lightdm_greeter_cancel_authentication (greeter, &error); /* Query authentication state */ gboolean in_auth = lightdm_greeter_get_in_authentication (greeter); gboolean is_authed = lightdm_greeter_get_is_authenticated (greeter); const gchar *auth_user = lightdm_greeter_get_authentication_user (greeter); ``` ``` -------------------------------- ### System Information API (C) Source: https://context7.com/ubuntu/lightdm/llms.txt Retrieves system information including hostname, OS identification details (ID, name, version), and the message of the day (MOTD). The MOTD string is dynamically allocated and must be freed by the caller. ```c const gchar *hostname = lightdm_get_hostname (); const gchar *os_id = lightdm_get_os_id (); /* e.g. "ubuntu" */ const gchar *os_name = lightdm_get_os_name (); /* e.g. "Ubuntu" */ const gchar *os_pretty = lightdm_get_os_pretty_name (); /* e.g. "Ubuntu 24.04 LTS" */ const gchar *os_version = lightdm_get_os_version (); /* e.g. "24.04 LTS" */ const gchar *os_ver_id = lightdm_get_os_version_id (); /* e.g. "24.04" */ gchar *motd = lightdm_get_motd (); /* caller frees */ g_print ("Welcome to %s on %s\n", os_pretty, hostname); if (motd && *motd) g_print ("%s\n", motd); g_free (motd); ``` -------------------------------- ### dm-tool: Session Bus Connection Source: https://context7.com/ubuntu/lightdm/llms.txt Connect to the session bus with `dm-tool` for interacting with a test-mode LightDM instance. ```bash # Connect via session bus (for test-mode LightDM) dm-tool --session-bus list-seats ``` -------------------------------- ### Configure and Handle Resettable Greeter Signals Source: https://context7.com/ubuntu/lightdm/llms.txt Enable resettable greeter behavior by calling `lightdm_greeter_set_resettable` before connecting to the daemon. Connect to the `idle` and `reset` signals to manage the greeter's state when sessions end or a new login is required. ```c /* Opt in to being resettable before connecting */ lightdm_greeter_set_resettable (greeter, TRUE); g_signal_connect (greeter, LIGHTDM_GREETER_SIGNAL_IDLE, G_CALLBACK (idle_cb), NULL); g_signal_connect (greeter, LIGHTDM_GREETER_SIGNAL_RESET, G_CALLBACK (reset_cb), NULL); lightdm_greeter_connect_to_daemon_sync (greeter, NULL); static void idle_cb (LightDMGreeter *greeter, gpointer data) { /* All sessions ended — hide UI, dim screen, etc. */ show_idle_screen (); } static void reset_cb (LightDMGreeter *greeter, gpointer data) { /* New login required — re-read hints, reset UI */ const gchar *user = lightdm_greeter_get_select_user_hint (greeter); reset_login_form (user); } ``` -------------------------------- ### lightdm_get_sessions Source: https://context7.com/ubuntu/lightdm/llms.txt Enumerates available desktop session types by discovering `.desktop` files in configured sessions directories. It can list both local (X11/Wayland) and remote sessions. ```APIDOC ## `lightdm_get_sessions` / `LightDMSession` — available session types (GObject) Enumerates desktop session types discovered from `.desktop` files in the configured sessions directories. ```c /* Local sessions (X11 + Wayland) */ GList *sessions = lightdm_get_sessions (); for (GList *l = sessions; l != NULL; l = l->next) { LightDMSession *s = LIGHTDM_SESSION (l->data); g_print ("key=%-15s type=%-8s name=%s\n", lightdm_session_get_key (s), lightdm_session_get_session_type (s), lightdm_session_get_name (s)); /* lightdm_session_get_comment(s) → Description field from .desktop */ } /* Remote sessions */ GList *remote = lightdm_get_remote_sessions (); for (GList *l = remote; l != NULL; l = l->next) { LightDMSession *s = LIGHTDM_SESSION (l->data); g_print ("remote: %s\n", lightdm_session_get_key (s)); } ``` ``` -------------------------------- ### Qt5 UsersModel for User List Management Source: https://context7.com/ubuntu/lightdm/llms.txt Utilize QLightDM::UsersModel as a QAbstractListModel to display user information in QML or Qt Widgets. Access user details like name, real name, session, and login status using specific roles. ```cpp #include #include QLightDM::UsersModel users; int count = users.rowCount(QModelIndex()); qDebug() << "Users:" << count; for (int i = 0; i < count; ++i) { QModelIndex idx = users.index(i, 0); QString name = users.data(idx, QLightDM::UsersModel::NameRole).toString(); QString realName = users.data(idx, QLightDM::UsersModel::RealNameRole).toString(); QString session = users.data(idx, QLightDM::UsersModel::SessionRole).toString(); QString imagePath = users.data(idx, QLightDM::UsersModel::ImagePathRole).toString(); QString background = users.data(idx, QLightDM::UsersModel::BackgroundPathRole).toString(); bool loggedIn = users.data(idx, QLightDM::UsersModel::LoggedInRole).toBool(); bool locked = users.data(idx, QLightDM::UsersModel::IsLockedRole).toBool(); bool hasMsgs = users.data(idx, QLightDM::UsersModel::HasMessagesRole).toBool(); uint uid = users.data(idx, QLightDM::UsersModel::UidRole).toUInt(); qDebug() << name << realName << "session:" << session << "loggedIn:" << loggedIn << "uid:" << uid; } // In QML: model: usersModel → delegate accesses model.display (name), model.decoration, etc. ``` -------------------------------- ### Enumerate and Monitor Users Source: https://context7.com/ubuntu/lightdm/llms.txt Provides access to user information and allows monitoring of user list changes. Uses GObject for user representation and signals for change notifications. ```c /* Get the singleton */ LightDMUserList *user_list = lightdm_user_list_get_instance (); /* Total number of displayable users */ gint n = lightdm_user_list_get_length (user_list); g_print ("Users: %d\n", n); /* Iterate all users */ GList *users = lightdm_user_list_get_users (user_list); for (GList *l = users; l != NULL; l = l->next) { LightDMUser *u = LIGHTDM_USER (l->data); g_print (" %s (%s) logged_in=%s locked=%s\n", lightdm_user_get_name (u), lightdm_user_get_display_name (u), lightdm_user_get_logged_in (u) ? "yes" : "no", lightdm_user_get_is_locked (u) ? "yes" : "no"); g_print (" home=%s image=%s session=%s lang=%s layout=%s\n", lightdm_user_get_home_directory (u), lightdm_user_get_image (u), lightdm_user_get_session (u), lightdm_user_get_language (u), lightdm_user_get_layout (u)); } /* Look up one user */ LightDMUser *alice = lightdm_user_list_get_user_by_name (user_list, "alice"); uid_t uid = lightdm_user_get_uid (alice); /* Monitor changes */ g_signal_connect (user_list, LIGHTDM_USER_LIST_SIGNAL_USER_ADDED, G_CALLBACK (user_added_cb), NULL); g_signal_connect (user_list, LIGHTDM_USER_LIST_SIGNAL_USER_CHANGED, G_CALLBACK (user_changed_cb), NULL); g_signal_connect (user_list, LIGHTDM_USER_LIST_SIGNAL_USER_REMOVED, G_CALLBACK (user_removed_cb), NULL); /* Watch a single user for changes */ g_signal_connect (alice, LIGHTDM_SIGNAL_USER_CHANGED, G_CALLBACK (user_changed_cb), NULL); ``` -------------------------------- ### Python (GObject introspection) greeter Source: https://context7.com/ubuntu/lightdm/llms.txt Utilizes LightDM's GObject library via `gi.repository.LightDM` for Python greeter applications. ```APIDOC ## Python (GObject introspection) greeter LightDM's GObject library is fully introspectable. Python greeters use the same API surface via `gi.repository.LightDM`. ```python #!/usr/bin/python3 from gi.repository import GLib, LightDM loop = GLib.MainLoop() def show_prompt_cb(greeter, text, prompt_type): # Collect and respond secret = (prompt_type == LightDM.PromptType.SECRET) response = collect_input(text, secret) greeter.respond(response) def show_message_cb(greeter, text, msg_type): print(f"[{'ERROR' if msg_type == LightDM.MessageType.ERROR else 'INFO'}] {text}") def authentication_complete_cb(greeter): if not greeter.get_is_authenticated(): greeter.authenticate(None) # retry return try: greeter.start_session_sync(None) # default session except GLib.Error as e: print(f"Session failed: {e.message}") greeter = LightDM.Greeter() greeter.connect('show-prompt', show_prompt_cb) greeter.connect('show-message', show_message_cb) greeter.connect('authentication-complete', authentication_complete_cb) try: greeter.connect_to_daemon_sync() except GLib.Error as e: print(f"Cannot connect: {e.message}") exit(1) # Read daemon hints default_session = greeter.get_default_session_hint() select_user = greeter.get_select_user_hint() autologin_to = greeter.get_autologin_timeout_hint() has_guest = greeter.get_has_guest_account_hint() # User list user_list = LightDM.UserList.get_instance() for user in user_list.get_users(): print(user.get_name(), user.get_display_name(), user.get_session()) # Session list for session in sorted(LightDM.get_sessions(), key=lambda s: s.get_key()): print(session.get_key(), session.get_name()) # Power if LightDM.get_can_shutdown(): LightDM.shutdown() # Language for lang in LightDM.get_languages(): print(lang.get_code(), lang.get_name()) # Layout current_layout = LightDM.get_layout() print("Layout:", current_layout.get_name()) greeter.authenticate(select_user) loop.run() ``` ```