diff options
author | Perberos <[email protected]> | 2011-12-01 20:53:10 -0300 |
---|---|---|
committer | Perberos <[email protected]> | 2011-12-01 20:53:10 -0300 |
commit | 916e2eafe251b44f9d0339282f5d00723899caec (patch) | |
tree | d650ca8c97d834499ca107a2a59a41c86c1fc4a9 /libmatekbd/matekbd-indicator.c | |
download | libmatekbd-916e2eafe251b44f9d0339282f5d00723899caec.tar.bz2 libmatekbd-916e2eafe251b44f9d0339282f5d00723899caec.tar.xz |
moving from https://github.com/perberos/mate-desktop-environment
Diffstat (limited to 'libmatekbd/matekbd-indicator.c')
-rw-r--r-- | libmatekbd/matekbd-indicator.c | 968 |
1 files changed, 968 insertions, 0 deletions
diff --git a/libmatekbd/matekbd-indicator.c b/libmatekbd/matekbd-indicator.c new file mode 100644 index 0000000..c4928aa --- /dev/null +++ b/libmatekbd/matekbd-indicator.c @@ -0,0 +1,968 @@ +/* + * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <memory.h> + +#include <gdk/gdkkeysyms.h> +#include <gdk/gdkx.h> +#include <glib/gi18n.h> + +#include <matekbd-indicator.h> +#include <matekbd-indicator-marshal.h> + +#include <matekbd-desktop-config.h> +#include <matekbd-indicator-config.h> + +#include <matekbd-indicator-plugin-manager.h> + +typedef struct _gki_globals { + XklEngine *engine; + XklConfigRegistry *registry; + + MatekbdDesktopConfig cfg; + MatekbdIndicatorConfig ind_cfg; + MatekbdKeyboardConfig kbd_cfg; + + MatekbdIndicatorPluginContainer plugin_container; + MatekbdIndicatorPluginManager plugin_manager; + + const gchar *tooltips_format; + gchar **full_group_names; + gchar **short_group_names; + GSList *widget_instances; + GSList *images; +} gki_globals; + +struct _MatekbdIndicatorPrivate { + gboolean set_parent_tooltips; + gdouble angle; +}; + +/* one instance for ALL widgets */ +static gki_globals globals; + +#define ForAllIndicators() \ + { \ + GSList* cur; \ + for (cur = globals.widget_instances; cur != NULL; cur = cur->next) { \ + MatekbdIndicator * gki = (MatekbdIndicator*)cur->data; +#define NextIndicator() \ + } \ + } + +G_DEFINE_TYPE (MatekbdIndicator, matekbd_indicator, GTK_TYPE_NOTEBOOK) + +static void +matekbd_indicator_global_init (void); +static void +matekbd_indicator_global_term (void); +static GtkWidget * +matekbd_indicator_prepare_drawing (MatekbdIndicator * gki, int group); +static void +matekbd_indicator_set_current_page_for_group (MatekbdIndicator * gki, int group); +static void +matekbd_indicator_set_current_page (MatekbdIndicator * gki); +static void +matekbd_indicator_cleanup (MatekbdIndicator * gki); +static void +matekbd_indicator_fill (MatekbdIndicator * gki); +static void +matekbd_indicator_set_tooltips (MatekbdIndicator * gki, const char *str); + +void +matekbd_indicator_load_images () +{ + int i; + GSList *image_filename; + + globals.images = NULL; + matekbd_indicator_config_load_image_filenames (&globals.ind_cfg, + &globals.kbd_cfg); + + if (!globals.ind_cfg.show_flags) + return; + + image_filename = globals.ind_cfg.image_filenames; + + for (i = xkl_engine_get_max_num_groups (globals.engine); + --i >= 0; image_filename = image_filename->next) { + GdkPixbuf *image = NULL; + char *image_file = (char *) image_filename->data; + + if (image_file != NULL) { + GError *gerror = NULL; + image = + gdk_pixbuf_new_from_file (image_file, &gerror); + if (image == NULL) { + GtkWidget *dialog = + gtk_message_dialog_new (NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + _ + ("There was an error loading an image: %s"), + gerror-> + message); + g_signal_connect (G_OBJECT (dialog), + "response", + G_CALLBACK + (gtk_widget_destroy), + NULL); + + gtk_window_set_resizable (GTK_WINDOW + (dialog), FALSE); + + gtk_widget_show (dialog); + g_error_free (gerror); + } + xkl_debug (150, + "Image %d[%s] loaded -> %p[%dx%d]\n", + i, image_file, image, + gdk_pixbuf_get_width (image), + gdk_pixbuf_get_height (image)); + } + /* We append the image anyway - even if it is NULL! */ + globals.images = g_slist_append (globals.images, image); + } +} + +static void +matekbd_indicator_free_images () +{ + GdkPixbuf *pi; + GSList *img_node; + + matekbd_indicator_config_free_image_filenames (&globals.ind_cfg); + + while ((img_node = globals.images) != NULL) { + pi = GDK_PIXBUF (img_node->data); + /* It can be NULL - some images may be missing */ + if (pi != NULL) { + g_object_unref (pi); + } + globals.images = + g_slist_remove_link (globals.images, img_node); + g_slist_free_1 (img_node); + } +} + +static void +matekbd_indicator_update_images (void) +{ + matekbd_indicator_free_images (); + matekbd_indicator_load_images (); +} + +void +matekbd_indicator_set_tooltips (MatekbdIndicator * gki, const char *str) +{ + g_assert (str == NULL || g_utf8_validate (str, -1, NULL)); + + gtk_widget_set_tooltip_text (GTK_WIDGET (gki), str); + + if (gki->priv->set_parent_tooltips) { + GtkWidget *parent = + gtk_widget_get_parent (GTK_WIDGET (gki)); + if (parent) { + gtk_widget_set_tooltip_text (parent, str); + } + } +} + +void +matekbd_indicator_cleanup (MatekbdIndicator * gki) +{ + int i; + GtkNotebook *notebook = GTK_NOTEBOOK (gki); + + /* Do not remove the first page! It is the default page */ + for (i = gtk_notebook_get_n_pages (notebook); --i > 0;) { + gtk_notebook_remove_page (notebook, i); + } +} + +void +matekbd_indicator_fill (MatekbdIndicator * gki) +{ + int grp; + int total_groups = xkl_engine_get_num_groups (globals.engine); + GtkNotebook *notebook = GTK_NOTEBOOK (gki); + + for (grp = 0; grp < total_groups; grp++) { + GtkWidget *page, *decorated_page = NULL; + gchar *full_group_name = + (grp < + g_strv_length (globals.full_group_names)) ? + globals.full_group_names[grp] : "?"; + page = matekbd_indicator_prepare_drawing (gki, grp); + + if (page == NULL) + page = gtk_label_new (""); + + decorated_page = + matekbd_indicator_plugin_manager_decorate_widget + (&globals.plugin_manager, page, grp, + full_group_name, &globals.kbd_cfg); + + page = decorated_page == NULL ? page : decorated_page; + + gtk_notebook_append_page (notebook, page, NULL); + gtk_widget_show_all (page); + } +} + +static gboolean +matekbd_indicator_key_pressed (GtkWidget * + widget, GdkEventKey * event, + MatekbdIndicator * gki) +{ + switch (event->keyval) { + case GDK_KP_Enter: + case GDK_ISO_Enter: + case GDK_3270_Enter: + case GDK_Return: + case GDK_space: + case GDK_KP_Space: + matekbd_desktop_config_lock_next_group (&globals.cfg); + return TRUE; + default: + break; + } + return FALSE; +} + +static gboolean +matekbd_indicator_button_pressed (GtkWidget * + widget, + GdkEventButton * event, MatekbdIndicator * gki) +{ + GtkWidget *img = gtk_bin_get_child (GTK_BIN (widget)); + GtkAllocation allocation; + gtk_widget_get_allocation (img, &allocation); + xkl_debug (150, "Flag img size %d x %d\n", + allocation.width, allocation.height); + if (event->button == 1 && event->type == GDK_BUTTON_PRESS) { + xkl_debug (150, "Mouse button pressed on applet\n"); + matekbd_desktop_config_lock_next_group (&globals.cfg); + return TRUE; + } + return FALSE; +} + +static void +flag_exposed (GtkWidget * flag, GdkEventExpose * event, GdkPixbuf * image) +{ + /* Image width and height */ + int iw = gdk_pixbuf_get_width (image); + int ih = gdk_pixbuf_get_height (image); + GtkAllocation allocation; + double xwiratio, ywiratio, wiratio; + cairo_t *cr; + + gtk_widget_get_allocation (flag, &allocation); + + cr = gdk_cairo_create (event->window); + gdk_cairo_region (cr, event->region); + cairo_clip (cr); + + /* widget-to-image scales, X and Y */ + xwiratio = 1.0 * allocation.width / iw; + ywiratio = 1.0 * allocation.height / ih; + wiratio = xwiratio < ywiratio ? xwiratio : ywiratio; + + /* transform cairo context */ + cairo_translate (cr, allocation.width / 2.0, allocation.height / 2.0); + cairo_scale (cr, wiratio, wiratio); + cairo_translate (cr, - iw / 2.0, - ih / 2.0); + + gdk_cairo_set_source_pixbuf (cr, image, 0, 0); + cairo_paint (cr); + + cairo_destroy (cr); +} + +gchar * +matekbd_indicator_extract_layout_name (int group, XklEngine * engine, + MatekbdKeyboardConfig * kbd_cfg, + gchar ** short_group_names, + gchar ** full_group_names) +{ + char *layout_name = NULL; + if (group < g_strv_length (short_group_names)) { + if (xkl_engine_get_features (engine) & + XKLF_MULTIPLE_LAYOUTS_SUPPORTED) { + char *full_layout_name = (char *) + g_slist_nth_data (kbd_cfg->layouts_variants, + group); + char *variant_name; + if (!matekbd_keyboard_config_split_items + (full_layout_name, &layout_name, + &variant_name)) + /* just in case */ + layout_name = full_layout_name; + + /* make it freeable */ + layout_name = g_strdup (layout_name); + + if (short_group_names != NULL) { + char *short_group_name = + short_group_names[group]; + if (short_group_name != NULL + && *short_group_name != '\0') { + /* drop the long name */ + g_free (layout_name); + layout_name = + g_strdup (short_group_name); + } + } + } else { + layout_name = g_strdup (full_group_names[group]); + } + } + + if (layout_name == NULL) + layout_name = g_strdup (""); + + return layout_name; +} + +gchar * +matekbd_indicator_create_label_title (int group, GHashTable ** ln2cnt_map, + gchar * layout_name) +{ + gpointer pcounter = NULL; + char *prev_layout_name = NULL; + char *lbl_title = NULL; + int counter = 0; + + if (group == 0) { + *ln2cnt_map = + g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); + } + + /* Process layouts with repeating description */ + if (g_hash_table_lookup_extended + (*ln2cnt_map, layout_name, (gpointer *) & prev_layout_name, + &pcounter)) { + /* "next" same description */ + gchar appendix[10] = ""; + gint utf8length; + gunichar cidx; + counter = GPOINTER_TO_INT (pcounter); + /* Unicode subscript 2, 3, 4 */ + cidx = 0x2081 + counter; + utf8length = g_unichar_to_utf8 (cidx, appendix); + appendix[utf8length] = '\0'; + lbl_title = g_strconcat (layout_name, appendix, NULL); + } else { + /* "first" time this description */ + lbl_title = g_strdup (layout_name); + } + g_hash_table_insert (*ln2cnt_map, layout_name, + GINT_TO_POINTER (counter + 1)); + return lbl_title; +} + +static GtkWidget * +matekbd_indicator_prepare_drawing (MatekbdIndicator * gki, int group) +{ + gpointer pimage; + GdkPixbuf *image; + GtkWidget *ebox; + + pimage = g_slist_nth_data (globals.images, group); + ebox = gtk_event_box_new (); + gtk_event_box_set_visible_window (GTK_EVENT_BOX (ebox), FALSE); + if (globals.ind_cfg.show_flags) { + GtkWidget *flag; + if (pimage == NULL) + return NULL; + image = GDK_PIXBUF (pimage); + flag = gtk_drawing_area_new (); + gtk_widget_add_events (GTK_WIDGET (flag), + GDK_BUTTON_PRESS_MASK); + g_signal_connect (G_OBJECT (flag), "expose_event", + G_CALLBACK (flag_exposed), image); + gtk_container_add (GTK_CONTAINER (ebox), flag); + } else { + char *lbl_title = NULL; + char *layout_name = NULL; + GtkWidget *align, *label; + static GHashTable *ln2cnt_map = NULL; + + layout_name = + matekbd_indicator_extract_layout_name (group, + globals.engine, + &globals.kbd_cfg, + globals.short_group_names, + globals.full_group_names); + + lbl_title = + matekbd_indicator_create_label_title (group, + &ln2cnt_map, + layout_name); + + align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0); + label = gtk_label_new (lbl_title); + g_free (lbl_title); + gtk_label_set_angle (GTK_LABEL (label), gki->priv->angle); + + if (group + 1 == + xkl_engine_get_num_groups (globals.engine)) { + g_hash_table_destroy (ln2cnt_map); + ln2cnt_map = NULL; + } + + gtk_container_add (GTK_CONTAINER (align), label); + gtk_container_add (GTK_CONTAINER (ebox), align); + + gtk_container_set_border_width (GTK_CONTAINER (align), 2); + } + + g_signal_connect (G_OBJECT (ebox), + "button_press_event", + G_CALLBACK (matekbd_indicator_button_pressed), gki); + + g_signal_connect (G_OBJECT (gki), + "key_press_event", + G_CALLBACK (matekbd_indicator_key_pressed), gki); + + /* We have everything prepared for that size */ + + return ebox; +} + +static void +matekbd_indicator_update_tooltips (MatekbdIndicator * gki) +{ + XklState *state = xkl_engine_get_current_state (globals.engine); + gchar *buf; + if (state == NULL || state->group < 0 + || state->group >= g_strv_length (globals.full_group_names)) + return; + + buf = g_strdup_printf (globals.tooltips_format, + globals.full_group_names[state->group]); + + matekbd_indicator_set_tooltips (gki, buf); + g_free (buf); +} + +static void +matekbd_indicator_parent_set (GtkWidget * gki, GtkWidget * previous_parent) +{ + matekbd_indicator_update_tooltips (MATEKBD_INDICATOR (gki)); +} + + +void +matekbd_indicator_reinit_ui (MatekbdIndicator * gki) +{ + matekbd_indicator_cleanup (gki); + matekbd_indicator_fill (gki); + + matekbd_indicator_set_current_page (gki); + + g_signal_emit_by_name (gki, "reinit-ui"); +} + +/* Should be called once for all widgets */ +static void +matekbd_indicator_cfg_changed (MateConfClient * client, + guint cnxn_id, MateConfEntry * entry) +{ + xkl_debug (100, + "General configuration changed in MateConf - reiniting...\n"); + matekbd_desktop_config_load_from_mateconf (&globals.cfg); + matekbd_desktop_config_activate (&globals.cfg); + ForAllIndicators () { + matekbd_indicator_reinit_ui (gki); + } NextIndicator (); +} + +/* Should be called once for all widgets */ +static void +matekbd_indicator_ind_cfg_changed (MateConfClient * client, + guint cnxn_id, MateConfEntry * entry) +{ + xkl_debug (100, + "Applet configuration changed in MateConf - reiniting...\n"); + matekbd_indicator_config_load_from_mateconf (&globals.ind_cfg); + matekbd_indicator_update_images (); + matekbd_indicator_config_activate (&globals.ind_cfg); + + matekbd_indicator_plugin_manager_toggle_plugins + (&globals.plugin_manager, &globals.plugin_container, + globals.ind_cfg.enabled_plugins); + + ForAllIndicators () { + matekbd_indicator_reinit_ui (gki); + } NextIndicator (); +} + +static void +matekbd_indicator_load_group_names (const gchar ** layout_ids, + const gchar ** variant_ids) +{ + if (!matekbd_desktop_config_load_group_descriptions + (&globals.cfg, globals.registry, layout_ids, variant_ids, + &globals.short_group_names, &globals.full_group_names)) { + /* We just populate no short names (remain NULL) - + * full names are going to be used anyway */ + gint i, total_groups = + xkl_engine_get_num_groups (globals.engine); + globals.full_group_names = + g_new0 (char *, total_groups + 1); + + if (xkl_engine_get_features (globals.engine) & + XKLF_MULTIPLE_LAYOUTS_SUPPORTED) { + GSList *lst = globals.kbd_cfg.layouts_variants; + for (i = 0; lst; lst = lst->next, i++) { + globals.full_group_names[i] = + g_strdup ((char *) lst->data); + } + } else { + for (i = total_groups; --i >= 0;) { + globals.full_group_names[i] = + g_strdup_printf ("Group %d", i); + } + } + } +} + +/* Should be called once for all widgets */ +static void +matekbd_indicator_kbd_cfg_callback (MatekbdIndicator * gki) +{ + XklConfigRec *xklrec = xkl_config_rec_new (); + xkl_debug (100, + "XKB configuration changed on X Server - reiniting...\n"); + + matekbd_keyboard_config_load_from_x_current (&globals.kbd_cfg, + xklrec); + matekbd_indicator_update_images (); + + g_strfreev (globals.full_group_names); + globals.full_group_names = NULL; + + if (globals.short_group_names != NULL) { + g_strfreev (globals.short_group_names); + globals.short_group_names = NULL; + } + + matekbd_indicator_load_group_names ((const gchar **) xklrec->layouts, + (const gchar **) + xklrec->variants); + + ForAllIndicators () { + matekbd_indicator_reinit_ui (gki); + } NextIndicator (); + g_object_unref (G_OBJECT (xklrec)); +} + +/* Should be called once for all applets */ +static void +matekbd_indicator_state_callback (XklEngine * engine, + XklEngineStateChange changeType, + gint group, gboolean restore) +{ + xkl_debug (150, "group is now %d, restore: %d\n", group, restore); + + if (changeType == GROUP_CHANGED) { + ForAllIndicators () { + matekbd_indicator_plugin_manager_group_changed + (&globals.plugin_manager, GTK_WIDGET (gki), + group); + xkl_debug (200, "do repaint\n"); + matekbd_indicator_set_current_page_for_group + (gki, group); + } + NextIndicator (); + } +} + + +void +matekbd_indicator_set_current_page (MatekbdIndicator * gki) +{ + XklState *cur_state; + cur_state = xkl_engine_get_current_state (globals.engine); + if (cur_state->group >= 0) + matekbd_indicator_set_current_page_for_group (gki, + cur_state-> + group); +} + +void +matekbd_indicator_set_current_page_for_group (MatekbdIndicator * gki, int group) +{ + xkl_debug (200, "Revalidating for group %d\n", group); + + gtk_notebook_set_current_page (GTK_NOTEBOOK (gki), group + 1); + + matekbd_indicator_update_tooltips (gki); +} + +/* Should be called once for all widgets */ +static GdkFilterReturn +matekbd_indicator_filter_x_evt (GdkXEvent * xev, GdkEvent * event) +{ + XEvent *xevent = (XEvent *) xev; + + xkl_engine_filter_events (globals.engine, xevent); + switch (xevent->type) { + case ReparentNotify: + { + XReparentEvent *rne = (XReparentEvent *) xev; + + ForAllIndicators () { + GdkWindow *w = + gtk_widget_get_parent_window + (GTK_WIDGET (gki)); + + /* compare the indicator's parent window with the even window */ + if (w != NULL + && GDK_WINDOW_XID (w) == rne->window) { + /* if so - make it transparent... */ + xkl_engine_set_window_transparent + (globals.engine, rne->window, + TRUE); + } + } + NextIndicator () + } + break; + } + return GDK_FILTER_CONTINUE; +} + + +/* Should be called once for all widgets */ +static void +matekbd_indicator_start_listen (void) +{ + gdk_window_add_filter (NULL, (GdkFilterFunc) + matekbd_indicator_filter_x_evt, NULL); + gdk_window_add_filter (gdk_get_default_root_window (), + (GdkFilterFunc) + matekbd_indicator_filter_x_evt, NULL); + + xkl_engine_start_listen (globals.engine, + XKLL_TRACK_KEYBOARD_STATE); +} + +/* Should be called once for all widgets */ +static void +matekbd_indicator_stop_listen (void) +{ + xkl_engine_stop_listen (globals.engine, XKLL_TRACK_KEYBOARD_STATE); + + gdk_window_remove_filter (NULL, (GdkFilterFunc) + matekbd_indicator_filter_x_evt, NULL); + gdk_window_remove_filter + (gdk_get_default_root_window (), + (GdkFilterFunc) matekbd_indicator_filter_x_evt, NULL); +} + +static gboolean +matekbd_indicator_scroll (GtkWidget * gki, GdkEventScroll * event) +{ + /* mouse wheel events should be ignored, otherwise funny effects appear */ + return TRUE; +} + +static void +matekbd_indicator_init (MatekbdIndicator * gki) +{ + GtkWidget *def_drawing; + GtkNotebook *notebook; + + if (!g_slist_length (globals.widget_instances)) + matekbd_indicator_global_init (); + + gki->priv = g_new0 (MatekbdIndicatorPrivate, 1); + + notebook = GTK_NOTEBOOK (gki); + + xkl_debug (100, "Initiating the widget startup process for %p\n", + gki); + + gtk_notebook_set_show_tabs (notebook, FALSE); + gtk_notebook_set_show_border (notebook, FALSE); + + def_drawing = + gtk_image_new_from_stock (GTK_STOCK_STOP, + GTK_ICON_SIZE_BUTTON); + + gtk_notebook_append_page (notebook, def_drawing, + gtk_label_new ("")); + + if (globals.engine == NULL) { + matekbd_indicator_set_tooltips (gki, + _ + ("XKB initialization error")); + return; + } + + matekbd_indicator_set_tooltips (gki, NULL); + + matekbd_indicator_fill (gki); + matekbd_indicator_set_current_page (gki); + + gtk_widget_add_events (GTK_WIDGET (gki), GDK_BUTTON_PRESS_MASK); + + /* append AFTER all initialization work is finished */ + globals.widget_instances = + g_slist_append (globals.widget_instances, gki); +} + +static void +matekbd_indicator_finalize (GObject * obj) +{ + MatekbdIndicator *gki = MATEKBD_INDICATOR (obj); + xkl_debug (100, + "Starting the mate-kbd-indicator widget shutdown process for %p\n", + gki); + + /* remove BEFORE all termination work is finished */ + globals.widget_instances = + g_slist_remove (globals.widget_instances, gki); + + matekbd_indicator_cleanup (gki); + + xkl_debug (100, + "The instance of mate-kbd-indicator successfully finalized\n"); + + g_free (gki->priv); + + G_OBJECT_CLASS (matekbd_indicator_parent_class)->finalize (obj); + + if (!g_slist_length (globals.widget_instances)) + matekbd_indicator_global_term (); +} + +static void +matekbd_indicator_global_term (void) +{ + xkl_debug (100, "*** Last MatekbdIndicator instance *** \n"); + matekbd_indicator_stop_listen (); + + matekbd_desktop_config_stop_listen (&globals.cfg); + matekbd_indicator_config_stop_listen (&globals.ind_cfg); + + matekbd_indicator_plugin_manager_term_initialized_plugins + (&globals.plugin_manager); + matekbd_indicator_plugin_manager_term (&globals.plugin_manager); + + matekbd_indicator_config_term (&globals.ind_cfg); + matekbd_keyboard_config_term (&globals.kbd_cfg); + matekbd_desktop_config_term (&globals.cfg); + + matekbd_indicator_plugin_container_term (&globals.plugin_container); + + g_object_unref (G_OBJECT (globals.registry)); + globals.registry = NULL; + g_object_unref (G_OBJECT (globals.engine)); + globals.engine = NULL; + xkl_debug (100, "*** Terminated globals *** \n"); +} + +static void +matekbd_indicator_class_init (MatekbdIndicatorClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + xkl_debug (100, "*** First MatekbdIndicator instance *** \n"); + + memset (&globals, 0, sizeof (globals)); + + /* Initing some global vars */ + globals.tooltips_format = "%s"; + + /* Initing vtable */ + object_class->finalize = matekbd_indicator_finalize; + + widget_class->scroll_event = matekbd_indicator_scroll; + widget_class->parent_set = matekbd_indicator_parent_set; + + /* Signals */ + g_signal_new ("reinit-ui", MATEKBD_TYPE_INDICATOR, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MatekbdIndicatorClass, reinit_ui), + NULL, NULL, matekbd_indicator_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +matekbd_indicator_global_init (void) +{ + MateConfClient *mateconf_client; + XklConfigRec *xklrec = xkl_config_rec_new (); + + globals.engine = xkl_engine_get_instance (GDK_DISPLAY ()); + if (globals.engine == NULL) { + xkl_debug (0, "Libxklavier initialization error"); + return; + } + + mateconf_client = mateconf_client_get_default (); + + g_signal_connect (globals.engine, "X-state-changed", + G_CALLBACK (matekbd_indicator_state_callback), + NULL); + g_signal_connect (globals.engine, "X-config-changed", + G_CALLBACK (matekbd_indicator_kbd_cfg_callback), + NULL); + + matekbd_indicator_plugin_container_init (&globals.plugin_container, + mateconf_client); + + matekbd_desktop_config_init (&globals.cfg, mateconf_client, + globals.engine); + matekbd_keyboard_config_init (&globals.kbd_cfg, mateconf_client, + globals.engine); + matekbd_indicator_config_init (&globals.ind_cfg, mateconf_client, + globals.engine); + + g_object_unref (mateconf_client); + + matekbd_desktop_config_load_from_mateconf (&globals.cfg); + matekbd_desktop_config_activate (&globals.cfg); + + globals.registry = + xkl_config_registry_get_instance (globals.engine); + xkl_config_registry_load (globals.registry, + globals.cfg.load_extra_items); + + matekbd_keyboard_config_load_from_x_current (&globals.kbd_cfg, + xklrec); + + matekbd_indicator_config_load_from_mateconf (&globals.ind_cfg); + matekbd_indicator_update_images (); + matekbd_indicator_config_activate (&globals.ind_cfg); + + matekbd_indicator_load_group_names ((const gchar **) xklrec->layouts, + (const gchar **) + xklrec->variants); + g_object_unref (G_OBJECT (xklrec)); + + matekbd_indicator_plugin_manager_init (&globals.plugin_manager); + matekbd_indicator_plugin_manager_init_enabled_plugins + (&globals.plugin_manager, &globals.plugin_container, + globals.ind_cfg.enabled_plugins); + matekbd_desktop_config_start_listen (&globals.cfg, + (MateConfClientNotifyFunc) + matekbd_indicator_cfg_changed, + NULL); + matekbd_indicator_config_start_listen (&globals.ind_cfg, + (MateConfClientNotifyFunc) + matekbd_indicator_ind_cfg_changed, + NULL); + matekbd_indicator_start_listen (); + + xkl_debug (100, "*** Inited globals *** \n"); +} + +GtkWidget * +matekbd_indicator_new (void) +{ + return + GTK_WIDGET (g_object_new (matekbd_indicator_get_type (), NULL)); +} + +void +matekbd_indicator_set_parent_tooltips (MatekbdIndicator * gki, gboolean spt) +{ + gki->priv->set_parent_tooltips = spt; + matekbd_indicator_update_tooltips (gki); +} + +void +matekbd_indicator_set_tooltips_format (const gchar format[]) +{ + globals.tooltips_format = format; + ForAllIndicators () + matekbd_indicator_update_tooltips (gki); + NextIndicator () +} + +XklEngine * +matekbd_indicator_get_xkl_engine () +{ + return globals.engine; +} + +gchar ** +matekbd_indicator_get_group_names () +{ + return globals.full_group_names; +} + +gchar * +matekbd_indicator_get_image_filename (guint group) +{ + if (!globals.ind_cfg.show_flags) + return NULL; + return matekbd_indicator_config_get_images_file (&globals.ind_cfg, + &globals.kbd_cfg, + group); +} + +gdouble +matekbd_indicator_get_max_width_height_ratio (void) +{ + gdouble rv = 0.0; + GSList *ip = globals.images; + if (!globals.ind_cfg.show_flags) + return 0; + while (ip != NULL) { + GdkPixbuf *img = GDK_PIXBUF (ip->data); + gdouble r = + 1.0 * gdk_pixbuf_get_width (img) / + gdk_pixbuf_get_height (img); + if (r > rv) + rv = r; + ip = ip->next; + } + return rv; +} + +void +matekbd_indicator_set_angle (MatekbdIndicator * gki, gdouble angle) +{ + gki->priv->angle = angle; +} + +/* Plugin support */ +/* Preserve the plugin container functions during the linking */ +void +matekbd_indicator_plugin_container_reinit_ui (MatekbdIndicatorPluginContainer * + pc) +{ + ForAllIndicators () { + matekbd_indicator_reinit_ui (gki); + } NextIndicator (); +} + +gchar **matekbd_indicator_plugin_load_localized_group_names + (MatekbdIndicatorPluginContainer * pc) { + return globals.full_group_names; +} |