Updates from Pootle
[lxde/lxpanel.git] / src / plugins / xkb / xkb-plugin.c
CommitLineData
22242ed4
HJYP
1/*
2//====================================================================
3// xfce4-xkb-plugin - XFCE4 Xkb Layout Indicator panel plugin
4// -------------------------------------------------------------------
5// Alexander Iliev <sasoiliev@mamul.org>
6// 20-Feb-04
7// -------------------------------------------------------------------
8// Parts of this code belong to Michael Glickman <wmalms@yahooo.com>
9// and his program wmxkb.
10// WARNING: DO NOT BOTHER Michael Glickman WITH QUESTIONS ABOUT THIS
11// PROGRAM!!! SEND INSTEAD EMAILS TO <sasoiliev@mamul.org>
12//====================================================================
13*/
14
15/* Modified by Hong Jen Yee (PCMan) <pcman.tw@gmail.com> on 2008-04-06 for lxpanel */
16
17#ifdef HAVE_CONFIG_H
18#include <config.h>
19#endif
20
21#include <glib/gi18n.h>
22
23#include <stdio.h>
24#include <ctype.h>
25
26#include "xkb.h"
27
1a6e8e06
JH
28static t_xkb_options_dlg *dlg = NULL;
29static GIOChannel *channel;
30static guint source_id;
22242ed4 31
1a6e8e06 32static gulong win_change_hanler, win_close_hanler;
22242ed4
HJYP
33
34static void
35xkb_free(t_xkb *xkb);
36
37static void
8f9e6256 38xkb_configure(Plugin * p, GtkWindow * parent);
22242ed4
HJYP
39
40static t_xkb_options_dlg*
8f9e6256 41xkb_options_dlg_create(t_xkb * xkb);
22242ed4
HJYP
42
43static void
44free_xkb_options_dlg(GtkDialog *dialog, gint arg1, gpointer user_data);
45
46static void
47xkb_options_dlg_set_xkb(t_xkb_options_dlg *dlg, t_xkb *xkb);
48
2918994e 49static gboolean
50change_group(GtkWidget * widget, GdkEventButton * event, gpointer data) ;
22242ed4
HJYP
51
52static void
53active_window_changed(FbEv *ev, gpointer data) ;
54
55static void
56application_closed( FbEv* ev, Window win, gpointer data) ;
57
22242ed4
HJYP
58/* ------------------------------------------------------------------ *
59 * Panel Plugin Interface *
60 * ------------------------------------------------------------------ */
61
2918994e 62static int
22242ed4
HJYP
63xkb_constructor (Plugin *plugin, char** fp);
64
65static void
66xkb_destructor (Plugin *plugin);
67
68static void
69xkb_orientation_changed(Plugin *plugin,
70 GtkOrientation orientation,
71 t_xkb *xkb);
72
73static gboolean
74xkb_set_size(Plugin *plugin,gint size,
75 t_xkb *xkb);
76
77static void
78xkb_free_data(Plugin *plugin,t_xkb *xkb);
79
22242ed4
HJYP
80
81static void
82xkb_about(Plugin *plugin, t_xkb *xkb);
83
84/* create widgets and connect to signals */
2918994e 85static int
22242ed4
HJYP
86xkb_constructor (Plugin *plugin, char** fp)
87{
88 t_xkb *xkb;
f669ce5e 89
22242ed4
HJYP
90
91 const char *initial_group;
92
8f9e6256 93 xkb = g_new0(t_xkb, 1);
94 xkb->plugin = plugin;
95 plugin->priv = xkb;
22242ed4 96
8f9e6256 97 xkb->size = plugin->panel->icon_size;
22242ed4
HJYP
98 xkb->display_type = IMAGE;
99 xkb->enable_perapp = TRUE;
100 xkb->default_group = 0;
101
f669ce5e 102 line s;
103 s.len = 256;
22242ed4
HJYP
104 if( fp )
105 {
106 while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END) {
107 if (s.type == LINE_NONE) {
108 ERR( "xkb: illegal token %s\n", s.str);
109 goto error;
110 }
111 if (s.type == LINE_VAR) {
112 if (!g_ascii_strcasecmp(s.t[0], "DisplayType"))
113 xkb->display_type = atoi(s.t[1]);
114 else if (!g_ascii_strcasecmp(s.t[0], "PerAppLayout"))
115 xkb->enable_perapp = str2num(bool_pair, s.t[1], 0);
116 else if (!g_ascii_strcasecmp(s.t[0], "DefaultGroup"))
117 xkb->default_group = atoi(s.t[1]);
118 else {
119 ERR( "xkb: unknown var %s\n", s.t[0]);
22242ed4
HJYP
120 }
121 } else {
122 ERR( "xkb: illegal in this context %s\n", s.str);
123 goto error;
124 }
125 }
126 }
127
22242ed4 128
2918994e 129 plugin->pwid = gtk_event_box_new();
130 gtk_widget_add_events(plugin->pwid, GDK_BUTTON_PRESS_MASK);
22242ed4 131 xkb->btn = gtk_button_new();
2918994e 132 gtk_container_add(GTK_CONTAINER(plugin->pwid), xkb->btn);
22242ed4 133 gtk_button_set_relief(GTK_BUTTON(xkb->btn), GTK_RELIEF_NONE);
8f9e6256 134 GTK_WIDGET_UNSET_FLAGS(xkb->btn, GTK_CAN_FOCUS);
135 GTK_WIDGET_UNSET_FLAGS(xkb->btn, GTK_CAN_DEFAULT);
22242ed4
HJYP
136
137 gtk_widget_show(xkb->btn);
2918994e 138 g_signal_connect(xkb->btn, "button-press-event", G_CALLBACK(change_group), xkb);
22242ed4 139
f669ce5e 140 xkb->hbox = gtk_hbox_new(FALSE, 0);
141 gtk_container_add(GTK_CONTAINER(xkb->btn), xkb->hbox);
142 gtk_widget_show(xkb->hbox);
22242ed4
HJYP
143
144 xkb->label = gtk_label_new("");
f669ce5e 145 gtk_container_add(GTK_CONTAINER(xkb->hbox), xkb->label);
22242ed4 146 xkb->image = gtk_image_new();
f669ce5e 147 gtk_container_add(GTK_CONTAINER(xkb->hbox), xkb->image);
22242ed4
HJYP
148
149 initial_group = initialize_xkb(xkb);
150
8f9e6256 151 set_new_locale(xkb);
22242ed4
HJYP
152
153 channel = g_io_channel_unix_new(get_connection_number());
154 source_id = g_io_add_watch(channel, G_IO_IN | G_IO_PRI,
155 (GIOFunc) &gio_callback, (gpointer) xkb);
156
157 /* track signals about window change */
158 win_change_hanler = g_signal_connect( G_OBJECT (fbev),
159 "active_window", G_CALLBACK(active_window_changed), xkb);
160
2918994e 161// win_close_hanler = g_signal_connect( G_OBJECT (fbev),
162// "destroy_window", G_CALLBACK(application_closed), xkb);
22242ed4 163
8f9e6256 164 gtk_widget_show(plugin->pwid);
22242ed4 165
2918994e 166
22242ed4
HJYP
167
168 RET(1);
169error:
22242ed4
HJYP
170 RET(0);
171}
172
173static void
174xkb_destructor (Plugin *plugin)
175{
176 t_xkb *xkb = (t_xkb*)plugin->priv;
177 xkb_free( xkb );
178}
179
180gboolean
181xkb_set_size(Plugin *plugin, gint size,
182 t_xkb *xkb)
183{
2918994e 184// GtkOrientation orientation;
185// DBG ("setting size %d", size);
186// xkb->size = size;
22242ed4
HJYP
187/*
188 orientation = xfce_panel_plugin_get_orientation (plugin);
189 if (orientation == GTK_ORIENTATION_HORIZONTAL)
190 gtk_widget_set_size_request(xkb->btn, -1, xkb->size);
191 else
192 gtk_widget_set_size_request(xkb->btn, xkb->size, -1);
193 */
194 set_new_locale(xkb);
195 return TRUE;
196}
197
198void
199xkb_free_data(Plugin *plugin, t_xkb *xkb)
200{
201 xkb_free(xkb);
202}
203
8f9e6256 204/* Callback when the configuration dialog is to be shown. */
205static void xkb_configure(Plugin * p, GtkWindow * parent)
22242ed4 206{
8f9e6256 207 t_xkb * xkb = (t_xkb *) p->priv;
208 dlg = xkb_options_dlg_create(xkb);
209 xkb_options_dlg_set_xkb(dlg, xkb);
210 gtk_widget_set_size_request(GTK_WIDGET(dlg->dialog), 400, -1); /* Improve geometry */
211 gtk_dialog_run(GTK_DIALOG(dlg->dialog));
22242ed4
HJYP
212}
213
214void
215xkb_about(Plugin *plugin, t_xkb *xkb)
216{
217 GtkWidget *about;
218 const gchar* authors[2] = {
219 "Alexander Iliev <sasoiliev@mamul.org>",
220 NULL
221 };
222 about = gtk_about_dialog_new();
223 gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(about),
224 _("Keyboard Layout Switcher"));
225 gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about),
226 NULL);
227 gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(about),
228 (const gchar**) authors);
229 gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(about),
230 _("Allows you to switch the keyboard layout and\n"
231 "displays the currently selected layout."));
232 gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about),
233 "http://xfce-goodies.berlios.de");
234 gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(about),
235 _("Other plugins available here"));
236 gtk_dialog_run(GTK_DIALOG(about));
237 gtk_widget_destroy (about);
238}
239
240/* ----------------- xkb plugin stuff -----------------------*/
241
22242ed4
HJYP
242void
243active_window_changed(FbEv *ev, gpointer data)
244{
2918994e 245 Window * win = fb_ev_active_window( ev );
1a6e8e06 246 DBG( "win = %p, pid=%d", win, get_net_wm_pid(win) );
2918994e 247 if( *win == None )
22242ed4 248 return;
2918994e 249 react_active_window_changed(get_net_wm_pid( *win ), (t_xkb *) data);
22242ed4
HJYP
250}
251
252void
253application_closed( FbEv* ev, Window win, gpointer data)
254{
1a6e8e06 255 DBG("win: %p", win);
22242ed4
HJYP
256 react_application_closed(get_net_wm_pid(win));
257}
258
2918994e 259static gboolean
260change_group(GtkWidget *widget, GdkEventButton * event, gpointer data)
22242ed4 261{
2918994e 262 t_xkb * xkb = (t_xkb *) data;
263
264 /* Standard right-click handling. */
265 if (plugin_button_press_event(widget, event, xkb->plugin))
266 return TRUE;
267
268 do_change_group(1, xkb);
22242ed4
HJYP
269}
270
22242ed4
HJYP
271static void
272xkb_free(t_xkb *xkb)
273{
274 g_signal_handler_disconnect(fbev, win_change_hanler);
275// g_signal_handler_disconnect(netk_screen, win_close_hanler);
276
277 g_source_remove(source_id);
278 deinitialize_xkb();
279
280 g_return_if_fail(xkb != NULL);
281
282 gtk_widget_destroy(xkb->btn);
283
284 g_free(xkb);
285}
286
287/* ----------------- xkb options dialog callbacks -----------------------*/
288
289static void
290xkb_display_type_changed(GtkComboBox *cb, gpointer *data)
291{
292 t_xkb *xkb = (t_xkb *) data;
293 xkb->display_type = gtk_combo_box_get_active(cb);
8f9e6256 294 set_new_locale(xkb);
22242ed4
HJYP
295}
296
297static void
298xkb_enable_perapp_changed(GtkToggleButton *tb, gpointer *data)
299{
300 t_xkb_options_dlg *dlg = (t_xkb_options_dlg *) data;
301 dlg->xkb->enable_perapp = gtk_toggle_button_get_active(tb);
302 gtk_widget_set_sensitive(dlg->per_app_default_layout_menu,
303 dlg->xkb->enable_perapp);
8f9e6256 304 set_new_locale(dlg->xkb);
22242ed4
HJYP
305}
306
307static void
308xkb_def_lang_changed(GtkComboBox *cb, gpointer *data)
309{
310 t_xkb *xkb = (t_xkb *) data;
311 xkb->default_group = gtk_combo_box_get_active(cb);
8f9e6256 312 set_new_locale(xkb);
22242ed4
HJYP
313}
314
315/* ----------------- xkb options dialog -----------------------*/
316
317static t_xkb_options_dlg*
8f9e6256 318xkb_options_dlg_create(t_xkb * xkb)
22242ed4
HJYP
319{
320 int x;
321 GtkWidget *vbox, *hbox, *display_type_frame,
322 *per_app_frame, *alignment1, *alignment2, *hbox3, *label4;
323
324 dlg = g_new0(t_xkb_options_dlg, 1);
325
326 dlg->dialog = gtk_dialog_new_with_buttons (
327 _("Configure Keyboard Layout Switcher"),
328 NULL,
329 GTK_DIALOG_NO_SEPARATOR,
330 GTK_STOCK_CLOSE,
331 GTK_RESPONSE_OK,
332 NULL
333 );
8f9e6256 334 panel_apply_icon(GTK_WINDOW(dlg->dialog));
335
22242ed4
HJYP
336
337 vbox = gtk_vbox_new(FALSE, 2);
338 gtk_widget_show(vbox);
339 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dlg->dialog)->vbox), vbox);
340
341 display_type_frame = gtk_frame_new (NULL);
342 gtk_frame_set_label (GTK_FRAME (display_type_frame), _("Show layout as"));
343 gtk_widget_show (display_type_frame);
344 gtk_box_pack_start (GTK_BOX (vbox), display_type_frame, TRUE, TRUE, 2);
345 gtk_container_set_border_width (GTK_CONTAINER (display_type_frame), 5);
346
347 alignment2 = gtk_alignment_new (0.5, 0.5, 1, 1);
348 gtk_widget_show (alignment2);
349 gtk_container_add (GTK_CONTAINER (display_type_frame), alignment2);
350 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment2), 4, 4, 10, 10);
351
352 hbox = gtk_hbox_new(FALSE, 2);
353 gtk_widget_show(hbox);
354 gtk_container_add (GTK_CONTAINER (alignment2), hbox);
355
356 dlg->display_type_optmenu = gtk_combo_box_new_text ();
357 gtk_combo_box_append_text (GTK_COMBO_BOX (dlg->display_type_optmenu), _("image"));
358 gtk_combo_box_append_text (GTK_COMBO_BOX (dlg->display_type_optmenu), _("text"));
359 gtk_box_pack_start(GTK_BOX(hbox), dlg->display_type_optmenu, TRUE, TRUE, 2);
360
361 per_app_frame = gtk_frame_new (NULL);
362 gtk_frame_set_label (GTK_FRAME (per_app_frame), _("Per application settings"));
363 gtk_widget_show (per_app_frame);
364 gtk_box_pack_start (GTK_BOX (vbox), per_app_frame, TRUE, TRUE, 2);
365 gtk_container_set_border_width (GTK_CONTAINER (per_app_frame), 5);
366
367 alignment1 = gtk_alignment_new (0.5, 0.5, 1, 1);
368 gtk_widget_show (alignment1);
369 gtk_container_add (GTK_CONTAINER (per_app_frame), alignment1);
370 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment1), 4, 4, 10, 10);
371
372 dlg->per_app_vbox = gtk_vbox_new (FALSE, 2);
373 gtk_widget_show (dlg->per_app_vbox);
374 gtk_container_add (GTK_CONTAINER (alignment1), dlg->per_app_vbox);
375
376 dlg->per_app_checkbutton = gtk_check_button_new_with_mnemonic(_("_Remember layout for each application"));
377 gtk_widget_show (dlg->per_app_checkbutton);
378 gtk_box_pack_start (GTK_BOX (dlg->per_app_vbox), dlg->per_app_checkbutton, FALSE, FALSE, 2);
379 gtk_toggle_button_set_active((GtkToggleButton*) dlg->per_app_checkbutton, TRUE);
380
381 hbox3 = gtk_hbox_new (FALSE, 2);
382 gtk_widget_show (hbox3);
383 gtk_box_pack_start (GTK_BOX (dlg->per_app_vbox), hbox3, TRUE, TRUE, 2);
384
385 label4 = gtk_label_new (_("Default layout:"));
386 gtk_widget_show (label4);
387 gtk_box_pack_start (GTK_BOX (hbox3), label4, FALSE, FALSE, 2);
388
389 dlg->per_app_default_layout_menu = gtk_combo_box_new_text ();
390 gtk_widget_show (dlg->per_app_default_layout_menu);
391 gtk_box_pack_start (GTK_BOX (hbox3), dlg->per_app_default_layout_menu, FALSE, TRUE, 2);
392
393 for (x = 0; x < get_group_count(); x++)
394 {
395 gtk_combo_box_append_text(
396 GTK_COMBO_BOX(dlg->per_app_default_layout_menu),
397 get_symbol_name_by_res_no(x));
398 }
399
400
401
402 gtk_widget_show_all(vbox);
403
404 g_signal_connect_swapped( (gpointer)dlg->dialog, "response",
405 G_CALLBACK (free_xkb_options_dlg), NULL);
406
407 return dlg;
408}
409
410void
411free_xkb_options_dlg(GtkDialog *dialog, gint arg1, gpointer user_data)
412{
413 DBG("destroy options dialog\n");
414 gtk_widget_hide(dlg->dialog);
415 gtk_widget_destroy(dlg->dialog);
8f9e6256 416
417 panel_config_save(dlg->xkb->plugin->panel);
418 set_new_locale(dlg->xkb);
22242ed4
HJYP
419
420 g_free(dlg);
421 dlg = NULL;
422}
423
424static void
425xkb_options_dlg_set_xkb(t_xkb_options_dlg *dlg, t_xkb *xkb)
426{
427 dlg->xkb = xkb;
428
429 gtk_combo_box_set_active(GTK_COMBO_BOX(dlg->display_type_optmenu), xkb->display_type);
430
431 gtk_combo_box_set_active((GtkComboBox*)dlg->per_app_default_layout_menu, xkb->default_group);
432
433 gtk_toggle_button_set_active((GtkToggleButton*)dlg->per_app_checkbutton, xkb->enable_perapp);
434
435 g_signal_connect(dlg->display_type_optmenu, "changed", G_CALLBACK(xkb_display_type_changed), xkb);
436 g_signal_connect(dlg->per_app_checkbutton, "toggled", G_CALLBACK(xkb_enable_perapp_changed), dlg);
437 g_signal_connect(dlg->per_app_default_layout_menu, "changed", G_CALLBACK(xkb_def_lang_changed), xkb);
438}
439
8f9e6256 440/* Callback when the configuration is to be saved. */
441static void xkb_save_configuration(Plugin * p, FILE * fp)
442{
443 t_xkb * xkb = (t_xkb *) p->priv;
444 lxpanel_put_int(fp, "DisplayType", xkb->display_type);
445 lxpanel_put_int(fp, "PerAppLayout", xkb->enable_perapp);
446 lxpanel_put_int(fp, "DefaultGroup", xkb->default_group);
447}
448
449/* Callback when panel configuration changes. */
450static void xkb_panel_configuration_changed(Plugin * p)
451{
452 /* Do a full redraw. */
453 t_xkb * xkb = (t_xkb *) p->priv;
454 xkb->size = p->panel->icon_size;
455 set_new_locale(xkb);
456}
22242ed4
HJYP
457
458PluginClass xkb_plugin_class = {
2918994e 459
460 PLUGINCLASS_VERSIONING,
22242ed4
HJYP
461
462 type : "xkb",
2918994e 463 name : N_("Keyboard Layout Switcher"),
22242ed4
HJYP
464 version: "1.0",
465 description : N_("Switch between available keyboard layouts"),
466
8f9e6256 467 /* Due to static variable usage; when context migrated to t_xkb, can be removed. */
468 one_per_system : TRUE,
469
22242ed4
HJYP
470 constructor : xkb_constructor,
471 destructor : xkb_destructor,
8f9e6256 472 config : xkb_configure,
473 save : xkb_save_configuration,
474 panel_configuration_changed : xkb_panel_configuration_changed
22242ed4 475};