aboutsummaryrefslogtreecommitdiffstats
path: root/src/callbacks.c
diff options
context:
space:
mode:
authorSpacedio <spacedio@thernusen.net>2026-02-26 19:20:14 -0500
committerSpacedio <spacedio@thernusen.net>2026-02-26 19:20:14 -0500
commitdb657412e6ae93341ed42d59df6aef564a739a1f (patch)
tree6f67f55f6dc61fb0afa8829a950f0dbf1a0aeadf /src/callbacks.c
downloadlightdm-mini-greeter-db657412e6ae93341ed42d59df6aef564a739a1f.tar.gz
Initial commit after cloneHEADmaster
Diffstat (limited to 'src/callbacks.c')
-rw-r--r--src/callbacks.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/src/callbacks.c b/src/callbacks.c
new file mode 100644
index 0000000..7cefa42
--- /dev/null
+++ b/src/callbacks.c
@@ -0,0 +1,152 @@
+/* Callback Functions for LightDM & GTK */
+#include <gtk/gtk.h>
+#include <lightdm.h>
+#include <string.h>
+#include <time.h>
+
+#include "app.h"
+#include "utils.h"
+#include "focus_ring.h"
+#include "callbacks.h"
+#include "compat.h"
+
+static void set_ui_feedback_label(App *app, gchar *feedback_text);
+
+
+/* LightDM Callbacks */
+
+/* Start the Selected Session Once Fully Authenticated.
+ *
+ * The callback will clear & re-enable the input widget, and re-add the
+ * `handle_password` callback so the user can try again if authentication
+ * fails.
+ */
+void authentication_complete_cb(LightDMGreeter *greeter, App *app)
+{
+ if (lightdm_greeter_get_is_authenticated(greeter)) {
+ const gchar *session = focus_ring_get_value(app->session_ring);
+
+ g_message("Attempting to start session: %s", session);
+
+ gboolean session_started_successfully =
+ !lightdm_greeter_start_session_sync(greeter, session, NULL);
+
+ if (!session_started_successfully) {
+ g_message("Unable to start session");
+ }
+ } else {
+ g_message("Authentication failed");
+ if (strlen(app->config->invalid_password_text) > 0) {
+ set_ui_feedback_label(app, app->config->invalid_password_text);
+ }
+ begin_authentication_as_default_user(app);
+ }
+ gtk_entry_set_text(GTK_ENTRY(APP_PASSWORD_INPUT(app)), "");
+ gtk_editable_set_editable(GTK_EDITABLE(APP_PASSWORD_INPUT(app)), TRUE);
+ app->password_callback_id =
+ g_signal_connect(GTK_ENTRY(APP_PASSWORD_INPUT(app)), "activate",
+ G_CALLBACK(handle_password), app);
+}
+
+
+
+/* GUI Callbacks */
+
+/* Attempt to Authenticate When a Password is Entered.
+ *
+ * The callback disables itself & the input widget to prevent two
+ * authentication attempts from running at the same time - which would cause
+ * LightDM to throw a critical error.
+ */
+void handle_password(GtkWidget *password_input, App *app)
+{
+ if (app->password_callback_id != 0) {
+ g_signal_handler_disconnect(GTK_ENTRY(APP_PASSWORD_INPUT(app)),
+ app->password_callback_id);
+ app->password_callback_id = 0;
+ }
+
+ if (!lightdm_greeter_get_is_authenticated(app->greeter)) {
+ gtk_editable_set_editable(GTK_EDITABLE(password_input), FALSE);
+ if (!lightdm_greeter_get_in_authentication(app->greeter)) {
+ begin_authentication_as_default_user(app);
+ }
+ g_message("Using entered password to authenticate");
+ const gchar *password_text =
+ gtk_entry_get_text(GTK_ENTRY(password_input));
+ compat_greeter_respond(app->greeter, password_text, NULL);
+ } else {
+ g_message("Password entered while already authenticated");
+ }
+}
+
+
+/* Select the Password input if the Tab Key is Pressed */
+gboolean handle_tab_key(GtkWidget *widget, GdkEvent *event, App *app)
+{
+ (void) widget; // Window accessible through app.
+
+ GdkEventKey *key_event = (GdkEventKey *) event;
+ if (event->type == GDK_KEY_PRESS && key_event->keyval == GDK_KEY_Tab) {
+ g_message("Handling Tab Key Press");
+ gtk_window_present(GTK_WINDOW(APP_MAIN_WINDOW(app)));
+ gtk_widget_grab_focus(GTK_WIDGET(APP_PASSWORD_INPUT(app)));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* Shutdown, Restart, Hibernate, Suspend, or Switch Sessions if the correct
+ * keys are pressed.
+ */
+gboolean handle_hotkeys(GtkWidget *widget, GdkEventKey *event, App *app)
+{
+ (void) widget;
+ Config *config = app->config;
+ FocusRing *sessions = app->session_ring;
+
+ if (event->state & config->mod_bit) {
+ if (event->keyval == config->suspend_key && lightdm_get_can_suspend()) {
+ lightdm_suspend(NULL);
+ } else if (event->keyval == config->hibernate_key &&
+ lightdm_get_can_hibernate()) {
+ lightdm_hibernate(NULL);
+ } else if (event->keyval == config->restart_key &&
+ lightdm_get_can_restart()) {
+ lightdm_restart(NULL);
+ } else if (event->keyval == config->shutdown_key &&
+ lightdm_get_can_shutdown()) {
+ lightdm_shutdown(NULL);
+ } else if (event->keyval == config->session_key && sessions != NULL) {
+ gchar *new_session = focus_ring_next(sessions);
+ set_ui_feedback_label(app, new_session);
+ } else {
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/** Determine the current time & update the time GtkLabel.
+ */
+gboolean handle_time_update(App *app)
+{
+ time_t now = time(NULL);
+ struct tm *local_now = localtime(&now);
+ gchar date_string[30];
+ strftime(date_string, 29, "%H:%M", local_now);
+ gtk_label_set_text(GTK_LABEL(APP_TIME_LABEL(app)), date_string);
+
+ return TRUE;
+}
+
+/* Set the Feedback Label's text & ensure it is visible. */
+static void set_ui_feedback_label(App *app, gchar *feedback_text)
+{
+ if (!gtk_widget_get_visible(APP_FEEDBACK_LABEL(app))) {
+ gtk_widget_show(APP_FEEDBACK_LABEL(app));
+ }
+ gtk_label_set_text(GTK_LABEL(APP_FEEDBACK_LABEL(app)), feedback_text);
+}