Codebase list xapp / 42cebaa
Add XAppKbdLayoutController - this is a wrapper around libgnomekbd api to provide unique icons for each layout. Michael Webster 7 years ago
261 changed file(s) with 870 addition(s) and 9 deletion(s). Raw diff Collapse all Expand all
4646 GDK_PIXBUF_REQUIRED=2.22.0
4747 GTK_REQUIRED=3.3.16
4848 GLIB_REQUIRED=2.37.3
49 CLUTTER_REQUIRED=1.10
4950
5051 AC_SUBST(GTK_REQUIRED)
5152 AC_SUBST(GLIB_REQUIRED)
6869 dnl pkg-config dependency checks
6970
7071 PKG_CHECK_MODULES(XAPP, gdk-pixbuf-2.0 >= $GDK_PIXBUF_REQUIRED
71 gtk+-3.0 >= $GTK_REQUIRED
72 glib-2.0 >= $GLIB_REQUIRED
73 gio-2.0 >= $GLIB_REQUIRED)
72 gtk+-3.0 >= $GTK_REQUIRED
73 glib-2.0 >= $GLIB_REQUIRED
74 gio-2.0 >= $GLIB_REQUIRED
75 cairo
76 libgnomekbdui
77 clutter-1.0 >= CLUTTER_REQUIRED)
7478
7579 dnl Language Support
7680
33 usr/share/locale
44 usr/bin/
55 usr/share/icons
6 usr/share/xapps
1313 AM_CFLAGS = $(WARN_CFLAGS)
1414
1515 introspection_sources = \
16 xapp-display.c
16 xapp-display.c \
17 xapp-kbd-layout-controller.c
1718
1819 libxapp_la_SOURCES = \
1920 $(introspection_sources)
3334
3435 libxappdir = $(includedir)/xapp/libxapp
3536 libxapp_HEADERS = \
36 xapp-display.h
37 xapp-display.h \
38 xapp-kbd-layout-controller.h
3739
3840 -include $(INTROSPECTION_MAKEFILE)
3941 INTROSPECTION_GIRS =
4345 if HAVE_INTROSPECTION
4446
4547 XApp-1.0.gir: libxapp.la
46 XApp_1_0_gir_INCLUDES = GObject-2.0 Gtk-3.0
47 XApp_1_0_gir_PACKAGES = gdk-pixbuf-2.0 glib-2.0 gobject-2.0 gio-2.0 gtk+-3.0
48 XApp_1_0_gir_INCLUDES = GObject-2.0 Gtk-3.0 Clutter-1.0
49 XApp_1_0_gir_PACKAGES = gdk-pixbuf-2.0 glib-2.0 gobject-2.0 gio-2.0 gtk+-3.0 clutter-1.0
4850 XApp_1_0_gir_EXPORT_PACKAGES = xapp
4951 XApp_1_0_gir_CFLAGS = -DGNOME_DESKTOP_USE_UNSTABLE_API -I$(top_srcdir)
5052 XApp_1_0_gir_LIBS = libxapp.la
0
1 #include <config.h>
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <math.h>
7
8 #include <glib/gstdio.h>
9 #include <gdk/gdk.h>
10 #include <gtk/gtk.h>
11 #include <cairo.h>
12
13 #include <libgnomekbd/gkbd-configuration.h>
14
15 #include "xapp-kbd-layout-controller.h"
16
17 enum
18 {
19 PROP_0,
20
21 PROP_ENABLED,
22 PROP_USE_CAPS,
23 };
24
25 enum
26 {
27 KBD_LAYOUT_CHANGED,
28 KBD_CONFIG_CHANGED,
29
30 LAST_SIGNAL
31 };
32
33 static guint signals[LAST_SIGNAL] = { 0, };
34
35 struct _XAppKbdLayoutControllerPrivate
36 {
37 GkbdConfiguration *config;
38
39 gint num_groups;
40 gchar *flag_dir;
41 gchar *temp_flag_theme_dir;
42
43 gchar *icon_names[4];
44 gchar *text_store[4];
45
46 gulong changed_id;
47 gulong group_changed_id;
48 guint idle_changed_id;
49
50 gboolean enabled;
51 };
52
53 G_DEFINE_TYPE (XAppKbdLayoutController, xapp_kbd_layout_controller, G_TYPE_OBJECT);
54
55 static void
56 initialize_flag_dir (XAppKbdLayoutController *controller)
57 {
58 XAppKbdLayoutControllerPrivate *priv = controller->priv;
59 gint i;
60
61 const char * const * data_dirs;
62
63 data_dirs = g_get_system_data_dirs ();
64
65 for (i = 0; data_dirs[i] != NULL; i++)
66 {
67 gchar *try_path = g_build_filename (data_dirs[i], "xapps", "flags", NULL);
68
69 if (g_file_test (try_path, G_FILE_TEST_EXISTS))
70 {
71 priv->flag_dir = g_strdup (try_path);
72 break;
73 }
74
75 g_free (try_path);
76 }
77 }
78
79 static void
80 initialize_icon_theme (XAppKbdLayoutController *controller)
81 {
82 XAppKbdLayoutControllerPrivate *priv = controller->priv;
83
84 const gchar *cache_dir = g_get_user_cache_dir ();
85
86 gchar *path = g_build_filename (cache_dir, "xapp-kbd-layout-controller", NULL);
87
88 g_mkdir_with_parents (path, 0700);
89
90 priv->temp_flag_theme_dir = path;
91
92 gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), path);
93 }
94
95 static void
96 clear_stores (XAppKbdLayoutController *controller)
97 {
98 XAppKbdLayoutControllerPrivate *priv = controller->priv;
99
100 gint i;
101
102 for (i = 0; i < 4; i++)
103 {
104 g_clear_pointer (&priv->text_store[i], g_free);
105 g_clear_pointer (&priv->icon_names[i], g_free);
106 }
107 }
108
109 typedef struct
110 {
111 gchar *group;
112 gint id;
113 } GroupData;
114
115 static void
116 group_data_free (GroupData *data)
117 {
118 g_clear_pointer (&data->group, g_free);
119 data->id = 0;
120
121 g_slice_free (GroupData, data);
122 }
123
124 static gchar *
125 create_text (XAppKbdLayoutController *controller,
126 const gchar *name,
127 gint id)
128 {
129 if (g_utf8_validate (name, -1, NULL))
130 {
131 gchar utf8[20];
132 gchar *utf8_cased = NULL;
133
134 g_utf8_strncpy (utf8, name, 2);
135
136 utf8_cased = g_utf8_strdown (utf8, -1);
137
138 GString *string = g_string_new (utf8_cased);
139
140 g_free (utf8_cased);
141
142 if (id > 0)
143 {
144 string = g_string_append_unichar (string, 0x2080 + id);
145 }
146
147 return g_string_free (string, FALSE);
148 }
149
150 return NULL;
151 }
152
153 static GdkPixbuf *
154 add_notation (GdkPixbuf *original, gint id)
155 {
156 gint width, height;
157 cairo_surface_t *surface;
158 cairo_t *cr;
159
160 width = gdk_pixbuf_get_width (original);
161 height = gdk_pixbuf_get_height (original);
162
163 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
164
165 if (surface == NULL)
166 {
167 return original;
168 }
169
170 cr = cairo_create (surface);
171
172 gdk_cairo_set_source_pixbuf (cr, original, 0, 0);
173 cairo_paint (cr);
174
175 gint rx, ry, rw, rh;
176
177 rx = rw = width / 2;
178 ry = rh = height / 2;
179
180 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, .5);
181 cairo_rectangle (cr, rx, ry, rw, rh);
182 cairo_fill (cr);
183
184 cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, .8);
185 cairo_rectangle (cr, rx - 1, ry - 1, rw, rh);
186 cairo_fill (cr);
187
188 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
189
190 gchar *num_string = g_strdup_printf ("%d", id);
191 cairo_select_font_face (cr, "sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
192 cairo_set_font_size (cr, height / 2);
193
194 cairo_text_extents_t ext;
195 cairo_text_extents (cr, num_string, &ext);
196
197 cairo_move_to (cr, rx + (rw / 2) - (ext.width / 2) - 1, ry + (rh / 2) + (ext.height / 2) - 1);
198
199 cairo_show_text (cr, num_string);
200 g_free (num_string);
201
202 GdkPixbuf *ret = gdk_pixbuf_get_from_surface (surface, 0, 0, width, height);
203
204 cairo_surface_destroy (surface);
205 cairo_destroy (cr);
206
207 if (ret == NULL)
208 {
209 return original;
210 }
211
212 g_object_unref (original);
213
214 return ret;
215 }
216
217 static gchar *
218 create_pixbuf (XAppKbdLayoutController *controller,
219 guint group,
220 const gchar *name,
221 gint id)
222 {
223 XAppKbdLayoutControllerPrivate *priv = controller->priv;
224 GdkPixbuf *pixbuf = NULL;
225
226 GdkPixbuf *flag_pixbuf;
227
228 gchar *filename = g_strdup_printf ("%s.png", name);
229 gchar *full_path = g_build_filename (priv->flag_dir, filename, NULL);
230
231 flag_pixbuf = gdk_pixbuf_new_from_file (full_path, NULL);
232
233 g_free (filename);
234 g_free (full_path);
235
236 if (flag_pixbuf != NULL)
237 {
238 if (id == 0)
239 {
240 pixbuf = flag_pixbuf;
241 }
242 else
243 {
244 pixbuf = add_notation (flag_pixbuf, id);
245 }
246 }
247
248 if (flag_pixbuf != NULL)
249 {
250 gchar *save_name = g_strdup_printf ("xapp-kbd-layout-%d.png", group);
251
252 gchar *path = g_build_filename (priv->temp_flag_theme_dir, save_name, NULL);
253 g_remove (path);
254
255 gdk_pixbuf_save (pixbuf,
256 path,
257 "png",
258 NULL,
259 NULL);
260
261 g_object_unref (pixbuf);
262
263 g_free (save_name);
264 g_free (path);
265 }
266 else
267 {
268 return NULL;
269 }
270
271 return g_strdup_printf ("xapp-kbd-layout-%d", group);
272 }
273
274 static void
275 load_stores (XAppKbdLayoutController *controller)
276 {
277 XAppKbdLayoutControllerPrivate *priv = controller->priv;
278
279 gchar **group_names = gkbd_configuration_get_group_names (priv->config);
280 priv->num_groups = g_strv_length (group_names);
281
282 /* We do nothing if there's only one keyboard layout enabled */
283 if (priv->num_groups == 1)
284 {
285 priv->enabled = FALSE;
286 return;
287 }
288
289 priv->enabled = TRUE;
290
291 /* Make a list of [name, id] tuples, where name is the group/flag name,
292 * and id is either 0, or, if a flag name is duplicated, a 1, 2, 3, etc...
293 */
294 gint i, j, id;
295 GPtrArray *list = g_ptr_array_new_with_free_func ((GDestroyNotify) group_data_free);
296
297 for (i = 0; i < priv->num_groups; i++)
298 {
299 GroupData *data = g_slice_new0 (GroupData);
300
301 gchar *name = gkbd_configuration_get_group_name (priv->config, i);
302 id = 0;
303
304 for (j = 0; j < list->len; j++)
305 {
306 GroupData *iter = g_ptr_array_index (list, j);
307
308 if (g_strcmp0 (name, iter->group) == 0)
309 {
310 id++;
311 iter->id = id;
312 }
313 }
314
315 if (id > 0)
316 {
317 id++;
318 }
319
320 data->group = name;
321 data->id = id;
322
323 g_ptr_array_add (list, data);
324 }
325
326 for (i = 0; i < list->len; i++)
327 {
328 GroupData *data = g_ptr_array_index (list, i);
329
330 priv->icon_names[i] = create_pixbuf (controller, i, data->group, data->id);
331 priv->text_store[i] = create_text (controller, data->group, data->id);
332 }
333
334 gtk_icon_theme_rescan_if_needed (gtk_icon_theme_get_default ());
335
336 g_ptr_array_unref (list);
337 }
338
339 static gboolean
340 idle_config_changed (XAppKbdLayoutController *controller)
341 {
342 XAppKbdLayoutControllerPrivate *priv = controller->priv;
343
344 clear_stores (controller);
345 load_stores (controller);
346
347 if (gkbd_configuration_get_current_group (priv->config) >= priv->num_groups)
348 {
349 xapp_kbd_layout_controller_set_current_group (controller, 0);
350 }
351
352 g_signal_emit (controller, signals[KBD_CONFIG_CHANGED], 0);
353
354 priv->idle_changed_id = 0;
355 return FALSE;
356 }
357
358 static void
359 on_configuration_changed (GkbdConfiguration *config,
360 XAppKbdLayoutController *controller)
361 {
362 XAppKbdLayoutControllerPrivate *priv = controller->priv;
363
364 if (priv->idle_changed_id != 0)
365 {
366 g_source_remove (priv->idle_changed_id);
367 priv->idle_changed_id = 0;
368 }
369
370 priv->idle_changed_id = g_idle_add ((GSourceFunc) idle_config_changed, controller);
371 }
372
373
374 static void
375 on_configuration_group_changed (GkbdConfiguration *config,
376 gint group,
377 XAppKbdLayoutController *controller)
378 {
379 g_signal_emit (controller, signals[KBD_LAYOUT_CHANGED], 0, (guint) group);
380 }
381
382 static void
383 xapp_kbd_layout_controller_init (XAppKbdLayoutController *controller)
384 {
385 controller->priv = G_TYPE_INSTANCE_GET_PRIVATE (controller, XAPP_TYPE_KBD_LAYOUT_CONTROLLER, XAppKbdLayoutControllerPrivate);
386
387 XAppKbdLayoutControllerPrivate *priv = controller->priv;
388
389 priv->config = gkbd_configuration_get ();
390 priv->enabled = FALSE;
391 priv->flag_dir = NULL;
392 priv->temp_flag_theme_dir = NULL;
393 priv->idle_changed_id = 0;
394 }
395
396 static void
397 xapp_kbd_layout_controller_constructed (GObject *object)
398 {
399 G_OBJECT_CLASS (xapp_kbd_layout_controller_parent_class)->constructed (object);
400
401 XAppKbdLayoutController *controller = XAPP_KBD_LAYOUT_CONTROLLER (object);
402 XAppKbdLayoutControllerPrivate *priv = controller->priv;
403
404 initialize_flag_dir (controller);
405
406 initialize_icon_theme (controller);
407
408 gkbd_configuration_start_listen (priv->config);
409
410 priv->changed_id = g_signal_connect_object (priv->config,
411 "changed",
412 G_CALLBACK (on_configuration_changed),
413 controller, 0);
414
415 priv->group_changed_id = g_signal_connect_object (priv->config,
416 "group-changed",
417 G_CALLBACK (on_configuration_group_changed),
418 controller, 0);
419 clear_stores (controller);
420 load_stores (controller);
421 }
422
423 static void
424 xapp_kbd_layout_controller_get_property (GObject *gobject,
425 guint prop_id,
426 GValue *value,
427 GParamSpec *pspec)
428 {
429 XAppKbdLayoutController *controller = XAPP_KBD_LAYOUT_CONTROLLER (gobject);
430 XAppKbdLayoutControllerPrivate *priv = controller->priv;
431
432 switch (prop_id)
433 {
434 case PROP_ENABLED:
435 g_value_set_boolean (value, priv->enabled);
436 break;
437 default:
438 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
439 break;
440 }
441 }
442
443 static void
444 xapp_kbd_layout_controller_dispose (GObject *object)
445 {
446 XAppKbdLayoutController *controller = XAPP_KBD_LAYOUT_CONTROLLER (object);
447 XAppKbdLayoutControllerPrivate *priv = controller->priv;
448
449 gkbd_configuration_stop_listen (priv->config);
450
451 clear_stores (controller);
452
453 if (priv->changed_id > 0)
454 {
455 g_signal_handler_disconnect (priv->config, priv->changed_id);
456 priv->changed_id = 0;
457 }
458
459 if (priv->group_changed_id > 0)
460 {
461 g_signal_handler_disconnect (priv->config, priv->group_changed_id);
462 priv->group_changed_id = 0;
463 }
464
465 if (priv->idle_changed_id != 0)
466 {
467 g_source_remove (priv->idle_changed_id);
468 priv->idle_changed_id = 0;
469 }
470
471 G_OBJECT_CLASS (xapp_kbd_layout_controller_parent_class)->dispose (object);
472 }
473
474 static void
475 xapp_kbd_layout_controller_finalize (GObject *object)
476 {
477 XAppKbdLayoutController *controller = XAPP_KBD_LAYOUT_CONTROLLER (object);
478 XAppKbdLayoutControllerPrivate *priv = controller->priv;
479
480 g_clear_object (&priv->config);
481 g_clear_pointer (&priv->flag_dir, g_free);
482 g_clear_pointer (&priv->temp_flag_theme_dir, g_free);
483
484 G_OBJECT_CLASS (xapp_kbd_layout_controller_parent_class)->finalize (object);
485 }
486
487 static void
488 xapp_kbd_layout_controller_class_init (XAppKbdLayoutControllerClass *klass)
489 {
490 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
491
492 gobject_class->dispose = xapp_kbd_layout_controller_dispose;
493 gobject_class->finalize = xapp_kbd_layout_controller_finalize;
494 gobject_class->get_property = xapp_kbd_layout_controller_get_property;
495 gobject_class->constructed = xapp_kbd_layout_controller_constructed;
496
497 g_type_class_add_private (gobject_class, sizeof (XAppKbdLayoutControllerPrivate));
498
499 g_object_class_install_property (gobject_class, PROP_ENABLED,
500 g_param_spec_boolean ("enabled",
501 "Enabled",
502 "Whether we're enabled (more than one keyboard layout is installed)",
503 FALSE,
504 G_PARAM_READABLE)
505 );
506
507 signals[KBD_LAYOUT_CHANGED] = g_signal_new ("layout-changed",
508 G_TYPE_FROM_CLASS (gobject_class),
509 G_SIGNAL_RUN_LAST,
510 0,
511 NULL, NULL,
512 g_cclosure_marshal_VOID__UINT,
513 G_TYPE_NONE,
514 1, G_TYPE_UINT);
515
516 signals[KBD_CONFIG_CHANGED] = g_signal_new ("config-changed",
517 G_TYPE_FROM_CLASS (gobject_class),
518 G_SIGNAL_RUN_LAST,
519 0,
520 NULL, NULL,
521 g_cclosure_marshal_VOID__VOID,
522 G_TYPE_NONE,
523 0, G_TYPE_NONE);
524 }
525
526 XAppKbdLayoutController *
527 xapp_kbd_layout_controller_new (void)
528 {
529 return g_object_new (XAPP_TYPE_KBD_LAYOUT_CONTROLLER, NULL);
530 }
531
532 gboolean
533 xapp_kbd_layout_controller_get_enabled (XAppKbdLayoutController *controller)
534 {
535 return controller->priv->enabled;
536 }
537
538 guint
539 xapp_kbd_layout_controller_get_current_group (XAppKbdLayoutController *controller)
540 {
541 g_return_val_if_fail (controller->priv->enabled, 0);
542
543 return gkbd_configuration_get_current_group (controller->priv->config);
544 }
545
546 void
547 xapp_kbd_layout_controller_set_current_group (XAppKbdLayoutController *controller,
548 guint group)
549 {
550 g_return_if_fail (controller->priv->enabled);
551 g_return_if_fail (group <= controller->priv->num_groups);
552
553 guint current = gkbd_configuration_get_current_group (controller->priv->config);
554
555 if (current != group)
556 {
557 gkbd_configuration_lock_group (controller->priv->config, group);
558 }
559 }
560
561 void
562 xapp_kbd_layout_controller_next_group (XAppKbdLayoutController *controller)
563 {
564 g_return_if_fail (controller->priv->enabled);
565
566 gkbd_configuration_lock_next_group (controller->priv->config);
567 }
568
569 void
570 xapp_kbd_layout_controller_previous_group (XAppKbdLayoutController *controller)
571 {
572 g_return_if_fail (controller->priv->enabled);
573
574 XAppKbdLayoutControllerPrivate *priv = controller->priv;
575
576 gint current = gkbd_configuration_get_current_group (priv->config);
577
578 if (current > 0)
579 {
580 current--;
581 }
582 else
583 {
584 current = priv->num_groups - 1;
585 }
586
587 gkbd_configuration_lock_group (controller->priv->config, current);
588 }
589
590 /**
591 * xapp_kbd_layout_controller_get_current_name:
592 *
593 * Returns the full name of the current keyboard layout.
594 *
595 * Returns: (transfer full): the newly created string or NULL
596 * if something went wrong.
597 */
598 gchar *
599 xapp_kbd_layout_controller_get_current_name (XAppKbdLayoutController *controller)
600 {
601 g_return_val_if_fail (controller->priv->enabled, NULL);
602
603 return gkbd_configuration_get_current_tooltip (controller->priv->config);
604 }
605
606 /**
607 * xapp_kbd_layout_controller_get_all_names:
608 *
609 * Returns an array of all full layout names
610 *
611 * Returns: (transfer none) (array zero-terminated=1): array of names
612 */
613 gchar **
614 xapp_kbd_layout_controller_get_all_names (XAppKbdLayoutController *controller)
615 {
616 g_return_val_if_fail (controller->priv->enabled, NULL);
617
618 return gkbd_configuration_get_group_names (controller->priv->config);
619 }
620
621 /**
622 * xapp_kbd_layout_controller_get_current_icon_name:
623 *
624 * Returns the icon name to use for the current layout
625 *
626 * Returns: (transfer full): a new string with the icon name.
627 */
628 gchar *
629 xapp_kbd_layout_controller_get_current_icon_name (XAppKbdLayoutController *controller)
630 {
631 g_return_val_if_fail (controller->priv->enabled, NULL);
632
633 XAppKbdLayoutControllerPrivate *priv = controller->priv;
634
635 guint current = gkbd_configuration_get_current_group (priv->config);
636
637 return g_strdup (priv->icon_names[current]);
638 }
639
640
641 /**
642 * xapp_kbd_layout_controller_get_icon_name_for_group:
643 *
644 * Returns the icon name to use for the specified layout.
645 *
646 * Returns: (transfer full): a new string with the icon name.
647 */
648 gchar *
649 xapp_kbd_layout_controller_get_icon_name_for_group (XAppKbdLayoutController *controller, guint group)
650 {
651 g_return_val_if_fail (controller->priv->enabled, NULL);
652 g_return_val_if_fail (group <= controller->priv->num_groups, NULL);
653
654 XAppKbdLayoutControllerPrivate *priv = controller->priv;
655
656 return g_strdup (priv->icon_names[group]);
657 }
658
659 /**
660 * xapp_kbd_layout_controller_get_current_short_name:
661 *
662 * Returns the short name (and subscript, if any) of the current layout
663 *
664 * Returns: (transfer full): a new string or NULL.
665 */
666 gchar *
667 xapp_kbd_layout_controller_get_short_name (XAppKbdLayoutController *controller)
668 {
669 g_return_val_if_fail (controller->priv->enabled, NULL);
670
671 XAppKbdLayoutControllerPrivate *priv = controller->priv;
672
673 guint current = gkbd_configuration_get_current_group (priv->config);
674
675 return g_strdup (priv->text_store[current]);
676 }
677
678 /**
679 * xapp_kbd_layout_controller_get_short_name_for_group:
680 *
681 * Returns the short name and subscript of the specified group.
682 *
683 * Returns: (transfer full): a new string or NULL.
684 */
685 gchar *
686 xapp_kbd_layout_controller_get_short_name_for_group (XAppKbdLayoutController *controller,
687 guint group)
688 {
689 g_return_val_if_fail (controller->priv->enabled, NULL);
690
691 XAppKbdLayoutControllerPrivate *priv = controller->priv;
692
693 g_return_val_if_fail (group < controller->priv->num_groups, NULL);
694
695 return g_strdup (priv->text_store[group]);
696 }
0 #ifndef __XAPP_KBD_LAYOUT_CONTROLLER_H__
1 #define __XAPP_KBD_LAYOUT_CONTROLLER_H__
2
3 #include <stdio.h>
4 #include <gdk-pixbuf/gdk-pixbuf.h>
5 #include <clutter/clutter.h>
6
7 #include <glib-object.h>
8
9 G_BEGIN_DECLS
10
11 #define XAPP_TYPE_KBD_LAYOUT_CONTROLLER (xapp_kbd_layout_controller_get_type ())
12 #define XAPP_KBD_LAYOUT_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XAPP_TYPE_KBD_LAYOUT_CONTROLLER, XAppKbdLayoutController))
13 #define XAPP_KBD_LAYOUT_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XAPP_TYPE_KBD_LAYOUT_CONTROLLER, XAppKbdLayoutControllerClass))
14 #define XAPP_IS_KBD_LAYOUT_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XAPP_TYPE_KBD_LAYOUT_CONTROLLER))
15 #define XAPP_IS_KBD_LAYOUT_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XAPP_TYPE_KBD_LAYOUT_CONTROLLER))
16 #define XAPP_KBD_LAYOUT_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XAPP_TYPE_KBD_LAYOUT_CONTROLLER, XAppKbdLayoutControllerClass))
17
18 typedef struct _XAppKbdLayoutControllerPrivate XAppKbdLayoutControllerPrivate;
19 typedef struct _XAppKbdLayoutController XAppKbdLayoutController;
20 typedef struct _XAppKbdLayoutControllerClass XAppKbdLayoutControllerClass;
21
22 struct _XAppKbdLayoutController
23 {
24 GObject parent_object;
25
26 XAppKbdLayoutControllerPrivate *priv;
27 };
28
29 struct _XAppKbdLayoutControllerClass
30 {
31 GObjectClass parent_class;
32 };
33
34 GType xapp_kbd_layout_controller_get_type (void);
35 XAppKbdLayoutController *xapp_kbd_layout_controller_new (void);
36 gboolean xapp_kbd_layout_controller_get_enabled (XAppKbdLayoutController *controller);
37 guint xapp_kbd_layout_controller_get_current_group (XAppKbdLayoutController *controller);
38 void xapp_kbd_layout_controller_set_current_group (XAppKbdLayoutController *controller,
39 guint group);
40 void xapp_kbd_layout_controller_next_group (XAppKbdLayoutController *controller);
41 void xapp_kbd_layout_controller_previous_group (XAppKbdLayoutController *controller);
42 gchar *xapp_kbd_layout_controller_get_current_name (XAppKbdLayoutController *controller);
43 gchar **xapp_kbd_layout_controller_get_all_names (XAppKbdLayoutController *controller);
44 gchar *xapp_kbd_layout_controller_get_current_icon_name (XAppKbdLayoutController *controller);
45 gchar *xapp_kbd_layout_controller_get_icon_name_for_group (XAppKbdLayoutController *controller,
46 guint group);
47 gchar *xapp_kbd_layout_controller_get_short_name (XAppKbdLayoutController *controller);
48 gchar *xapp_kbd_layout_controller_get_short_name_for_group (XAppKbdLayoutController *controller,
49 guint group);
50
51 G_END_DECLS
52
53 #endif /* __XAPP_KBD_LAYOUT_CONTROLLER_H__ */
44
55 Name: xapp
66 Description: Utility library for loading .desktop files
7 Requires: gtk+-3.0
7 Requires: gtk+-3.0 clutter-1.0
88 Version: @VERSION@
99 Libs: ${pc_top_builddir}/${pcfiledir}/libxapp.la
1010 Cflags: -I${pc_top_builddir}/${pcfiledir}/..
44
55 Name: xapp
66 Description: Utility library for loading .desktop files
7 Requires: gtk+-3.0
7 Requires: gtk+-3.0 clutter-1.0
88 Requires.private: xkbfile
99 Version: @VERSION@
1010 Libs: -L${libdir} -lxapp
0 #! /usr/bin/python3
1
2 """
3 A demo/test script for the XAppKbdLayoutController class
4 """
5 import sys, os
6 import signal
7 import gettext
8
9 import gi
10 gi.require_version('Gtk', '3.0')
11 gi.require_version('XApp', '1.0')
12
13 from gi.repository import Gtk, XApp, GObject
14
15 signal.signal(signal.SIGINT, signal.SIG_DFL)
16
17 class Main:
18 def __init__(self):
19 win = Gtk.Window()
20 frame = Gtk.Frame()
21 frame.set_margin_start(6)
22 frame.set_margin_end(6)
23 frame.set_margin_top(6)
24 frame.set_margin_bottom(6)
25
26 win.add(frame)
27
28 box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
29 frame.add(box)
30
31 self.show_flags = False
32 self.use_caps = False
33
34 self.controller = XApp.KbdLayoutController()
35 self.controller.connect("layout-changed", self.on_layout_changed)
36 self.controller.connect("config-changed", self.on_config_changed)
37
38 hbox = Gtk.HBox()
39 box.pack_start(hbox, True, True, 4)
40
41 self.button = Gtk.Button()
42 self.button.set_size_request(48, 48)
43 self.button.connect("clicked", self.on_button_clicked)
44 hbox.pack_start(self.button, False, False, 4)
45
46 self.label = Gtk.Label()
47 self.label.set_text(self.controller.get_current_name())
48 hbox.pack_start(self.label, True, True, 4)
49
50 check = Gtk.CheckButton.new_with_label("Show flags")
51 check.connect("toggled", self.on_flag_toggled)
52 box.pack_start(check, True, True, 4)
53
54 check = Gtk.CheckButton.new_with_label("Use caps")
55 check.connect("toggled", self.on_caps_toggled)
56 box.pack_start(check, True, True, 4)
57
58 frame.show_all()
59
60 win.connect("delete-event", lambda w, e: Gtk.main_quit())
61
62 self.on_layout_changed(self.controller)
63
64 win.present()
65
66 Gtk.main()
67
68 def on_flag_toggled(self, widget):
69 self.show_flags = widget.get_active()
70 self.on_layout_changed(self.controller)
71
72 def on_caps_toggled(self, widget):
73 self.use_caps = widget.get_active()
74 self.on_layout_changed(self.controller)
75
76 def on_button_clicked(self, widget, data=None):
77 self.controller.next_group()
78
79 def on_layout_changed(self, controller, group=None):
80 handled = False
81 if self.show_flags:
82 name = self.controller.get_current_icon_name()
83 if name != None:
84 image = Gtk.Image.new_from_icon_name(name, Gtk.IconSize.DIALOG)
85 self.button.set_image(image)
86 handled = True
87
88 if not handled:
89 name = self.controller.get_short_name()
90 if self.use_caps:
91 name = name.upper()
92 label = Gtk.Label(name)
93 label.show()
94 self.button.set_image(label)
95
96 self.label.set_text(self.controller.get_current_name())
97
98 def on_config_changed(self, controller):
99 GObject.idle_add(self.on_layout_changed, controller)
100
101 if __name__ == "__main__":
102 main = Main()