1 /* $Id$ */
2 /* Copyright (c) 2011-2015 Pierre Pronchery <khorben@defora.org> */
3 /* This file is part of DeforaOS Desktop Locker */
4 /* This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 3 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16
17
18 #include <System.h>
19 #ifdef __NetBSD__
20 # include <sys/param.h>
21 # include <sys/sysctl.h>
22 # include <errno.h>
23 #else
24 # include <fcntl.h>
25 # include <unistd.h>
26 #endif
27 #include <string.h>
28 #include "Locker.h"
29
30
31 /* Slider */
32 /* private */
33 /* types */
34 typedef struct _LockerAuth
35 {
36 LockerAuthHelper * helper;
37 guint source;
38 gboolean locked;
39
40 /* widgets */
41 GtkWidget * widget;
42 GtkWidget * icon1;
43 GtkWidget * scale;
44 GtkWidget * icon2;
45 } Slider;
46
47 typedef struct _SliderTheme
48 {
49 char const * name;
50 char const * icon1;
51 char const * icon2;
52 } SliderTheme;
53
54
55 /* constants */
56 static const SliderTheme _slider_themes[] =
57 {
58 { "changes", "changes-prevent", "changes-allow" },
59 { "dialog", "dialog-error", "dialog-information" },
60 { "emblem", "emblem-important", "emblem-default" },
61 { "filesystem", "emblem-readonly", "emblem-shared" },
62 { "security", "security-high", "security-low" },
63 { "smiley", "face-sad", "face-smile" },
64 { "user", "user-idle", "user-available" },
65 { NULL, NULL, NULL }
66 };
67 #define SLIDER_THEME_DEFAULT 0
68
69
70 /* prototypes */
71 /* plug-in */
72 static Slider * _slider_init(LockerAuthHelper * helper);
73 static void _slider_destroy(Slider * slider);
74 static GtkWidget * _slider_get_widget(Slider * slider);
75 static int _slider_action(Slider * slider, LockerAction action);
76
77 /* useful */
78 static int _slider_load(Slider * slider);
79
80 /* callbacks */
81 static void _slider_on_scale_value_changed(gpointer data);
82 static gboolean _slider_on_scale_value_changed_timeout(gpointer data);
83 static gboolean _slider_on_timeout(gpointer data);
84
85
86 /* public */
87 /* variables */
88 /* plug-in */
89 LockerAuthDefinition plugin =
90 {
91 "Slider",
92 NULL,
93 NULL,
94 _slider_init,
95 _slider_destroy,
96 _slider_get_widget,
97 _slider_action
98 };
99
100
101 /* private */
102 /* functions */
103 /* slider_init */
_slider_init(LockerAuthHelper * helper)104 static Slider * _slider_init(LockerAuthHelper * helper)
105 {
106 Slider * slider;
107 GtkWidget * vbox;
108 GtkWidget * hbox;
109
110 if((slider = object_new(sizeof(*slider))) == NULL)
111 return NULL;
112 slider->helper = helper;
113 slider->source = 0;
114 slider->locked = FALSE;
115 #if GTK_CHECK_VERSION(3, 0, 0)
116 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
117 #else
118 vbox = gtk_vbox_new(FALSE, 4);
119 #endif
120 slider->widget = vbox;
121 #if GTK_CHECK_VERSION(3, 0, 0)
122 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
123 #else
124 hbox = gtk_hbox_new(FALSE, 4);
125 #endif
126 slider->icon1 = NULL;
127 slider->scale = NULL;
128 slider->icon2 = NULL;
129 _slider_load(slider);
130 /* left image */
131 #if GTK_CHECK_VERSION(3, 0, 0)
132 g_object_set(slider->icon1, "halign", GTK_ALIGN_END,
133 "margin-bottom", 96, "margin-top", 96, NULL);
134 #else
135 gtk_misc_set_alignment(GTK_MISC(slider->icon1), 1.0, 0.5);
136 gtk_misc_set_padding(GTK_MISC(slider->icon1), 0, 96);
137 #endif
138 gtk_box_pack_start(GTK_BOX(hbox), slider->icon1, TRUE, TRUE, 0);
139 /* scale */
140 #if GTK_CHECK_VERSION(3, 0, 0)
141 slider->scale = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,
142 0.0, 100.0, 1.0);
143 #else
144 slider->scale = gtk_hscale_new_with_range(0.0, 100.0, 1.0);
145 #endif
146 gtk_range_set_value(GTK_RANGE(slider->scale), 0.0);
147 gtk_scale_set_draw_value(GTK_SCALE(slider->scale), FALSE);
148 gtk_widget_set_size_request(slider->scale, 240, -1);
149 g_signal_connect_swapped(slider->scale, "value-changed", G_CALLBACK(
150 _slider_on_scale_value_changed), slider);
151 gtk_box_pack_start(GTK_BOX(hbox), slider->scale, FALSE, TRUE, 0);
152 /* right image */
153 #if GTK_CHECK_VERSION(3, 0, 0)
154 g_object_set(slider->icon2, "halign", GTK_ALIGN_START,
155 "margin-bottom", 96, "margin-top", 96, NULL);
156 #else
157 gtk_misc_set_alignment(GTK_MISC(slider->icon2), 0.0, 0.5);
158 gtk_misc_set_padding(GTK_MISC(slider->icon2), 0, 96);
159 #endif
160 gtk_box_pack_start(GTK_BOX(hbox), slider->icon2, TRUE, TRUE, 0);
161 gtk_widget_show_all(hbox);
162 gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
163 return slider;
164 }
165
166
167 /* slider_destroy */
_slider_destroy(Slider * slider)168 static void _slider_destroy(Slider * slider)
169 {
170 gtk_widget_destroy(slider->widget);
171 if(slider->source != 0)
172 g_source_remove(slider->source);
173 object_delete(slider);
174 }
175
176
177 /* slider_get_widget */
_slider_get_widget(Slider * slider)178 static GtkWidget * _slider_get_widget(Slider * slider)
179 {
180 return slider->widget;
181 }
182
183
184 /* slider_action */
_slider_action(Slider * slider,LockerAction action)185 static int _slider_action(Slider * slider, LockerAction action)
186 {
187 #ifdef DEBUG
188 fprintf(stderr, "DEBUG: %s(%u)\n", __func__, action);
189 #endif
190 switch(action)
191 {
192 case LOCKER_ACTION_DEACTIVATE:
193 if(slider->source != 0)
194 g_source_remove(slider->source);
195 slider->source = 0;
196 if(slider->locked)
197 {
198 gtk_range_set_value(GTK_RANGE(slider->scale),
199 0.0);
200 gtk_widget_grab_focus(slider->scale);
201 gtk_widget_show(slider->widget);
202 slider->source = g_timeout_add(3000,
203 _slider_on_timeout, slider);
204 }
205 break;
206 case LOCKER_ACTION_LOCK:
207 gtk_widget_hide(slider->widget);
208 if(slider->source != 0)
209 g_source_remove(slider->source);
210 slider->source = 0;
211 slider->locked = TRUE;
212 break;
213 case LOCKER_ACTION_UNLOCK:
214 slider->locked = FALSE;
215 /* fallback */
216 case LOCKER_ACTION_ACTIVATE:
217 case LOCKER_ACTION_CYCLE:
218 case LOCKER_ACTION_START:
219 gtk_widget_hide(slider->widget);
220 if(slider->source != 0)
221 g_source_remove(slider->source);
222 slider->source = 0;
223 break;
224 default:
225 break;
226 }
227 return 0;
228 }
229
230
231 /* useful */
232 /* slider_load */
_slider_load(Slider * slider)233 static int _slider_load(Slider * slider)
234 {
235 LockerAuthHelper * helper = slider->helper;
236 size_t i = SLIDER_THEME_DEFAULT;
237 String const * p;
238
239 /* load the theme configured */
240 if((p = helper->config_get(helper->locker, "slider", "theme")) != NULL)
241 for(i = 0; _slider_themes[i].name != NULL; i++)
242 if(strcmp(_slider_themes[i].name, p) == 0)
243 break;
244 /* load the first icon */
245 if((p = _slider_themes[i].icon1) == NULL
246 && (p = helper->config_get(helper->locker, "slider",
247 "icon1")) == NULL)
248 p = _slider_themes[SLIDER_THEME_DEFAULT].icon1;
249 if(slider->icon1 == NULL)
250 slider->icon1 = gtk_image_new_from_icon_name(p,
251 GTK_ICON_SIZE_LARGE_TOOLBAR);
252 else
253 gtk_image_set_from_icon_name(GTK_IMAGE(slider->icon1), p,
254 GTK_ICON_SIZE_LARGE_TOOLBAR);
255 /* load the second icon */
256 if((p = _slider_themes[i].icon2) == NULL
257 && (p = helper->config_get(helper->locker, "slider",
258 "icon2")) == NULL)
259 p = _slider_themes[SLIDER_THEME_DEFAULT].icon2;
260 if(slider->icon2 == NULL)
261 slider->icon2 = gtk_image_new_from_icon_name(p,
262 GTK_ICON_SIZE_LARGE_TOOLBAR);
263 else
264 gtk_image_set_from_icon_name(GTK_IMAGE(slider->icon2), p,
265 GTK_ICON_SIZE_LARGE_TOOLBAR);
266 return 0;
267 }
268
269
270 /* callbacks */
271 /* slider_on_scale_value_changed */
_slider_on_scale_value_changed(gpointer data)272 static void _slider_on_scale_value_changed(gpointer data)
273 {
274 Slider * slider = data;
275 LockerAuthHelper * helper = slider->helper;
276 gdouble value;
277
278 if(slider->source != 0)
279 g_source_remove(slider->source);
280 slider->source = 0;
281 value = gtk_range_get_value(GTK_RANGE(slider->scale));
282 if(value >= 100.0)
283 helper->action(helper->locker, LOCKER_ACTION_UNLOCK);
284 else if(value > 0.0)
285 slider->source = g_timeout_add(1000,
286 _slider_on_scale_value_changed_timeout, slider);
287 }
288
289
290 /* slider_on_scale_value_changed_timeout */
_slider_on_scale_value_changed_timeout(gpointer data)291 static gboolean _slider_on_scale_value_changed_timeout(gpointer data)
292 {
293 Slider * slider = data;
294
295 #ifdef DEBUG
296 fprintf(stderr, "DEBUG: %s()\n", __func__);
297 #endif
298 gtk_range_set_value(GTK_RANGE(slider->scale), 0.0);
299 slider->source = g_timeout_add(3000, _slider_on_timeout, slider);
300 return FALSE;
301 }
302
303
304 /* slider_on_timeout */
_slider_on_timeout(gpointer data)305 static gboolean _slider_on_timeout(gpointer data)
306 {
307 Slider * slider = data;
308 LockerAuthHelper * helper = slider->helper;
309
310 slider->source = 0;
311 helper->action(helper->locker, LOCKER_ACTION_ACTIVATE);
312 return FALSE;
313 }
314