-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
-
108
-
109
-
110
-
111
-
112
-
113
-
114
-
115
-
116
-
117
-
118
-
119
-
120
-
121
-
122
-
123
-
124
-
125
-
126
-
127
-
128
-
129
-
130
-
131
-
132
-
133
-
134
-
135
-
136
-
137
-
138
-
139
-
140
-
141
-
142
-
143
-
144
-
145
-
146
-
147
-
148
-
149
-
150
-
151
-
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);
}