Commit from LXDE Translation Project with Pootle by user lOtz1009.: 315 of 318 messag...
[lxde/lxpanel.git] / src / plugins / xkb / xkb-plugin.c
CommitLineData
438d9fdb
MJ
1/**
2 * Copyright (c) 2010 LxDE Developers, see the file AUTHORS for details.
3 *
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; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19/* Originally derived from xfce4-xkb-plugin, Copyright 2004 Alexander Iliev,
20 * which credits Michael Glickman. */
22242ed4 21
4496e880
JL
22/* Modified by Giuseppe Penone <giuspen@gmail.com> starting from 2012-07 and lxpanel 0.5.10 */
23
22242ed4
HJYP
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include <glib/gi18n.h>
29
30#include <stdio.h>
45bd719e 31#include <stdlib.h>
22242ed4
HJYP
32#include <ctype.h>
33
34#include "xkb.h"
35
4496e880
JL
36enum
37{
38 COLUMN_ICON,
39 COLUMN_LAYOUT,
40 COLUMN_VARIANT,
41 NUM_COLUMNS
42};
43
44enum
45{
46 COLUMN_ADD_ICON,
47 COLUMN_ADD_LAYOUT,
48 COLUMN_ADD_DESC,
49 NUM_ADD_COLUMNS
50};
51
52enum
53{
54 COLUMN_MODEL_NAME,
55 COLUMN_MODEL_DESC,
56 NUM_MODEL_COLUMNS
57};
58
59enum
60{
61 COLUMN_CHANGE_NAME,
62 COLUMN_CHANGE_DESC,
63 NUM_CHANGE_COLUMNS
64};
65
18ecfe2a 66void panel_config_save(Panel * panel); /* defined in configurator.c */
67
4496e880
JL
68static int xkb_constructor(Plugin * p_plugin, char ** fp);
69static void xkb_destructor(Plugin * p_plugin);
70static void xkb_configure(Plugin * p, GtkWindow * parent);
71static void xkb_save_configuration(Plugin * p, FILE * fp);
72static void xkb_panel_configuration_changed(Plugin * p);
73static void xkb_settings_fill_layout_tree_model_with_config(XkbPlugin *p_xkb);
74static void xkb_setxkbmap(XkbPlugin *p_xkb);
75static void xkb_update_layouts_n_variants(XkbPlugin *p_xkb);
76static void xkb_add_layout(XkbPlugin *p_xkb, gchar *layout, gchar*variant);
77static int xkb_get_flag_size(XkbPlugin *p_xkb);
78
79static gboolean on_xkb_button_scroll_event(GtkWidget * widget, GdkEventScroll * event, gpointer p_data);
80static gboolean on_xkb_button_press_event(GtkWidget * widget, GdkEventButton * event, gpointer p_data);
81static void on_radiobutton_disp_type_image_toggled(GtkToggleButton *p_radiobutton, gpointer p_data);
82static void on_radiobutton_disp_type_image_cust_toggled(GtkToggleButton *p_radiobutton, gpointer p_data);
83static void on_radiobutton_disp_type_text_toggled(GtkToggleButton *p_radiobutton, gpointer p_data);
84static void on_hscale_flag_size_value_changed(GtkRange *p_range, gpointer p_data);
85static void on_dialog_config_response(GtkDialog *p_dialog, gint response, gpointer p_data);
86
87static unsigned char user_active = FALSE;
88static const gchar flag_filepath_generator[] = "%s/%s.png";
89
90static int xkb_get_flag_size(XkbPlugin *p_xkb)
91{
92 int size = p_xkb->p_plugin->panel->icon_size;
93 switch(p_xkb->flag_size)
94 {
95 case 1: return size*0.5;
96 case 2: return size*0.6;
97 case 3: return size*0.7;
98 case 4: return size*0.8;
99 default: break;
100 }
101 return size*0.9;
102}
d862b520 103
104/* Redraw the graphics. */
4496e880 105void xkb_redraw(XkbPlugin *p_xkb)
22242ed4 106{
d862b520 107 /* Set the image. */
108 gboolean valid_image = FALSE;
4496e880
JL
109 int size = xkb_get_flag_size(p_xkb);
110 if( (p_xkb->display_type == DISP_TYPE_IMAGE) || (p_xkb->display_type == DISP_TYPE_IMAGE_CUST) )
22242ed4 111 {
4496e880
JL
112 char * group_name = (char *)xkb_get_current_symbol_name_lowercase(p_xkb);
113 if(group_name != NULL)
d862b520 114 {
4496e880
JL
115 gchar *flag_filepath = NULL;
116 gchar *flags_dir = (p_xkb->cust_dir_exists && (p_xkb->display_type == DISP_TYPE_IMAGE_CUST)) ? g_strdup(FLAGSCUSTDIR):g_strdup(FLAGSDIR);
117 if(strchr(group_name, '/') != NULL)
118 {
119 gchar *layout_mod = g_strdup(group_name);
120 layout_mod = g_strdelimit(layout_mod, "/", '-');
121 flag_filepath = g_strdup_printf(flag_filepath_generator, flags_dir, layout_mod);
122 g_free(layout_mod);
123 }
124 else
125 {
126 flag_filepath = g_strdup_printf(flag_filepath_generator, flags_dir, group_name);
127 }
128 GdkPixbuf * unscaled_pixbuf = gdk_pixbuf_new_from_file(flag_filepath, NULL);
129 g_free(flag_filepath);
130 g_free(flags_dir);
438d9fdb
MJ
131 g_free(group_name);
132
4496e880 133 if(unscaled_pixbuf != NULL)
d862b520 134 {
438d9fdb
MJ
135 /* Loaded successfully. */
136 int width = gdk_pixbuf_get_width(unscaled_pixbuf);
137 int height = gdk_pixbuf_get_height(unscaled_pixbuf);
138 GdkPixbuf * pixbuf = gdk_pixbuf_scale_simple(unscaled_pixbuf, size * width / height, size, GDK_INTERP_BILINEAR);
4496e880 139 if(pixbuf != NULL)
438d9fdb 140 {
4496e880 141 gtk_image_set_from_pixbuf(GTK_IMAGE(p_xkb->p_image), pixbuf);
438d9fdb 142 g_object_unref(G_OBJECT(pixbuf));
4496e880
JL
143 gtk_widget_hide(p_xkb->p_label);
144 gtk_widget_show(p_xkb->p_image);
145 gtk_widget_set_tooltip_text(p_xkb->p_plugin->pwid, xkb_get_current_group_name(p_xkb));
438d9fdb
MJ
146 valid_image = TRUE;
147 }
148 g_object_unref(unscaled_pixbuf);
22242ed4
HJYP
149 }
150 }
151 }
152
d862b520 153 /* Set the label. */
4496e880 154 if( (p_xkb->display_type == DISP_TYPE_TEXT) || ( ! valid_image) )
d862b520 155 {
4496e880 156 char *group_name = (char *)xkb_get_current_symbol_name(p_xkb);
438d9fdb
MJ
157 if (group_name != NULL)
158 {
4496e880
JL
159 GString *p_gstring_markup = g_string_new("");
160 g_string_printf(p_gstring_markup, "<span font='%u' weight='heavy'>%s</span>", size/2, group_name);
161 gtk_label_set_markup(GTK_LABEL(p_xkb->p_label), p_gstring_markup->str);
162 g_string_free(p_gstring_markup, TRUE/*free also gstring->str*/);
163 gtk_widget_hide(p_xkb->p_image);
164 gtk_widget_show(p_xkb->p_label);
165 gtk_widget_set_tooltip_text(p_xkb->p_plugin->pwid, xkb_get_current_group_name(p_xkb));
d862b520 166 }
167 }
22242ed4
HJYP
168}
169
d862b520 170/* Handler for "scroll-event" on drawing area. */
4496e880 171static gboolean on_xkb_button_scroll_event(GtkWidget * widget, GdkEventScroll * event, gpointer p_data)
22242ed4 172{
4496e880 173 XkbPlugin * xkb = (XkbPlugin *)p_data;
22242ed4 174
d862b520 175 /* Change to next or previous group. */
176 xkb_change_group(xkb,
177 (((event->direction == GDK_SCROLL_UP) || (event->direction == GDK_SCROLL_RIGHT)) ? 1 : -1));
178 return TRUE;
22242ed4
HJYP
179}
180
d862b520 181/* Handler for button-press-event on top level widget. */
4496e880 182static gboolean on_xkb_button_press_event(GtkWidget * widget, GdkEventButton * event, gpointer p_data)
22242ed4 183{
4496e880 184 XkbPlugin * xkb = (XkbPlugin *)p_data;
22242ed4 185
d862b520 186 /* Standard right-click handling. */
4496e880 187 if (plugin_button_press_event(widget, event, xkb->p_plugin))
d862b520 188 return TRUE;
22242ed4 189
d862b520 190 /* Change to next group. */
191 xkb_change_group(xkb, 1);
18ecfe2a 192 return TRUE;
22242ed4
HJYP
193}
194
d862b520 195/* Plugin constructor. */
4496e880 196static int xkb_constructor(Plugin * p_plugin, char ** fp)
22242ed4 197{
d862b520 198 /* Allocate plugin context and set into Plugin private data pointer. */
4496e880
JL
199 XkbPlugin * p_xkb = g_new0(XkbPlugin, 1);
200 p_xkb->p_plugin = p_plugin;
201 p_plugin->priv = p_xkb;
d862b520 202
203 /* Initialize to defaults. */
4496e880
JL
204 p_xkb->display_type = DISP_TYPE_IMAGE;
205 p_xkb->kbd_model = NULL;
206 p_xkb->kbd_layouts = NULL;
207 p_xkb->kbd_variants = NULL;
208 p_xkb->kbd_change_option = NULL;
209 p_xkb->flag_size = 3;
210 p_xkb->cust_dir_exists = g_file_test(FLAGSCUSTDIR, G_FILE_TEST_IS_DIR);
d862b520 211
212 /* Load parameters from the configuration file. */
213 line s;
214 s.len = 256;
215 if (fp != NULL)
216 {
217 while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END)
218 {
219 if (s.type == LINE_NONE)
220 {
221 ERR( "xkb: illegal token %s\n", s.str);
222 return 0;
223 }
224 if (s.type == LINE_VAR)
225 {
4496e880
JL
226 if(g_ascii_strcasecmp(s.t[0], "DisplayType") == 0)
227 {
228 p_xkb->display_type = atoi(s.t[1]);
229 }
230 else if(g_ascii_strcasecmp(s.t[0], "Model") == 0)
231 {
232 p_xkb->kbd_model = g_strdup(s.t[1]);
233 }
234 else if(g_ascii_strcasecmp(s.t[0], "LayoutsList") == 0)
235 {
236 p_xkb->kbd_layouts = g_strdup(s.t[1]);
237 }
238 else if(g_ascii_strcasecmp(s.t[0], "VariantsList") == 0)
239 {
240 p_xkb->kbd_variants = g_strdup(s.t[1]);
241 }
242 else if(g_ascii_strcasecmp(s.t[0], "ToggleOpt") == 0)
243 {
244 p_xkb->kbd_change_option = g_strdup(s.t[1]);
245 }
246 else if(g_ascii_strcasecmp(s.t[0], "FlagSize") == 0)
247 {
248 p_xkb->flag_size = atoi(s.t[1]);
249 }
d862b520 250 else
251 ERR( "xkb: unknown var %s\n", s.t[0]);
252 }
253 else
254 {
255 ERR( "xkb: illegal in this context %s\n", s.str);
256 return 0;
257 }
258 }
259 }
4496e880
JL
260
261 if( (p_xkb->kbd_model == NULL) || (p_xkb->kbd_layouts == NULL) ||
262 (p_xkb->kbd_variants == NULL) || (p_xkb->kbd_change_option == NULL) )
263 {
264 if(p_xkb->kbd_model != NULL) g_free(p_xkb->kbd_model);
265 if(p_xkb->kbd_layouts != NULL) g_free(p_xkb->kbd_layouts);
266 if(p_xkb->kbd_variants != NULL) g_free(p_xkb->kbd_variants);
267 if(p_xkb->kbd_change_option != NULL) g_free(p_xkb->kbd_change_option);
268
269 FILE *fp;
270 char buf[MAX_ROW_LEN];
271 fp = popen("setxkbmap -query", "r");
272 if(fp != NULL)
273 {
274 GRegex *p_regex_model = g_regex_new("(?<=model:).*", 0, 0, NULL);
275 GRegex *p_regex_layouts = g_regex_new("(?<=layout:).*", 0, 0, NULL);
276 GRegex *p_regex_variants = g_regex_new("(?<=variant:).*", 0, 0, NULL);
277 GMatchInfo *p_match_info;
278 while(fgets(buf, MAX_ROW_LEN, fp) != NULL)
279 {
280 // model
281 g_regex_match(p_regex_model, buf, 0, &p_match_info);
282 if(g_match_info_matches(p_match_info))
283 {
284 p_xkb->kbd_model = g_strchug(g_match_info_fetch(p_match_info, 0));
285 g_match_info_free(p_match_info);
286 continue;
287 }
288 g_match_info_free(p_match_info);
289
290 // layouts
291 g_regex_match(p_regex_layouts, buf, 0, &p_match_info);
292 if(g_match_info_matches(p_match_info))
293 {
294 p_xkb->kbd_layouts = g_strchug(g_match_info_fetch(p_match_info, 0));
295 g_match_info_free(p_match_info);
296 continue;
297 }
298 g_match_info_free(p_match_info);
299
300 // variants
301 g_regex_match(p_regex_variants, buf, 0, &p_match_info);
302 if(g_match_info_matches(p_match_info))
303 {
304 p_xkb->kbd_variants = g_strchug(g_match_info_fetch(p_match_info, 0));
305 g_match_info_free(p_match_info);
306 continue;
307 }
308 g_match_info_free(p_match_info);
309 }
310
311 g_regex_unref(p_regex_model);
312 g_regex_unref(p_regex_layouts);
313 g_regex_unref(p_regex_variants);
314
315 /* close */
316 pclose(fp);
317 }
318 if(p_xkb->kbd_model == NULL) p_xkb->kbd_model = g_strdup("pc105");
319 if(p_xkb->kbd_layouts == NULL) p_xkb->kbd_layouts = g_strdup("us");
320 if(p_xkb->kbd_variants == NULL) p_xkb->kbd_variants = g_strdup(",");
321 if(p_xkb->kbd_change_option == NULL) p_xkb->kbd_change_option = g_strdup("shift_caps_toggle");
322 }
323 else
324 xkb_setxkbmap(p_xkb);
2918994e 325
d862b520 326 /* Allocate top level widget and set into Plugin widget pointer. */
4496e880
JL
327 p_plugin->pwid = gtk_event_box_new();
328 gtk_widget_add_events(p_plugin->pwid, GDK_BUTTON_PRESS_MASK);
d862b520 329
330 /* Create a horizontal box as the child of the button. */
331 GtkWidget * hbox = gtk_hbox_new(FALSE, 0);
4496e880
JL
332 gtk_container_set_border_width(GTK_CONTAINER(hbox), 1);
333 gtk_container_add(GTK_CONTAINER(p_xkb->p_plugin->pwid), hbox);
d862b520 334 gtk_widget_show(hbox);
335
336 /* Create a label and an image as children of the horizontal box.
337 * Only one of these is visible at a time, controlled by user preference
338 * and the successful loading of the image. */
4496e880
JL
339 p_xkb->p_label = gtk_label_new("");
340 gtk_container_add(GTK_CONTAINER(hbox), p_xkb->p_label);
341 p_xkb->p_image = gtk_image_new();
342 gtk_container_add(GTK_CONTAINER(hbox), p_xkb->p_image);
d862b520 343
344 /* Initialize the XKB interface. */
4496e880 345 xkb_mechanism_constructor(p_xkb);
d862b520 346
d862b520 347 /* Connect signals. */
4496e880
JL
348 g_signal_connect(p_plugin->pwid, "button-press-event", G_CALLBACK(on_xkb_button_press_event), p_xkb);
349 g_signal_connect(p_plugin->pwid, "scroll-event", G_CALLBACK(on_xkb_button_scroll_event), p_xkb);
d862b520 350
351 /* Show the widget and return. */
4496e880
JL
352 xkb_redraw(p_xkb);
353 gtk_widget_show(p_plugin->pwid);
d862b520 354 return 1;
22242ed4
HJYP
355}
356
d862b520 357/* Plugin destructor. */
4496e880 358static void xkb_destructor(Plugin * p_plugin)
22242ed4 359{
4496e880 360 XkbPlugin *p_xkb = (XkbPlugin *)p_plugin->priv;
22242ed4 361
d862b520 362 /* Disconnect from the XKB mechanism. */
4496e880
JL
363 g_source_remove(p_xkb->source_id);
364 xkb_mechanism_destructor(p_xkb);
22242ed4 365
d862b520 366 /* Ensure that the configuration dialog is dismissed. */
4496e880
JL
367 if(p_xkb->p_dialog_config != NULL)
368 gtk_widget_destroy(p_xkb->p_dialog_config);
22242ed4 369
d862b520 370 /* Deallocate all memory. */
4496e880
JL
371 g_free(p_xkb->kbd_model);
372 g_free(p_xkb->kbd_layouts);
373 g_free(p_xkb->kbd_variants);
374 g_free(p_xkb->kbd_change_option);
375 g_free(p_xkb);
376}
377
378static void on_radiobutton_flag_size_1_toggled(GtkToggleButton *p_radiobutton, gpointer p_data)
379{
380 if( (user_active == TRUE) && gtk_toggle_button_get_active(p_radiobutton) )
381 {
382 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
383 p_xkb->flag_size = 1;
384 xkb_redraw(p_xkb);
385 }
386}
387
388static void on_radiobutton_flag_size_2_toggled(GtkToggleButton *p_radiobutton, gpointer p_data)
389{
390 if( (user_active == TRUE) && gtk_toggle_button_get_active(p_radiobutton) )
391 {
392 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
393 p_xkb->flag_size = 2;
394 xkb_redraw(p_xkb);
395 }
22242ed4
HJYP
396}
397
4496e880 398static void on_radiobutton_flag_size_3_toggled(GtkToggleButton *p_radiobutton, gpointer p_data)
22242ed4 399{
4496e880
JL
400 if( (user_active == TRUE) && gtk_toggle_button_get_active(p_radiobutton) )
401 {
402 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
403 p_xkb->flag_size = 3;
404 xkb_redraw(p_xkb);
405 }
22242ed4
HJYP
406}
407
4496e880 408static void on_radiobutton_flag_size_4_toggled(GtkToggleButton *p_radiobutton, gpointer p_data)
22242ed4 409{
4496e880
JL
410 if( (user_active == TRUE) && gtk_toggle_button_get_active(p_radiobutton) )
411 {
412 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
413 p_xkb->flag_size = 4;
414 xkb_redraw(p_xkb);
415 }
22242ed4
HJYP
416}
417
4496e880 418static void on_radiobutton_flag_size_5_toggled(GtkToggleButton *p_radiobutton, gpointer p_data)
22242ed4 419{
4496e880
JL
420 if( (user_active == TRUE) && gtk_toggle_button_get_active(p_radiobutton) )
421 {
422 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
423 p_xkb->flag_size = 5;
424 xkb_redraw(p_xkb);
425 }
426}
427
428/* Handler for "toggled" event on display type image radiobutton of configuration dialog. */
429static void on_radiobutton_disp_type_image_toggled(GtkToggleButton *p_radiobutton, gpointer p_data)
430{
431 if( (user_active == TRUE) && gtk_toggle_button_get_active(p_radiobutton) )
432 {
433 /* Fetch the new value and redraw. */
434 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
435 p_xkb->display_type = DISP_TYPE_IMAGE;
436 xkb_redraw(p_xkb);
437 }
438}
439
440/* Handler for "toggled" event on display type image radiobutton of configuration dialog. */
441static void on_radiobutton_disp_type_image_cust_toggled(GtkToggleButton *p_radiobutton, gpointer p_data)
442{
443 if( (user_active == TRUE) && gtk_toggle_button_get_active(p_radiobutton) )
444 {
445 /* Fetch the new value and redraw. */
446 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
447 p_xkb->display_type = DISP_TYPE_IMAGE_CUST;
448 xkb_redraw(p_xkb);
449 }
450}
451
452/* Handler for "toggled" event on display type image radiobutton of configuration dialog. */
453static void on_radiobutton_disp_type_text_toggled(GtkToggleButton *p_radiobutton, gpointer p_data)
454{
455 if( (user_active == TRUE) && gtk_toggle_button_get_active(p_radiobutton) )
456 {
457 /* Fetch the new value and redraw. */
458 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
459 p_xkb->display_type = DISP_TYPE_TEXT;
460 xkb_redraw(p_xkb);
461 }
22242ed4
HJYP
462}
463
d862b520 464/* Handler for "response" event on configuration dialog. */
4496e880 465static void on_dialog_config_response(GtkDialog *p_dialog, gint response, gpointer data)
22242ed4 466{
4496e880 467 XkbPlugin * p_xkb = (XkbPlugin *)data;
22242ed4 468
d862b520 469 /* Save the new configuration and redraw the plugin. */
4496e880
JL
470 panel_config_save(p_xkb->p_plugin->panel);
471 xkb_redraw(p_xkb);
22242ed4 472
d862b520 473 /* Destroy the dialog. */
4496e880
JL
474 gtk_widget_destroy(p_xkb->p_dialog_config);
475 p_xkb->p_dialog_config = NULL;
476}
477
478static void on_hscale_flag_size_value_changed(GtkRange *p_range, gpointer p_data)
479{
480
481}
482
483static void on_button_kbd_model_clicked(GtkButton *p_button, gpointer *p_data)
484{
485 XkbPlugin *p_xkb = (XkbPlugin *)p_data;
486
487 // dialog
488 GtkWidget *p_dialog = gtk_dialog_new_with_buttons(_("Select Keyboard Model"),
489 GTK_WINDOW(p_xkb->p_dialog_config),
490 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
491 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
492 GTK_STOCK_OK, GTK_RESPONSE_OK,
493 NULL);
494
495 // scrolledwindow
496 GtkWidget * p_scrolledwindow_kbd_model = gtk_scrolled_window_new(NULL, NULL);
497 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(p_scrolledwindow_kbd_model),
498 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
499 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(p_dialog)->vbox), p_scrolledwindow_kbd_model, TRUE, TRUE, 2);
500
501 // liststore
502 GtkListStore *p_liststore_kbd_model = gtk_list_store_new(NUM_MODEL_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
503 GtkWidget *p_treeview_kbd_model = gtk_tree_view_new_with_model(GTK_TREE_MODEL(p_liststore_kbd_model));
504 g_object_unref(G_OBJECT(p_liststore_kbd_model));
505 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(p_treeview_kbd_model), TRUE);
506 gtk_container_add(GTK_CONTAINER(p_scrolledwindow_kbd_model), p_treeview_kbd_model);
507 GtkCellRenderer *p_renderer;
508 GtkTreeViewColumn *p_column;
509 // model
510 p_renderer = gtk_cell_renderer_text_new();
511 p_column = gtk_tree_view_column_new_with_attributes(_("Model"), p_renderer, "text", COLUMN_CHANGE_NAME, NULL);
512 gtk_tree_view_append_column(GTK_TREE_VIEW(p_treeview_kbd_model), p_column);
513 // desc
514 p_renderer = gtk_cell_renderer_text_new();
515 p_column = gtk_tree_view_column_new_with_attributes(_("Description"), p_renderer, "text", COLUMN_CHANGE_DESC, NULL);
516 gtk_tree_view_append_column(GTK_TREE_VIEW(p_treeview_kbd_model), p_column);
517
518 // populate model
519 GKeyFile *p_keyfile = g_key_file_new();
520 gchar *xkbcfg_filepath = g_strdup_printf("%s/models.cfg", XKBCONFDIR);
521 if(g_key_file_load_from_file(p_keyfile, xkbcfg_filepath, 0, NULL))
522 {
523 gchar **keys_models = g_key_file_get_keys(p_keyfile, "MODELS", NULL, NULL);
524 guint model_idx = 0;
525 GtkTreeIter tree_iter;
526 gchar *p_model_desc;
527 while(keys_models[model_idx] != NULL)
528 {
529 p_model_desc = g_key_file_get_string(p_keyfile, "MODELS", keys_models[model_idx], NULL);
530 gtk_list_store_append(p_liststore_kbd_model, &tree_iter);
531 gtk_list_store_set(p_liststore_kbd_model, &tree_iter,
532 COLUMN_MODEL_NAME, keys_models[model_idx],
533 COLUMN_MODEL_DESC, p_model_desc,
534 -1);
535 g_free(p_model_desc);
536 model_idx++;
537 }
538 g_strfreev(keys_models);
539 g_key_file_free(p_keyfile);
540 }
541 g_free(xkbcfg_filepath);
542
543 // callback for double click
544 gboolean on_treeview_kbd_model_button_press_event(GtkWidget *p_widget,
545 GdkEventButton *p_event,
546 gpointer p_data)
547 {
548 if(p_event->button == 1)
549 {
550 if(p_event->type == GDK_2BUTTON_PRESS)
551 {
552 GtkButton *p_button_ok = (GtkButton *)gtk_dialog_get_widget_for_response(GTK_DIALOG(p_dialog), GTK_RESPONSE_OK);
553 gtk_button_clicked(p_button_ok);
554 }
555 }
556 return FALSE;
557 }
558 g_signal_connect(p_treeview_kbd_model, "button-press-event",
559 G_CALLBACK(on_treeview_kbd_model_button_press_event), NULL);
560 gtk_widget_set_size_request(p_dialog, 600, 500);
561 gtk_widget_show_all(GTK_WIDGET(p_scrolledwindow_kbd_model));
562 gint response = gtk_dialog_run(GTK_DIALOG(p_dialog));
563 if(response == GTK_RESPONSE_OK)
564 {
565 GtkTreeIter tree_iter_sel;
566 GtkTreeSelection *p_treeselection_kbd_model = gtk_tree_view_get_selection(GTK_TREE_VIEW(p_treeview_kbd_model));
567 if(gtk_tree_selection_get_selected(p_treeselection_kbd_model,
568 (GtkTreeModel **)(&p_liststore_kbd_model),
569 &tree_iter_sel))
570 {
571 gchar *kbd_model_new;
572 gtk_tree_model_get(GTK_TREE_MODEL(p_liststore_kbd_model),
573 &tree_iter_sel, COLUMN_MODEL_NAME, &kbd_model_new, -1);
574 g_free(p_xkb->kbd_model);
575 p_xkb->kbd_model = g_strdup(kbd_model_new);
576 gtk_button_set_label(GTK_BUTTON(p_xkb->p_button_kbd_model), p_xkb->kbd_model);
577 g_free(kbd_model_new);
578 xkb_setxkbmap(p_xkb);
579 xkb_redraw(p_xkb);
580 }
581 }
582 gtk_widget_destroy(p_dialog);
583}
584
585static void on_button_kbd_change_layout_clicked(GtkButton *p_button, gpointer *p_data)
586{
587 XkbPlugin *p_xkb = (XkbPlugin *)p_data;
588
589 // dialog
590 GtkWidget *p_dialog = gtk_dialog_new_with_buttons(_("Select Layout Change Type"),
591 GTK_WINDOW(p_xkb->p_dialog_config),
592 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
593 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
594 GTK_STOCK_OK, GTK_RESPONSE_OK,
595 NULL);
596
597 // scrolledwindow
598 GtkWidget * p_scrolledwindow_kbd_change = gtk_scrolled_window_new(NULL, NULL);
599 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(p_scrolledwindow_kbd_change),
600 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
601 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(p_dialog)->vbox), p_scrolledwindow_kbd_change, TRUE, TRUE, 2);
602
603 // liststore
604 GtkListStore *p_liststore_kbd_change = gtk_list_store_new(NUM_CHANGE_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
605 GtkWidget *p_treeview_kbd_change = gtk_tree_view_new_with_model(GTK_TREE_MODEL(p_liststore_kbd_change));
606 g_object_unref(G_OBJECT(p_liststore_kbd_change));
607 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(p_treeview_kbd_change), TRUE);
608 gtk_container_add(GTK_CONTAINER(p_scrolledwindow_kbd_change), p_treeview_kbd_change);
609 GtkCellRenderer *p_renderer;
610 GtkTreeViewColumn *p_column;
611 // model
612 p_renderer = gtk_cell_renderer_text_new();
613 p_column = gtk_tree_view_column_new_with_attributes(_("Change Type"), p_renderer, "text", COLUMN_CHANGE_NAME, NULL);
614 gtk_tree_view_append_column(GTK_TREE_VIEW(p_treeview_kbd_change), p_column);
615 // desc
616 p_renderer = gtk_cell_renderer_text_new();
617 p_column = gtk_tree_view_column_new_with_attributes(_("Description"), p_renderer, "text", COLUMN_CHANGE_DESC, NULL);
618 gtk_tree_view_append_column(GTK_TREE_VIEW(p_treeview_kbd_change), p_column);
619
620 // populate model
621 GKeyFile *p_keyfile = g_key_file_new();
622 gchar *xkbcfg_filepath = g_strdup_printf("%s/toggle.cfg", XKBCONFDIR);
623 if(g_key_file_load_from_file(p_keyfile, xkbcfg_filepath, 0, NULL))
624 {
625 gchar **keys_changes = g_key_file_get_keys(p_keyfile, "TOGGLE", NULL, NULL);
626 guint change_idx = 0;
627 GtkTreeIter tree_iter;
628 gchar *p_change_desc;
629 while(keys_changes[change_idx] != NULL)
630 {
631 p_change_desc = g_key_file_get_string(p_keyfile, "TOGGLE", keys_changes[change_idx], NULL);
632 gtk_list_store_append(p_liststore_kbd_change, &tree_iter);
633 gtk_list_store_set(p_liststore_kbd_change, &tree_iter,
634 COLUMN_CHANGE_NAME, keys_changes[change_idx],
635 COLUMN_CHANGE_DESC, p_change_desc,
636 -1);
637 g_free(p_change_desc);
638 change_idx++;
639 }
640 g_strfreev(keys_changes);
641 g_key_file_free(p_keyfile);
642 }
643 g_free(xkbcfg_filepath);
644
645 // callback for double click
646 gboolean on_treeview_kbd_change_button_press_event(GtkWidget *p_widget,
647 GdkEventButton *p_event,
648 gpointer p_data)
649 {
650 if(p_event->button == 1)
651 {
652 if(p_event->type == GDK_2BUTTON_PRESS)
653 {
654 GtkButton *p_button_ok = (GtkButton *)gtk_dialog_get_widget_for_response(GTK_DIALOG(p_dialog), GTK_RESPONSE_OK);
655 gtk_button_clicked(p_button_ok);
656 }
657 }
658 return FALSE;
659 }
660 g_signal_connect(p_treeview_kbd_change, "button-press-event",
661 G_CALLBACK(on_treeview_kbd_change_button_press_event), NULL);
662 gtk_widget_set_size_request(p_dialog, 600, 500);
663 gtk_widget_show_all(GTK_WIDGET(p_scrolledwindow_kbd_change));
664 gint response = gtk_dialog_run(GTK_DIALOG(p_dialog));
665 if(response == GTK_RESPONSE_OK)
666 {
667 GtkTreeIter tree_iter_sel;
668 GtkTreeSelection *p_treeselection_kbd_change = gtk_tree_view_get_selection(GTK_TREE_VIEW(p_treeview_kbd_change));
669 if(gtk_tree_selection_get_selected(p_treeselection_kbd_change,
670 (GtkTreeModel **)(&p_liststore_kbd_change),
671 &tree_iter_sel))
672 {
673 gchar *kbd_change_new;
674 gtk_tree_model_get(GTK_TREE_MODEL(p_liststore_kbd_change),
675 &tree_iter_sel, COLUMN_CHANGE_NAME, &kbd_change_new, -1);
676 g_free(p_xkb->kbd_change_option);
677 p_xkb->kbd_change_option = g_strdup(kbd_change_new);
678 gtk_button_set_label(GTK_BUTTON(p_xkb->p_button_change_layout), p_xkb->kbd_change_option);
679 g_free(kbd_change_new);
680 xkb_setxkbmap(p_xkb);
681 xkb_redraw(p_xkb);
682 }
683 }
684 gtk_widget_destroy(p_dialog);
685}
686
687static void on_button_up_layout_clicked(GtkButton *p_button, gpointer *p_data)
688{
689 XkbPlugin *p_xkb = (XkbPlugin *)p_data;
690 GtkTreeIter tree_iter_sel;
691 GtkTreeIter tree_iter_prev;
692 if(gtk_tree_selection_get_selected(p_xkb->p_treeselection_layout,
693 (GtkTreeModel **)(&p_xkb->p_liststore_layout),
694 &tree_iter_sel))
695 {
696 GtkTreePath *p_tree_path = gtk_tree_model_get_path(GTK_TREE_MODEL(p_xkb->p_liststore_layout),
697 &tree_iter_sel);
698 if( (gtk_tree_path_prev(p_tree_path)) &&
699 (gtk_tree_model_get_iter(GTK_TREE_MODEL(p_xkb->p_liststore_layout),
700 &tree_iter_prev,
701 p_tree_path)))
702 {
703 gtk_list_store_swap(p_xkb->p_liststore_layout, &tree_iter_sel, &tree_iter_prev);
704 xkb_update_layouts_n_variants(p_xkb);
705 }
706 gtk_tree_path_free(p_tree_path);
707 }
708}
709
710static void on_button_down_layout_clicked(GtkButton *p_button, gpointer *p_data)
711{
712 XkbPlugin *p_xkb = (XkbPlugin *)p_data;
713 GtkTreeIter tree_iter_sel;
714 GtkTreeIter tree_iter_next;
715 if(gtk_tree_selection_get_selected(p_xkb->p_treeselection_layout,
716 (GtkTreeModel **)(&p_xkb->p_liststore_layout),
717 &tree_iter_sel))
718 {
719 tree_iter_next = tree_iter_sel;
720 if(gtk_tree_model_iter_next(GTK_TREE_MODEL(p_xkb->p_liststore_layout),
721 &tree_iter_next))
722 {
723 gtk_list_store_swap(p_xkb->p_liststore_layout, &tree_iter_sel, &tree_iter_next);
724 xkb_update_layouts_n_variants(p_xkb);
725 }
726 }
727}
728
729static void on_button_rm_layout_clicked(GtkButton *p_button, gpointer *p_data)
730{
731 XkbPlugin *p_xkb = (XkbPlugin *)p_data;
732 GtkTreeIter tree_iter_sel;
733 if(gtk_tree_selection_get_selected(p_xkb->p_treeselection_layout,
734 (GtkTreeModel **)(&p_xkb->p_liststore_layout),
735 &tree_iter_sel))
736 {
737 gtk_list_store_remove(p_xkb->p_liststore_layout, &tree_iter_sel);
738 xkb_update_layouts_n_variants(p_xkb);
739 gtk_widget_set_sensitive(p_xkb->p_button_rm_layout, p_xkb->num_layouts > 1);
740 }
741}
742
743static void on_button_add_layout_clicked(GtkButton *p_button, gpointer *p_data)
744{
745 XkbPlugin *p_xkb = (XkbPlugin *)p_data;
746
747 // dialog
748 GtkWidget *p_dialog = gtk_dialog_new_with_buttons(_("Add Keyboard Layout"),
749 GTK_WINDOW(p_xkb->p_dialog_config),
750 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
751 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
752 GTK_STOCK_OK, GTK_RESPONSE_OK,
753 NULL);
754
755 // scrolledwindow
756 GtkWidget * p_scrolledwindow_add_layout = gtk_scrolled_window_new(NULL, NULL);
757 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(p_scrolledwindow_add_layout),
758 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
759 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(p_dialog)->vbox), p_scrolledwindow_add_layout, TRUE, TRUE, 2);
760
761 // treestore
762 GtkTreeStore *p_treestore_add_layout = gtk_tree_store_new(NUM_ADD_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
763 GtkWidget *p_treeview_add_layout = gtk_tree_view_new_with_model(GTK_TREE_MODEL(p_treestore_add_layout));
764 g_object_unref(G_OBJECT(p_treestore_add_layout));
765 gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(p_treeview_add_layout), TRUE);
766 gtk_container_add(GTK_CONTAINER(p_scrolledwindow_add_layout), p_treeview_add_layout);
767 GtkCellRenderer *p_renderer;
768 GtkTreeViewColumn *p_column;
769 // icon
770 p_renderer = gtk_cell_renderer_pixbuf_new();
771 p_column = gtk_tree_view_column_new_with_attributes(_("Flag"), p_renderer, "pixbuf", COLUMN_ICON, NULL);
772 gtk_tree_view_append_column(GTK_TREE_VIEW(p_treeview_add_layout), p_column);
773 // layout
774 p_renderer = gtk_cell_renderer_text_new();
775 p_column = gtk_tree_view_column_new_with_attributes(_("Layout"), p_renderer, "text", COLUMN_LAYOUT, NULL);
776 gtk_tree_view_append_column(GTK_TREE_VIEW(p_treeview_add_layout), p_column);
777 // desc
778 p_renderer = gtk_cell_renderer_text_new();
779 p_column = gtk_tree_view_column_new_with_attributes(_("Description"), p_renderer, "text", COLUMN_VARIANT, NULL);
780 gtk_tree_view_append_column(GTK_TREE_VIEW(p_treeview_add_layout), p_column);
781
782 // populate model
783 GKeyFile *p_keyfile = g_key_file_new();
784 gchar *xkbcfg_filepath = g_strdup_printf("%s/layouts.cfg", XKBCONFDIR);
785 if(g_key_file_load_from_file(p_keyfile, xkbcfg_filepath, 0, NULL))
786 {
787 gchar **keys_layouts = g_key_file_get_keys(p_keyfile, "LAYOUTS", NULL, NULL);
788 guint layout_idx = 0;
789 GtkTreeIter tree_top, tree_child;
790 gchar *p_layout_desc;
791 while(keys_layouts[layout_idx] != NULL)
792 {
793 p_layout_desc = g_key_file_get_string(p_keyfile, "LAYOUTS", keys_layouts[layout_idx], NULL);
794 if(strchr(keys_layouts[layout_idx], '(') == NULL)
795 {
796 gchar *flag_filepath = NULL;
797 gchar *flags_dir = (p_xkb->cust_dir_exists && (p_xkb->display_type == DISP_TYPE_IMAGE_CUST)) ? g_strdup(FLAGSCUSTDIR):g_strdup(FLAGSDIR);
798 if(strchr(keys_layouts[layout_idx], '/') != NULL)
799 {
800 gchar *layout_mod = g_strdup(keys_layouts[layout_idx]);
801 layout_mod = g_strdelimit(layout_mod, "/", '-');
802 flag_filepath = g_strdup_printf(flag_filepath_generator, flags_dir, layout_mod);
803 g_free(layout_mod);
804 }
805 else
806 {
807 flag_filepath = g_strdup_printf(flag_filepath_generator, flags_dir, keys_layouts[layout_idx]);
808 }
809 GdkPixbuf *p_pixbuf = gdk_pixbuf_new_from_file_at_size(flag_filepath, -1, 16, NULL);
810 gtk_tree_store_append(p_treestore_add_layout, &tree_top, NULL);
811 if(p_pixbuf != NULL)
812 {
813 gtk_tree_store_set(p_treestore_add_layout, &tree_top,
814 COLUMN_ADD_ICON, p_pixbuf,
815 COLUMN_ADD_LAYOUT, keys_layouts[layout_idx],
816 COLUMN_ADD_DESC, p_layout_desc,
817 -1);
818 g_object_unref(G_OBJECT(p_pixbuf));
819 }
820 else
821 {
822 gtk_tree_store_set(p_treestore_add_layout, &tree_top,
823 COLUMN_ADD_LAYOUT, keys_layouts[layout_idx],
824 COLUMN_ADD_DESC, p_layout_desc,
825 -1);
826 }
827 g_free(flag_filepath);
828 g_free(flags_dir);
829 }
830 else
831 {
832
833 gtk_tree_store_append(p_treestore_add_layout, &tree_child, &tree_top);
834 gtk_tree_store_set(p_treestore_add_layout, &tree_child,
835 COLUMN_ADD_LAYOUT, keys_layouts[layout_idx],
836 COLUMN_ADD_DESC, p_layout_desc,
837 -1);
838 }
839 g_free(p_layout_desc);
840 layout_idx++;
841 }
842 g_strfreev(keys_layouts);
843 g_key_file_free(p_keyfile);
844 }
845 g_free(xkbcfg_filepath);
846
847 // callback for double click
848 gboolean on_treeview_add_layout_button_press_event(GtkWidget *p_widget,
849 GdkEventButton *p_event,
850 gpointer p_data)
851 {
852 if(p_event->button == 1)
853 {
854 if(p_event->type == GDK_2BUTTON_PRESS)
855 {
856 GtkButton *p_button_ok = (GtkButton *)gtk_dialog_get_widget_for_response(GTK_DIALOG(p_dialog), GTK_RESPONSE_OK);
857 gtk_button_clicked(p_button_ok);
858 }
859 }
860 return FALSE;
861 }
862 g_signal_connect(p_treeview_add_layout, "button-press-event",
863 G_CALLBACK(on_treeview_add_layout_button_press_event), NULL);
864 gtk_widget_set_size_request(p_dialog, 600, 500);
865 gtk_widget_show_all(GTK_WIDGET(p_scrolledwindow_add_layout));
866 gint response = gtk_dialog_run(GTK_DIALOG(p_dialog));
867 if(response == GTK_RESPONSE_OK)
868 {
869 GtkTreeIter tree_iter_sel;
870 GtkTreeSelection *p_treeselection_add_layout = gtk_tree_view_get_selection(GTK_TREE_VIEW(p_treeview_add_layout));
871 if(gtk_tree_selection_get_selected(p_treeselection_add_layout,
872 (GtkTreeModel **)(&p_treestore_add_layout),
873 &tree_iter_sel))
874 {
875 gchar *layout_add;
876 GString *p_gstring_new_layout = g_string_new("");
877 GString *p_gstring_new_variant = g_string_new("");
878 gtk_tree_model_get(GTK_TREE_MODEL(p_treestore_add_layout),
879 &tree_iter_sel, COLUMN_ADD_LAYOUT, &layout_add, -1);
880
881 if(strchr(layout_add, '(') == NULL)
882 {
883 g_string_append(p_gstring_new_layout, layout_add);
884 }
885 else
886 {
887 gboolean parsing_variant = FALSE;
888 guchar i;
889 for(i=0; layout_add[i]; i++)
890 {
891 if(!parsing_variant)
892 {
893 if(layout_add[i] == '(')
894 parsing_variant = TRUE;
895 else
896 g_string_append_c(p_gstring_new_layout, layout_add[i]);
897 }
898 else
899 {
900 if(layout_add[i] == ')')
901 break;
902 else
903 g_string_append_c(p_gstring_new_variant, layout_add[i]);
904 }
905 }
906 }
907 xkb_add_layout(p_xkb, p_gstring_new_layout->str, p_gstring_new_variant->str);
908 xkb_update_layouts_n_variants(p_xkb);
909
910 gtk_widget_set_sensitive(p_xkb->p_button_rm_layout, p_xkb->num_layouts > 1);
911
912 g_free(layout_add);
913 g_string_free(p_gstring_new_layout, TRUE/*free also gstring->str*/);
914 g_string_free(p_gstring_new_variant, TRUE/*free also gstring->str*/);
915 }
916 }
917 gtk_widget_destroy(p_dialog);
918}
919
920static void xkb_setxkbmap(XkbPlugin *p_xkb)
921{
922 GString *p_gstring_syscmd = g_string_new("");
923 g_string_printf(p_gstring_syscmd,
924 "setxkbmap -model %s -layout %s -variant %s -option grp:%s",
925 p_xkb->kbd_model, p_xkb->kbd_layouts, p_xkb->kbd_variants, p_xkb->kbd_change_option);
926 if(system("setxkbmap -option")) {}; // reset options
927 if(system(p_gstring_syscmd->str)) {}; // set new map
928 //g_printf("\n%s\n", p_gstring_syscmd->str);
929 g_string_free(p_gstring_syscmd, TRUE/*free also gstring->str*/);
930}
931
932static gboolean layouts_tree_model_foreach(GtkTreeModel *p_model,
933 GtkTreePath *p_path,
934 GtkTreeIter *p_iter,
935 gpointer p_data)
936{
937 XkbPlugin *p_xkb = (XkbPlugin *)p_data;
938 gchar *layout_val;
939 gchar *variant_val;
940
941 gtk_tree_model_get(p_model, p_iter, COLUMN_LAYOUT, &layout_val, -1);
942 gtk_tree_model_get(p_model, p_iter, COLUMN_VARIANT, &variant_val, -1);
943
944 if(strlen(p_xkb->p_gstring_layouts_partial->str))
945 {
946 g_string_append_c(p_xkb->p_gstring_layouts_partial, ',');
947 g_string_append_c(p_xkb->p_gstring_variants_partial, ',');
948 }
949 g_string_append(p_xkb->p_gstring_layouts_partial, layout_val);
950 g_string_append(p_xkb->p_gstring_variants_partial, variant_val);
951
952 //printf("\npartial layouts = '%s'\n", p_xkb->p_gstring_layouts_partial->str);
953 //printf("partial variants = '%s'\n", p_xkb->p_gstring_variants_partial->str);
954
955 g_free(layout_val);
956 g_free(variant_val);
957 p_xkb->num_layouts++;
958 return FALSE;
959}
960
961static void xkb_update_layouts_n_variants(XkbPlugin *p_xkb)
962{
963 p_xkb->p_gstring_layouts_partial = g_string_new("");
964 p_xkb->p_gstring_variants_partial = g_string_new("");
965 p_xkb->num_layouts = 0;
966 gtk_tree_model_foreach(GTK_TREE_MODEL(p_xkb->p_liststore_layout),
967 layouts_tree_model_foreach,
968 p_xkb);
969 if(!strlen(p_xkb->p_gstring_variants_partial->str))
970 {
971 g_string_append_c(p_xkb->p_gstring_variants_partial, ',');
972 }
973 g_free(p_xkb->kbd_layouts);
974 g_free(p_xkb->kbd_variants);
975 p_xkb->kbd_layouts = g_strdup(p_xkb->p_gstring_layouts_partial->str);
976 p_xkb->kbd_variants = g_strdup(p_xkb->p_gstring_variants_partial->str);
977 g_string_free(p_xkb->p_gstring_layouts_partial, TRUE/*free also gstring->str*/);
978 g_string_free(p_xkb->p_gstring_variants_partial, TRUE/*free also gstring->str*/);
979 xkb_setxkbmap(p_xkb);
980 xkb_mechanism_destructor(p_xkb);
981 xkb_mechanism_constructor(p_xkb);
982 xkb_redraw(p_xkb);
983}
984
985static void xkb_add_layout(XkbPlugin *p_xkb, gchar *layout, gchar*variant)
986{
987 GtkTreeIter tree_iter;
988 gtk_list_store_append(p_xkb->p_liststore_layout, &tree_iter);
989 gchar *flag_filepath = NULL;
990 gchar *flags_dir = (p_xkb->cust_dir_exists && (p_xkb->display_type == DISP_TYPE_IMAGE_CUST)) ? g_strdup(FLAGSCUSTDIR):g_strdup(FLAGSDIR);
991 if(strchr(layout, '/') != NULL)
992 {
993 gchar *layout_mod = g_strdup(layout);
994 layout_mod = g_strdelimit(layout_mod, "/", '-');
995 flag_filepath = g_strdup_printf(flag_filepath_generator, flags_dir, layout_mod);
996 g_free(layout_mod);
997 }
998 else
999 {
1000 flag_filepath = g_strdup_printf(flag_filepath_generator, flags_dir, layout);
1001 }
1002 GdkPixbuf *p_pixbuf = gdk_pixbuf_new_from_file_at_size(flag_filepath, -1, 20, NULL);
1003 if(p_pixbuf != NULL)
1004 {
1005 gtk_list_store_set(p_xkb->p_liststore_layout, &tree_iter,
1006 COLUMN_ICON, p_pixbuf,
1007 COLUMN_LAYOUT, layout,
1008 COLUMN_VARIANT, variant,
1009 -1);
1010 g_object_unref(G_OBJECT(p_pixbuf));
1011 }
1012 else
1013 {
1014 gtk_list_store_set(p_xkb->p_liststore_layout, &tree_iter,
1015 COLUMN_LAYOUT, layout,
1016 COLUMN_VARIANT, variant,
1017 -1);
1018 }
1019 g_free(flag_filepath);
1020 g_free(flags_dir);
1021}
1022
1023static void xkb_settings_fill_layout_tree_model_with_config(XkbPlugin *p_xkb)
1024{
1025 p_xkb->num_layouts = 0;
1026 if(strlen(p_xkb->kbd_layouts) && strlen(p_xkb->kbd_variants))
1027 {
1028 char **layouts = g_strsplit_set(p_xkb->kbd_layouts, ",", 0);
1029 char **variants = g_strsplit_set(p_xkb->kbd_variants, ",", 0);
1030
1031 while(layouts[p_xkb->num_layouts] != NULL)
1032 {
1033 xkb_add_layout(p_xkb, layouts[p_xkb->num_layouts], variants[p_xkb->num_layouts]);
1034 p_xkb->num_layouts++;
1035 }
1036 gtk_widget_set_sensitive(p_xkb->p_button_rm_layout, p_xkb->num_layouts > 1);
1037
1038 g_strfreev(layouts);
1039 g_strfreev(variants);
1040 }
22242ed4
HJYP
1041}
1042
d862b520 1043/* Callback when the configuration dialog is to be shown. */
1044static void xkb_configure(Plugin * p, GtkWindow * parent)
22242ed4 1045{
4496e880
JL
1046 XkbPlugin * p_xkb = (XkbPlugin *)p->priv;
1047 gchar markup_str[MAX_MARKUP_LEN];
1048
1049 user_active = FALSE;
d862b520 1050
4496e880 1051 // configuration dialog
d862b520 1052 GtkWidget * dlg = gtk_dialog_new_with_buttons(
4496e880 1053 _("Keyboard Layout Handler"),
d862b520 1054 NULL,
1055 GTK_DIALOG_NO_SEPARATOR,
4496e880 1056 GTK_STOCK_CLOSE,
d862b520 1057 GTK_RESPONSE_OK,
1058 NULL);
4496e880 1059 p_xkb->p_dialog_config = dlg;
d862b520 1060 panel_apply_icon(GTK_WINDOW(dlg));
1061
4496e880
JL
1062 // main vbox of the config dialog
1063 GtkWidget * p_vbox_main = gtk_vbox_new(FALSE, 0);
1064 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dlg)->vbox), p_vbox_main);
1065
1066
1067 // 'KEYBOARD MODEL' frame
1068 GtkWidget * p_frame_kbd_model = gtk_frame_new(NULL);
1069 GtkWidget * p_label_kbd_model = gtk_label_new(NULL);
1070 snprintf(markup_str, MAX_MARKUP_LEN, "<b>%s</b>", _("Keyboard Model"));
1071 gtk_label_set_markup(GTK_LABEL(p_label_kbd_model), markup_str);
1072 gtk_misc_set_padding(GTK_MISC(p_label_kbd_model), 1, 0);
1073 gtk_frame_set_label_widget(GTK_FRAME(p_frame_kbd_model), p_label_kbd_model);
1074 gtk_frame_set_shadow_type(GTK_FRAME(p_frame_kbd_model), GTK_SHADOW_NONE);
1075 gtk_box_pack_start(GTK_BOX(p_vbox_main), p_frame_kbd_model, TRUE, TRUE, 2);
1076 gtk_container_set_border_width(GTK_CONTAINER(p_frame_kbd_model), 3);
1077
1078 // frame alignment
1079 GtkWidget * p_alignment_kbd_model = gtk_alignment_new(0.5, 0.5, 1, 1);
1080 gtk_container_add(GTK_CONTAINER(p_frame_kbd_model), p_alignment_kbd_model);
1081 gtk_alignment_set_padding(GTK_ALIGNMENT(p_alignment_kbd_model), 4, 4, 10, 10);
1082 p_xkb->p_button_kbd_model = gtk_button_new_with_label(p_xkb->kbd_model);
1083 g_signal_connect(p_xkb->p_button_kbd_model, "clicked", G_CALLBACK(on_button_kbd_model_clicked), p_xkb);
1084 gtk_container_add(GTK_CONTAINER(p_alignment_kbd_model), p_xkb->p_button_kbd_model);
1085
1086
1087 // 'KEYBOARD LAYOUTS' frame
1088 GtkWidget * p_frame_kbd_layouts = gtk_frame_new(NULL);
1089 GtkWidget * p_label_kbd_layouts = gtk_label_new(NULL);
1090 snprintf(markup_str, MAX_MARKUP_LEN, "<b>%s</b>", _("Keyboard Layouts"));
1091 gtk_label_set_markup(GTK_LABEL(p_label_kbd_layouts), markup_str);
1092 gtk_misc_set_padding(GTK_MISC(p_label_kbd_layouts), 1, 0);
1093 gtk_frame_set_label_widget(GTK_FRAME(p_frame_kbd_layouts), p_label_kbd_layouts);
1094 gtk_frame_set_shadow_type(GTK_FRAME(p_frame_kbd_layouts), GTK_SHADOW_NONE);
1095 gtk_box_pack_start(GTK_BOX(p_vbox_main), p_frame_kbd_layouts, TRUE, TRUE, 2);
1096 gtk_container_set_border_width(GTK_CONTAINER(p_frame_kbd_layouts), 3);
1097 gtk_widget_set_size_request(GTK_WIDGET(p_frame_kbd_layouts), -1, 180);
1098
1099 // frame alignment
1100 GtkWidget * p_alignment_kbd_layouts = gtk_alignment_new(0.5, 0.5, 1, 1);
1101 gtk_container_add(GTK_CONTAINER(p_frame_kbd_layouts), p_alignment_kbd_layouts);
1102 gtk_alignment_set_padding(GTK_ALIGNMENT(p_alignment_kbd_layouts), 4, 4, 10, 10);
1103 GtkWidget * p_hbox_kbd_layouts = gtk_hbox_new(FALSE, 0);
1104 gtk_container_add(GTK_CONTAINER(p_alignment_kbd_layouts), p_hbox_kbd_layouts);
1105
1106 // scrolledwindow and buttons
1107 GtkWidget * p_scrolledwindow_kbd_layouts = gtk_scrolled_window_new(NULL, NULL);
1108 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(p_scrolledwindow_kbd_layouts),
1109 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1110 gtk_box_pack_start(GTK_BOX(p_hbox_kbd_layouts), p_scrolledwindow_kbd_layouts, TRUE, TRUE, 2);
1111 GtkWidget * p_vbox_kbd_layouts = gtk_vbox_new(FALSE, 2);
1112 gtk_box_pack_start(GTK_BOX(p_hbox_kbd_layouts), p_vbox_kbd_layouts, FALSE, TRUE, 4);
1113 GtkWidget * p_button_add_layout = gtk_button_new_from_stock(GTK_STOCK_ADD);
1114 GtkWidget * p_button_up_layout = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
1115 GtkWidget * p_button_down_layout = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
1116 p_xkb->p_button_rm_layout = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
1117 g_signal_connect(p_button_add_layout, "clicked", G_CALLBACK(on_button_add_layout_clicked), p_xkb);
1118 g_signal_connect(p_xkb->p_button_rm_layout, "clicked", G_CALLBACK(on_button_rm_layout_clicked), p_xkb);
1119 g_signal_connect(p_button_up_layout, "clicked", G_CALLBACK(on_button_up_layout_clicked), p_xkb);
1120 g_signal_connect(p_button_down_layout, "clicked", G_CALLBACK(on_button_down_layout_clicked), p_xkb);
1121 gtk_box_pack_start(GTK_BOX(p_vbox_kbd_layouts), p_button_add_layout, FALSE, TRUE, 0);
1122 gtk_box_pack_start(GTK_BOX(p_vbox_kbd_layouts), p_xkb->p_button_rm_layout, FALSE, TRUE, 0);
1123 gtk_box_pack_start(GTK_BOX(p_vbox_kbd_layouts), p_button_up_layout, FALSE, TRUE, 0);
1124 gtk_box_pack_start(GTK_BOX(p_vbox_kbd_layouts), p_button_down_layout, FALSE, TRUE, 0);
1125
1126 // liststore
1127 p_xkb->p_liststore_layout = gtk_list_store_new(NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
1128 p_xkb->p_treeview_layout = gtk_tree_view_new_with_model(GTK_TREE_MODEL(p_xkb->p_liststore_layout));
1129 g_object_unref(G_OBJECT(p_xkb->p_liststore_layout));
1130 p_xkb->p_treeselection_layout = gtk_tree_view_get_selection(GTK_TREE_VIEW(p_xkb->p_treeview_layout));
1131 gtk_container_add(GTK_CONTAINER(p_scrolledwindow_kbd_layouts), p_xkb->p_treeview_layout);
1132 GtkCellRenderer *p_renderer;
1133 GtkTreeViewColumn *p_column;
1134 // icon
1135 p_renderer = gtk_cell_renderer_pixbuf_new();
1136 p_column = gtk_tree_view_column_new_with_attributes(_("Flag"), p_renderer, "pixbuf", COLUMN_ICON, NULL);
1137 gtk_tree_view_append_column(GTK_TREE_VIEW(p_xkb->p_treeview_layout), p_column);
1138 // layout
1139 p_renderer = gtk_cell_renderer_text_new();
1140 p_column = gtk_tree_view_column_new_with_attributes(_("Layout"), p_renderer, "text", COLUMN_LAYOUT, NULL);
1141 gtk_tree_view_append_column(GTK_TREE_VIEW(p_xkb->p_treeview_layout), p_column);
1142 // variant
1143 p_renderer = gtk_cell_renderer_text_new();
1144 p_column = gtk_tree_view_column_new_with_attributes(_("Variant"), p_renderer, "text", COLUMN_VARIANT, NULL);
1145 gtk_tree_view_append_column(GTK_TREE_VIEW(p_xkb->p_treeview_layout), p_column);
1146 xkb_settings_fill_layout_tree_model_with_config(p_xkb);
1147
1148
1149 // 'CHANGE LAYOUT OPTION' frame
1150 GtkWidget * p_frame_change_layout = gtk_frame_new(NULL);
1151 GtkWidget * p_label_change_layout = gtk_label_new(NULL);
1152 snprintf(markup_str, MAX_MARKUP_LEN, "<b>%s</b>", _("Change Layout Option"));
1153 gtk_label_set_markup(GTK_LABEL(p_label_change_layout), markup_str);
1154 gtk_misc_set_padding(GTK_MISC(p_label_change_layout), 1, 0);
1155 gtk_frame_set_label_widget(GTK_FRAME(p_frame_change_layout), p_label_change_layout);
1156 gtk_frame_set_shadow_type(GTK_FRAME(p_frame_change_layout), GTK_SHADOW_NONE);
1157 gtk_box_pack_start(GTK_BOX(p_vbox_main), p_frame_change_layout, TRUE, TRUE, 2);
1158 gtk_container_set_border_width(GTK_CONTAINER(p_frame_change_layout), 3);
1159
1160 // frame alignment
1161 GtkWidget * p_alignment_change_layout = gtk_alignment_new(0.5, 0.5, 1, 1);
1162 gtk_container_add(GTK_CONTAINER(p_frame_change_layout), p_alignment_change_layout);
1163 gtk_alignment_set_padding(GTK_ALIGNMENT(p_alignment_change_layout), 4, 4, 10, 10);
1164 p_xkb->p_button_change_layout = gtk_button_new_with_label(p_xkb->kbd_change_option);
1165 g_signal_connect(p_xkb->p_button_change_layout, "clicked", G_CALLBACK(on_button_kbd_change_layout_clicked), p_xkb);
1166 gtk_container_add(GTK_CONTAINER(p_alignment_change_layout), p_xkb->p_button_change_layout);
1167
1168
1169 // 'SHOW LAYOUT AS' frame
1170 GtkWidget * p_frame_display_type = gtk_frame_new(NULL);
1171 GtkWidget * p_label_show_layout_as = gtk_label_new(NULL);
1172 snprintf(markup_str, MAX_MARKUP_LEN, "<b>%s</b>", _("Show Layout as"));
1173 gtk_label_set_markup(GTK_LABEL(p_label_show_layout_as), markup_str);
1174 gtk_misc_set_padding(GTK_MISC(p_label_show_layout_as), 1, 0);
1175 gtk_frame_set_label_widget(GTK_FRAME(p_frame_display_type), p_label_show_layout_as);
1176 gtk_frame_set_shadow_type(GTK_FRAME(p_frame_display_type), GTK_SHADOW_NONE);
1177 gtk_box_pack_start(GTK_BOX(p_vbox_main), p_frame_display_type, TRUE, TRUE, 2);
1178 gtk_container_set_border_width(GTK_CONTAINER(p_frame_display_type), 3);
1179
1180 // frame alignment
1181 GtkWidget * p_alignment_display_type = gtk_alignment_new(0.5, 0.5, 1, 1);
1182 gtk_container_add(GTK_CONTAINER(p_frame_display_type), p_alignment_display_type);
1183 gtk_alignment_set_padding(GTK_ALIGNMENT(p_alignment_display_type), 4, 4, 10, 10);
1184 GtkWidget *p_table = gtk_table_new(3, 2, FALSE);
1185 gtk_table_set_col_spacings(GTK_TABLE(p_table), 10);
1186 gtk_container_add(GTK_CONTAINER(p_alignment_display_type), p_table);
1187
1188 // radiobuttons
1189 GtkWidget * p_image_disp_type_image = gtk_image_new();
1190 GtkWidget * p_image_disp_type_image_cust = NULL;
1191 gchar *symbol_name_lowercase = (char *)xkb_get_current_symbol_name_lowercase(p_xkb);
1192 gchar *flag_filepath = NULL;
1193 gchar *flag_filepath_cust = NULL;
1194 if(strchr(symbol_name_lowercase, '/') != NULL)
1195 {
1196 gchar *layout_mod = g_strdup(symbol_name_lowercase);
1197 layout_mod = g_strdelimit(layout_mod, "/", '-');
1198 flag_filepath = g_strdup_printf(flag_filepath_generator, FLAGSDIR, layout_mod);
1199 if(p_xkb->cust_dir_exists)
1200 flag_filepath_cust = g_strdup_printf(flag_filepath_generator, FLAGSCUSTDIR, layout_mod);
1201 g_free(layout_mod);
1202 }
1203 else
1204 {
1205 flag_filepath = g_strdup_printf(flag_filepath_generator, FLAGSDIR, symbol_name_lowercase);
1206 if(p_xkb->cust_dir_exists)
1207 flag_filepath_cust = g_strdup_printf(flag_filepath_generator, FLAGSCUSTDIR, symbol_name_lowercase);
1208 }
1209 GdkPixbuf *p_pixbuf = gdk_pixbuf_new_from_file_at_size(flag_filepath, -1, 16, NULL);
1210 if(p_pixbuf != NULL)
1211 {
1212 gtk_image_set_from_pixbuf(GTK_IMAGE(p_image_disp_type_image), p_pixbuf);
1213 g_object_unref(G_OBJECT(p_pixbuf));
1214 }
1215 if(flag_filepath_cust != NULL)
1216 {
1217 p_image_disp_type_image_cust = gtk_image_new();
1218 GdkPixbuf *p_pixbuf_cust = gdk_pixbuf_new_from_file_at_size(flag_filepath_cust, -1, 16, NULL);
1219 if(p_pixbuf_cust != NULL)
1220 {
1221 gtk_image_set_from_pixbuf(GTK_IMAGE(p_image_disp_type_image_cust), p_pixbuf_cust);
1222 g_object_unref(G_OBJECT(p_pixbuf_cust));
1223 }
1224 }
1225 g_free(flag_filepath);
1226 if(flag_filepath_cust != NULL)
1227 g_free(flag_filepath_cust);
1228 g_free(symbol_name_lowercase);
1229 GtkWidget * p_label_disp_type_text = gtk_label_new(NULL);
1230 snprintf(markup_str, MAX_MARKUP_LEN, "<span font='%d' font_weight='heavy'>%s</span>", 16, xkb_get_current_symbol_name(p_xkb));
1231 gtk_label_set_markup(GTK_LABEL(p_label_disp_type_text), markup_str);
1232 GtkWidget * p_radiobutton_disp_type_image = gtk_radio_button_new_with_label(NULL, (const gchar *)_("Flag Image"));
1233 GtkWidget * p_radiobutton_disp_type_image_cust = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(p_radiobutton_disp_type_image), (const gchar *)_("Custom Image"));
1234 GtkWidget * p_radiobutton_disp_type_text = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(p_radiobutton_disp_type_image), (const gchar *)_("Text"));
1235
1236 gtk_table_attach(GTK_TABLE(p_table), p_image_disp_type_image, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
1237 gtk_table_attach(GTK_TABLE(p_table), p_radiobutton_disp_type_image, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
1238 if(p_xkb->cust_dir_exists)
1239 {
1240 gtk_table_attach(GTK_TABLE(p_table), p_image_disp_type_image_cust, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
1241 gtk_table_attach(GTK_TABLE(p_table), p_radiobutton_disp_type_image_cust, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
1242 }
1243 gtk_table_attach(GTK_TABLE(p_table), p_label_disp_type_text, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
1244 gtk_table_attach(GTK_TABLE(p_table), p_radiobutton_disp_type_text, 1, 2, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
1245
1246 g_signal_connect(p_radiobutton_disp_type_image, "toggled", G_CALLBACK(on_radiobutton_disp_type_image_toggled), p_xkb);
1247 if(p_xkb->cust_dir_exists)
1248 g_signal_connect(p_radiobutton_disp_type_image_cust, "toggled", G_CALLBACK(on_radiobutton_disp_type_image_cust_toggled), p_xkb);
1249 g_signal_connect(p_radiobutton_disp_type_text, "toggled", G_CALLBACK(on_radiobutton_disp_type_text_toggled), p_xkb);
1250 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_radiobutton_disp_type_image), (p_xkb->display_type == DISP_TYPE_IMAGE) ||
1251 ( (p_xkb->display_type == DISP_TYPE_IMAGE_CUST) && (!p_xkb->cust_dir_exists) ) );
1252 if(p_xkb->cust_dir_exists)
1253 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_radiobutton_disp_type_image_cust), p_xkb->display_type == DISP_TYPE_IMAGE_CUST);
1254 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_radiobutton_disp_type_text), p_xkb->display_type == DISP_TYPE_TEXT);
1255
1256
1257 // 'PANEL ICON SIZE' frame
1258 GtkWidget * p_frame_flag_size = gtk_frame_new(NULL);
1259 GtkWidget * p_label_flag_size = gtk_label_new(NULL);
1260 snprintf(markup_str, MAX_MARKUP_LEN, "<b>%s</b>", _("Panel Icon Size"));
1261 gtk_label_set_markup(GTK_LABEL(p_label_flag_size), markup_str);
1262 gtk_misc_set_padding(GTK_MISC(p_label_flag_size), 1, 0);
1263 gtk_frame_set_label_widget(GTK_FRAME(p_frame_flag_size), p_label_flag_size);
1264 gtk_frame_set_shadow_type(GTK_FRAME(p_frame_flag_size), GTK_SHADOW_NONE);
1265 gtk_box_pack_start(GTK_BOX(p_vbox_main), p_frame_flag_size, TRUE, TRUE, 2);
1266 gtk_container_set_border_width(GTK_CONTAINER(p_frame_flag_size), 3);
1267
1268 // frame alignment
1269 GtkWidget * p_alignment_flag_size = gtk_alignment_new(0.5, 0.5, 1, 1);
1270 gtk_container_add(GTK_CONTAINER(p_frame_flag_size), p_alignment_flag_size);
1271 gtk_alignment_set_padding(GTK_ALIGNMENT(p_alignment_flag_size), 4, 4, 10, 10);
1272 GtkWidget *p_hbox_flag_size = gtk_hbox_new(FALSE, 2);
1273 gtk_container_add(GTK_CONTAINER(p_alignment_flag_size), p_hbox_flag_size);
1274
1275 GtkWidget *p_radiobutton_flag_size_1 = gtk_radio_button_new_with_label(NULL, "1");
1276 GtkWidget *p_radiobutton_flag_size_2 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(p_radiobutton_flag_size_1), "2");
1277 GtkWidget *p_radiobutton_flag_size_3 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(p_radiobutton_flag_size_1), "3");
1278 GtkWidget *p_radiobutton_flag_size_4 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(p_radiobutton_flag_size_1), "4");
1279 GtkWidget *p_radiobutton_flag_size_5 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(p_radiobutton_flag_size_1), "5");
1280 g_signal_connect(p_radiobutton_flag_size_1, "toggled", G_CALLBACK(on_radiobutton_flag_size_1_toggled), p_xkb);
1281 g_signal_connect(p_radiobutton_flag_size_2, "toggled", G_CALLBACK(on_radiobutton_flag_size_2_toggled), p_xkb);
1282 g_signal_connect(p_radiobutton_flag_size_3, "toggled", G_CALLBACK(on_radiobutton_flag_size_3_toggled), p_xkb);
1283 g_signal_connect(p_radiobutton_flag_size_4, "toggled", G_CALLBACK(on_radiobutton_flag_size_4_toggled), p_xkb);
1284 g_signal_connect(p_radiobutton_flag_size_5, "toggled", G_CALLBACK(on_radiobutton_flag_size_5_toggled), p_xkb);
1285 gtk_box_pack_start(GTK_BOX(p_hbox_flag_size), p_radiobutton_flag_size_1, TRUE, TRUE, 2);
1286 gtk_box_pack_start(GTK_BOX(p_hbox_flag_size), p_radiobutton_flag_size_2, TRUE, TRUE, 2);
1287 gtk_box_pack_start(GTK_BOX(p_hbox_flag_size), p_radiobutton_flag_size_3, TRUE, TRUE, 2);
1288 gtk_box_pack_start(GTK_BOX(p_hbox_flag_size), p_radiobutton_flag_size_4, TRUE, TRUE, 2);
1289 gtk_box_pack_start(GTK_BOX(p_hbox_flag_size), p_radiobutton_flag_size_5, TRUE, TRUE, 2);
1290 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_radiobutton_flag_size_1), p_xkb->flag_size == 1);
1291 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_radiobutton_flag_size_2), p_xkb->flag_size == 2);
1292 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_radiobutton_flag_size_3), p_xkb->flag_size == 3);
1293 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_radiobutton_flag_size_4), p_xkb->flag_size == 4);
1294 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_radiobutton_flag_size_5), p_xkb->flag_size == 5);
22242ed4 1295
d862b520 1296 /* Connect signals. */
4496e880 1297 g_signal_connect(p_xkb->p_dialog_config, "response", G_CALLBACK(on_dialog_config_response), p_xkb);
22242ed4 1298
d862b520 1299 /* Display the dialog. */
4496e880
JL
1300 gtk_widget_set_size_request(p_xkb->p_dialog_config, 350, -1);
1301 gtk_widget_show_all(p_xkb->p_dialog_config);
1302 gtk_window_present(GTK_WINDOW(p_xkb->p_dialog_config));
1303
1304 user_active = TRUE;
22242ed4
HJYP
1305}
1306
8f9e6256 1307/* Callback when the configuration is to be saved. */
1308static void xkb_save_configuration(Plugin * p, FILE * fp)
1309{
4496e880
JL
1310 XkbPlugin * p_xkb = (XkbPlugin *)p->priv;
1311 lxpanel_put_int(fp, "DisplayType", p_xkb->display_type);
1312 lxpanel_put_str(fp, "Model", p_xkb->kbd_model);
1313 lxpanel_put_str(fp, "LayoutsList", p_xkb->kbd_layouts);
1314 lxpanel_put_str(fp, "VariantsList", p_xkb->kbd_variants);
1315 lxpanel_put_str(fp, "ToggleOpt", p_xkb->kbd_change_option);
1316 lxpanel_put_int(fp, "FlagSize", p_xkb->flag_size);
8f9e6256 1317}
1318
1319/* Callback when panel configuration changes. */
1320static void xkb_panel_configuration_changed(Plugin * p)
1321{
1322 /* Do a full redraw. */
4496e880
JL
1323 XkbPlugin * p_xkb = (XkbPlugin *)p->priv;
1324 xkb_redraw(p_xkb);
8f9e6256 1325}
22242ed4 1326
d862b520 1327/* Plugin descriptor. */
22242ed4 1328PluginClass xkb_plugin_class = {
2918994e 1329
1330 PLUGINCLASS_VERSIONING,
22242ed4
HJYP
1331
1332 type : "xkb",
4496e880
JL
1333 name : N_("Keyboard Layout Handler"),
1334 version: "2.0",
1335 description : N_("Handle keyboard layouts"),
22242ed4
HJYP
1336
1337 constructor : xkb_constructor,
1338 destructor : xkb_destructor,
8f9e6256 1339 config : xkb_configure,
1340 save : xkb_save_configuration,
1341 panel_configuration_changed : xkb_panel_configuration_changed
d862b520 1342
22242ed4 1343};
4496e880 1344