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