8 | 8 |
#include <glib/gstdio.h>
|
9 | 9 |
#include <gdk/gdk.h>
|
10 | 10 |
#include <gtk/gtk.h>
|
11 | |
#include <cairo.h>
|
12 | 11 |
|
13 | 12 |
#include <libgnomekbd/gkbd-configuration.h>
|
14 | 13 |
|
|
18 | 17 |
{
|
19 | 18 |
PROP_0,
|
20 | 19 |
|
21 | |
PROP_ENABLED,
|
22 | |
PROP_USE_CAPS,
|
|
20 |
PROP_ENABLED
|
23 | 21 |
};
|
24 | 22 |
|
25 | 23 |
enum
|
|
32 | 30 |
|
33 | 31 |
static guint signals[LAST_SIGNAL] = { 0, };
|
34 | 32 |
|
|
33 |
typedef struct
|
|
34 |
{
|
|
35 |
gchar *group_name;
|
|
36 |
gchar *variant_name;
|
|
37 |
|
|
38 |
gchar *group_label;
|
|
39 |
gint group_dupe_id;
|
|
40 |
|
|
41 |
gchar *variant_label;
|
|
42 |
gint variant_dupe_id;
|
|
43 |
} GroupData;
|
|
44 |
|
|
45 |
#define GROUP_DATA(ptr, idx) ((GroupData *) g_ptr_array_index (ptr, idx))
|
|
46 |
|
|
47 |
static void
|
|
48 |
group_data_free (GroupData *data)
|
|
49 |
{
|
|
50 |
g_clear_pointer (&data->group_name, g_free);
|
|
51 |
g_clear_pointer (&data->group_label, g_free);
|
|
52 |
g_clear_pointer (&data->variant_label, g_free);
|
|
53 |
data->group_dupe_id = 0;
|
|
54 |
data->variant_dupe_id = 0;
|
|
55 |
|
|
56 |
g_slice_free (GroupData, data);
|
|
57 |
}
|
|
58 |
|
35 | 59 |
struct _XAppKbdLayoutControllerPrivate
|
36 | 60 |
{
|
37 | 61 |
GkbdConfiguration *config;
|
38 | 62 |
|
39 | 63 |
gint num_groups;
|
40 | |
gchar *flag_dir;
|
41 | |
gchar *temp_flag_theme_dir;
|
42 | |
|
43 | |
gchar *icon_names[4];
|
44 | |
gchar *text_store[4];
|
|
64 |
|
|
65 |
GPtrArray *group_data;
|
45 | 66 |
|
46 | 67 |
gulong changed_id;
|
47 | 68 |
gulong group_changed_id;
|
|
53 | 74 |
G_DEFINE_TYPE (XAppKbdLayoutController, xapp_kbd_layout_controller, G_TYPE_OBJECT);
|
54 | 75 |
|
55 | 76 |
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 | 77 |
clear_stores (XAppKbdLayoutController *controller)
|
97 | 78 |
{
|
98 | 79 |
XAppKbdLayoutControllerPrivate *priv = controller->priv;
|
99 | 80 |
|
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);
|
|
81 |
g_clear_pointer (&priv->group_data, g_ptr_array_unref);
|
122 | 82 |
}
|
123 | 83 |
|
124 | 84 |
static gchar *
|
125 | |
create_text (XAppKbdLayoutController *controller,
|
126 | |
const gchar *name,
|
127 | |
gint id)
|
|
85 |
create_label (XAppKbdLayoutController *controller,
|
|
86 |
const gchar *name,
|
|
87 |
gint dupe_id)
|
128 | 88 |
{
|
129 | 89 |
if (g_utf8_validate (name, -1, NULL))
|
130 | 90 |
{
|
|
139 | 99 |
|
140 | 100 |
g_free (utf8_cased);
|
141 | 101 |
|
142 | |
if (id > 0)
|
|
102 |
if (dupe_id > 0)
|
143 | 103 |
{
|
144 | |
string = g_string_append_unichar (string, 0x2080 + id);
|
|
104 |
string = g_string_append_unichar (string, 0x2080 + dupe_id);
|
145 | 105 |
}
|
146 | 106 |
|
147 | 107 |
return g_string_free (string, FALSE);
|
148 | 108 |
}
|
149 | 109 |
|
150 | 110 |
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 | 111 |
}
|
273 | 112 |
|
274 | 113 |
static void
|
|
288 | 127 |
|
289 | 128 |
priv->enabled = TRUE;
|
290 | 129 |
|
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;
|
|
130 |
/* Populate the GroupData pointer array */
|
|
131 |
|
|
132 |
gint i, j, group_dupe_id, variant_dupe_id;
|
295 | 133 |
GPtrArray *list = g_ptr_array_new_with_free_func ((GDestroyNotify) group_data_free);
|
296 | 134 |
|
297 | 135 |
for (i = 0; i < priv->num_groups; i++)
|
298 | 136 |
{
|
299 | 137 |
GroupData *data = g_slice_new0 (GroupData);
|
300 | 138 |
|
301 | |
gchar *name = gkbd_configuration_get_group_name (priv->config, i);
|
302 | |
id = 0;
|
|
139 |
/* Iterate through group names, figure out subscript values for duplicates */
|
|
140 |
|
|
141 |
gchar *group_name = gkbd_configuration_get_group_name (priv->config, i);
|
|
142 |
group_dupe_id = 0;
|
303 | 143 |
|
304 | 144 |
for (j = 0; j < list->len; j++)
|
305 | 145 |
{
|
306 | 146 |
GroupData *iter = g_ptr_array_index (list, j);
|
307 | 147 |
|
308 | |
if (g_strcmp0 (name, iter->group) == 0)
|
|
148 |
if (g_strcmp0 (group_name, iter->group_name) == 0)
|
309 | 149 |
{
|
310 | |
id++;
|
311 | |
iter->id = id;
|
|
150 |
group_dupe_id++;
|
|
151 |
iter->group_dupe_id = group_dupe_id;
|
312 | 152 |
}
|
313 | 153 |
}
|
314 | 154 |
|
315 | |
if (id > 0)
|
|
155 |
if (group_dupe_id > 0)
|
316 | 156 |
{
|
317 | |
id++;
|
|
157 |
group_dupe_id++;
|
318 | 158 |
}
|
319 | 159 |
|
320 | |
data->group = name;
|
321 | |
data->id = id;
|
322 | |
|
|
160 |
data->group_name = group_name;
|
|
161 |
data->group_dupe_id = group_dupe_id;
|
|
162 |
|
|
163 |
/* Iterate through layout/variant names, figure out subscript values for duplicates */
|
|
164 |
|
|
165 |
gchar *variant_name = gkbd_configuration_extract_layout_name (priv->config, i);
|
|
166 |
variant_dupe_id = 0;
|
|
167 |
|
|
168 |
for (j = 0; j < list->len; j++)
|
|
169 |
{
|
|
170 |
GroupData *iter = g_ptr_array_index (list, j);
|
|
171 |
|
|
172 |
if (g_strcmp0 (variant_name, iter->variant_name) == 0)
|
|
173 |
{
|
|
174 |
variant_dupe_id++;
|
|
175 |
iter->variant_dupe_id = variant_dupe_id;
|
|
176 |
}
|
|
177 |
}
|
|
178 |
|
|
179 |
if (variant_dupe_id > 0)
|
|
180 |
{
|
|
181 |
variant_dupe_id++;
|
|
182 |
}
|
|
183 |
|
|
184 |
data->variant_name = variant_name;
|
|
185 |
data->variant_dupe_id = variant_dupe_id;
|
|
186 |
|
|
187 |
/* Finally, add the GroupData slice to the array */
|
323 | 188 |
g_ptr_array_add (list, data);
|
324 | 189 |
}
|
325 | 190 |
|
326 | |
for (i = 0; i < list->len; i++)
|
|
191 |
for (i = 0; i < priv->num_groups; i++)
|
327 | 192 |
{
|
328 | 193 |
GroupData *data = g_ptr_array_index (list, i);
|
329 | 194 |
|
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);
|
|
195 |
/* Now generate labels for group names and for variant names. This is done
|
|
196 |
* in its own loop after the initial run, because previous dupe ids could have
|
|
197 |
* changed later in the loop.
|
|
198 |
*/
|
|
199 |
|
|
200 |
data->group_label = create_label (controller, data->group_name, data->group_dupe_id);
|
|
201 |
data->variant_label = create_label (controller, data->variant_name, data->variant_dupe_id);
|
|
202 |
}
|
|
203 |
|
|
204 |
priv->group_data = list;
|
337 | 205 |
}
|
338 | 206 |
|
339 | 207 |
static gboolean
|
|
388 | 256 |
|
389 | 257 |
priv->config = gkbd_configuration_get ();
|
390 | 258 |
priv->enabled = FALSE;
|
391 | |
priv->flag_dir = NULL;
|
392 | |
priv->temp_flag_theme_dir = NULL;
|
393 | 259 |
priv->idle_changed_id = 0;
|
|
260 |
|
|
261 |
priv->group_data = NULL;
|
394 | 262 |
}
|
395 | 263 |
|
396 | 264 |
static void
|
|
400 | 268 |
|
401 | 269 |
XAppKbdLayoutController *controller = XAPP_KBD_LAYOUT_CONTROLLER (object);
|
402 | 270 |
XAppKbdLayoutControllerPrivate *priv = controller->priv;
|
403 | |
|
404 | |
initialize_flag_dir (controller);
|
405 | |
|
406 | |
initialize_icon_theme (controller);
|
407 | 271 |
|
408 | 272 |
gkbd_configuration_start_listen (priv->config);
|
409 | 273 |
|
|
478 | 342 |
XAppKbdLayoutControllerPrivate *priv = controller->priv;
|
479 | 343 |
|
480 | 344 |
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 | 345 |
|
484 | 346 |
G_OBJECT_CLASS (xapp_kbd_layout_controller_parent_class)->finalize (object);
|
485 | 347 |
}
|
|
621 | 483 |
/**
|
622 | 484 |
* xapp_kbd_layout_controller_get_current_icon_name:
|
623 | 485 |
*
|
624 | |
* Returns the icon name to use for the current layout
|
|
486 |
* Returns the icon file name (no path or extension) to use for the current layout
|
625 | 487 |
*
|
626 | 488 |
* Returns: (transfer full): a new string with the icon name.
|
627 | 489 |
*/
|
|
634 | 496 |
|
635 | 497 |
guint current = gkbd_configuration_get_current_group (priv->config);
|
636 | 498 |
|
637 | |
return g_strdup (priv->icon_names[current]);
|
638 | |
}
|
639 | |
|
|
499 |
return g_strdup (GROUP_DATA (priv->group_data, current)->group_name);
|
|
500 |
}
|
640 | 501 |
|
641 | 502 |
/**
|
642 | 503 |
* xapp_kbd_layout_controller_get_icon_name_for_group:
|
643 | 504 |
*
|
644 | |
* Returns the icon name to use for the specified layout.
|
|
505 |
* Returns the icon file name (no path or extension) to use for the specified layout.
|
645 | 506 |
*
|
646 | 507 |
* Returns: (transfer full): a new string with the icon name.
|
647 | 508 |
*/
|
648 | 509 |
gchar *
|
649 | |
xapp_kbd_layout_controller_get_icon_name_for_group (XAppKbdLayoutController *controller, guint group)
|
|
510 |
xapp_kbd_layout_controller_get_icon_name_for_group (XAppKbdLayoutController *controller,
|
|
511 |
guint group)
|
650 | 512 |
{
|
651 | 513 |
g_return_val_if_fail (controller->priv->enabled, NULL);
|
652 | 514 |
g_return_val_if_fail (group <= controller->priv->num_groups, NULL);
|
653 | 515 |
|
654 | 516 |
XAppKbdLayoutControllerPrivate *priv = controller->priv;
|
655 | 517 |
|
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
|
|
518 |
return g_strdup (GROUP_DATA (priv->group_data, group)->group_name);
|
|
519 |
}
|
|
520 |
|
|
521 |
/**
|
|
522 |
* xapp_kbd_layout_controller_get_current_flag_id:
|
|
523 |
*
|
|
524 |
* Returns the duplicate id for the current layout
|
|
525 |
*
|
|
526 |
* Returns: the id
|
|
527 |
*/
|
|
528 |
gint
|
|
529 |
xapp_kbd_layout_controller_get_current_flag_id (XAppKbdLayoutController *controller)
|
|
530 |
{
|
|
531 |
g_return_val_if_fail (controller->priv->enabled, 0);
|
|
532 |
|
|
533 |
XAppKbdLayoutControllerPrivate *priv = controller->priv;
|
|
534 |
|
|
535 |
guint current = gkbd_configuration_get_current_group (priv->config);
|
|
536 |
|
|
537 |
return GROUP_DATA (priv->group_data, current)->group_dupe_id;
|
|
538 |
}
|
|
539 |
|
|
540 |
|
|
541 |
/**
|
|
542 |
* xapp_kbd_layout_controller_flag_id_for_group:
|
|
543 |
*
|
|
544 |
* Returns the duplicate id for the specified layout
|
|
545 |
*
|
|
546 |
* Returns: the id
|
|
547 |
*/
|
|
548 |
gint
|
|
549 |
xapp_kbd_layout_controller_get_flag_id_for_group (XAppKbdLayoutController *controller,
|
|
550 |
guint group)
|
|
551 |
{
|
|
552 |
g_return_val_if_fail (controller->priv->enabled, 0);
|
|
553 |
g_return_val_if_fail (group < controller->priv->num_groups, 0);
|
|
554 |
|
|
555 |
XAppKbdLayoutControllerPrivate *priv = controller->priv;
|
|
556 |
|
|
557 |
return GROUP_DATA (priv->group_data, group)->group_dupe_id;
|
|
558 |
}
|
|
559 |
|
|
560 |
/**
|
|
561 |
* xapp_kbd_layout_controller_get_current_short_group_label:
|
|
562 |
*
|
|
563 |
* Returns the short group label (and subscript, if any) of the current layout
|
663 | 564 |
*
|
664 | 565 |
* Returns: (transfer full): a new string or NULL.
|
665 | 566 |
*/
|
666 | 567 |
gchar *
|
667 | |
xapp_kbd_layout_controller_get_short_name (XAppKbdLayoutController *controller)
|
|
568 |
xapp_kbd_layout_controller_get_current_short_group_label (XAppKbdLayoutController *controller)
|
668 | 569 |
{
|
669 | 570 |
g_return_val_if_fail (controller->priv->enabled, NULL);
|
670 | 571 |
|
|
672 | 573 |
|
673 | 574 |
guint current = gkbd_configuration_get_current_group (priv->config);
|
674 | 575 |
|
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.
|
|
576 |
return g_strdup (GROUP_DATA (priv->group_data, current)->group_label);
|
|
577 |
}
|
|
578 |
|
|
579 |
/**
|
|
580 |
* xapp_kbd_layout_controller_get_short_group_label_for_group:
|
|
581 |
*
|
|
582 |
* Returns the short group label and subscript of the specified layout.
|
682 | 583 |
*
|
683 | 584 |
* Returns: (transfer full): a new string or NULL.
|
684 | 585 |
*/
|
685 | 586 |
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 | |
|
|
587 |
xapp_kbd_layout_controller_get_short_group_label_for_group (XAppKbdLayoutController *controller,
|
|
588 |
guint group)
|
|
589 |
{
|
|
590 |
g_return_val_if_fail (controller->priv->enabled, NULL);
|
693 | 591 |
g_return_val_if_fail (group < controller->priv->num_groups, NULL);
|
694 | 592 |
|
695 | |
return g_strdup (priv->text_store[group]);
|
696 | |
}
|
|
593 |
XAppKbdLayoutControllerPrivate *priv = controller->priv;
|
|
594 |
|
|
595 |
|
|
596 |
return g_strdup (GROUP_DATA (priv->group_data, group)->group_label);
|
|
597 |
}
|
|
598 |
|
|
599 |
/**
|
|
600 |
* xapp_kbd_layout_controller_get_current_variant_label:
|
|
601 |
*
|
|
602 |
* Returns the variant label (and subscript, if any) of the current layout
|
|
603 |
*
|
|
604 |
* Returns: (transfer full): a new string or NULL.
|
|
605 |
*/
|
|
606 |
gchar *
|
|
607 |
xapp_kbd_layout_controller_get_current_variant_label (XAppKbdLayoutController *controller)
|
|
608 |
{
|
|
609 |
g_return_val_if_fail (controller->priv->enabled, NULL);
|
|
610 |
|
|
611 |
XAppKbdLayoutControllerPrivate *priv = controller->priv;
|
|
612 |
|
|
613 |
guint current = gkbd_configuration_get_current_group (priv->config);
|
|
614 |
|
|
615 |
return g_strdup (GROUP_DATA (priv->group_data, current)->variant_label);
|
|
616 |
}
|
|
617 |
|
|
618 |
/**
|
|
619 |
* xapp_kbd_layout_controller_get_variant_label_for_group:
|
|
620 |
*
|
|
621 |
* Returns the variant label and subscript of the specified layout.
|
|
622 |
*
|
|
623 |
* Returns: (transfer full): a new string or NULL.
|
|
624 |
*/
|
|
625 |
gchar *
|
|
626 |
xapp_kbd_layout_controller_get_variant_label_for_group (XAppKbdLayoutController *controller,
|
|
627 |
guint group)
|
|
628 |
{
|
|
629 |
g_return_val_if_fail (controller->priv->enabled, NULL);
|
|
630 |
|
|
631 |
XAppKbdLayoutControllerPrivate *priv = controller->priv;
|
|
632 |
|
|
633 |
g_return_val_if_fail (group < controller->priv->num_groups, NULL);
|
|
634 |
|
|
635 |
return g_strdup (GROUP_DATA (priv->group_data, group)->variant_label);
|
|
636 |
}
|
|
637 |
|
|
638 |
void
|
|
639 |
xapp_kbd_layout_controller_render_cairo_subscript (cairo_t *cr,
|
|
640 |
gdouble x,
|
|
641 |
gdouble y,
|
|
642 |
gdouble width,
|
|
643 |
gdouble height,
|
|
644 |
gint subscript)
|
|
645 |
{
|
|
646 |
if (subscript == 0)
|
|
647 |
{
|
|
648 |
return;
|
|
649 |
}
|
|
650 |
|
|
651 |
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, .5);
|
|
652 |
cairo_rectangle (cr, x, y, width, height);
|
|
653 |
cairo_fill (cr);
|
|
654 |
|
|
655 |
cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, .8);
|
|
656 |
cairo_rectangle (cr, x + 1, y + 1, width - 2, height - 2);
|
|
657 |
cairo_fill (cr);
|
|
658 |
|
|
659 |
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
|
|
660 |
|
|
661 |
gchar *num_string = g_strdup_printf ("%d", subscript);
|
|
662 |
cairo_select_font_face (cr, "sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
|
|
663 |
cairo_set_font_size (cr, height - 2.0);
|
|
664 |
|
|
665 |
cairo_text_extents_t ext;
|
|
666 |
cairo_text_extents (cr, num_string, &ext);
|
|
667 |
|
|
668 |
cairo_move_to (cr,
|
|
669 |
(x + (width / 2.0) - (ext.width / 2.0)),
|
|
670 |
(y + (height / 2.0) + (ext.height / 2.0)));
|
|
671 |
|
|
672 |
cairo_show_text (cr, num_string);
|
|
673 |
g_free (num_string);
|
|
674 |
}
|
|
675 |
|