Fix GtkComboBoxEntry in 'netstatus' plugin.
[lxde/lxpanel.git] / plugins / xkb / xkb-plugin.c
CommitLineData
438d9fdb 1/**
b840f7cc 2 * Copyright (c) 2010-2014 LxDE Developers, see the file AUTHORS for details.
438d9fdb
MJ
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"
97088cd4 35#include "gtk-compat.h"
22242ed4 36
4496e880
JL
37enum
38{
39 COLUMN_ICON,
40 COLUMN_LAYOUT,
41 COLUMN_VARIANT,
42 NUM_COLUMNS
43};
44
45enum
46{
47 COLUMN_ADD_ICON,
48 COLUMN_ADD_LAYOUT,
49 COLUMN_ADD_DESC,
50 NUM_ADD_COLUMNS
51};
52
53enum
54{
edeca7f1 55 COLUMN_MODEL_ID,
4496e880
JL
56 COLUMN_MODEL_DESC,
57 NUM_MODEL_COLUMNS
58};
59
60enum
61{
edeca7f1 62 COLUMN_CHANGE_ID,
4496e880 63 COLUMN_CHANGE_DESC,
0f8664b0 64 COLUMN_CHANGE_INCL,
f740757c 65 COLUMN_CHANGE_WEIGHT,
4496e880
JL
66 NUM_CHANGE_COLUMNS
67};
68
ec3e265f 69static void xkb_destructor(gpointer user_data);
4496e880 70static void xkb_settings_fill_layout_tree_model_with_config(XkbPlugin *p_xkb);
4496e880
JL
71static void xkb_update_layouts_n_variants(XkbPlugin *p_xkb);
72static void xkb_add_layout(XkbPlugin *p_xkb, gchar *layout, gchar*variant);
73static int xkb_get_flag_size(XkbPlugin *p_xkb);
74
895da737 75static void on_xkb_fbev_active_window_event(FbEv *ev, gpointer p_data);
4496e880 76static gboolean on_xkb_button_scroll_event(GtkWidget * widget, GdkEventScroll * event, gpointer p_data);
4496e880
JL
77static void on_radiobutton_disp_type_image_toggled(GtkToggleButton *p_radiobutton, gpointer p_data);
78static void on_radiobutton_disp_type_image_cust_toggled(GtkToggleButton *p_radiobutton, gpointer p_data);
79static void on_radiobutton_disp_type_text_toggled(GtkToggleButton *p_radiobutton, gpointer p_data);
895da737 80static void on_xkb_checkbutton_per_app_toggled(GtkToggleButton *tb, gpointer p_data);
876e3dd1 81static void on_xkb_checkbutton_no_reset_opt_toggled(GtkToggleButton *tb, gpointer p_data);
b3d38a01 82static void on_xkb_checkbutton_keep_system_layouts_toggled(GtkToggleButton *tb, gpointer p_data);
4496e880 83static void on_dialog_config_response(GtkDialog *p_dialog, gint response, gpointer p_data);
035ee619
GP
84static void on_xkb_entry_advanced_opt_icon_press(GtkEntry *p_entry,
85 GtkEntryIconPosition icon_pos,
86 GdkEvent *p_event,
87 gpointer p_data);
4496e880
JL
88
89static unsigned char user_active = FALSE;
90static const gchar flag_filepath_generator[] = "%s/%s.png";
91
92static int xkb_get_flag_size(XkbPlugin *p_xkb)
93{
ec3e265f 94 int size = panel_get_icon_size(p_xkb->panel);
4496e880
JL
95 switch(p_xkb->flag_size)
96 {
97 case 1: return size*0.5;
98 case 2: return size*0.6;
99 case 3: return size*0.7;
100 case 4: return size*0.8;
895da737 101 case 5: return size*0.9;
4496e880
JL
102 default: break;
103 }
895da737 104 return size;
4496e880 105}
d862b520 106
107/* Redraw the graphics. */
4496e880 108void xkb_redraw(XkbPlugin *p_xkb)
22242ed4 109{
d862b520 110 /* Set the image. */
111 gboolean valid_image = FALSE;
4496e880
JL
112 int size = xkb_get_flag_size(p_xkb);
113 if( (p_xkb->display_type == DISP_TYPE_IMAGE) || (p_xkb->display_type == DISP_TYPE_IMAGE_CUST) )
22242ed4 114 {
4496e880
JL
115 char * group_name = (char *)xkb_get_current_symbol_name_lowercase(p_xkb);
116 if(group_name != NULL)
d862b520 117 {
4496e880
JL
118 gchar *flag_filepath = NULL;
119 gchar *flags_dir = (p_xkb->cust_dir_exists && (p_xkb->display_type == DISP_TYPE_IMAGE_CUST)) ? g_strdup(FLAGSCUSTDIR):g_strdup(FLAGSDIR);
120 if(strchr(group_name, '/') != NULL)
121 {
122 gchar *layout_mod = g_strdup(group_name);
123 layout_mod = g_strdelimit(layout_mod, "/", '-');
124 flag_filepath = g_strdup_printf(flag_filepath_generator, flags_dir, layout_mod);
125 g_free(layout_mod);
126 }
127 else
128 {
129 flag_filepath = g_strdup_printf(flag_filepath_generator, flags_dir, group_name);
130 }
131 GdkPixbuf * unscaled_pixbuf = gdk_pixbuf_new_from_file(flag_filepath, NULL);
132 g_free(flag_filepath);
133 g_free(flags_dir);
438d9fdb
MJ
134 g_free(group_name);
135
4496e880 136 if(unscaled_pixbuf != NULL)
d862b520 137 {
438d9fdb
MJ
138 /* Loaded successfully. */
139 int width = gdk_pixbuf_get_width(unscaled_pixbuf);
140 int height = gdk_pixbuf_get_height(unscaled_pixbuf);
141 GdkPixbuf * pixbuf = gdk_pixbuf_scale_simple(unscaled_pixbuf, size * width / height, size, GDK_INTERP_BILINEAR);
4496e880 142 if(pixbuf != NULL)
438d9fdb 143 {
4496e880 144 gtk_image_set_from_pixbuf(GTK_IMAGE(p_xkb->p_image), pixbuf);
438d9fdb 145 g_object_unref(G_OBJECT(pixbuf));
4496e880
JL
146 gtk_widget_hide(p_xkb->p_label);
147 gtk_widget_show(p_xkb->p_image);
ec3e265f 148 gtk_widget_set_tooltip_text(p_xkb->p_plugin, xkb_get_current_group_name(p_xkb));
438d9fdb
MJ
149 valid_image = TRUE;
150 }
151 g_object_unref(unscaled_pixbuf);
22242ed4
HJYP
152 }
153 }
154 }
155
d862b520 156 /* Set the label. */
4496e880 157 if( (p_xkb->display_type == DISP_TYPE_TEXT) || ( ! valid_image) )
d862b520 158 {
4496e880 159 char *group_name = (char *)xkb_get_current_symbol_name(p_xkb);
438d9fdb
MJ
160 if (group_name != NULL)
161 {
a7bd16a4 162 lxpanel_draw_label_text(p_xkb->panel, p_xkb->p_label, group_name,
3fd2186c 163 TRUE, size*4/(5*10.0), TRUE);
4496e880
JL
164 gtk_widget_hide(p_xkb->p_image);
165 gtk_widget_show(p_xkb->p_label);
ec3e265f 166 gtk_widget_set_tooltip_text(p_xkb->p_plugin, xkb_get_current_group_name(p_xkb));
d862b520 167 }
168 }
22242ed4
HJYP
169}
170
895da737 171/* Handler for "active_window" event on root window listener. */
0bcf9045 172static void on_xkb_fbev_active_window_event(FbEv * ev, gpointer p_data)
895da737
JL
173{
174 XkbPlugin * xkb = (XkbPlugin *)p_data;
175 if (xkb->enable_perwin)
176 {
177 Window * win = fb_ev_active_window(ev);
178 if (*win != None)
179 {
180 xkb_active_window_changed(xkb, *win);
181 xkb_redraw(xkb);
182 }
183 }
184}
185
d862b520 186/* Handler for "scroll-event" on drawing area. */
4496e880 187static gboolean on_xkb_button_scroll_event(GtkWidget * widget, GdkEventScroll * event, gpointer p_data)
22242ed4 188{
4496e880 189 XkbPlugin * xkb = (XkbPlugin *)p_data;
22242ed4 190
d862b520 191 /* Change to next or previous group. */
192 xkb_change_group(xkb,
193 (((event->direction == GDK_SCROLL_UP) || (event->direction == GDK_SCROLL_RIGHT)) ? 1 : -1));
194 return TRUE;
22242ed4
HJYP
195}
196
d862b520 197/* Handler for button-press-event on top level widget. */
a7bd16a4 198static gboolean on_xkb_button_press_event(GtkWidget * widget, GdkEventButton * event, LXPanel * panel)
22242ed4 199{
d862b520 200 /* Change to next group. */
ec3e265f 201 xkb_change_group(lxpanel_plugin_get_data(widget), 1);
18ecfe2a 202 return TRUE;
22242ed4
HJYP
203}
204
035ee619
GP
205static void on_xkb_entry_advanced_opt_icon_press(GtkEntry *p_entry,
206 GtkEntryIconPosition icon_pos,
207 GdkEvent *p_event,
208 gpointer p_data)
209{
210 XkbPlugin *p_xkb = (XkbPlugin *)p_data;
211 g_free(p_xkb->kbd_advanced_options);
212 p_xkb->kbd_advanced_options = g_strdup(gtk_entry_get_text(p_entry));
ec3e265f 213 config_group_set_string(p_xkb->settings, "AdvancedOpt", p_xkb->kbd_advanced_options);
226cc442 214 xkb_setxkbmap(p_xkb);
035ee619
GP
215}
216
d862b520 217/* Plugin constructor. */
a7bd16a4 218static GtkWidget *xkb_constructor(LXPanel *panel, config_setting_t *settings)
22242ed4 219{
d862b520 220 /* Allocate plugin context and set into Plugin private data pointer. */
4496e880 221 XkbPlugin * p_xkb = g_new0(XkbPlugin, 1);
ec3e265f
AG
222 GtkWidget * p;
223 const char *tmp;
224 int tmp_int;
225
226 p_xkb->panel = panel;
227 p_xkb->settings = settings;
d862b520 228
229 /* Initialize to defaults. */
4496e880 230 p_xkb->display_type = DISP_TYPE_IMAGE;
ec3e265f
AG
231 //p_xkb->enable_perwin = FALSE;
232 //p_xkb->do_not_reset_opt = FALSE;
0078760f 233 p_xkb->keep_system_layouts = TRUE;
ec3e265f
AG
234 //p_xkb->kbd_model = NULL;
235 //p_xkb->kbd_layouts = NULL;
236 //p_xkb->kbd_variants = NULL;
237 //p_xkb->kbd_change_option = NULL;
238 //p_xkb->kbd_advanced_options = NULL;
4496e880
JL
239 p_xkb->flag_size = 3;
240 p_xkb->cust_dir_exists = g_file_test(FLAGSCUSTDIR, G_FILE_TEST_IS_DIR);
d862b520 241
242 /* Load parameters from the configuration file. */
ec3e265f
AG
243 config_setting_lookup_int(settings, "DisplayType", &p_xkb->display_type);
244 if (config_setting_lookup_int(settings, "PerWinLayout", &tmp_int))
245 p_xkb->enable_perwin = tmp_int != 0;
246 if (config_setting_lookup_int(settings, "NoResetOpt", &tmp_int))
247 p_xkb->do_not_reset_opt = tmp_int != 0;
248 if (config_setting_lookup_int(settings, "KeepSysLayouts", &tmp_int))
117ae9de 249 p_xkb->keep_system_layouts = tmp_int != 0;
ec3e265f
AG
250 if (config_setting_lookup_string(settings, "Model", &tmp))
251 p_xkb->kbd_model = g_strdup(tmp);
252 if (config_setting_lookup_string(settings, "LayoutsList", &tmp))
117ae9de 253 p_xkb->kbd_layouts = g_strdup(tmp);
ec3e265f 254 if (config_setting_lookup_string(settings, "VariantsList", &tmp))
117ae9de 255 p_xkb->kbd_variants = g_strdup(tmp);
ec3e265f 256 if (config_setting_lookup_string(settings, "ToggleOpt", &tmp))
117ae9de 257 p_xkb->kbd_change_option = g_strdup(tmp);
ec3e265f 258 if (config_setting_lookup_string(settings, "AdvancedOpt", &tmp))
117ae9de 259 p_xkb->kbd_advanced_options = g_strdup(tmp);
ec3e265f 260 config_setting_lookup_int(settings, "FlagSize", &p_xkb->flag_size);
2918994e 261
d862b520 262 /* Allocate top level widget and set into Plugin widget pointer. */
ec3e265f
AG
263 p_xkb->p_plugin = p = gtk_event_box_new();
264 lxpanel_plugin_set_data(p, p_xkb, xkb_destructor);
265 gtk_widget_add_events(p, GDK_BUTTON_PRESS_MASK);
d862b520 266
267 /* Create a horizontal box as the child of the button. */
268 GtkWidget * hbox = gtk_hbox_new(FALSE, 0);
0078760f 269 gtk_container_set_border_width(GTK_CONTAINER(hbox), 3);
ec3e265f 270 gtk_container_add(GTK_CONTAINER(p), hbox);
d862b520 271 gtk_widget_show(hbox);
272
273 /* Create a label and an image as children of the horizontal box.
274 * Only one of these is visible at a time, controlled by user preference
275 * and the successful loading of the image. */
4496e880
JL
276 p_xkb->p_label = gtk_label_new("");
277 gtk_container_add(GTK_CONTAINER(hbox), p_xkb->p_label);
278 p_xkb->p_image = gtk_image_new();
279 gtk_container_add(GTK_CONTAINER(hbox), p_xkb->p_image);
d862b520 280
117ae9de 281 /* Check for first run */
895da737
JL
282 if( (p_xkb->kbd_model == NULL) || (p_xkb->kbd_layouts == NULL) ||
283 (p_xkb->kbd_variants == NULL) || (p_xkb->kbd_change_option == NULL) )
284 {
285 /* This is a first run, read the current layout */
286 xkb_mechanism_constructor(p_xkb);
ec3e265f 287
895da737
JL
288 if(p_xkb->kbd_model != NULL) g_free(p_xkb->kbd_model);
289 if(p_xkb->kbd_layouts != NULL) g_free(p_xkb->kbd_layouts);
290 if(p_xkb->kbd_variants != NULL) g_free(p_xkb->kbd_variants);
291 if(p_xkb->kbd_change_option != NULL) g_free(p_xkb->kbd_change_option);
ec3e265f 292
895da737
JL
293 p_xkb->kbd_model = g_strdup("pc105");
294 gchar *symbol_name_lowercase = (char *)xkb_get_current_symbol_name_lowercase(p_xkb);
295 p_xkb->kbd_layouts = g_strdup(symbol_name_lowercase);
296 g_free(symbol_name_lowercase);
297 p_xkb->kbd_variants = g_strdup(",");
2218ae4f 298 p_xkb->kbd_change_option = g_strdup("grp:shift_caps_toggle");
ec3e265f
AG
299 config_group_set_string(p_xkb->settings, "Model", p_xkb->kbd_model);
300 config_group_set_string(p_xkb->settings, "LayoutsList", p_xkb->kbd_layouts);
301 config_group_set_string(p_xkb->settings, "VariantsList", p_xkb->kbd_variants);
302 config_group_set_string(p_xkb->settings, "ToggleOpt", p_xkb->kbd_change_option);
303
895da737
JL
304 xkb_mechanism_destructor(p_xkb);
305 }
ec3e265f 306
d862b520 307 /* Initialize the XKB interface. */
895da737 308 xkb_setxkbmap(p_xkb);
4496e880 309 xkb_mechanism_constructor(p_xkb);
d862b520 310
d862b520 311 /* Connect signals. */
ec3e265f 312 g_signal_connect(p, "scroll-event", G_CALLBACK(on_xkb_button_scroll_event), p_xkb);
93a217b3 313 g_signal_connect(G_OBJECT(fbev), "active-window", G_CALLBACK(on_xkb_fbev_active_window_event), p_xkb);
d862b520 314
315 /* Show the widget and return. */
4496e880 316 xkb_redraw(p_xkb);
ec3e265f 317 return p;
22242ed4
HJYP
318}
319
d862b520 320/* Plugin destructor. */
ec3e265f 321static void xkb_destructor(gpointer user_data)
22242ed4 322{
ec3e265f 323 XkbPlugin *p_xkb = (XkbPlugin *)user_data;
22242ed4 324
895da737
JL
325 /* Disconnect root window event handler. */
326 g_signal_handlers_disconnect_by_func(G_OBJECT(fbev), on_xkb_fbev_active_window_event, p_xkb);
327
d862b520 328 /* Disconnect from the XKB mechanism. */
4496e880 329 xkb_mechanism_destructor(p_xkb);
22242ed4 330
d862b520 331 /* Deallocate all memory. */
4496e880
JL
332 g_free(p_xkb->kbd_model);
333 g_free(p_xkb->kbd_layouts);
334 g_free(p_xkb->kbd_variants);
335 g_free(p_xkb->kbd_change_option);
f8918f4a 336 g_free(p_xkb->kbd_advanced_options);
4496e880
JL
337 g_free(p_xkb);
338}
339
895da737 340/* Handler for "toggled" event on per-application check box of configuration dialog. */
0bcf9045 341static void on_xkb_checkbutton_per_app_toggled(GtkToggleButton *tb, gpointer p_data)
895da737
JL
342{
343 if(user_active == TRUE)
344 {
345 /* Fetch the new value and redraw. */
346 XkbPlugin * xkb = (XkbPlugin *)p_data;
347 xkb->enable_perwin = gtk_toggle_button_get_active(tb);
348 if(!xkb->enable_perwin)
349 {
350 /* at deactivation clear the hash table */
351 if(xkb->p_hash_table_group != NULL)
352 g_hash_table_destroy(xkb->p_hash_table_group);
353 xkb->p_hash_table_group = g_hash_table_new(g_direct_hash, NULL);
354 }
ec3e265f 355 config_group_set_int(xkb->settings, "PerWinLayout", xkb->enable_perwin);
895da737
JL
356 xkb_redraw(xkb);
357 }
358}
359
876e3dd1 360/* Handler for "toggled" event on no reset options check box of configuration dialog. */
b3d38a01 361static void on_xkb_checkbutton_no_reset_opt_toggled(GtkToggleButton *tb, gpointer p_data)
876e3dd1
GP
362{
363 if(user_active == TRUE)
364 {
365 /* Fetch the new value and redraw. */
366 XkbPlugin * xkb = (XkbPlugin *)p_data;
367 xkb->do_not_reset_opt = gtk_toggle_button_get_active(tb);
ec3e265f 368 config_group_set_int(xkb->settings, "NoResetOpt", xkb->do_not_reset_opt);
876e3dd1
GP
369 xkb_redraw(xkb);
370 }
371}
372
b3d38a01
GP
373/* Handler for "toggled" event on keep system layouts check box of configuration dialog. */
374static void on_xkb_checkbutton_keep_system_layouts_toggled(GtkToggleButton *tb, gpointer p_data)
375{
376 if(user_active == TRUE)
377 {
378 /* Fetch the new value and redraw. */
0078760f
GP
379 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
380 p_xkb->keep_system_layouts = gtk_toggle_button_get_active(tb);
ec3e265f 381 config_group_set_int(p_xkb->settings, "KeepSysLayouts", p_xkb->keep_system_layouts);
0078760f 382 xkb_redraw(p_xkb);
0bcf9045 383
0078760f
GP
384 gtk_widget_set_sensitive(p_xkb->p_frame_kbd_model, !p_xkb->keep_system_layouts);
385 gtk_widget_set_sensitive(p_xkb->p_frame_kbd_layouts, !p_xkb->keep_system_layouts);
386 gtk_widget_set_sensitive(p_xkb->p_frame_change_layout, !p_xkb->keep_system_layouts);
387 gtk_widget_set_sensitive(p_xkb->p_entry_advanced_opt, !p_xkb->keep_system_layouts);
388 gtk_widget_set_sensitive(p_xkb->p_checkbutton_no_reset_opt, !p_xkb->keep_system_layouts);
0bcf9045 389
cdbeb303
GP
390 if(!p_xkb->keep_system_layouts)
391 {
392 gtk_entry_set_icon_from_stock(GTK_ENTRY(p_xkb->p_entry_advanced_opt), GTK_ENTRY_ICON_SECONDARY, "gtk-save");
393 xkb_update_layouts_n_variants(p_xkb);
394 }
395 else
396 {
36328812 397 GtkWidget *dialog;
ec3e265f 398 dialog = gtk_message_dialog_new(p_xkb->p_dialog_config,
36328812
GP
399 GTK_DIALOG_DESTROY_WITH_PARENT,
400 GTK_MESSAGE_WARNING,
401 GTK_BUTTONS_OK,
06ad4725 402 _("New session is required for this option to take effect"));
36328812
GP
403 gtk_window_set_title(GTK_WINDOW(dialog), "Warning");
404 gtk_dialog_run(GTK_DIALOG(dialog));
405 gtk_widget_destroy(dialog);
cdbeb303 406 }
b3d38a01
GP
407 }
408}
409
4496e880
JL
410static void on_radiobutton_flag_size_1_toggled(GtkToggleButton *p_radiobutton, gpointer p_data)
411{
412 if( (user_active == TRUE) && gtk_toggle_button_get_active(p_radiobutton) )
413 {
414 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
415 p_xkb->flag_size = 1;
ec3e265f 416 config_group_set_int(p_xkb->settings, "FlagSize", 1);
4496e880
JL
417 xkb_redraw(p_xkb);
418 }
419}
420
421static void on_radiobutton_flag_size_2_toggled(GtkToggleButton *p_radiobutton, gpointer p_data)
422{
423 if( (user_active == TRUE) && gtk_toggle_button_get_active(p_radiobutton) )
424 {
425 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
426 p_xkb->flag_size = 2;
ec3e265f 427 config_group_set_int(p_xkb->settings, "FlagSize", 2);
4496e880
JL
428 xkb_redraw(p_xkb);
429 }
22242ed4
HJYP
430}
431
4496e880 432static void on_radiobutton_flag_size_3_toggled(GtkToggleButton *p_radiobutton, gpointer p_data)
22242ed4 433{
4496e880
JL
434 if( (user_active == TRUE) && gtk_toggle_button_get_active(p_radiobutton) )
435 {
436 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
437 p_xkb->flag_size = 3;
ec3e265f 438 config_group_set_int(p_xkb->settings, "FlagSize", 3);
4496e880
JL
439 xkb_redraw(p_xkb);
440 }
22242ed4
HJYP
441}
442
4496e880 443static void on_radiobutton_flag_size_4_toggled(GtkToggleButton *p_radiobutton, gpointer p_data)
22242ed4 444{
4496e880
JL
445 if( (user_active == TRUE) && gtk_toggle_button_get_active(p_radiobutton) )
446 {
447 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
448 p_xkb->flag_size = 4;
ec3e265f 449 config_group_set_int(p_xkb->settings, "FlagSize", 4);
4496e880
JL
450 xkb_redraw(p_xkb);
451 }
22242ed4
HJYP
452}
453
4496e880 454static void on_radiobutton_flag_size_5_toggled(GtkToggleButton *p_radiobutton, gpointer p_data)
22242ed4 455{
4496e880
JL
456 if( (user_active == TRUE) && gtk_toggle_button_get_active(p_radiobutton) )
457 {
458 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
459 p_xkb->flag_size = 5;
ec3e265f 460 config_group_set_int(p_xkb->settings, "FlagSize", 5);
4496e880
JL
461 xkb_redraw(p_xkb);
462 }
463}
464
895da737
JL
465static void on_radiobutton_flag_size_6_toggled(GtkToggleButton *p_radiobutton, gpointer p_data)
466{
467 if( (user_active == TRUE) && gtk_toggle_button_get_active(p_radiobutton) )
468 {
469 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
470 p_xkb->flag_size = 6;
ec3e265f 471 config_group_set_int(p_xkb->settings, "FlagSize", 6);
895da737
JL
472 xkb_redraw(p_xkb);
473 }
474}
475
4496e880
JL
476/* Handler for "toggled" event on display type image radiobutton of configuration dialog. */
477static void on_radiobutton_disp_type_image_toggled(GtkToggleButton *p_radiobutton, gpointer p_data)
478{
479 if( (user_active == TRUE) && gtk_toggle_button_get_active(p_radiobutton) )
480 {
481 /* Fetch the new value and redraw. */
482 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
483 p_xkb->display_type = DISP_TYPE_IMAGE;
ec3e265f 484 config_group_set_int(p_xkb->settings, "DisplayType", p_xkb->display_type);
4496e880
JL
485 xkb_redraw(p_xkb);
486 }
487}
488
489/* Handler for "toggled" event on display type image radiobutton of configuration dialog. */
490static void on_radiobutton_disp_type_image_cust_toggled(GtkToggleButton *p_radiobutton, gpointer p_data)
491{
492 if( (user_active == TRUE) && gtk_toggle_button_get_active(p_radiobutton) )
493 {
494 /* Fetch the new value and redraw. */
495 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
496 p_xkb->display_type = DISP_TYPE_IMAGE_CUST;
ec3e265f 497 config_group_set_int(p_xkb->settings, "DisplayType", p_xkb->display_type);
4496e880
JL
498 xkb_redraw(p_xkb);
499 }
500}
501
502/* Handler for "toggled" event on display type image radiobutton of configuration dialog. */
503static void on_radiobutton_disp_type_text_toggled(GtkToggleButton *p_radiobutton, gpointer p_data)
504{
505 if( (user_active == TRUE) && gtk_toggle_button_get_active(p_radiobutton) )
506 {
507 /* Fetch the new value and redraw. */
508 XkbPlugin * p_xkb = (XkbPlugin *)p_data;
509 p_xkb->display_type = DISP_TYPE_TEXT;
ec3e265f 510 config_group_set_int(p_xkb->settings, "DisplayType", p_xkb->display_type);
4496e880
JL
511 xkb_redraw(p_xkb);
512 }
22242ed4
HJYP
513}
514
d862b520 515/* Handler for "response" event on configuration dialog. */
4496e880 516static void on_dialog_config_response(GtkDialog *p_dialog, gint response, gpointer data)
22242ed4 517{
4496e880 518 XkbPlugin * p_xkb = (XkbPlugin *)data;
22242ed4 519
ec3e265f 520 /* Reset pointer because dialog will be destroyed */
4496e880
JL
521 p_xkb->p_dialog_config = NULL;
522}
523
0f8664b0
GP
524static void on_cell_renderer_layout_change_incl_toggled(GtkCellRendererToggle *cell,
525 gchar *path_str,
526 gpointer data)
527{
528 GtkTreeModel *p_model = (GtkTreeModel *)data;
529 GtkTreeIter tree_iter;
530 GtkTreePath *p_tree_path = gtk_tree_path_new_from_string(path_str);
531 gboolean included;
0bcf9045 532
0f8664b0
GP
533 /* get toggled iter */
534 gtk_tree_model_get_iter(p_model, &tree_iter, p_tree_path);
535 gtk_tree_model_get(p_model, &tree_iter, COLUMN_CHANGE_INCL, &included, -1);
0bcf9045 536
0f8664b0
GP
537 /* do something with the value */
538 included = !included;
0bcf9045 539
0f8664b0
GP
540 /* set new value */
541 gtk_list_store_set(GTK_LIST_STORE(p_model), &tree_iter, COLUMN_CHANGE_INCL, included, -1);
f740757c 542 gtk_list_store_set(GTK_LIST_STORE(p_model), &tree_iter, COLUMN_CHANGE_WEIGHT, included ? PANGO_WEIGHT_ULTRAHEAVY : PANGO_WEIGHT_NORMAL, -1);
0bcf9045 543
0f8664b0
GP
544 /* clean up */
545 gtk_tree_path_free(p_tree_path);
546}
547
895da737
JL
548static gboolean on_treeviews_lists_button_press_event(GtkWidget *p_widget,
549 GdkEventButton *p_event,
550 gpointer p_data)
4496e880 551{
895da737
JL
552 if(p_event->button == 1)
553 {
554 if(p_event->type == GDK_2BUTTON_PRESS)
555 {
556 GtkButton *p_button_ok = (GtkButton *)p_data;
557 gtk_button_clicked(p_button_ok);
558 }
559 }
1d0e30c1
GP
560 else if(p_event->button == 2)
561 {
562 GtkTreePath *p_tree_path;
563 if(gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(p_widget),
564 p_event->x, p_event->y,
565 &p_tree_path,
566 NULL, NULL, NULL))
567 {
568 if(gtk_tree_view_row_expanded(GTK_TREE_VIEW(p_widget), p_tree_path))
569 gtk_tree_view_collapse_row(GTK_TREE_VIEW(p_widget), p_tree_path);
570 else
571 gtk_tree_view_expand_row(GTK_TREE_VIEW(p_widget), p_tree_path, FALSE);
572 gtk_tree_path_free(p_tree_path);
573 }
574 }
895da737 575 return FALSE;
4496e880
JL
576}
577
578static void on_button_kbd_model_clicked(GtkButton *p_button, gpointer *p_data)
579{
580 XkbPlugin *p_xkb = (XkbPlugin *)p_data;
0bcf9045 581
4496e880
JL
582 // dialog
583 GtkWidget *p_dialog = gtk_dialog_new_with_buttons(_("Select Keyboard Model"),
ec3e265f 584 p_xkb->p_dialog_config,
4496e880
JL
585 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
586 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
587 GTK_STOCK_OK, GTK_RESPONSE_OK,
588 NULL);
0bcf9045 589
4496e880
JL
590 // scrolledwindow
591 GtkWidget * p_scrolledwindow_kbd_model = gtk_scrolled_window_new(NULL, NULL);
592 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(p_scrolledwindow_kbd_model),
593 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
175f73d1
AG
594 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(p_dialog))),
595 p_scrolledwindow_kbd_model, TRUE, TRUE, 2);
0bcf9045 596
4496e880
JL
597 // liststore
598 GtkListStore *p_liststore_kbd_model = gtk_list_store_new(NUM_MODEL_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
599 GtkWidget *p_treeview_kbd_model = gtk_tree_view_new_with_model(GTK_TREE_MODEL(p_liststore_kbd_model));
600 g_object_unref(G_OBJECT(p_liststore_kbd_model));
601 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(p_treeview_kbd_model), TRUE);
602 gtk_container_add(GTK_CONTAINER(p_scrolledwindow_kbd_model), p_treeview_kbd_model);
603 GtkCellRenderer *p_renderer;
604 GtkTreeViewColumn *p_column;
edeca7f1 605 // model desc
4496e880 606 p_renderer = gtk_cell_renderer_text_new();
edeca7f1
GP
607 p_column = gtk_tree_view_column_new_with_attributes(_("Description"), p_renderer, "text", COLUMN_MODEL_DESC, NULL);
608 gtk_tree_view_column_set_sort_column_id(p_column, COLUMN_MODEL_DESC);
4496e880 609 gtk_tree_view_append_column(GTK_TREE_VIEW(p_treeview_kbd_model), p_column);
edeca7f1 610 // model id
4496e880 611 p_renderer = gtk_cell_renderer_text_new();
edeca7f1
GP
612 p_column = gtk_tree_view_column_new_with_attributes(_("Id"), p_renderer, "text", COLUMN_MODEL_ID, NULL);
613 gtk_tree_view_column_set_sort_column_id(p_column, COLUMN_MODEL_ID);
4496e880 614 gtk_tree_view_append_column(GTK_TREE_VIEW(p_treeview_kbd_model), p_column);
0bcf9045
AG
615
616
4496e880
JL
617 // populate model
618 GKeyFile *p_keyfile = g_key_file_new();
619 gchar *xkbcfg_filepath = g_strdup_printf("%s/models.cfg", XKBCONFDIR);
620 if(g_key_file_load_from_file(p_keyfile, xkbcfg_filepath, 0, NULL))
621 {
622 gchar **keys_models = g_key_file_get_keys(p_keyfile, "MODELS", NULL, NULL);
623 guint model_idx = 0;
624 GtkTreeIter tree_iter;
625 gchar *p_model_desc;
626 while(keys_models[model_idx] != NULL)
627 {
628 p_model_desc = g_key_file_get_string(p_keyfile, "MODELS", keys_models[model_idx], NULL);
629 gtk_list_store_append(p_liststore_kbd_model, &tree_iter);
630 gtk_list_store_set(p_liststore_kbd_model, &tree_iter,
edeca7f1 631 COLUMN_MODEL_ID, keys_models[model_idx],
f6dd866e 632 COLUMN_MODEL_DESC, g_dgettext("xkeyboard-config", p_model_desc),
4496e880
JL
633 -1);
634 g_free(p_model_desc);
635 model_idx++;
636 }
637 g_strfreev(keys_models);
638 g_key_file_free(p_keyfile);
639 }
640 g_free(xkbcfg_filepath);
0bcf9045 641
4496e880 642 // callback for double click
4496e880 643 g_signal_connect(p_treeview_kbd_model, "button-press-event",
895da737
JL
644 G_CALLBACK(on_treeviews_lists_button_press_event),
645 gtk_dialog_get_widget_for_response(GTK_DIALOG(p_dialog), GTK_RESPONSE_OK));
e03d81df
GP
646 // sort for description
647 gtk_tree_view_column_clicked(p_column);
0bcf9045 648
e03d81df 649 gtk_widget_set_size_request(p_dialog, 700, 500);
4496e880
JL
650 gtk_widget_show_all(GTK_WIDGET(p_scrolledwindow_kbd_model));
651 gint response = gtk_dialog_run(GTK_DIALOG(p_dialog));
652 if(response == GTK_RESPONSE_OK)
653 {
654 GtkTreeIter tree_iter_sel;
655 GtkTreeSelection *p_treeselection_kbd_model = gtk_tree_view_get_selection(GTK_TREE_VIEW(p_treeview_kbd_model));
656 if(gtk_tree_selection_get_selected(p_treeselection_kbd_model,
657 (GtkTreeModel **)(&p_liststore_kbd_model),
658 &tree_iter_sel))
659 {
660 gchar *kbd_model_new;
661 gtk_tree_model_get(GTK_TREE_MODEL(p_liststore_kbd_model),
edeca7f1 662 &tree_iter_sel, COLUMN_MODEL_ID, &kbd_model_new, -1);
4496e880
JL
663 g_free(p_xkb->kbd_model);
664 p_xkb->kbd_model = g_strdup(kbd_model_new);
ec3e265f 665 config_group_set_string(p_xkb->settings, "Model", kbd_model_new);
4496e880
JL
666 gtk_button_set_label(GTK_BUTTON(p_xkb->p_button_kbd_model), p_xkb->kbd_model);
667 g_free(kbd_model_new);
668 xkb_setxkbmap(p_xkb);
669 xkb_redraw(p_xkb);
670 }
671 }
672 gtk_widget_destroy(p_dialog);
673}
674
aa9fca99
GP
675static gboolean change_opt_tree_model_foreach(GtkTreeModel *p_model,
676 GtkTreePath *p_path,
677 GtkTreeIter *p_iter,
678 gpointer p_data)
679{
680 XkbPlugin *p_xkb = (XkbPlugin *)p_data;
0bcf9045 681
aa9fca99 682 gboolean included;
0bcf9045 683
aa9fca99
GP
684 gtk_tree_model_get(p_model, p_iter, COLUMN_CHANGE_INCL, &included, -1);
685 if(included)
686 {
687 gchar *change_opt_id;
688 gtk_tree_model_get(p_model, p_iter, COLUMN_CHANGE_ID, &change_opt_id, -1);
689 if(strlen(p_xkb->p_gstring_change_opt_partial->str))
690 {
691 g_string_append_c(p_xkb->p_gstring_change_opt_partial, ',');
692 }
693 g_string_append(p_xkb->p_gstring_change_opt_partial, change_opt_id);
0bcf9045 694
aa9fca99 695 //g_printf("\npartial change opt = '%s'\n", p_xkb->p_gstring_change_opt_partial->str);
0bcf9045 696
aa9fca99
GP
697 g_free(change_opt_id);
698 }
699 return FALSE;
700}
701
4496e880
JL
702static void on_button_kbd_change_layout_clicked(GtkButton *p_button, gpointer *p_data)
703{
704 XkbPlugin *p_xkb = (XkbPlugin *)p_data;
0bcf9045 705
4496e880
JL
706 // dialog
707 GtkWidget *p_dialog = gtk_dialog_new_with_buttons(_("Select Layout Change Type"),
ec3e265f 708 p_xkb->p_dialog_config,
4496e880
JL
709 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
710 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
711 GTK_STOCK_OK, GTK_RESPONSE_OK,
712 NULL);
0bcf9045 713
4496e880
JL
714 // scrolledwindow
715 GtkWidget * p_scrolledwindow_kbd_change = gtk_scrolled_window_new(NULL, NULL);
716 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(p_scrolledwindow_kbd_change),
717 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
175f73d1
AG
718 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(p_dialog))),
719 p_scrolledwindow_kbd_change, TRUE, TRUE, 2);
0bcf9045 720
4496e880 721 // liststore
f740757c 722 GtkListStore *p_liststore_kbd_change = gtk_list_store_new(NUM_CHANGE_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INT);
4496e880
JL
723 GtkWidget *p_treeview_kbd_change = gtk_tree_view_new_with_model(GTK_TREE_MODEL(p_liststore_kbd_change));
724 g_object_unref(G_OBJECT(p_liststore_kbd_change));
725 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(p_treeview_kbd_change), TRUE);
726 gtk_container_add(GTK_CONTAINER(p_scrolledwindow_kbd_change), p_treeview_kbd_change);
727 GtkCellRenderer *p_renderer;
728 GtkTreeViewColumn *p_column;
0f8664b0
GP
729 // change included
730 p_renderer = gtk_cell_renderer_toggle_new();
731 g_signal_connect(p_renderer, "toggled", G_CALLBACK(on_cell_renderer_layout_change_incl_toggled), p_liststore_kbd_change);
732 p_column = gtk_tree_view_column_new_with_attributes("", p_renderer, "active", COLUMN_CHANGE_INCL, NULL);
733 gtk_tree_view_append_column(GTK_TREE_VIEW(p_treeview_kbd_change), p_column);
2db4799c 734 // change desc
4496e880 735 p_renderer = gtk_cell_renderer_text_new();
f740757c
GP
736 p_column = gtk_tree_view_column_new_with_attributes(_("Description"), p_renderer, "text", COLUMN_CHANGE_DESC,
737 "weight", COLUMN_CHANGE_WEIGHT,
738 NULL);
edeca7f1 739 gtk_tree_view_column_set_sort_column_id(p_column, COLUMN_CHANGE_DESC);
4496e880 740 gtk_tree_view_append_column(GTK_TREE_VIEW(p_treeview_kbd_change), p_column);
edeca7f1 741 // change id
4496e880 742 p_renderer = gtk_cell_renderer_text_new();
f740757c
GP
743 p_column = gtk_tree_view_column_new_with_attributes(_("Id"), p_renderer, "text", COLUMN_CHANGE_ID,
744 "weight", COLUMN_CHANGE_WEIGHT,
745 NULL);
edeca7f1 746 gtk_tree_view_column_set_sort_column_id(p_column, COLUMN_CHANGE_ID);
4496e880 747 gtk_tree_view_append_column(GTK_TREE_VIEW(p_treeview_kbd_change), p_column);
0bcf9045 748
4496e880
JL
749 // populate model
750 GKeyFile *p_keyfile = g_key_file_new();
751 gchar *xkbcfg_filepath = g_strdup_printf("%s/toggle.cfg", XKBCONFDIR);
752 if(g_key_file_load_from_file(p_keyfile, xkbcfg_filepath, 0, NULL))
753 {
1899e9b6
GP
754 char **change_opts = g_strsplit_set(p_xkb->kbd_change_option, ",", 0);
755 int num_change_opts;
4496e880
JL
756 gchar **keys_changes = g_key_file_get_keys(p_keyfile, "TOGGLE", NULL, NULL);
757 guint change_idx = 0;
758 GtkTreeIter tree_iter;
759 gchar *p_change_desc;
760 while(keys_changes[change_idx] != NULL)
761 {
762 p_change_desc = g_key_file_get_string(p_keyfile, "TOGGLE", keys_changes[change_idx], NULL);
763 gtk_list_store_append(p_liststore_kbd_change, &tree_iter);
1899e9b6
GP
764 gboolean included = FALSE;
765 num_change_opts = 0;
766 while(change_opts[num_change_opts] != NULL)
767 {
ab5849e5 768 if(strcmp(change_opts[num_change_opts], keys_changes[change_idx]) == 0)
1899e9b6
GP
769 {
770 included = TRUE;
771 break;
772 }
773 num_change_opts++;
774 }
4496e880 775 gtk_list_store_set(p_liststore_kbd_change, &tree_iter,
edeca7f1 776 COLUMN_CHANGE_ID, keys_changes[change_idx],
f6dd866e 777 COLUMN_CHANGE_DESC, g_dgettext("xkeyboard-config", p_change_desc),
1899e9b6 778 COLUMN_CHANGE_INCL, included,
f740757c 779 COLUMN_CHANGE_WEIGHT, included ? PANGO_WEIGHT_ULTRAHEAVY : PANGO_WEIGHT_NORMAL,
4496e880
JL
780 -1);
781 g_free(p_change_desc);
782 change_idx++;
783 }
784 g_strfreev(keys_changes);
785 g_key_file_free(p_keyfile);
1899e9b6 786 g_strfreev(change_opts);
4496e880
JL
787 }
788 g_free(xkbcfg_filepath);
0bcf9045 789
4496e880 790 // callback for double click
0f8664b0
GP
791 //g_signal_connect(p_treeview_kbd_change, "button-press-event",
792 //G_CALLBACK(on_treeviews_lists_button_press_event),
793 //gtk_dialog_get_widget_for_response(GTK_DIALOG(p_dialog), GTK_RESPONSE_OK));
e03d81df 794 gtk_widget_set_size_request(p_dialog, 700, 500);
4496e880
JL
795 gtk_widget_show_all(GTK_WIDGET(p_scrolledwindow_kbd_change));
796 gint response = gtk_dialog_run(GTK_DIALOG(p_dialog));
797 if(response == GTK_RESPONSE_OK)
798 {
aa9fca99
GP
799 p_xkb->p_gstring_change_opt_partial = g_string_new("");
800 gtk_tree_model_foreach(GTK_TREE_MODEL(p_liststore_kbd_change),
801 change_opt_tree_model_foreach,
802 p_xkb);
803 if(!strlen(p_xkb->p_gstring_change_opt_partial->str))
4496e880 804 {
aa9fca99 805 g_string_append_c(p_xkb->p_gstring_change_opt_partial, ',');
4496e880 806 }
aa9fca99
GP
807 g_free(p_xkb->kbd_change_option);
808 p_xkb->kbd_change_option = g_strdup(p_xkb->p_gstring_change_opt_partial->str);
ec3e265f 809 config_group_set_string(p_xkb->settings, "ToggleOpt", p_xkb->kbd_change_option);
aa9fca99 810 g_string_free(p_xkb->p_gstring_change_opt_partial, TRUE/*free also gstring->str*/);
0bcf9045 811
aa9fca99
GP
812 gtk_button_set_label(GTK_BUTTON(p_xkb->p_button_change_layout), p_xkb->kbd_change_option);
813 xkb_setxkbmap(p_xkb);
814 xkb_redraw(p_xkb);
4496e880
JL
815 }
816 gtk_widget_destroy(p_dialog);
817}
818
819static void on_button_up_layout_clicked(GtkButton *p_button, gpointer *p_data)
820{
821 XkbPlugin *p_xkb = (XkbPlugin *)p_data;
822 GtkTreeIter tree_iter_sel;
823 GtkTreeIter tree_iter_prev;
824 if(gtk_tree_selection_get_selected(p_xkb->p_treeselection_layout,
825 (GtkTreeModel **)(&p_xkb->p_liststore_layout),
826 &tree_iter_sel))
827 {
828 GtkTreePath *p_tree_path = gtk_tree_model_get_path(GTK_TREE_MODEL(p_xkb->p_liststore_layout),
829 &tree_iter_sel);
830 if( (gtk_tree_path_prev(p_tree_path)) &&
831 (gtk_tree_model_get_iter(GTK_TREE_MODEL(p_xkb->p_liststore_layout),
832 &tree_iter_prev,
833 p_tree_path)))
834 {
835 gtk_list_store_swap(p_xkb->p_liststore_layout, &tree_iter_sel, &tree_iter_prev);
836 xkb_update_layouts_n_variants(p_xkb);
837 }
838 gtk_tree_path_free(p_tree_path);
839 }
840}
841
842static void on_button_down_layout_clicked(GtkButton *p_button, gpointer *p_data)
843{
844 XkbPlugin *p_xkb = (XkbPlugin *)p_data;
845 GtkTreeIter tree_iter_sel;
846 GtkTreeIter tree_iter_next;
847 if(gtk_tree_selection_get_selected(p_xkb->p_treeselection_layout,
848 (GtkTreeModel **)(&p_xkb->p_liststore_layout),
849 &tree_iter_sel))
850 {
851 tree_iter_next = tree_iter_sel;
852 if(gtk_tree_model_iter_next(GTK_TREE_MODEL(p_xkb->p_liststore_layout),
853 &tree_iter_next))
854 {
855 gtk_list_store_swap(p_xkb->p_liststore_layout, &tree_iter_sel, &tree_iter_next);
856 xkb_update_layouts_n_variants(p_xkb);
857 }
858 }
859}
860
861static void on_button_rm_layout_clicked(GtkButton *p_button, gpointer *p_data)
862{
863 XkbPlugin *p_xkb = (XkbPlugin *)p_data;
864 GtkTreeIter tree_iter_sel;
865 if(gtk_tree_selection_get_selected(p_xkb->p_treeselection_layout,
866 (GtkTreeModel **)(&p_xkb->p_liststore_layout),
867 &tree_iter_sel))
868 {
869 gtk_list_store_remove(p_xkb->p_liststore_layout, &tree_iter_sel);
870 xkb_update_layouts_n_variants(p_xkb);
871 gtk_widget_set_sensitive(p_xkb->p_button_rm_layout, p_xkb->num_layouts > 1);
872 }
873}
874
875static void on_button_add_layout_clicked(GtkButton *p_button, gpointer *p_data)
876{
877 XkbPlugin *p_xkb = (XkbPlugin *)p_data;
0bcf9045 878
4496e880
JL
879 // dialog
880 GtkWidget *p_dialog = gtk_dialog_new_with_buttons(_("Add Keyboard Layout"),
ec3e265f 881 p_xkb->p_dialog_config,
4496e880
JL
882 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
883 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
884 GTK_STOCK_OK, GTK_RESPONSE_OK,
885 NULL);
0bcf9045 886
4496e880
JL
887 // scrolledwindow
888 GtkWidget * p_scrolledwindow_add_layout = gtk_scrolled_window_new(NULL, NULL);
889 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(p_scrolledwindow_add_layout),
890 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
175f73d1
AG
891 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(p_dialog))),
892 p_scrolledwindow_add_layout, TRUE, TRUE, 2);
0bcf9045 893
4496e880
JL
894 // treestore
895 GtkTreeStore *p_treestore_add_layout = gtk_tree_store_new(NUM_ADD_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
896 GtkWidget *p_treeview_add_layout = gtk_tree_view_new_with_model(GTK_TREE_MODEL(p_treestore_add_layout));
897 g_object_unref(G_OBJECT(p_treestore_add_layout));
898 gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(p_treeview_add_layout), TRUE);
899 gtk_container_add(GTK_CONTAINER(p_scrolledwindow_add_layout), p_treeview_add_layout);
900 GtkCellRenderer *p_renderer;
895da737 901 GtkTreeViewColumn *p_column, *p_column_desc;
4496e880
JL
902 // icon
903 p_renderer = gtk_cell_renderer_pixbuf_new();
895da737
JL
904 p_column = gtk_tree_view_column_new_with_attributes(_("Flag"), p_renderer, "pixbuf", COLUMN_ADD_ICON, NULL);
905 gtk_tree_view_column_set_sort_column_id(p_column, COLUMN_ADD_DESC);
4496e880
JL
906 gtk_tree_view_append_column(GTK_TREE_VIEW(p_treeview_add_layout), p_column);
907 // layout
908 p_renderer = gtk_cell_renderer_text_new();
895da737
JL
909 p_column = gtk_tree_view_column_new_with_attributes(_("Layout"), p_renderer, "text", COLUMN_ADD_LAYOUT, NULL);
910 gtk_tree_view_column_set_sort_column_id(p_column, COLUMN_ADD_LAYOUT);
4496e880
JL
911 gtk_tree_view_append_column(GTK_TREE_VIEW(p_treeview_add_layout), p_column);
912 // desc
913 p_renderer = gtk_cell_renderer_text_new();
895da737
JL
914 p_column_desc = gtk_tree_view_column_new_with_attributes(_("Description"), p_renderer, "text", COLUMN_ADD_DESC, NULL);
915 gtk_tree_view_column_set_sort_column_id(p_column_desc, COLUMN_ADD_DESC);
916 gtk_tree_view_append_column(GTK_TREE_VIEW(p_treeview_add_layout), p_column_desc);
917 // search column
918 gtk_tree_view_set_search_column(GTK_TREE_VIEW(p_treeview_add_layout), COLUMN_ADD_DESC);
0bcf9045 919
4496e880
JL
920 // populate model
921 GKeyFile *p_keyfile = g_key_file_new();
922 gchar *xkbcfg_filepath = g_strdup_printf("%s/layouts.cfg", XKBCONFDIR);
923 if(g_key_file_load_from_file(p_keyfile, xkbcfg_filepath, 0, NULL))
924 {
925 gchar **keys_layouts = g_key_file_get_keys(p_keyfile, "LAYOUTS", NULL, NULL);
926 guint layout_idx = 0;
927 GtkTreeIter tree_top, tree_child;
928 gchar *p_layout_desc;
929 while(keys_layouts[layout_idx] != NULL)
930 {
931 p_layout_desc = g_key_file_get_string(p_keyfile, "LAYOUTS", keys_layouts[layout_idx], NULL);
932 if(strchr(keys_layouts[layout_idx], '(') == NULL)
933 {
934 gchar *flag_filepath = NULL;
935 gchar *flags_dir = (p_xkb->cust_dir_exists && (p_xkb->display_type == DISP_TYPE_IMAGE_CUST)) ? g_strdup(FLAGSCUSTDIR):g_strdup(FLAGSDIR);
936 if(strchr(keys_layouts[layout_idx], '/') != NULL)
937 {
938 gchar *layout_mod = g_strdup(keys_layouts[layout_idx]);
939 layout_mod = g_strdelimit(layout_mod, "/", '-');
940 flag_filepath = g_strdup_printf(flag_filepath_generator, flags_dir, layout_mod);
941 g_free(layout_mod);
942 }
943 else
944 {
945 flag_filepath = g_strdup_printf(flag_filepath_generator, flags_dir, keys_layouts[layout_idx]);
946 }
947 GdkPixbuf *p_pixbuf = gdk_pixbuf_new_from_file_at_size(flag_filepath, -1, 16, NULL);
948 gtk_tree_store_append(p_treestore_add_layout, &tree_top, NULL);
949 if(p_pixbuf != NULL)
950 {
951 gtk_tree_store_set(p_treestore_add_layout, &tree_top,
952 COLUMN_ADD_ICON, p_pixbuf,
953 COLUMN_ADD_LAYOUT, keys_layouts[layout_idx],
f6dd866e 954 COLUMN_ADD_DESC, g_dgettext("xkeyboard-config", p_layout_desc),
4496e880
JL
955 -1);
956 g_object_unref(G_OBJECT(p_pixbuf));
957 }
958 else
959 {
960 gtk_tree_store_set(p_treestore_add_layout, &tree_top,
961 COLUMN_ADD_LAYOUT, keys_layouts[layout_idx],
962 COLUMN_ADD_DESC, p_layout_desc,
963 -1);
964 }
965 g_free(flag_filepath);
966 g_free(flags_dir);
967 }
968 else
969 {
0bcf9045 970
4496e880
JL
971 gtk_tree_store_append(p_treestore_add_layout, &tree_child, &tree_top);
972 gtk_tree_store_set(p_treestore_add_layout, &tree_child,
973 COLUMN_ADD_LAYOUT, keys_layouts[layout_idx],
974 COLUMN_ADD_DESC, p_layout_desc,
975 -1);
976 }
977 g_free(p_layout_desc);
978 layout_idx++;
979 }
980 g_strfreev(keys_layouts);
981 g_key_file_free(p_keyfile);
982 }
983 g_free(xkbcfg_filepath);
0bcf9045 984
4496e880 985 // callback for double click
4496e880 986 g_signal_connect(p_treeview_add_layout, "button-press-event",
895da737
JL
987 G_CALLBACK(on_treeviews_lists_button_press_event),
988 gtk_dialog_get_widget_for_response(GTK_DIALOG(p_dialog), GTK_RESPONSE_OK));
989 // sort for description
990 gtk_tree_view_column_clicked(p_column_desc);
0bcf9045 991
e03d81df 992 gtk_widget_set_size_request(p_dialog, 700, 500);
4496e880
JL
993 gtk_widget_show_all(GTK_WIDGET(p_scrolledwindow_add_layout));
994 gint response = gtk_dialog_run(GTK_DIALOG(p_dialog));
995 if(response == GTK_RESPONSE_OK)
996 {
997 GtkTreeIter tree_iter_sel;
998 GtkTreeSelection *p_treeselection_add_layout = gtk_tree_view_get_selection(GTK_TREE_VIEW(p_treeview_add_layout));
999 if(gtk_tree_selection_get_selected(p_treeselection_add_layout,
1000 (GtkTreeModel **)(&p_treestore_add_layout),
1001 &tree_iter_sel))
1002 {
1003 gchar *layout_add;
1004 GString *p_gstring_new_layout = g_string_new("");
1005 GString *p_gstring_new_variant = g_string_new("");
1006 gtk_tree_model_get(GTK_TREE_MODEL(p_treestore_add_layout),
1007 &tree_iter_sel, COLUMN_ADD_LAYOUT, &layout_add, -1);
0bcf9045 1008
4496e880
JL
1009 if(strchr(layout_add, '(') == NULL)
1010 {
1011 g_string_append(p_gstring_new_layout, layout_add);
1012 }
1013 else
1014 {
1015 gboolean parsing_variant = FALSE;
1016 guchar i;
1017 for(i=0; layout_add[i]; i++)
1018 {
1019 if(!parsing_variant)
1020 {
1021 if(layout_add[i] == '(')
1022 parsing_variant = TRUE;
1023 else
1024 g_string_append_c(p_gstring_new_layout, layout_add[i]);
1025 }
1026 else
1027 {
1028 if(layout_add[i] == ')')
1029 break;
1030 else
1031 g_string_append_c(p_gstring_new_variant, layout_add[i]);
1032 }
1033 }
1034 }
1035 xkb_add_layout(p_xkb, p_gstring_new_layout->str, p_gstring_new_variant->str);
1036 xkb_update_layouts_n_variants(p_xkb);
0bcf9045 1037
4496e880 1038 gtk_widget_set_sensitive(p_xkb->p_button_rm_layout, p_xkb->num_layouts > 1);
0bcf9045 1039
4496e880
JL
1040 g_free(layout_add);
1041 g_string_free(p_gstring_new_layout, TRUE/*free also gstring->str*/);
1042 g_string_free(p_gstring_new_variant, TRUE/*free also gstring->str*/);
1043 }
1044 }
1045 gtk_widget_destroy(p_dialog);
1046}
1047
047cf801 1048void xkb_setxkbmap(XkbPlugin *p_xkb)
4496e880 1049{
ec3e265f
AG
1050 GString *p_gstring_syscmd;
1051 int rc;
1052
b3d38a01 1053 if(p_xkb->keep_system_layouts) return;
ec3e265f
AG
1054
1055 p_gstring_syscmd = g_string_new("");
4496e880 1056 g_string_printf(p_gstring_syscmd,
2218ae4f 1057 "setxkbmap -model %s -layout %s -variant %s -option %s",
226cc442
GP
1058 p_xkb->kbd_model, p_xkb->kbd_layouts, p_xkb->kbd_variants,
1059 p_xkb->kbd_change_option);
1060 if( (p_xkb->kbd_advanced_options != NULL) && strlen(p_xkb->kbd_advanced_options) )
1061 {
1062 g_string_append(p_gstring_syscmd, " ");
1063 g_string_append(p_gstring_syscmd, p_xkb->kbd_advanced_options);
1064 }
876e3dd1 1065 if(!p_xkb->do_not_reset_opt)
895da737 1066 {
ec3e265f
AG
1067 rc = system("setxkbmap -option"); // reset options
1068 if(rc)
876e3dd1 1069 {
ec3e265f 1070 g_warning("xkb: system(setxkbmap -option) returned %d", rc);
876e3dd1 1071 }
895da737 1072 }
ec3e265f
AG
1073 rc = system(p_gstring_syscmd->str); // set new map
1074 if(rc)
895da737 1075 {
ec3e265f 1076 g_warning("xkb: system(%s) returned %d", p_gstring_syscmd->str, rc);
895da737 1077 }
4496e880
JL
1078 //g_printf("\n%s\n", p_gstring_syscmd->str);
1079 g_string_free(p_gstring_syscmd, TRUE/*free also gstring->str*/);
1080}
1081
aa9fca99
GP
1082static gboolean layouts_tree_model_foreach(GtkTreeModel *p_model,
1083 GtkTreePath *p_path,
1084 GtkTreeIter *p_iter,
1085 gpointer p_data)
4496e880
JL
1086{
1087 XkbPlugin *p_xkb = (XkbPlugin *)p_data;
1088 gchar *layout_val;
1089 gchar *variant_val;
0bcf9045 1090
4496e880
JL
1091 gtk_tree_model_get(p_model, p_iter, COLUMN_LAYOUT, &layout_val, -1);
1092 gtk_tree_model_get(p_model, p_iter, COLUMN_VARIANT, &variant_val, -1);
0bcf9045 1093
4496e880
JL
1094 if(strlen(p_xkb->p_gstring_layouts_partial->str))
1095 {
1096 g_string_append_c(p_xkb->p_gstring_layouts_partial, ',');
1097 g_string_append_c(p_xkb->p_gstring_variants_partial, ',');
1098 }
1099 g_string_append(p_xkb->p_gstring_layouts_partial, layout_val);
1100 g_string_append(p_xkb->p_gstring_variants_partial, variant_val);
0bcf9045 1101
895da737
JL
1102 //g_printf("\npartial layouts = '%s'\n", p_xkb->p_gstring_layouts_partial->str);
1103 //g_printf("partial variants = '%s'\n", p_xkb->p_gstring_variants_partial->str);
0bcf9045 1104
4496e880
JL
1105 g_free(layout_val);
1106 g_free(variant_val);
1107 p_xkb->num_layouts++;
1108 return FALSE;
1109}
1110
1111static void xkb_update_layouts_n_variants(XkbPlugin *p_xkb)
1112{
1113 p_xkb->p_gstring_layouts_partial = g_string_new("");
1114 p_xkb->p_gstring_variants_partial = g_string_new("");
1115 p_xkb->num_layouts = 0;
1116 gtk_tree_model_foreach(GTK_TREE_MODEL(p_xkb->p_liststore_layout),
1117 layouts_tree_model_foreach,
1118 p_xkb);
1119 if(!strlen(p_xkb->p_gstring_variants_partial->str))
1120 {
1121 g_string_append_c(p_xkb->p_gstring_variants_partial, ',');
1122 }
1123 g_free(p_xkb->kbd_layouts);
1124 g_free(p_xkb->kbd_variants);
1125 p_xkb->kbd_layouts = g_strdup(p_xkb->p_gstring_layouts_partial->str);
1126 p_xkb->kbd_variants = g_strdup(p_xkb->p_gstring_variants_partial->str);
1127 g_string_free(p_xkb->p_gstring_layouts_partial, TRUE/*free also gstring->str*/);
1128 g_string_free(p_xkb->p_gstring_variants_partial, TRUE/*free also gstring->str*/);
1129 xkb_setxkbmap(p_xkb);
1130 xkb_mechanism_destructor(p_xkb);
1131 xkb_mechanism_constructor(p_xkb);
ec3e265f
AG
1132 config_group_set_string(p_xkb->settings, "LayoutsList", p_xkb->kbd_layouts);
1133 config_group_set_string(p_xkb->settings, "VariantsList", p_xkb->kbd_variants);
4496e880
JL
1134 xkb_redraw(p_xkb);
1135}
1136
1137static void xkb_add_layout(XkbPlugin *p_xkb, gchar *layout, gchar*variant)
1138{
1139 GtkTreeIter tree_iter;
1140 gtk_list_store_append(p_xkb->p_liststore_layout, &tree_iter);
1141 gchar *flag_filepath = NULL;
1142 gchar *flags_dir = (p_xkb->cust_dir_exists && (p_xkb->display_type == DISP_TYPE_IMAGE_CUST)) ? g_strdup(FLAGSCUSTDIR):g_strdup(FLAGSDIR);
1143 if(strchr(layout, '/') != NULL)
1144 {
1145 gchar *layout_mod = g_strdup(layout);
1146 layout_mod = g_strdelimit(layout_mod, "/", '-');
1147 flag_filepath = g_strdup_printf(flag_filepath_generator, flags_dir, layout_mod);
1148 g_free(layout_mod);
1149 }
1150 else
1151 {
1152 flag_filepath = g_strdup_printf(flag_filepath_generator, flags_dir, layout);
1153 }
1154 GdkPixbuf *p_pixbuf = gdk_pixbuf_new_from_file_at_size(flag_filepath, -1, 20, NULL);
1155 if(p_pixbuf != NULL)
1156 {
1157 gtk_list_store_set(p_xkb->p_liststore_layout, &tree_iter,
1158 COLUMN_ICON, p_pixbuf,
1159 COLUMN_LAYOUT, layout,
1160 COLUMN_VARIANT, variant,
1161 -1);
1162 g_object_unref(G_OBJECT(p_pixbuf));
1163 }
1164 else
1165 {
1166 gtk_list_store_set(p_xkb->p_liststore_layout, &tree_iter,
1167 COLUMN_LAYOUT, layout,
1168 COLUMN_VARIANT, variant,
1169 -1);
1170 }
1171 g_free(flag_filepath);
1172 g_free(flags_dir);
1173}
1174
1175static void xkb_settings_fill_layout_tree_model_with_config(XkbPlugin *p_xkb)
1176{
1177 p_xkb->num_layouts = 0;
1178 if(strlen(p_xkb->kbd_layouts) && strlen(p_xkb->kbd_variants))
1179 {
1180 char **layouts = g_strsplit_set(p_xkb->kbd_layouts, ",", 0);
1181 char **variants = g_strsplit_set(p_xkb->kbd_variants, ",", 0);
1182
1183 while(layouts[p_xkb->num_layouts] != NULL)
1184 {
1185 xkb_add_layout(p_xkb, layouts[p_xkb->num_layouts], variants[p_xkb->num_layouts]);
1186 p_xkb->num_layouts++;
1187 }
1188 gtk_widget_set_sensitive(p_xkb->p_button_rm_layout, p_xkb->num_layouts > 1);
1189
1190 g_strfreev(layouts);
1191 g_strfreev(variants);
1192 }
22242ed4
HJYP
1193}
1194
d862b520 1195/* Callback when the configuration dialog is to be shown. */
752ee4e2 1196static GtkWidget *xkb_configure(LXPanel *panel, GtkWidget *p)
22242ed4 1197{
ec3e265f 1198 XkbPlugin * p_xkb = lxpanel_plugin_get_data(p);
4496e880
JL
1199 gchar markup_str[MAX_MARKUP_LEN];
1200
1201 user_active = FALSE;
d862b520 1202
4496e880 1203 // configuration dialog
d862b520 1204 GtkWidget * dlg = gtk_dialog_new_with_buttons(
4496e880 1205 _("Keyboard Layout Handler"),
d862b520 1206 NULL,
1207 GTK_DIALOG_NO_SEPARATOR,
4496e880 1208 GTK_STOCK_CLOSE,
d862b520 1209 GTK_RESPONSE_OK,
1210 NULL);
ec3e265f
AG
1211 p_xkb->p_dialog_config = GTK_WINDOW(dlg);
1212 panel_apply_icon(p_xkb->p_dialog_config);
d862b520 1213
4496e880 1214 // main vbox of the config dialog
59df548f
GP
1215 GtkWidget * p_hbox_main = gtk_hbox_new(TRUE, 0);
1216 GtkWidget * p_vbox_left = gtk_vbox_new(FALSE, 0);
1217 GtkWidget * p_vbox_right = gtk_vbox_new(FALSE, 0);
175f73d1
AG
1218 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dlg))),
1219 p_hbox_main);
59df548f
GP
1220 gtk_box_pack_start(GTK_BOX(p_hbox_main), p_vbox_left, FALSE, TRUE, 0);
1221 gtk_box_pack_start(GTK_BOX(p_hbox_main), p_vbox_right, FALSE, TRUE, 0);
4496e880
JL
1222
1223
1224 // 'KEYBOARD MODEL' frame
0078760f
GP
1225 p_xkb->p_frame_kbd_model = gtk_frame_new(NULL);
1226 gtk_widget_set_sensitive(p_xkb->p_frame_kbd_model, !p_xkb->keep_system_layouts);
4496e880
JL
1227 GtkWidget * p_label_kbd_model = gtk_label_new(NULL);
1228 snprintf(markup_str, MAX_MARKUP_LEN, "<b>%s</b>", _("Keyboard Model"));
1229 gtk_label_set_markup(GTK_LABEL(p_label_kbd_model), markup_str);
1230 gtk_misc_set_padding(GTK_MISC(p_label_kbd_model), 1, 0);
0078760f
GP
1231 gtk_frame_set_label_widget(GTK_FRAME(p_xkb->p_frame_kbd_model), p_label_kbd_model);
1232 gtk_frame_set_shadow_type(GTK_FRAME(p_xkb->p_frame_kbd_model), GTK_SHADOW_NONE);
1233 gtk_box_pack_start(GTK_BOX(p_vbox_left), p_xkb->p_frame_kbd_model, TRUE, TRUE, 2);
1234 gtk_container_set_border_width(GTK_CONTAINER(p_xkb->p_frame_kbd_model), 3);
4496e880
JL
1235
1236 // frame alignment
1237 GtkWidget * p_alignment_kbd_model = gtk_alignment_new(0.5, 0.5, 1, 1);
0078760f 1238 gtk_container_add(GTK_CONTAINER(p_xkb->p_frame_kbd_model), p_alignment_kbd_model);
4496e880
JL
1239 gtk_alignment_set_padding(GTK_ALIGNMENT(p_alignment_kbd_model), 4, 4, 10, 10);
1240 p_xkb->p_button_kbd_model = gtk_button_new_with_label(p_xkb->kbd_model);
1241 g_signal_connect(p_xkb->p_button_kbd_model, "clicked", G_CALLBACK(on_button_kbd_model_clicked), p_xkb);
1242 gtk_container_add(GTK_CONTAINER(p_alignment_kbd_model), p_xkb->p_button_kbd_model);
1243
1244
1245 // 'KEYBOARD LAYOUTS' frame
0078760f
GP
1246 p_xkb->p_frame_kbd_layouts = gtk_frame_new(NULL);
1247 gtk_widget_set_sensitive(p_xkb->p_frame_kbd_layouts, !p_xkb->keep_system_layouts);
4496e880
JL
1248 GtkWidget * p_label_kbd_layouts = gtk_label_new(NULL);
1249 snprintf(markup_str, MAX_MARKUP_LEN, "<b>%s</b>", _("Keyboard Layouts"));
1250 gtk_label_set_markup(GTK_LABEL(p_label_kbd_layouts), markup_str);
1251 gtk_misc_set_padding(GTK_MISC(p_label_kbd_layouts), 1, 0);
0078760f
GP
1252 gtk_frame_set_label_widget(GTK_FRAME(p_xkb->p_frame_kbd_layouts), p_label_kbd_layouts);
1253 gtk_frame_set_shadow_type(GTK_FRAME(p_xkb->p_frame_kbd_layouts), GTK_SHADOW_NONE);
1254 gtk_box_pack_start(GTK_BOX(p_vbox_left), p_xkb->p_frame_kbd_layouts, TRUE, TRUE, 2);
1255 gtk_container_set_border_width(GTK_CONTAINER(p_xkb->p_frame_kbd_layouts), 3);
1256 gtk_widget_set_size_request(GTK_WIDGET(p_xkb->p_frame_kbd_layouts), 300, 180);
4496e880
JL
1257
1258 // frame alignment
1259 GtkWidget * p_alignment_kbd_layouts = gtk_alignment_new(0.5, 0.5, 1, 1);
0078760f 1260 gtk_container_add(GTK_CONTAINER(p_xkb->p_frame_kbd_layouts), p_alignment_kbd_layouts);
4496e880
JL
1261 gtk_alignment_set_padding(GTK_ALIGNMENT(p_alignment_kbd_layouts), 4, 4, 10, 10);
1262 GtkWidget * p_hbox_kbd_layouts = gtk_hbox_new(FALSE, 0);
1263 gtk_container_add(GTK_CONTAINER(p_alignment_kbd_layouts), p_hbox_kbd_layouts);
1264
1265 // scrolledwindow and buttons
1266 GtkWidget * p_scrolledwindow_kbd_layouts = gtk_scrolled_window_new(NULL, NULL);
1267 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(p_scrolledwindow_kbd_layouts),
1268 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1269 gtk_box_pack_start(GTK_BOX(p_hbox_kbd_layouts), p_scrolledwindow_kbd_layouts, TRUE, TRUE, 2);
1270 GtkWidget * p_vbox_kbd_layouts = gtk_vbox_new(FALSE, 2);
1271 gtk_box_pack_start(GTK_BOX(p_hbox_kbd_layouts), p_vbox_kbd_layouts, FALSE, TRUE, 4);
1272 GtkWidget * p_button_add_layout = gtk_button_new_from_stock(GTK_STOCK_ADD);
1273 GtkWidget * p_button_up_layout = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
1274 GtkWidget * p_button_down_layout = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
1275 p_xkb->p_button_rm_layout = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
1276 g_signal_connect(p_button_add_layout, "clicked", G_CALLBACK(on_button_add_layout_clicked), p_xkb);
1277 g_signal_connect(p_xkb->p_button_rm_layout, "clicked", G_CALLBACK(on_button_rm_layout_clicked), p_xkb);
1278 g_signal_connect(p_button_up_layout, "clicked", G_CALLBACK(on_button_up_layout_clicked), p_xkb);
1279 g_signal_connect(p_button_down_layout, "clicked", G_CALLBACK(on_button_down_layout_clicked), p_xkb);
1280 gtk_box_pack_start(GTK_BOX(p_vbox_kbd_layouts), p_button_add_layout, FALSE, TRUE, 0);
1281 gtk_box_pack_start(GTK_BOX(p_vbox_kbd_layouts), p_xkb->p_button_rm_layout, FALSE, TRUE, 0);
1282 gtk_box_pack_start(GTK_BOX(p_vbox_kbd_layouts), p_button_up_layout, FALSE, TRUE, 0);
1283 gtk_box_pack_start(GTK_BOX(p_vbox_kbd_layouts), p_button_down_layout, FALSE, TRUE, 0);
ec3e265f 1284
4496e880
JL
1285 // liststore
1286 p_xkb->p_liststore_layout = gtk_list_store_new(NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
1287 p_xkb->p_treeview_layout = gtk_tree_view_new_with_model(GTK_TREE_MODEL(p_xkb->p_liststore_layout));
1288 g_object_unref(G_OBJECT(p_xkb->p_liststore_layout));
1289 p_xkb->p_treeselection_layout = gtk_tree_view_get_selection(GTK_TREE_VIEW(p_xkb->p_treeview_layout));
1290 gtk_container_add(GTK_CONTAINER(p_scrolledwindow_kbd_layouts), p_xkb->p_treeview_layout);
1291 GtkCellRenderer *p_renderer;
1292 GtkTreeViewColumn *p_column;
1293 // icon
1294 p_renderer = gtk_cell_renderer_pixbuf_new();
1295 p_column = gtk_tree_view_column_new_with_attributes(_("Flag"), p_renderer, "pixbuf", COLUMN_ICON, NULL);
1296 gtk_tree_view_append_column(GTK_TREE_VIEW(p_xkb->p_treeview_layout), p_column);
1297 // layout
1298 p_renderer = gtk_cell_renderer_text_new();
1299 p_column = gtk_tree_view_column_new_with_attributes(_("Layout"), p_renderer, "text", COLUMN_LAYOUT, NULL);
1300 gtk_tree_view_append_column(GTK_TREE_VIEW(p_xkb->p_treeview_layout), p_column);
1301 // variant
1302 p_renderer = gtk_cell_renderer_text_new();
1303 p_column = gtk_tree_view_column_new_with_attributes(_("Variant"), p_renderer, "text", COLUMN_VARIANT, NULL);
1304 gtk_tree_view_append_column(GTK_TREE_VIEW(p_xkb->p_treeview_layout), p_column);
1305 xkb_settings_fill_layout_tree_model_with_config(p_xkb);
1306
1307
1308 // 'CHANGE LAYOUT OPTION' frame
0078760f
GP
1309 p_xkb->p_frame_change_layout = gtk_frame_new(NULL);
1310 gtk_widget_set_sensitive(p_xkb->p_frame_change_layout, !p_xkb->keep_system_layouts);
4496e880
JL
1311 GtkWidget * p_label_change_layout = gtk_label_new(NULL);
1312 snprintf(markup_str, MAX_MARKUP_LEN, "<b>%s</b>", _("Change Layout Option"));
1313 gtk_label_set_markup(GTK_LABEL(p_label_change_layout), markup_str);
1314 gtk_misc_set_padding(GTK_MISC(p_label_change_layout), 1, 0);
0078760f
GP
1315 gtk_frame_set_label_widget(GTK_FRAME(p_xkb->p_frame_change_layout), p_label_change_layout);
1316 gtk_frame_set_shadow_type(GTK_FRAME(p_xkb->p_frame_change_layout), GTK_SHADOW_NONE);
1317 gtk_box_pack_start(GTK_BOX(p_vbox_left), p_xkb->p_frame_change_layout, TRUE, TRUE, 2);
1318 gtk_container_set_border_width(GTK_CONTAINER(p_xkb->p_frame_change_layout), 3);
4496e880
JL
1319
1320 // frame alignment
1321 GtkWidget * p_alignment_change_layout = gtk_alignment_new(0.5, 0.5, 1, 1);
0078760f 1322 gtk_container_add(GTK_CONTAINER(p_xkb->p_frame_change_layout), p_alignment_change_layout);
4496e880
JL
1323 gtk_alignment_set_padding(GTK_ALIGNMENT(p_alignment_change_layout), 4, 4, 10, 10);
1324 p_xkb->p_button_change_layout = gtk_button_new_with_label(p_xkb->kbd_change_option);
1325 g_signal_connect(p_xkb->p_button_change_layout, "clicked", G_CALLBACK(on_button_kbd_change_layout_clicked), p_xkb);
1326 gtk_container_add(GTK_CONTAINER(p_alignment_change_layout), p_xkb->p_button_change_layout);
1327
1328
ee25642c
GP
1329 // 'ADVANCED setxkbmap OPTIONS' frame
1330 GtkWidget * p_frame_advanced_opt = gtk_frame_new(NULL);
1331 GtkWidget * p_label_advanced_opt = gtk_label_new(NULL);
1332 snprintf(markup_str, MAX_MARKUP_LEN, "<b>%s</b>", _("Advanced setxkbmap Options"));
1333 gtk_label_set_markup(GTK_LABEL(p_label_advanced_opt), markup_str);
1334 gtk_misc_set_padding(GTK_MISC(p_label_advanced_opt), 1, 0);
1335 gtk_frame_set_label_widget(GTK_FRAME(p_frame_advanced_opt), p_label_advanced_opt);
1336 gtk_frame_set_shadow_type(GTK_FRAME(p_frame_advanced_opt), GTK_SHADOW_NONE);
1337 gtk_box_pack_start(GTK_BOX(p_vbox_right), p_frame_advanced_opt, TRUE, TRUE, 2);
1338 gtk_container_set_border_width(GTK_CONTAINER(p_frame_advanced_opt), 3);
1339
1340 // frame alignment
1341 GtkWidget * p_alignment_advanced_opt = gtk_alignment_new(0.5, 0.5, 1, 1);
1342 gtk_container_add(GTK_CONTAINER(p_frame_advanced_opt), p_alignment_advanced_opt);
1343 gtk_alignment_set_padding(GTK_ALIGNMENT(p_alignment_advanced_opt), 4, 4, 10, 10);
bf60cb65
GP
1344 GtkWidget * p_vbox_advanced_opt = gtk_vbox_new(FALSE, 0);
1345 gtk_container_add(GTK_CONTAINER(p_alignment_advanced_opt), p_vbox_advanced_opt);
0078760f
GP
1346 p_xkb->p_entry_advanced_opt = gtk_entry_new();
1347 gtk_widget_set_sensitive(p_xkb->p_entry_advanced_opt, !p_xkb->keep_system_layouts);
d23d9891
AG
1348 if (p_xkb->kbd_advanced_options)
1349 gtk_entry_set_text(GTK_ENTRY(p_xkb->p_entry_advanced_opt), p_xkb->kbd_advanced_options);
0078760f
GP
1350 gtk_entry_set_icon_from_stock(GTK_ENTRY(p_xkb->p_entry_advanced_opt), GTK_ENTRY_ICON_SECONDARY, "gtk-save");
1351 g_signal_connect(p_xkb->p_entry_advanced_opt, "icon-press", G_CALLBACK(on_xkb_entry_advanced_opt_icon_press), p_xkb);
1352 gtk_box_pack_start(GTK_BOX(p_vbox_advanced_opt), p_xkb->p_entry_advanced_opt, FALSE, TRUE, 0);
1353 p_xkb->p_checkbutton_no_reset_opt = gtk_check_button_new_with_mnemonic(_("Do _not reset existing options"));
1354 gtk_widget_set_sensitive(p_xkb->p_checkbutton_no_reset_opt, !p_xkb->keep_system_layouts);
1355 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_xkb->p_checkbutton_no_reset_opt), p_xkb->do_not_reset_opt);
1356 g_signal_connect(p_xkb->p_checkbutton_no_reset_opt, "toggled", G_CALLBACK(on_xkb_checkbutton_no_reset_opt_toggled), p_xkb);
1357 gtk_box_pack_start(GTK_BOX(p_vbox_advanced_opt), p_xkb->p_checkbutton_no_reset_opt, FALSE, TRUE, 0);
b3d38a01
GP
1358 GtkWidget *p_checkbutton_keep_system_layouts = gtk_check_button_new_with_mnemonic(_("Keep _system layouts"));
1359 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_checkbutton_keep_system_layouts), p_xkb->keep_system_layouts);
1360 g_signal_connect(p_checkbutton_keep_system_layouts, "toggled", G_CALLBACK(on_xkb_checkbutton_keep_system_layouts_toggled), p_xkb);
1361 gtk_box_pack_start(GTK_BOX(p_vbox_advanced_opt), p_checkbutton_keep_system_layouts, FALSE, TRUE, 0);
ee25642c
GP
1362
1363
895da737
JL
1364 // 'PER WINDOW SETTINGS' frame
1365 GtkWidget * p_frame_perapp_layout = gtk_frame_new(NULL);
1366 GtkWidget * p_label_perapp_layout = gtk_label_new(NULL);
1367 snprintf(markup_str, MAX_MARKUP_LEN, "<b>%s</b>", _("Per Window Settings"));
1368 gtk_label_set_markup(GTK_LABEL(p_label_perapp_layout), markup_str);
1369 gtk_misc_set_padding(GTK_MISC(p_label_perapp_layout), 1, 0);
1370 gtk_frame_set_label_widget(GTK_FRAME(p_frame_perapp_layout), p_label_perapp_layout);
1371 gtk_frame_set_shadow_type(GTK_FRAME(p_frame_perapp_layout), GTK_SHADOW_NONE);
59df548f 1372 gtk_box_pack_start(GTK_BOX(p_vbox_right), p_frame_perapp_layout, TRUE, TRUE, 2);
895da737
JL
1373 gtk_container_set_border_width(GTK_CONTAINER(p_frame_perapp_layout), 3);
1374
1375 // frame alignment
1376 GtkWidget * p_alignment_perapp_layout = gtk_alignment_new(0.5, 0.5, 1, 1);
1377 gtk_container_add(GTK_CONTAINER(p_frame_perapp_layout), p_alignment_perapp_layout);
1378 gtk_alignment_set_padding(GTK_ALIGNMENT(p_alignment_perapp_layout), 4, 4, 10, 10);
1379 GtkWidget *p_checkbutton_per_app = gtk_check_button_new_with_mnemonic(_("_Remember layout for each window"));
1380 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_checkbutton_per_app), p_xkb->enable_perwin);
1381 g_signal_connect(p_checkbutton_per_app, "toggled", G_CALLBACK(on_xkb_checkbutton_per_app_toggled), p_xkb);
1382 gtk_container_add(GTK_CONTAINER(p_alignment_perapp_layout), p_checkbutton_per_app);
1383
1384
4496e880
JL
1385 // 'SHOW LAYOUT AS' frame
1386 GtkWidget * p_frame_display_type = gtk_frame_new(NULL);
1387 GtkWidget * p_label_show_layout_as = gtk_label_new(NULL);
1388 snprintf(markup_str, MAX_MARKUP_LEN, "<b>%s</b>", _("Show Layout as"));
1389 gtk_label_set_markup(GTK_LABEL(p_label_show_layout_as), markup_str);
1390 gtk_misc_set_padding(GTK_MISC(p_label_show_layout_as), 1, 0);
1391 gtk_frame_set_label_widget(GTK_FRAME(p_frame_display_type), p_label_show_layout_as);
1392 gtk_frame_set_shadow_type(GTK_FRAME(p_frame_display_type), GTK_SHADOW_NONE);
59df548f 1393 gtk_box_pack_start(GTK_BOX(p_vbox_right), p_frame_display_type, TRUE, TRUE, 2);
4496e880
JL
1394 gtk_container_set_border_width(GTK_CONTAINER(p_frame_display_type), 3);
1395
1396 // frame alignment
1397 GtkWidget * p_alignment_display_type = gtk_alignment_new(0.5, 0.5, 1, 1);
1398 gtk_container_add(GTK_CONTAINER(p_frame_display_type), p_alignment_display_type);
1399 gtk_alignment_set_padding(GTK_ALIGNMENT(p_alignment_display_type), 4, 4, 10, 10);
1400 GtkWidget *p_table = gtk_table_new(3, 2, FALSE);
1401 gtk_table_set_col_spacings(GTK_TABLE(p_table), 10);
1402 gtk_container_add(GTK_CONTAINER(p_alignment_display_type), p_table);
ec3e265f 1403
4496e880
JL
1404 // radiobuttons
1405 GtkWidget * p_image_disp_type_image = gtk_image_new();
1406 GtkWidget * p_image_disp_type_image_cust = NULL;
1407 gchar *symbol_name_lowercase = (char *)xkb_get_current_symbol_name_lowercase(p_xkb);
1408 gchar *flag_filepath = NULL;
1409 gchar *flag_filepath_cust = NULL;
1410 if(strchr(symbol_name_lowercase, '/') != NULL)
1411 {
1412 gchar *layout_mod = g_strdup(symbol_name_lowercase);
1413 layout_mod = g_strdelimit(layout_mod, "/", '-');
1414 flag_filepath = g_strdup_printf(flag_filepath_generator, FLAGSDIR, layout_mod);
1415 if(p_xkb->cust_dir_exists)
1416 flag_filepath_cust = g_strdup_printf(flag_filepath_generator, FLAGSCUSTDIR, layout_mod);
1417 g_free(layout_mod);
1418 }
1419 else
1420 {
1421 flag_filepath = g_strdup_printf(flag_filepath_generator, FLAGSDIR, symbol_name_lowercase);
1422 if(p_xkb->cust_dir_exists)
1423 flag_filepath_cust = g_strdup_printf(flag_filepath_generator, FLAGSCUSTDIR, symbol_name_lowercase);
1424 }
1425 GdkPixbuf *p_pixbuf = gdk_pixbuf_new_from_file_at_size(flag_filepath, -1, 16, NULL);
1426 if(p_pixbuf != NULL)
1427 {
1428 gtk_image_set_from_pixbuf(GTK_IMAGE(p_image_disp_type_image), p_pixbuf);
1429 g_object_unref(G_OBJECT(p_pixbuf));
1430 }
1431 if(flag_filepath_cust != NULL)
1432 {
1433 p_image_disp_type_image_cust = gtk_image_new();
1434 GdkPixbuf *p_pixbuf_cust = gdk_pixbuf_new_from_file_at_size(flag_filepath_cust, -1, 16, NULL);
1435 if(p_pixbuf_cust != NULL)
1436 {
1437 gtk_image_set_from_pixbuf(GTK_IMAGE(p_image_disp_type_image_cust), p_pixbuf_cust);
1438 g_object_unref(G_OBJECT(p_pixbuf_cust));
1439 }
1440 }
1441 g_free(flag_filepath);
1442 if(flag_filepath_cust != NULL)
1443 g_free(flag_filepath_cust);
1444 g_free(symbol_name_lowercase);
1445 GtkWidget * p_label_disp_type_text = gtk_label_new(NULL);
1446 snprintf(markup_str, MAX_MARKUP_LEN, "<span font='%d' font_weight='heavy'>%s</span>", 16, xkb_get_current_symbol_name(p_xkb));
1447 gtk_label_set_markup(GTK_LABEL(p_label_disp_type_text), markup_str);
895da737 1448 GtkWidget * p_radiobutton_disp_type_image = gtk_radio_button_new_with_label(NULL, (const gchar *)_("Image"));
4496e880
JL
1449 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"));
1450 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"));
ec3e265f 1451
4496e880
JL
1452 gtk_table_attach(GTK_TABLE(p_table), p_image_disp_type_image, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
1453 gtk_table_attach(GTK_TABLE(p_table), p_radiobutton_disp_type_image, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
1454 if(p_xkb->cust_dir_exists)
1455 {
1456 gtk_table_attach(GTK_TABLE(p_table), p_image_disp_type_image_cust, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
1457 gtk_table_attach(GTK_TABLE(p_table), p_radiobutton_disp_type_image_cust, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
1458 }
1459 gtk_table_attach(GTK_TABLE(p_table), p_label_disp_type_text, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
1460 gtk_table_attach(GTK_TABLE(p_table), p_radiobutton_disp_type_text, 1, 2, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
ec3e265f 1461
4496e880
JL
1462 g_signal_connect(p_radiobutton_disp_type_image, "toggled", G_CALLBACK(on_radiobutton_disp_type_image_toggled), p_xkb);
1463 if(p_xkb->cust_dir_exists)
1464 g_signal_connect(p_radiobutton_disp_type_image_cust, "toggled", G_CALLBACK(on_radiobutton_disp_type_image_cust_toggled), p_xkb);
1465 g_signal_connect(p_radiobutton_disp_type_text, "toggled", G_CALLBACK(on_radiobutton_disp_type_text_toggled), p_xkb);
1466 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_radiobutton_disp_type_image), (p_xkb->display_type == DISP_TYPE_IMAGE) ||
1467 ( (p_xkb->display_type == DISP_TYPE_IMAGE_CUST) && (!p_xkb->cust_dir_exists) ) );
1468 if(p_xkb->cust_dir_exists)
1469 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_radiobutton_disp_type_image_cust), p_xkb->display_type == DISP_TYPE_IMAGE_CUST);
1470 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_radiobutton_disp_type_text), p_xkb->display_type == DISP_TYPE_TEXT);
1471
1472
1473 // 'PANEL ICON SIZE' frame
1474 GtkWidget * p_frame_flag_size = gtk_frame_new(NULL);
1475 GtkWidget * p_label_flag_size = gtk_label_new(NULL);
1476 snprintf(markup_str, MAX_MARKUP_LEN, "<b>%s</b>", _("Panel Icon Size"));
1477 gtk_label_set_markup(GTK_LABEL(p_label_flag_size), markup_str);
1478 gtk_misc_set_padding(GTK_MISC(p_label_flag_size), 1, 0);
1479 gtk_frame_set_label_widget(GTK_FRAME(p_frame_flag_size), p_label_flag_size);
1480 gtk_frame_set_shadow_type(GTK_FRAME(p_frame_flag_size), GTK_SHADOW_NONE);
59df548f 1481 gtk_box_pack_start(GTK_BOX(p_vbox_right), p_frame_flag_size, TRUE, TRUE, 2);
4496e880
JL
1482 gtk_container_set_border_width(GTK_CONTAINER(p_frame_flag_size), 3);
1483
1484 // frame alignment
1485 GtkWidget * p_alignment_flag_size = gtk_alignment_new(0.5, 0.5, 1, 1);
1486 gtk_container_add(GTK_CONTAINER(p_frame_flag_size), p_alignment_flag_size);
1487 gtk_alignment_set_padding(GTK_ALIGNMENT(p_alignment_flag_size), 4, 4, 10, 10);
1488 GtkWidget *p_hbox_flag_size = gtk_hbox_new(FALSE, 2);
1489 gtk_container_add(GTK_CONTAINER(p_alignment_flag_size), p_hbox_flag_size);
ec3e265f 1490
4496e880
JL
1491 GtkWidget *p_radiobutton_flag_size_1 = gtk_radio_button_new_with_label(NULL, "1");
1492 GtkWidget *p_radiobutton_flag_size_2 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(p_radiobutton_flag_size_1), "2");
1493 GtkWidget *p_radiobutton_flag_size_3 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(p_radiobutton_flag_size_1), "3");
1494 GtkWidget *p_radiobutton_flag_size_4 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(p_radiobutton_flag_size_1), "4");
1495 GtkWidget *p_radiobutton_flag_size_5 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(p_radiobutton_flag_size_1), "5");
895da737 1496 GtkWidget *p_radiobutton_flag_size_6 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(p_radiobutton_flag_size_1), "6");
4496e880
JL
1497 g_signal_connect(p_radiobutton_flag_size_1, "toggled", G_CALLBACK(on_radiobutton_flag_size_1_toggled), p_xkb);
1498 g_signal_connect(p_radiobutton_flag_size_2, "toggled", G_CALLBACK(on_radiobutton_flag_size_2_toggled), p_xkb);
1499 g_signal_connect(p_radiobutton_flag_size_3, "toggled", G_CALLBACK(on_radiobutton_flag_size_3_toggled), p_xkb);
1500 g_signal_connect(p_radiobutton_flag_size_4, "toggled", G_CALLBACK(on_radiobutton_flag_size_4_toggled), p_xkb);
1501 g_signal_connect(p_radiobutton_flag_size_5, "toggled", G_CALLBACK(on_radiobutton_flag_size_5_toggled), p_xkb);
895da737 1502 g_signal_connect(p_radiobutton_flag_size_6, "toggled", G_CALLBACK(on_radiobutton_flag_size_6_toggled), p_xkb);
4496e880
JL
1503 gtk_box_pack_start(GTK_BOX(p_hbox_flag_size), p_radiobutton_flag_size_1, TRUE, TRUE, 2);
1504 gtk_box_pack_start(GTK_BOX(p_hbox_flag_size), p_radiobutton_flag_size_2, TRUE, TRUE, 2);
1505 gtk_box_pack_start(GTK_BOX(p_hbox_flag_size), p_radiobutton_flag_size_3, TRUE, TRUE, 2);
1506 gtk_box_pack_start(GTK_BOX(p_hbox_flag_size), p_radiobutton_flag_size_4, TRUE, TRUE, 2);
1507 gtk_box_pack_start(GTK_BOX(p_hbox_flag_size), p_radiobutton_flag_size_5, TRUE, TRUE, 2);
895da737 1508 gtk_box_pack_start(GTK_BOX(p_hbox_flag_size), p_radiobutton_flag_size_6, TRUE, TRUE, 2);
4496e880
JL
1509 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_radiobutton_flag_size_1), p_xkb->flag_size == 1);
1510 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_radiobutton_flag_size_2), p_xkb->flag_size == 2);
1511 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_radiobutton_flag_size_3), p_xkb->flag_size == 3);
1512 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_radiobutton_flag_size_4), p_xkb->flag_size == 4);
1513 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_radiobutton_flag_size_5), p_xkb->flag_size == 5);
895da737 1514 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p_radiobutton_flag_size_6), p_xkb->flag_size == 6);
22242ed4 1515
d862b520 1516 /* Connect signals. */
ec3e265f 1517 g_signal_connect(dlg, "response", G_CALLBACK(on_dialog_config_response), p_xkb);
22242ed4 1518
d862b520 1519 /* Display the dialog. */
2c4d4abe 1520 gtk_widget_show_all(p_hbox_main);
22242ed4 1521
ec3e265f
AG
1522 user_active = TRUE;
1523 return dlg;
8f9e6256 1524}
1525
1526/* Callback when panel configuration changes. */
a7bd16a4 1527static void xkb_panel_configuration_changed(LXPanel *panel, GtkWidget *p)
8f9e6256 1528{
1529 /* Do a full redraw. */
ec3e265f 1530 xkb_redraw(lxpanel_plugin_get_data(p));
8f9e6256 1531}
22242ed4 1532
ec3e265f 1533FM_DEFINE_MODULE(lxpanel_gtk, xkb)
22242ed4 1534
ec3e265f
AG
1535/* Plugin descriptor. */
1536LXPanelPluginInit fm_module_init_lxpanel_gtk = {
3c3e9c9e 1537 .name = N_("Keyboard Layout Handler"),
3c3e9c9e
HG
1538 .description = N_("Handle keyboard layouts"),
1539
ec3e265f 1540 .new_instance = xkb_constructor,
3c3e9c9e 1541 .config = xkb_configure,
ec3e265f
AG
1542 .reconfigure = xkb_panel_configuration_changed,
1543 .button_press_event = on_xkb_button_press_event
22242ed4 1544};