1 | /* |
---|
2 | * This program is free software; you can redistribute it and/or modify |
---|
3 | * it under the terms of the GNU General Public License as published by |
---|
4 | * the Free Software Foundation; either version 2 of the License, or |
---|
5 | * (at your option) any later version. |
---|
6 | * |
---|
7 | * This program is distributed in the hope that it will be useful, |
---|
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
10 | * GNU Library General Public License for more details. |
---|
11 | * |
---|
12 | * You should have received a copy of the GNU General Public License |
---|
13 | * along with this program; if not, write to the Free Software |
---|
14 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
---|
15 | */ |
---|
16 | |
---|
17 | #include "config.h" |
---|
18 | |
---|
19 | #include <gdk/gdkscreen.h> |
---|
20 | #include <gdk/gdkx.h> |
---|
21 | #include <gnome.h> |
---|
22 | #include <glade/glade.h> |
---|
23 | |
---|
24 | #include <libxklavier/xklavier_config.h> |
---|
25 | |
---|
26 | #include "gswitchit-applet.h" |
---|
27 | |
---|
28 | #include "libgswitchit/gswitchit_util.h" |
---|
29 | #include "libgswitchit/gswitchit_plugin_manager.h" |
---|
30 | |
---|
31 | #if 1 |
---|
32 | #include <sys/types.h> |
---|
33 | #include <sys/stat.h> |
---|
34 | #include <fcntl.h> |
---|
35 | #include <unistd.h> |
---|
36 | #endif |
---|
37 | |
---|
38 | #define GROUPS_SUBMENU_PATH "/popups/popup/groups" |
---|
39 | |
---|
40 | static gboolean terminatedOnce = FALSE; |
---|
41 | static GSwitchItApplet *theAppletInstance = NULL; |
---|
42 | |
---|
43 | static void GSwitchItAppletCmdProps (BonoboUIComponent * uic, |
---|
44 | GSwitchItApplet * sia, |
---|
45 | const gchar * verb); |
---|
46 | |
---|
47 | static void GSwitchItAppletCmdCapplet (BonoboUIComponent * uic, |
---|
48 | GSwitchItApplet * sia, |
---|
49 | const gchar * verb); |
---|
50 | |
---|
51 | static void GSwitchItAppletCmdPlugins (BonoboUIComponent * uic, |
---|
52 | GSwitchItApplet * sia, |
---|
53 | const gchar * verb); |
---|
54 | |
---|
55 | static void GSwitchItAppletCmdAbout (BonoboUIComponent * uic, |
---|
56 | GSwitchItApplet * sia, |
---|
57 | const gchar * verb); |
---|
58 | |
---|
59 | static void GSwitchItAppletCmdHelp (BonoboUIComponent * uic, |
---|
60 | GSwitchItApplet * sia, |
---|
61 | const gchar * verb); |
---|
62 | |
---|
63 | static void GSwitchItAppletCmdSetGroup (BonoboUIComponent * uic, |
---|
64 | GSwitchItApplet * sia, |
---|
65 | const gchar * verb); |
---|
66 | |
---|
67 | static void GSwitchItAppletCleanupGroupsSubmenu (GSwitchItApplet * sia); |
---|
68 | |
---|
69 | static void GSwitchItAppletSetupGroupsSubmenu (GSwitchItApplet * sia); |
---|
70 | |
---|
71 | static GdkFilterReturn GSwitchItAppletWmProtocolsFilter (GdkXEvent * xev, |
---|
72 | GdkEvent * event, |
---|
73 | gpointer data); |
---|
74 | |
---|
75 | static void GSwitchItAppletFillNotebook (GSwitchItApplet * sia); |
---|
76 | |
---|
77 | static void GSwitchItAppletCleanupNotebook (GSwitchItApplet * sia); |
---|
78 | |
---|
79 | static gboolean GSwitchItAppletButtonPressed (GtkWidget * widget, |
---|
80 | GdkEventButton * event, |
---|
81 | GSwitchItAppletConfig * |
---|
82 | config); |
---|
83 | |
---|
84 | static gboolean GSwitchItAppletKeyPressed (GtkWidget * widget, |
---|
85 | GdkEventKey * event, |
---|
86 | GSwitchItAppletConfig * config); |
---|
87 | |
---|
88 | static const BonoboUIVerb gswitchitAppletMenuVerbs[] = { |
---|
89 | BONOBO_UI_UNSAFE_VERB ("Props", GSwitchItAppletCmdProps), |
---|
90 | BONOBO_UI_UNSAFE_VERB ("Capplet", GSwitchItAppletCmdCapplet), |
---|
91 | BONOBO_UI_UNSAFE_VERB ("Plugins", GSwitchItAppletCmdPlugins), |
---|
92 | BONOBO_UI_UNSAFE_VERB ("About", GSwitchItAppletCmdAbout), |
---|
93 | BONOBO_UI_UNSAFE_VERB ("Help", GSwitchItAppletCmdHelp), |
---|
94 | BONOBO_UI_VERB_END |
---|
95 | }; |
---|
96 | |
---|
97 | static void |
---|
98 | GSwitchItAppletSetTooltip (GSwitchItApplet * sia, const char *str) |
---|
99 | { |
---|
100 | GtkTooltips *tooltips; |
---|
101 | char buf[XKL_MAX_CI_DESC_LENGTH + 128]; |
---|
102 | |
---|
103 | if (str == NULL) |
---|
104 | return; |
---|
105 | tooltips = gtk_tooltips_new (); |
---|
106 | g_object_ref (G_OBJECT (tooltips)); |
---|
107 | gtk_object_sink (GTK_OBJECT (tooltips)); |
---|
108 | g_object_set_data_full (G_OBJECT (sia->applet), "tooltips", |
---|
109 | tooltips, (GDestroyNotify) g_object_unref); |
---|
110 | g_snprintf (buf, sizeof (buf), _("Keyboard Indicator (%s)"), str); |
---|
111 | gtk_tooltips_set_tip (tooltips, sia->applet, buf, NULL); |
---|
112 | } |
---|
113 | |
---|
114 | void |
---|
115 | GSwitchItAppletReinitUi (GSwitchItApplet * sia) |
---|
116 | { |
---|
117 | const char *pname; |
---|
118 | XklState *currentState; |
---|
119 | |
---|
120 | GSwitchItAppletCleanupGroupsSubmenu (sia); |
---|
121 | GSwitchItAppletSetupGroupsSubmenu (sia); |
---|
122 | |
---|
123 | GSwitchItAppletCleanupNotebook (sia); |
---|
124 | GSwitchItAppletFillNotebook (sia); |
---|
125 | |
---|
126 | GSwitchItAppletRevalidate (sia); |
---|
127 | |
---|
128 | /* also, update tooltips */ |
---|
129 | currentState = XklGetCurrentState (); |
---|
130 | if (currentState->group >= 0) { |
---|
131 | pname = sia->groupNames[currentState->group]; |
---|
132 | GSwitchItAppletSetTooltip (sia, pname); |
---|
133 | } |
---|
134 | } |
---|
135 | |
---|
136 | static void |
---|
137 | GSwitchItAppletConfigChanged (GConfClient * client, |
---|
138 | guint cnxn_id, |
---|
139 | GConfEntry * entry, GSwitchItApplet * sia) |
---|
140 | { |
---|
141 | XklDebug (100, |
---|
142 | "Applet configuration changed in GConf - reiniting...\n"); |
---|
143 | |
---|
144 | GSwitchItAppletConfigLoad (&sia->appletConfig); |
---|
145 | GSwitchItAppletConfigUpdateImages (&sia->appletConfig, |
---|
146 | &sia->xkbConfig); |
---|
147 | GSwitchItAppletConfigActivate (&sia->appletConfig); |
---|
148 | GSwitchItPluginManagerTogglePlugins (&sia->pluginManager, |
---|
149 | &sia->pluginContainer, |
---|
150 | sia->appletConfig. |
---|
151 | enabledPlugins); |
---|
152 | GSwitchItAppletReinitUi (sia); |
---|
153 | } |
---|
154 | |
---|
155 | static int |
---|
156 | GSwitchItAppletWindowCallback (Window win, Window parent, |
---|
157 | GSwitchItApplet * sia) |
---|
158 | { |
---|
159 | return GSwitchItPluginManagerWindowCreated (&sia->pluginManager, |
---|
160 | win, parent); |
---|
161 | } |
---|
162 | |
---|
163 | static void |
---|
164 | GSwitchItAppletXkbConfigCallback (GSwitchItApplet * sia) |
---|
165 | { |
---|
166 | XklDebug (100, |
---|
167 | "XKB configuration changed on X Server - reiniting...\n"); |
---|
168 | GSwitchItXkbConfigLoadCurrent (&sia->xkbConfig); |
---|
169 | GSwitchItAppletConfigUpdateImages (&sia->appletConfig, |
---|
170 | &sia->xkbConfig); |
---|
171 | GSwitchItAppletConfigLoadGroupDescriptionsUtf8 (&sia->appletConfig, |
---|
172 | sia->groupNames); |
---|
173 | |
---|
174 | GSwitchItAppletReinitUi (sia); |
---|
175 | } |
---|
176 | |
---|
177 | static void |
---|
178 | GSwitchItAppletStateCallback (XklStateChange |
---|
179 | changeType, |
---|
180 | int group, Bool restore, |
---|
181 | GSwitchItApplet * sia) |
---|
182 | { |
---|
183 | XklDebug (150, "group is now %d, restore: %d\n", group, restore); |
---|
184 | |
---|
185 | if (changeType == GROUP_CHANGED) { |
---|
186 | GSwitchItPluginManagerGroupChanged (&sia->pluginManager, |
---|
187 | group); |
---|
188 | XklDebug (200, "do repaint\n"); |
---|
189 | GSwitchItAppletRevalidateGroup (sia, group); |
---|
190 | } |
---|
191 | } |
---|
192 | |
---|
193 | GdkFilterReturn |
---|
194 | GSwitchItAppletFilterXEvt (GdkXEvent * xev, |
---|
195 | GdkEvent * event, GSwitchItApplet * sia) |
---|
196 | { |
---|
197 | XEvent *xevent = (XEvent *) xev; |
---|
198 | Display *display = xevent->xany.display; |
---|
199 | XklFilterEvents (xevent); |
---|
200 | switch (xevent->type) { |
---|
201 | case ReparentNotify: |
---|
202 | { |
---|
203 | XReparentEvent *rne = (XReparentEvent *) xev; |
---|
204 | GtkWidget *w1; |
---|
205 | GdkWindow *w; |
---|
206 | w1 = gtk_widget_get_ancestor (sia->applet, |
---|
207 | GTK_TYPE_WINDOW); |
---|
208 | if (w1 == NULL) |
---|
209 | break; |
---|
210 | w = w1->window; |
---|
211 | if (w == NULL || GDK_WINDOW_XID (w) != rne->window) |
---|
212 | break; |
---|
213 | XklSetTransparent (GDK_WINDOW_XID (w), TRUE); |
---|
214 | } |
---|
215 | break; |
---|
216 | } |
---|
217 | |
---|
218 | return GDK_FILTER_CONTINUE; |
---|
219 | } |
---|
220 | |
---|
221 | GdkFilterReturn |
---|
222 | GSwitchItAppletWmProtocolsFilter (GdkXEvent * |
---|
223 | xev, GdkEvent * event, gpointer data) |
---|
224 | { |
---|
225 | XEvent *xevent = (XEvent *) xev; |
---|
226 | Display *display = xevent->xany.display; |
---|
227 | if ((Atom) xevent->xclient.data.l[0] == |
---|
228 | XInternAtom (display, "_NET_WM_PING", FALSE)) { |
---|
229 | static long lastTimestamp = -1; |
---|
230 | long thisTimestamp = xevent->xclient.data.l[1]; |
---|
231 | /* allow only events we have not processed yet */ |
---|
232 | if (lastTimestamp == thisTimestamp) { |
---|
233 | return GDK_FILTER_REMOVE; |
---|
234 | } |
---|
235 | lastTimestamp = thisTimestamp; |
---|
236 | } |
---|
237 | |
---|
238 | return GDK_FILTER_CONTINUE; |
---|
239 | } |
---|
240 | |
---|
241 | void |
---|
242 | GSwitchItAppletRevalidate (GSwitchItApplet * sia) |
---|
243 | { |
---|
244 | XklState *currentState; |
---|
245 | currentState = XklGetCurrentState (); |
---|
246 | if (currentState->group >= 0) |
---|
247 | GSwitchItAppletRevalidateGroup (sia, currentState->group); |
---|
248 | } |
---|
249 | |
---|
250 | static void |
---|
251 | GSwitchItAppletCleanupNotebook (GSwitchItApplet * sia) |
---|
252 | { |
---|
253 | int i; |
---|
254 | GtkNotebook *notebook = GTK_NOTEBOOK (sia->notebook); |
---|
255 | |
---|
256 | /* Do not remove the first page! It is the default page */ |
---|
257 | for (i = gtk_notebook_get_n_pages (notebook); --i > 0;) { |
---|
258 | gtk_notebook_remove_page (notebook, i); |
---|
259 | } |
---|
260 | } |
---|
261 | |
---|
262 | static GtkWidget * |
---|
263 | GSwitchItAppletPrepareDrawing (GSwitchItApplet * sia, int group) |
---|
264 | { |
---|
265 | GdkPixbuf *image = sia->appletConfig.images[group]; |
---|
266 | GdkPixbuf *scaled; |
---|
267 | PanelAppletOrient orient; |
---|
268 | int psize, xsize = 0, ysize = 0; |
---|
269 | double xyratio; |
---|
270 | sia->ebox = gtk_event_box_new (); |
---|
271 | if (sia->appletConfig.showFlags) { |
---|
272 | GtkWidget *flagImg; |
---|
273 | if (image == NULL) |
---|
274 | return NULL; |
---|
275 | orient = |
---|
276 | panel_applet_get_orient (PANEL_APPLET (sia->applet)); |
---|
277 | psize = |
---|
278 | panel_applet_get_size (PANEL_APPLET (sia->applet)) - 4; |
---|
279 | XklDebug (150, "Resizing the applet for size %d\n", psize); |
---|
280 | xyratio = |
---|
281 | 1.0 * gdk_pixbuf_get_width (image) / |
---|
282 | gdk_pixbuf_get_height (image); |
---|
283 | switch (orient) { |
---|
284 | case PANEL_APPLET_ORIENT_UP: |
---|
285 | case PANEL_APPLET_ORIENT_DOWN: |
---|
286 | ysize = psize; |
---|
287 | xsize = psize * xyratio; |
---|
288 | break; |
---|
289 | case PANEL_APPLET_ORIENT_LEFT: |
---|
290 | case PANEL_APPLET_ORIENT_RIGHT: |
---|
291 | ysize = psize / xyratio; |
---|
292 | break; |
---|
293 | } |
---|
294 | |
---|
295 | scaled = |
---|
296 | gdk_pixbuf_scale_simple (image, xsize, ysize, |
---|
297 | GDK_INTERP_HYPER); |
---|
298 | flagImg = gtk_image_new_from_pixbuf (scaled); |
---|
299 | gtk_container_add (GTK_CONTAINER (sia->ebox), flagImg); |
---|
300 | g_object_unref (G_OBJECT (scaled)); |
---|
301 | } else { |
---|
302 | char *layoutName; |
---|
303 | char *allocLayoutName = NULL; |
---|
304 | XklConfigItem configItem; |
---|
305 | GtkWidget *align, *label; |
---|
306 | |
---|
307 | if (XklMultipleLayoutsSupported ()) { |
---|
308 | char *fullLayoutName = |
---|
309 | (char *) g_slist_nth_data (sia->xkbConfig. |
---|
310 | layouts, group); |
---|
311 | char *variantName; |
---|
312 | if (!GSwitchItConfigSplitItems |
---|
313 | (fullLayoutName, &layoutName, &variantName)) |
---|
314 | /* just in case */ |
---|
315 | layoutName = fullLayoutName; |
---|
316 | |
---|
317 | g_snprintf (configItem.name, |
---|
318 | sizeof (configItem.name), "%s", |
---|
319 | layoutName); |
---|
320 | |
---|
321 | if (XklConfigFindLayout (&configItem)) { |
---|
322 | char *sd = configItem.shortDescription; |
---|
323 | if (sd != NULL && *sd != '\0') { |
---|
324 | layoutName = allocLayoutName = |
---|
325 | g_locale_to_utf8 (sd, -1, NULL, |
---|
326 | NULL, NULL); |
---|
327 | } |
---|
328 | } |
---|
329 | } else |
---|
330 | layoutName = sia->groupNames[group]; |
---|
331 | align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0); |
---|
332 | label = gtk_label_new (layoutName); |
---|
333 | if (allocLayoutName != NULL) |
---|
334 | g_free (allocLayoutName); |
---|
335 | gtk_container_add (GTK_CONTAINER (align), label); |
---|
336 | gtk_container_add (GTK_CONTAINER (sia->ebox), align); |
---|
337 | |
---|
338 | gtk_container_set_border_width (GTK_CONTAINER (align), 2); |
---|
339 | } |
---|
340 | g_signal_connect (G_OBJECT (sia->ebox), |
---|
341 | "button_press_event", |
---|
342 | G_CALLBACK |
---|
343 | (GSwitchItAppletButtonPressed), sia); |
---|
344 | |
---|
345 | g_signal_connect (G_OBJECT (sia->applet), |
---|
346 | "key_press_event", |
---|
347 | G_CALLBACK |
---|
348 | (GSwitchItAppletKeyPressed), sia); |
---|
349 | |
---|
350 | return sia->ebox; |
---|
351 | } |
---|
352 | |
---|
353 | static void |
---|
354 | GSwitchItAppletFillNotebook (GSwitchItApplet * sia) |
---|
355 | { |
---|
356 | int grp; |
---|
357 | int totalGroups = XklGetNumGroups (); |
---|
358 | GtkNotebook *notebook = GTK_NOTEBOOK (sia->notebook); |
---|
359 | |
---|
360 | for (grp = 0; grp < totalGroups; grp++) { |
---|
361 | GtkWidget *page, *decoratedPage; |
---|
362 | XklDebug (150, |
---|
363 | "The widget for the group %d is not ready, let's prepare it!\n", |
---|
364 | grp); |
---|
365 | page = GSwitchItAppletPrepareDrawing (sia, grp); |
---|
366 | |
---|
367 | decoratedPage = |
---|
368 | GSwitchItPluginManagerDecorateWidget (&sia-> |
---|
369 | pluginManager, |
---|
370 | page, grp, |
---|
371 | sia-> |
---|
372 | groupNames[grp], |
---|
373 | &sia->xkbConfig); |
---|
374 | |
---|
375 | gtk_notebook_append_page (notebook, |
---|
376 | decoratedPage == |
---|
377 | NULL ? page : decoratedPage, |
---|
378 | gtk_label_new ("")); |
---|
379 | |
---|
380 | gtk_widget_show_all (page); |
---|
381 | } |
---|
382 | } |
---|
383 | |
---|
384 | void |
---|
385 | GSwitchItAppletRevalidateGroup (GSwitchItApplet * sia, int group) |
---|
386 | { |
---|
387 | const char *pname; |
---|
388 | XklDebug (200, "Revalidating for group %d\n", group); |
---|
389 | |
---|
390 | gtk_notebook_set_current_page (GTK_NOTEBOOK (sia->notebook), group + 1); |
---|
391 | |
---|
392 | pname = sia->groupNames[group]; |
---|
393 | GSwitchItAppletSetTooltip (sia, pname); |
---|
394 | } |
---|
395 | |
---|
396 | static void |
---|
397 | GSwitchItAppletChangePixelSize (PanelApplet * |
---|
398 | widget, guint size, GSwitchItApplet * sia) |
---|
399 | { |
---|
400 | GSwitchItAppletCleanupNotebook (sia); |
---|
401 | GSwitchItAppletFillNotebook (sia); |
---|
402 | |
---|
403 | GSwitchItAppletRevalidate (sia); |
---|
404 | } |
---|
405 | |
---|
406 | static void |
---|
407 | GSwitchItAppletChangeBackground (PanelApplet * |
---|
408 | widget, PanelAppletBackgroundType type, |
---|
409 | GdkColor * color, GdkPixmap * pixmap, |
---|
410 | GSwitchItApplet * sia) |
---|
411 | { |
---|
412 | GtkRcStyle *rc_style = gtk_rc_style_new (); |
---|
413 | |
---|
414 | switch (type) { |
---|
415 | case PANEL_PIXMAP_BACKGROUND: |
---|
416 | gtk_widget_modify_style (GTK_WIDGET (sia->ebox), |
---|
417 | rc_style); |
---|
418 | gtk_widget_modify_style (GTK_WIDGET (sia->applet), |
---|
419 | rc_style); |
---|
420 | break; |
---|
421 | |
---|
422 | case PANEL_COLOR_BACKGROUND: |
---|
423 | gtk_widget_modify_bg (GTK_WIDGET (sia->ebox), |
---|
424 | GTK_STATE_NORMAL, color); |
---|
425 | gtk_widget_modify_bg (GTK_WIDGET (sia->applet), |
---|
426 | GTK_STATE_NORMAL, color); |
---|
427 | break; |
---|
428 | |
---|
429 | case PANEL_NO_BACKGROUND: |
---|
430 | gtk_widget_modify_style (GTK_WIDGET (sia->ebox), |
---|
431 | rc_style); |
---|
432 | gtk_widget_modify_style (GTK_WIDGET (sia->applet), |
---|
433 | rc_style); |
---|
434 | break; |
---|
435 | |
---|
436 | default: |
---|
437 | gtk_widget_modify_style (GTK_WIDGET (sia->ebox), |
---|
438 | rc_style); |
---|
439 | gtk_widget_modify_style (GTK_WIDGET (sia->applet), |
---|
440 | rc_style); |
---|
441 | break; |
---|
442 | } |
---|
443 | |
---|
444 | gtk_rc_style_unref (rc_style); |
---|
445 | } |
---|
446 | |
---|
447 | static gboolean |
---|
448 | GSwitchItAppletKeyPressed (GtkWidget * |
---|
449 | widget, |
---|
450 | GdkEventKey * |
---|
451 | event, GSwitchItAppletConfig * config) |
---|
452 | { |
---|
453 | switch (event->keyval) { |
---|
454 | case GDK_KP_Enter: |
---|
455 | case GDK_ISO_Enter: |
---|
456 | case GDK_3270_Enter: |
---|
457 | case GDK_Return: |
---|
458 | case GDK_space: |
---|
459 | case GDK_KP_Space: |
---|
460 | GSwitchItAppletConfigLockNextGroup (); |
---|
461 | return TRUE; |
---|
462 | default: |
---|
463 | break; |
---|
464 | } |
---|
465 | return FALSE; |
---|
466 | } |
---|
467 | |
---|
468 | static gboolean |
---|
469 | GSwitchItAppletButtonPressed (GtkWidget * |
---|
470 | widget, |
---|
471 | GdkEventButton * |
---|
472 | event, GSwitchItAppletConfig * config) |
---|
473 | { |
---|
474 | if (event->button == 1 && event->type == GDK_BUTTON_PRESS) { |
---|
475 | XklDebug (150, "Mouse button pressed on applet\n"); |
---|
476 | GSwitchItAppletConfigLockNextGroup (); |
---|
477 | return TRUE; |
---|
478 | } |
---|
479 | return FALSE; |
---|
480 | } |
---|
481 | |
---|
482 | void |
---|
483 | GSwitchItAppletCmdProps (BonoboUIComponent * |
---|
484 | uic, GSwitchItApplet * sia, const gchar * verb) |
---|
485 | { |
---|
486 | /* Only one preferences window at a time */ |
---|
487 | if (sia->propsDialog) { |
---|
488 | gtk_window_set_screen (GTK_WINDOW (sia->propsDialog), |
---|
489 | gtk_widget_get_screen (GTK_WIDGET |
---|
490 | (sia-> |
---|
491 | applet))); |
---|
492 | |
---|
493 | gtk_window_present (GTK_WINDOW (sia->propsDialog)); |
---|
494 | return; |
---|
495 | } |
---|
496 | |
---|
497 | GSwitchItAppletPropsCreate (sia); |
---|
498 | } |
---|
499 | |
---|
500 | void |
---|
501 | GSwitchItAppletCmdCapplet (BonoboUIComponent * |
---|
502 | uic, GSwitchItApplet * sia, const gchar * verb) |
---|
503 | { |
---|
504 | GError *error = NULL; |
---|
505 | |
---|
506 | gdk_spawn_command_line_on_screen (gtk_widget_get_screen |
---|
507 | (GTK_WIDGET (sia->applet)), |
---|
508 | "gnome-keyboard-properties", |
---|
509 | &error); |
---|
510 | |
---|
511 | if (error != NULL) { |
---|
512 | /* FIXME: After string ui freeze are over, we want to show an error message here */ |
---|
513 | g_error_free (error); |
---|
514 | } |
---|
515 | } |
---|
516 | |
---|
517 | void |
---|
518 | GSwitchItAppletCmdPlugins (BonoboUIComponent * |
---|
519 | uic, GSwitchItApplet * sia, const gchar * verb) |
---|
520 | { |
---|
521 | GError *error = NULL; |
---|
522 | |
---|
523 | gdk_spawn_command_line_on_screen (gtk_widget_get_screen |
---|
524 | (GTK_WIDGET (sia->applet)), |
---|
525 | "gswitchit-plugins-capplet", |
---|
526 | &error); |
---|
527 | |
---|
528 | if (error != NULL) { |
---|
529 | /* FIXME: after string ui freeze are over, we want to show an error message here */ |
---|
530 | g_error_free (error); |
---|
531 | } |
---|
532 | } |
---|
533 | |
---|
534 | static void |
---|
535 | GSwitchItAppletCmdSetGroup (BonoboUIComponent |
---|
536 | * uic, GSwitchItApplet * sia, |
---|
537 | const gchar * verb) |
---|
538 | { |
---|
539 | XklState st; |
---|
540 | Window cur; |
---|
541 | if (sscanf (verb, "Group_%d", &st.group) != 1) { |
---|
542 | XklDebug (50, "Strange verb: [%s]\n", verb); |
---|
543 | return; |
---|
544 | } |
---|
545 | |
---|
546 | XklAllowOneSwitchToSecondaryGroup (); |
---|
547 | cur = XklGetCurrentWindow (); |
---|
548 | if (cur != (Window) NULL) { |
---|
549 | XklDebug (150, "Enforcing the state %d for window %lx\n", |
---|
550 | st.group, cur); |
---|
551 | XklSaveState (XklGetCurrentWindow (), &st); |
---|
552 | /* XSetInputFocus( GDK_DISPLAY(), cur, RevertToNone, CurrentTime );*/ |
---|
553 | } else { |
---|
554 | XklDebug (150, |
---|
555 | "??? Enforcing the state %d for unknown window\n", |
---|
556 | st.group); |
---|
557 | /* strange situation - bad things can happen */ |
---|
558 | } |
---|
559 | XklLockGroup (st.group); |
---|
560 | } |
---|
561 | |
---|
562 | void |
---|
563 | GSwitchItAppletCmdHelp (BonoboUIComponent |
---|
564 | * uic, GSwitchItApplet * sia, const gchar * verb) |
---|
565 | { |
---|
566 | GSwitchItHelp (GTK_WIDGET (sia->applet), NULL); |
---|
567 | } |
---|
568 | |
---|
569 | void |
---|
570 | GSwitchItAppletCmdAbout (BonoboUIComponent * |
---|
571 | uic, GSwitchItApplet * sia, const gchar * verb) |
---|
572 | { |
---|
573 | const gchar *authors[] = { |
---|
574 | "Sergey V. Udaltsov<svu@gnome.org>", |
---|
575 | NULL |
---|
576 | }; |
---|
577 | const gchar *documenters[] = { |
---|
578 | "Sergey V. Udaltsov<svu@gnome.org>", |
---|
579 | NULL |
---|
580 | }; |
---|
581 | gchar *translatorCredits; |
---|
582 | GdkPixbuf *pixbuf = NULL; |
---|
583 | gchar *file; |
---|
584 | if (sia->aboutDialog) { |
---|
585 | gtk_window_set_screen (GTK_WINDOW (sia->aboutDialog), |
---|
586 | gtk_widget_get_screen (GTK_WIDGET |
---|
587 | (sia-> |
---|
588 | applet))); |
---|
589 | |
---|
590 | gtk_window_present (GTK_WINDOW (sia->aboutDialog)); |
---|
591 | return; |
---|
592 | } |
---|
593 | |
---|
594 | file = |
---|
595 | gnome_program_locate_file (NULL, |
---|
596 | GNOME_FILE_DOMAIN_PIXMAP, |
---|
597 | "gswitchit-applet.png", TRUE, NULL); |
---|
598 | pixbuf = gdk_pixbuf_new_from_file (file, NULL); |
---|
599 | translatorCredits = _("translator_credits"); |
---|
600 | translatorCredits = |
---|
601 | strcmp (translatorCredits, |
---|
602 | "translator_credits") != 0 ? translatorCredits : NULL; |
---|
603 | sia->aboutDialog = |
---|
604 | gnome_about_new (_("Keyboard Indicator"), VERSION, |
---|
605 | /* Translators: Please replace (C) with the proper copyright character. */ |
---|
606 | _ |
---|
607 | ("Copyright (c) Sergey V. Udaltsov 1999-2004"), |
---|
608 | _ |
---|
609 | ("Keyboard layout indicator applet for GNOME"), |
---|
610 | authors, documenters, translatorCredits, |
---|
611 | pixbuf); |
---|
612 | g_object_add_weak_pointer (G_OBJECT (sia->aboutDialog), |
---|
613 | (gpointer) & (sia->aboutDialog)); |
---|
614 | gnome_window_icon_set_from_file (GTK_WINDOW (sia->aboutDialog), |
---|
615 | file); |
---|
616 | g_free (file); |
---|
617 | |
---|
618 | gtk_window_set_screen (GTK_WINDOW (sia->aboutDialog), |
---|
619 | gtk_widget_get_screen (GTK_WIDGET |
---|
620 | (sia->applet))); |
---|
621 | |
---|
622 | gtk_window_present (GTK_WINDOW (sia->aboutDialog)); |
---|
623 | } |
---|
624 | |
---|
625 | static void |
---|
626 | GSwitchItAppletCleanupGroupsSubmenu (GSwitchItApplet * sia) |
---|
627 | { |
---|
628 | int i; |
---|
629 | BonoboUIComponent *popup; |
---|
630 | popup = |
---|
631 | panel_applet_get_popup_component (PANEL_APPLET (sia->applet)); |
---|
632 | for (i = XkbNumKbdGroups; --i >= 0;) { |
---|
633 | char path[80]; |
---|
634 | g_snprintf (path, sizeof (path), |
---|
635 | GROUPS_SUBMENU_PATH "/Group_%d", i); |
---|
636 | if (bonobo_ui_component_path_exists (popup, path, NULL)) { |
---|
637 | bonobo_ui_component_rm (popup, path, NULL); |
---|
638 | XklDebug (160, |
---|
639 | "Unregistered group menu item \'%s\'\n", |
---|
640 | path); |
---|
641 | } |
---|
642 | } |
---|
643 | |
---|
644 | XklDebug (160, "Unregistered group submenu\n"); |
---|
645 | } |
---|
646 | |
---|
647 | static void |
---|
648 | GSwitchItAppletSetupGroupsSubmenu (GSwitchItApplet * sia) |
---|
649 | { |
---|
650 | unsigned i, nGroups; |
---|
651 | char *pname; |
---|
652 | BonoboUIComponent *popup; |
---|
653 | GSList *layout; |
---|
654 | popup = |
---|
655 | panel_applet_get_popup_component (PANEL_APPLET (sia->applet)); |
---|
656 | XklDebug (160, "Registered group submenu\n"); |
---|
657 | nGroups = XklGetNumGroups (); |
---|
658 | pname = (char *) sia->groupNames; |
---|
659 | layout = sia->xkbConfig.layouts; |
---|
660 | for (i = 0; i < nGroups; i++) { |
---|
661 | char verb[40]; |
---|
662 | BonoboUINode *node; |
---|
663 | g_snprintf (verb, sizeof (verb), "Group_%d", i); |
---|
664 | node = bonobo_ui_node_new ("menuitem"); |
---|
665 | bonobo_ui_node_set_attr (node, "name", verb); |
---|
666 | bonobo_ui_node_set_attr (node, "verb", verb); |
---|
667 | bonobo_ui_node_set_attr (node, "label", pname); |
---|
668 | bonobo_ui_node_set_attr (node, "pixtype", "filename"); |
---|
669 | if (sia->appletConfig.showFlags) { |
---|
670 | const char *imageFile = |
---|
671 | GSwitchItAppletConfigGetImagesFile (&sia-> |
---|
672 | appletConfig, |
---|
673 | &sia-> |
---|
674 | xkbConfig, |
---|
675 | i); |
---|
676 | if (imageFile != NULL) |
---|
677 | bonobo_ui_node_set_attr (node, "pixname", |
---|
678 | imageFile); |
---|
679 | } |
---|
680 | bonobo_ui_component_set_tree (popup, GROUPS_SUBMENU_PATH, |
---|
681 | node, NULL); |
---|
682 | bonobo_ui_component_add_verb (popup, verb, (BonoboUIVerbFn) |
---|
683 | GSwitchItAppletCmdSetGroup, |
---|
684 | sia); |
---|
685 | XklDebug (160, |
---|
686 | "Registered group menu item \'%s\' as \'%s\'\n", |
---|
687 | verb, pname); |
---|
688 | pname += sizeof (sia->groupNames[0]); |
---|
689 | layout = g_slist_next (layout); |
---|
690 | } |
---|
691 | } |
---|
692 | |
---|
693 | static void |
---|
694 | GSwitchItAppletSetupMenu (GSwitchItApplet * sia) |
---|
695 | { |
---|
696 | panel_applet_setup_menu_from_file |
---|
697 | (PANEL_APPLET (sia->applet), NULL, |
---|
698 | "GNOME_GSwitchItApplet.xml", NULL, gswitchitAppletMenuVerbs, |
---|
699 | sia); |
---|
700 | GSwitchItAppletSetupGroupsSubmenu (sia); |
---|
701 | } |
---|
702 | |
---|
703 | static void |
---|
704 | GSwitchItAppletStartListen (GSwitchItApplet * sia) |
---|
705 | { |
---|
706 | gdk_window_add_filter (NULL, |
---|
707 | (GdkFilterFunc) GSwitchItAppletFilterXEvt, |
---|
708 | sia); |
---|
709 | gdk_window_add_filter (gdk_get_default_root_window (), |
---|
710 | (GdkFilterFunc) GSwitchItAppletFilterXEvt, |
---|
711 | sia); |
---|
712 | XklStartListen (); |
---|
713 | } |
---|
714 | |
---|
715 | static void |
---|
716 | GSwitchItAppletStopListen (GSwitchItApplet * sia) |
---|
717 | { |
---|
718 | XklStopListen (); |
---|
719 | /* !! no client message filter removal in gnome 2.2 */ |
---|
720 | gdk_window_remove_filter (NULL, (GdkFilterFunc) |
---|
721 | GSwitchItAppletFilterXEvt, sia); |
---|
722 | gdk_window_remove_filter |
---|
723 | (gdk_get_default_root_window (), |
---|
724 | (GdkFilterFunc) GSwitchItAppletFilterXEvt, sia); |
---|
725 | } |
---|
726 | |
---|
727 | static void GSwitchItAppletTerm (PanelApplet * |
---|
728 | applet, GSwitchItApplet * sia); |
---|
729 | |
---|
730 | static gboolean |
---|
731 | GSwitchItAppletInit (GSwitchItApplet * sia, PanelApplet * applet) |
---|
732 | { |
---|
733 | GtkWidget *defDrawingArea; |
---|
734 | GtkNotebook *notebook; |
---|
735 | GConfClient *confClient; |
---|
736 | |
---|
737 | glade_gnome_init (); |
---|
738 | |
---|
739 | sia->applet = GTK_WIDGET (applet); |
---|
740 | |
---|
741 | panel_applet_set_flags (applet, PANEL_APPLET_EXPAND_MINOR); |
---|
742 | |
---|
743 | notebook = GTK_NOTEBOOK (sia->notebook = gtk_notebook_new ()); |
---|
744 | gtk_notebook_set_show_tabs (notebook, FALSE); |
---|
745 | gtk_notebook_set_show_border (notebook, FALSE); |
---|
746 | |
---|
747 | gtk_container_add (GTK_CONTAINER (sia->applet), |
---|
748 | GTK_WIDGET (notebook)); |
---|
749 | |
---|
750 | defDrawingArea = |
---|
751 | gtk_image_new_from_stock (GTK_STOCK_STOP, |
---|
752 | GTK_ICON_SIZE_BUTTON); |
---|
753 | |
---|
754 | gtk_notebook_append_page (notebook, defDrawingArea, |
---|
755 | gtk_label_new ("")); |
---|
756 | |
---|
757 | GSwitchItAppletSetTooltip (sia, _(PACKAGE)); |
---|
758 | gtk_widget_show_all (sia->applet); |
---|
759 | gtk_widget_realize (sia->applet); |
---|
760 | /* GSwitchItInstallGlibLogAppender( ); */ |
---|
761 | if (XklInit (GDK_DISPLAY ()) != 0) { |
---|
762 | GSwitchItAppletSetTooltip (sia, |
---|
763 | _("XKB initialization error")); |
---|
764 | return TRUE; |
---|
765 | } |
---|
766 | |
---|
767 | XklConfigInit (); |
---|
768 | if (!XklConfigLoadRegistry ()) { |
---|
769 | GSwitchItAppletSetTooltip (sia, |
---|
770 | _ |
---|
771 | ("Error loading XKB configuration registry")); |
---|
772 | return TRUE; |
---|
773 | } |
---|
774 | |
---|
775 | XklRegisterWindowCallback ((XklWinCallback) |
---|
776 | GSwitchItAppletWindowCallback, |
---|
777 | (void *) sia); |
---|
778 | XklRegisterStateCallback ((XklStateCallback) |
---|
779 | GSwitchItAppletStateCallback, |
---|
780 | (void *) sia); |
---|
781 | XklRegisterConfigCallback ((XklConfigCallback) |
---|
782 | GSwitchItAppletXkbConfigCallback, |
---|
783 | (void *) sia); |
---|
784 | |
---|
785 | confClient = gconf_client_get_default (); |
---|
786 | GSwitchItPluginContainerInit (&sia->pluginContainer, confClient); |
---|
787 | g_object_unref (confClient); |
---|
788 | |
---|
789 | GSwitchItXkbConfigInit (&sia->xkbConfig, confClient); |
---|
790 | GSwitchItAppletConfigInit (&sia->appletConfig, confClient); |
---|
791 | GSwitchItPluginManagerInit (&sia->pluginManager); |
---|
792 | GSwitchItXkbConfigLoadCurrent (&sia->xkbConfig); |
---|
793 | GSwitchItAppletConfigLoad (&sia->appletConfig); |
---|
794 | GSwitchItAppletConfigUpdateImages (&sia->appletConfig, |
---|
795 | &sia->xkbConfig); |
---|
796 | GSwitchItAppletConfigActivate (&sia->appletConfig); |
---|
797 | GSwitchItAppletConfigLoadGroupDescriptionsUtf8 (&sia->appletConfig, |
---|
798 | sia->groupNames); |
---|
799 | GSwitchItPluginManagerInitEnabledPlugins (&sia->pluginManager, |
---|
800 | &sia->pluginContainer, |
---|
801 | sia->appletConfig. |
---|
802 | enabledPlugins); |
---|
803 | GSwitchItAppletConfigStartListen (&sia->appletConfig, |
---|
804 | (GConfClientNotifyFunc) |
---|
805 | GSwitchItAppletConfigChanged, |
---|
806 | sia); |
---|
807 | GSwitchItAppletFillNotebook (sia); |
---|
808 | GSwitchItAppletRevalidate (sia); |
---|
809 | g_signal_connect (G_OBJECT (sia->applet), "change_size", |
---|
810 | G_CALLBACK (GSwitchItAppletChangePixelSize), sia); |
---|
811 | g_signal_connect (G_OBJECT (sia->applet), "change_background", |
---|
812 | G_CALLBACK (GSwitchItAppletChangeBackground), sia); |
---|
813 | g_signal_connect (G_OBJECT (sia->applet), "button_press_event", |
---|
814 | G_CALLBACK (GSwitchItAppletButtonPressed), sia); |
---|
815 | |
---|
816 | GSwitchItAppletStartListen (sia); |
---|
817 | gtk_widget_add_events (sia->applet, GDK_BUTTON_PRESS_MASK); |
---|
818 | |
---|
819 | g_signal_connect (GTK_OBJECT (sia->applet), "destroy", |
---|
820 | G_CALLBACK (GSwitchItAppletTerm), sia); |
---|
821 | gtk_object_set_data (GTK_OBJECT (sia->applet), "sia", sia); |
---|
822 | GSwitchItAppletSetupMenu (sia); |
---|
823 | return TRUE; |
---|
824 | } |
---|
825 | |
---|
826 | void |
---|
827 | GSwitchItAppletTerm (PanelApplet * applet, GSwitchItApplet * sia) |
---|
828 | { |
---|
829 | if (terminatedOnce) { |
---|
830 | XklDebug (0, |
---|
831 | "Please do not call the termination method twice!!!\n"); |
---|
832 | return; |
---|
833 | } |
---|
834 | terminatedOnce = TRUE; |
---|
835 | XklDebug (100, "Starting the applet shutdown process\n"); |
---|
836 | GSwitchItAppletStopListen (sia); |
---|
837 | GSwitchItAppletConfigStopListen (&sia->appletConfig); |
---|
838 | XklRegisterStateCallback (NULL, NULL); |
---|
839 | XklRegisterConfigCallback (NULL, NULL); |
---|
840 | XklRegisterWindowCallback (NULL, NULL); |
---|
841 | GSwitchItPluginManagerTermInitializedPlugins (&sia->pluginManager); |
---|
842 | GSwitchItPluginManagerTerm (&sia->pluginManager); |
---|
843 | GSwitchItAppletConfigTerm (&sia->appletConfig); |
---|
844 | GSwitchItXkbConfigTerm (&sia->xkbConfig); |
---|
845 | GSwitchItPluginContainerTerm (&sia->pluginContainer); |
---|
846 | GSwitchItAppletCleanupNotebook (sia); |
---|
847 | |
---|
848 | XklConfigFreeRegistry (); |
---|
849 | XklConfigTerm (); |
---|
850 | XklTerm (); |
---|
851 | |
---|
852 | terminatedOnce = TRUE; |
---|
853 | g_free (theAppletInstance); |
---|
854 | theAppletInstance = NULL; |
---|
855 | XklDebug (100, "The applet successfully terminated\n"); |
---|
856 | } |
---|
857 | |
---|
858 | gboolean |
---|
859 | GSwitchItAppletNew (PanelApplet * applet) |
---|
860 | { |
---|
861 | gboolean rv = TRUE; |
---|
862 | #if 0 |
---|
863 | GLogLevelFlags fatal_mask; |
---|
864 | fatal_mask = G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL; |
---|
865 | g_log_set_always_fatal (fatal_mask); |
---|
866 | #endif |
---|
867 | if (theAppletInstance == NULL) { |
---|
868 | terminatedOnce = FALSE; |
---|
869 | theAppletInstance = g_new0 (GSwitchItApplet, 1); |
---|
870 | rv = GSwitchItAppletInit (theAppletInstance, applet); |
---|
871 | XklDebug (100, "The applet successfully started: %d\n", |
---|
872 | rv); |
---|
873 | } else |
---|
874 | XklDebug (0, |
---|
875 | "Please do not call the initialization method twice!!!\n"); |
---|
876 | return rv; |
---|
877 | } |
---|
878 | |
---|
879 | /* Plugin support */ |
---|
880 | void |
---|
881 | GSwitchItPluginContainerReinitUi (GSwitchItPluginContainer * pc) |
---|
882 | { |
---|
883 | GSwitchItAppletReinitUi ((GSwitchItApplet *) pc); |
---|
884 | } |
---|
885 | |
---|
886 | void |
---|
887 | GSwitchItPluginLoadLocalizedGroupNames (GSwitchItPluginContainer |
---|
888 | * pc, |
---|
889 | const GroupDescriptionsBuffer |
---|
890 | ** outDescr) |
---|
891 | { |
---|
892 | *outDescr = |
---|
893 | (const GroupDescriptionsBuffer |
---|
894 | *) (&(((GSwitchItApplet *) pc)->groupNames)); |
---|
895 | } |
---|