diff options
author | Sergey V. Udaltsov <svu@gnome.org> | 2009-12-14 13:23:07 +0000 |
---|---|---|
committer | Sergey V. Udaltsov <svu@gnome.org> | 2009-12-14 13:23:07 +0000 |
commit | 3584dc898c8212f154cd9ae22185c5d8aa7b4218 (patch) | |
tree | c8b93a515b0c3025e8218b17300ff337989d430c | |
parent | d9ade98d2374648e237c4351c6b23445f3c7d8ef (diff) | |
download | libgnomekbd-3584dc898c8212f154cd9ae22185c5d8aa7b4218.tar.gz |
Introduced GkbdStatus for the notification area
Now it only works with flags
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | libgnomekbd/Makefile.am | 1 | ||||
-rw-r--r-- | libgnomekbd/gkbd-indicator-config.c | 96 | ||||
-rw-r--r-- | libgnomekbd/gkbd-indicator-config.h | 20 | ||||
-rw-r--r-- | libgnomekbd/gkbd-indicator.c | 104 | ||||
-rw-r--r-- | libgnomekbd/gkbd-status.c | 596 | ||||
-rw-r--r-- | libgnomekbd/gkbd-status.h | 72 | ||||
-rw-r--r-- | test/.gitignore | 1 | ||||
-rw-r--r-- | test/Makefile.am | 44 | ||||
-rw-r--r-- | test/gkbd-status-test.c | 55 |
10 files changed, 872 insertions, 123 deletions
@@ -1,6 +1,12 @@ 2009-12-14 svu * configure.in, NEWS: release 2.28.2 + * libgnomekbd/Makefile.am, libgnomekbd/gkbd-indicator-config.c, + libgnomekbd/gkbd-indicator-config.h, libgnomekbd/gkbd-indicator.c, + libgnomekbd/gkbd-status.c, libgnomekbd/gkbd-status.h, test/.gitignore, + test/Makefile.am, test/gkbd-status-test.c: introduced the status icon + widget (functions only with flags so far) + 2009-12-09 svu diff --git a/libgnomekbd/Makefile.am b/libgnomekbd/Makefile.am index fd848bd..17b67d3 100644 --- a/libgnomekbd/Makefile.am +++ b/libgnomekbd/Makefile.am @@ -44,6 +44,7 @@ libgnomekbd_la_SOURCES = \ libgnomekbdui_la_SOURCES = \ gkbd-indicator-config.c \ gkbd-indicator.c \ + gkbd-status.c \ gkbd-indicator-marshal.c \ gkbd-indicator-plugin-manager.c \ gkbd-keyboard-drawing-marshal.c \ diff --git a/libgnomekbd/gkbd-indicator-config.c b/libgnomekbd/gkbd-indicator-config.c index fdc7867..45d1d8f 100644 --- a/libgnomekbd/gkbd-indicator-config.c +++ b/libgnomekbd/gkbd-indicator-config.c @@ -66,26 +66,6 @@ gkbd_indicator_config_free_enabled_plugins (GkbdIndicatorConfig * } } -/** - * extern applet kbdConfig functions - */ -void -gkbd_indicator_config_free_images (GkbdIndicatorConfig * ind_config) -{ - GdkPixbuf *pi; - GSList *img_node; - while ((img_node = ind_config->images) != NULL) { - pi = GDK_PIXBUF (img_node->data); - /* It can be NULL - some images may be missing */ - if (pi != NULL) { - g_object_unref (pi); - } - ind_config->images = - g_slist_remove_link (ind_config->images, img_node); - g_slist_free_1 (img_node); - } -} - char * gkbd_indicator_config_get_images_file (GkbdIndicatorConfig * ind_config, @@ -100,9 +80,8 @@ gkbd_indicator_config_get_images_file (GkbdIndicatorConfig * if ((kbd_config->layouts_variants != NULL) && (g_slist_length (kbd_config->layouts_variants) > group)) { - char *full_layout_name = - (char *) g_slist_nth_data (kbd_config-> - layouts_variants, group); + char *full_layout_name = (char *) + g_slist_nth_data (kbd_config->layouts_variants, group); if (full_layout_name != NULL) { char *l, *v; @@ -130,59 +109,39 @@ gkbd_indicator_config_get_images_file (GkbdIndicatorConfig * } void -gkbd_indicator_config_load_images (GkbdIndicatorConfig * ind_config, - GkbdKeyboardConfig * kbd_config) +gkbd_indicator_config_load_image_filenames (GkbdIndicatorConfig * + ind_config, + GkbdKeyboardConfig * + kbd_config) { int i; - ind_config->images = NULL; + ind_config->image_filenames = NULL; if (!ind_config->show_flags) return; for (i = xkl_engine_get_max_num_groups (ind_config->engine); --i >= 0;) { - GdkPixbuf *image = NULL; char *image_file = gkbd_indicator_config_get_images_file (ind_config, kbd_config, i); + ind_config->image_filenames = + g_slist_prepend (ind_config->image_filenames, + image_file); + } +} - 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)); - g_free (image_file); - } - /* We append the image anyway - even if it is NULL! */ - ind_config->images = - g_slist_prepend (ind_config->images, image); +void +gkbd_indicator_config_free_image_filenames (GkbdIndicatorConfig * + ind_config) +{ + while (ind_config->image_filenames) { + if (ind_config->image_filenames->data) + g_free (ind_config->image_filenames->data); + ind_config->image_filenames = + g_slist_delete_link (ind_config->image_filenames, + ind_config->image_filenames); } } @@ -239,7 +198,7 @@ gkbd_indicator_config_term (GkbdIndicatorConfig * ind_config) #endif ind_config->icon_theme = NULL; - gkbd_indicator_config_free_images (ind_config); + gkbd_indicator_config_free_image_filenames (ind_config); gkbd_indicator_config_free_enabled_plugins (ind_config); g_object_unref (ind_config->conf_client); @@ -247,15 +206,6 @@ gkbd_indicator_config_term (GkbdIndicatorConfig * ind_config) } void -gkbd_indicator_config_update_images (GkbdIndicatorConfig * - ind_config, - GkbdKeyboardConfig * kbd_config) -{ - gkbd_indicator_config_free_images (ind_config); - gkbd_indicator_config_load_images (ind_config, kbd_config); -} - -void gkbd_indicator_config_load_from_gconf (GkbdIndicatorConfig * ind_config) { GError *gerror = NULL; diff --git a/libgnomekbd/gkbd-indicator-config.h b/libgnomekbd/gkbd-indicator-config.h index 556b911..38173bf 100644 --- a/libgnomekbd/gkbd-indicator-config.h +++ b/libgnomekbd/gkbd-indicator-config.h @@ -35,7 +35,7 @@ typedef struct _GkbdIndicatorConfig { /* private, transient */ GConfClient *conf_client; - GSList *images; + GSList *image_filenames; GtkIconTheme *icon_theme; int config_listener_id; XklEngine *engine; @@ -64,18 +64,12 @@ extern gchar GkbdKeyboardConfig * kbd_config, int group); -extern void gkbd_indicator_config_load_images (GkbdIndicatorConfig * - applet_config, - GkbdKeyboardConfig * - kbd_config); -extern void gkbd_indicator_config_free_images (GkbdIndicatorConfig * - applet_config); - -/* Should be updated on Indicator/GConf and Kbd/GConf configuration change */ -extern void gkbd_indicator_config_update_images (GkbdIndicatorConfig * - applet_config, - GkbdKeyboardConfig * - kbd_config); +extern void gkbd_indicator_config_load_image_filenames (GkbdIndicatorConfig + * applet_config, + GkbdKeyboardConfig + * kbd_config); +extern void gkbd_indicator_config_free_image_filenames (GkbdIndicatorConfig + * applet_config); /* Should be updated on Indicator/GConf configuration change */ extern void gkbd_indicator_config_activate (GkbdIndicatorConfig * diff --git a/libgnomekbd/gkbd-indicator.c b/libgnomekbd/gkbd-indicator.c index be573be..2ddd1f9 100644 --- a/libgnomekbd/gkbd-indicator.c +++ b/libgnomekbd/gkbd-indicator.c @@ -46,6 +46,7 @@ typedef struct _gki_globals { gchar **full_group_names; gchar **short_group_names; GSList *widget_instances; + GSList *images; } gki_globals; struct _GkbdIndicatorPrivate { @@ -85,6 +86,89 @@ static void gkbd_indicator_set_tooltips (GkbdIndicator * gki, const char *str); void +gkbd_indicator_load_images () +{ + int i; + GSList *image_filename; + + globals.images = NULL; + gkbd_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 +gkbd_indicator_free_images () +{ + GdkPixbuf *pi; + GSList *img_node; + + gkbd_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 +gkbd_indicator_update_images (void) +{ + gkbd_indicator_free_images (); + gkbd_indicator_load_images (); +} + +void gkbd_indicator_set_tooltips (GkbdIndicator * gki, const char *str) { g_assert (str == NULL || g_utf8_validate (str, -1, NULL)); @@ -226,7 +310,7 @@ gkbd_indicator_prepare_drawing (GkbdIndicator * gki, int group) GdkPixbuf *image; GtkWidget *ebox; - pimage = g_slist_nth_data (globals.ind_cfg.images, group); + 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) { @@ -264,8 +348,8 @@ gkbd_indicator_prepare_drawing (GkbdIndicator * gki, int group) if (xkl_engine_get_features (globals.engine) & XKLF_MULTIPLE_LAYOUTS_SUPPORTED) { char *full_layout_name = (char *) - g_slist_nth_data (globals.kbd_cfg. - layouts_variants, + g_slist_nth_data (globals. + kbd_cfg.layouts_variants, group); char *variant_name; if (!gkbd_keyboard_config_split_items @@ -408,8 +492,7 @@ gkbd_indicator_ind_cfg_changed (GConfClient * client, xkl_debug (100, "Applet configuration changed in GConf - reiniting...\n"); gkbd_indicator_config_load_from_gconf (&globals.ind_cfg); - gkbd_indicator_config_update_images (&globals.ind_cfg, - &globals.kbd_cfg); + gkbd_indicator_update_images (); gkbd_indicator_config_activate (&globals.ind_cfg); gkbd_indicator_plugin_manager_toggle_plugins @@ -461,8 +544,7 @@ gkbd_indicator_kbd_cfg_callback (GkbdIndicator * gki) gkbd_keyboard_config_load_from_x_current (&globals.kbd_cfg, xklrec); - gkbd_indicator_config_update_images (&globals.ind_cfg, - &globals.kbd_cfg); + gkbd_indicator_update_images (); g_strfreev (globals.full_group_names); globals.full_group_names = NULL; @@ -511,8 +593,7 @@ gkbd_indicator_set_current_page (GkbdIndicator * gki) cur_state = xkl_engine_get_current_state (globals.engine); if (cur_state->group >= 0) gkbd_indicator_set_current_page_for_group (gki, - cur_state-> - group); + cur_state->group); } void @@ -761,8 +842,7 @@ gkbd_indicator_global_init (void) xklrec); gkbd_indicator_config_load_from_gconf (&globals.ind_cfg); - gkbd_indicator_config_update_images (&globals.ind_cfg, - &globals.kbd_cfg); + gkbd_indicator_update_images (); gkbd_indicator_config_activate (&globals.ind_cfg); gkbd_indicator_load_group_names ((const gchar **) xklrec->layouts, @@ -836,7 +916,7 @@ gdouble gkbd_indicator_get_max_width_height_ratio (void) { gdouble rv = 0.0; - GSList *ip = globals.ind_cfg.images; + GSList *ip = globals.images; if (!globals.ind_cfg.show_flags) return 0; while (ip != NULL) { diff --git a/libgnomekbd/gkbd-status.c b/libgnomekbd/gkbd-status.c new file mode 100644 index 0000000..7e70088 --- /dev/null +++ b/libgnomekbd/gkbd-status.c @@ -0,0 +1,596 @@ +/* + * Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org> + * + * 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 <cairo.h> + +#include <gdk/gdkkeysyms.h> +#include <gdk/gdkx.h> +#include <glib/gi18n.h> + +#include <gkbd-status.h> + +#include <gkbd-desktop-config.h> +#include <gkbd-indicator-config.h> + +typedef struct _gki_globals { + XklEngine *engine; + XklConfigRegistry *registry; + + GkbdDesktopConfig cfg; + GkbdIndicatorConfig ind_cfg; + GkbdKeyboardConfig kbd_cfg; + + const gchar *tooltips_format; + gchar **full_group_names; + gchar **short_group_names; + + gint current_size; + GSList *icons; /* list of GdkPixbuf */ + GSList *widget_instances; /* list of GkbdStatus */ +} gki_globals; + +struct _GkbdStatusPrivate { + 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) { \ + GkbdStatus * gki = (GkbdStatus*)cur->data; +#define NextIndicator() \ + } \ + } + +G_DEFINE_TYPE (GkbdStatus, gkbd_status, GTK_TYPE_STATUS_ICON) + +static void +gkbd_status_global_init (void); +static void +gkbd_status_global_term (void); +static GdkPixbuf * +gkbd_status_prepare_drawing (GkbdStatus * gki, int group); +static void +gkbd_status_set_current_page_for_group (GkbdStatus * gki, int group); +static void +gkbd_status_set_current_page (GkbdStatus * gki); +static void +gkbd_status_cleanup (GkbdStatus * gki); +static void +gkbd_status_fill (GkbdStatus * gki); +static void +gkbd_status_set_tooltips (GkbdStatus * gki, const char *str); + +void +gkbd_status_set_tooltips (GkbdStatus * gki, const char *str) +{ + g_assert (str == NULL || g_utf8_validate (str, -1, NULL)); + + gtk_status_icon_set_tooltip_text (GTK_STATUS_ICON (gki), str); +} + +void +gkbd_status_cleanup (GkbdStatus * gki) +{ + while (globals.icons) { + if (globals.icons->data) + g_object_unref (G_OBJECT (globals.icons->data)); + globals.icons = + g_slist_delete_link (globals.icons, globals.icons); + } +} + +void +gkbd_status_fill (GkbdStatus * gki) +{ + int grp; + int total_groups = xkl_engine_get_num_groups (globals.engine); + + for (grp = 0; grp < total_groups; grp++) { + GdkPixbuf *page = gkbd_status_prepare_drawing (gki, grp); + globals.icons = g_slist_append (globals.icons, page); + } +} + +static void +gkbd_status_activate (GkbdStatus * gki) +{ + xkl_debug (150, "Mouse button pressed on applet\n"); + gkbd_desktop_config_lock_next_group (&globals.cfg); +} + +static GdkPixbuf * +gkbd_status_prepare_drawing (GkbdStatus * gki, int group) +{ + GError *gerror = NULL; + char *image_filename; + GdkPixbuf *image; + + if (globals.current_size == 0) + return NULL; + + image_filename = (char *) g_slist_nth_data (globals.ind_cfg.image_filenames, + group); + + image = gdk_pixbuf_new_from_file_at_size (image_filename, + globals.current_size, + globals.current_size, + &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 == + NULL ? + "Unknown" : + 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); + + return NULL; + } + xkl_debug (150, + "Image %d[%s] loaded -> %p[%dx%d]\n", + group, image_filename, image, + gdk_pixbuf_get_width (image), + gdk_pixbuf_get_height (image)); + + return image; +} + +static void +gkbd_status_update_tooltips (GkbdStatus * 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]); + + gkbd_status_set_tooltips (gki, buf); + g_free (buf); +} + +void +gkbd_status_reinit_ui (GkbdStatus * gki) +{ + gkbd_status_cleanup (gki); + gkbd_status_fill (gki); + + gkbd_status_set_current_page (gki); +} + +/* Should be called once for all widgets */ +static void +gkbd_status_cfg_changed (GConfClient * client, + guint cnxn_id, GConfEntry * entry) +{ + xkl_debug (100, + "General configuration changed in GConf - reiniting...\n"); + gkbd_desktop_config_load_from_gconf (&globals.cfg); + gkbd_desktop_config_activate (&globals.cfg); + ForAllIndicators () { + gkbd_status_reinit_ui (gki); + } NextIndicator (); +} + +/* Should be called once for all widgets */ +static void +gkbd_status_ind_cfg_changed (GConfClient * client, + guint cnxn_id, GConfEntry * entry) +{ + xkl_debug (100, + "Applet configuration changed in GConf - reiniting...\n"); + gkbd_indicator_config_load_from_gconf (&globals.ind_cfg); + + gkbd_indicator_config_free_image_filenames (&globals.ind_cfg); + gkbd_indicator_config_load_image_filenames (&globals.ind_cfg, + &globals.kbd_cfg); + + gkbd_indicator_config_activate (&globals.ind_cfg); + + ForAllIndicators () { + gkbd_status_reinit_ui (gki); + } NextIndicator (); +} + +static void +gkbd_status_load_group_names (const gchar ** layout_ids, + const gchar ** variant_ids) +{ + if (!gkbd_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 +gkbd_status_kbd_cfg_callback (GkbdStatus * gki) +{ + XklConfigRec *xklrec = xkl_config_rec_new (); + xkl_debug (100, + "XKB configuration changed on X Server - reiniting...\n"); + + gkbd_keyboard_config_load_from_x_current (&globals.kbd_cfg, + xklrec); + + gkbd_indicator_config_free_image_filenames (&globals.ind_cfg); + gkbd_indicator_config_load_image_filenames (&globals.ind_cfg, + &globals.kbd_cfg); + + 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; + } + + gkbd_status_load_group_names ((const gchar **) xklrec->layouts, + (const gchar **) + xklrec->variants); + + ForAllIndicators () { + gkbd_status_reinit_ui (gki); + } NextIndicator (); + g_object_unref (G_OBJECT (xklrec)); +} + +/* Should be called once for all applets */ +static void +gkbd_status_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 () { + xkl_debug (200, "do repaint\n"); + gkbd_status_set_current_page_for_group + (gki, group); + } + NextIndicator (); + } +} + + +void +gkbd_status_set_current_page (GkbdStatus * gki) +{ + XklState *cur_state; + cur_state = xkl_engine_get_current_state (globals.engine); + if (cur_state->group >= 0) + gkbd_status_set_current_page_for_group (gki, + cur_state->group); +} + +void +gkbd_status_set_current_page_for_group (GkbdStatus * gki, int group) +{ + xkl_debug (200, "Revalidating for group %d\n", group); + + gtk_status_icon_set_from_pixbuf (GTK_STATUS_ICON (gki), + GDK_PIXBUF (g_slist_nth_data + (globals.icons, + group))); + + gkbd_status_update_tooltips (gki); +} + +/* Should be called once for all widgets */ +static GdkFilterReturn +gkbd_status_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 () { + guint32 xid = + gtk_status_icon_get_x11_window_id + (GTK_STATUS_ICON (gki)); + + /* compare the indicator's parent window with the even window */ + if (xid == 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 +gkbd_status_start_listen (void) +{ + gdk_window_add_filter (NULL, (GdkFilterFunc) + gkbd_status_filter_x_evt, NULL); + gdk_window_add_filter (gdk_get_default_root_window (), + (GdkFilterFunc) + gkbd_status_filter_x_evt, NULL); + + xkl_engine_start_listen (globals.engine, + XKLL_TRACK_KEYBOARD_STATE); +} + +/* Should be called once for all widgets */ +static void +gkbd_status_stop_listen (void) +{ + xkl_engine_stop_listen (globals.engine); + + gdk_window_remove_filter (NULL, (GdkFilterFunc) + gkbd_status_filter_x_evt, NULL); + gdk_window_remove_filter + (gdk_get_default_root_window (), + (GdkFilterFunc) gkbd_status_filter_x_evt, NULL); +} + +static void +gkbd_status_size_changed (GkbdStatus * gki, gint size) +{ + if (globals.current_size != size) { + globals.current_size = size; + gkbd_status_reinit_ui (gki); + } +} + +static void +gkbd_status_init (GkbdStatus * gki) +{ + if (!g_slist_length (globals.widget_instances)) + gkbd_status_global_init (); + + gki->priv = g_new0 (GkbdStatusPrivate, 1); + + xkl_debug (100, "Initiating the widget startup process for %p\n", + gki); + + if (globals.engine == NULL) { + gkbd_status_set_tooltips (gki, + _("XKB initialization error")); + return; + } + + gkbd_status_set_tooltips (gki, NULL); + + gkbd_status_fill (gki); + gkbd_status_set_current_page (gki); + + /* append AFTER all initialization work is finished */ + globals.widget_instances = + g_slist_append (globals.widget_instances, gki); + + g_signal_connect (gki, "size-changed", + G_CALLBACK (gkbd_status_size_changed), NULL); + g_signal_connect (gki, "activate", + G_CALLBACK (gkbd_status_activate), NULL); +} + +static void +gkbd_status_finalize (GObject * obj) +{ + GkbdStatus *gki = GKBD_STATUS (obj); + xkl_debug (100, + "Starting the gnome-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); + + gkbd_status_cleanup (gki); + + xkl_debug (100, + "The instance of gnome-kbd-indicator successfully finalized\n"); + + g_free (gki->priv); + + G_OBJECT_CLASS (gkbd_status_parent_class)->finalize (obj); + + if (!g_slist_length (globals.widget_instances)) + gkbd_status_global_term (); +} + +static void +gkbd_status_global_term (void) +{ + xkl_debug (100, "*** Last GkbdStatus instance *** \n"); + gkbd_status_stop_listen (); + + gkbd_desktop_config_stop_listen (&globals.cfg); + gkbd_indicator_config_stop_listen (&globals.ind_cfg); + + gkbd_indicator_config_term (&globals.ind_cfg); + gkbd_keyboard_config_term (&globals.kbd_cfg); + gkbd_desktop_config_term (&globals.cfg); + + 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 +gkbd_status_class_init (GkbdStatusClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + xkl_debug (100, "*** First GkbdStatus instance *** \n"); + + memset (&globals, 0, sizeof (globals)); + + /* Initing some global vars */ + globals.tooltips_format = "%s"; + + /* Initing vtable */ + object_class->finalize = gkbd_status_finalize; + + /* Signals */ +} + +static void +gkbd_status_global_init (void) +{ + GConfClient *gconf_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; + } + + gconf_client = gconf_client_get_default (); + + g_signal_connect (globals.engine, "X-state-changed", + G_CALLBACK (gkbd_status_state_callback), NULL); + g_signal_connect (globals.engine, "X-config-changed", + G_CALLBACK (gkbd_status_kbd_cfg_callback), NULL); + + gkbd_desktop_config_init (&globals.cfg, gconf_client, + globals.engine); + gkbd_keyboard_config_init (&globals.kbd_cfg, gconf_client, + globals.engine); + gkbd_indicator_config_init (&globals.ind_cfg, gconf_client, + globals.engine); + + g_object_unref (gconf_client); + + gkbd_desktop_config_load_from_gconf (&globals.cfg); + gkbd_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); + + gkbd_keyboard_config_load_from_x_current (&globals.kbd_cfg, + xklrec); + + gkbd_indicator_config_load_from_gconf (&globals.ind_cfg); + + gkbd_indicator_config_load_image_filenames (&globals.ind_cfg, + &globals.kbd_cfg); + + gkbd_indicator_config_activate (&globals.ind_cfg); + + gkbd_status_load_group_names ((const gchar **) xklrec->layouts, + (const gchar **) + xklrec->variants); + g_object_unref (G_OBJECT (xklrec)); + + gkbd_desktop_config_start_listen (&globals.cfg, + (GConfClientNotifyFunc) + gkbd_status_cfg_changed, NULL); + gkbd_indicator_config_start_listen (&globals.ind_cfg, + (GConfClientNotifyFunc) + gkbd_status_ind_cfg_changed, + NULL); + gkbd_status_start_listen (); + + xkl_debug (100, "*** Inited globals *** \n"); +} + +GtkStatusIcon * +gkbd_status_new (void) +{ + return + GTK_STATUS_ICON (g_object_new (gkbd_status_get_type (), NULL)); +} + +XklEngine * +gkbd_status_get_xkl_engine () +{ + return globals.engine; +} + +gchar ** +gkbd_status_get_group_names () +{ + return globals.full_group_names; +} + +gchar * +gkbd_status_get_image_filename (guint group) +{ + if (!globals.ind_cfg.show_flags) + return NULL; + return gkbd_indicator_config_get_images_file (&globals.ind_cfg, + &globals.kbd_cfg, + group); +} + +void +gkbd_status_set_angle (GkbdStatus * gki, gdouble angle) +{ + gki->priv->angle = angle; +} diff --git a/libgnomekbd/gkbd-status.h b/libgnomekbd/gkbd-status.h new file mode 100644 index 0000000..5c99ea2 --- /dev/null +++ b/libgnomekbd/gkbd-status.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2009 Sergey V. Udaltsov <svu@gnome.org> + * + * 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. + */ + +#ifndef __GKBD_STATUS_H__ +#define __GKBD_STATUS_H__ + +#include <gtk/gtk.h> + +#include <libxklavier/xklavier.h> + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct _GkbdStatus GkbdStatus; + typedef struct _GkbdStatusPrivate GkbdStatusPrivate; + typedef struct _GkbdStatusClass GkbdStatusClass; + +#define GKBD_TYPE_STATUS (gkbd_status_get_type ()) +#define GKBD_STATUS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GKBD_TYPE_STATUS, GkbdStatus)) +#define GKBD_INDCATOR_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GKBD_TYPE_STATUS, GkbdStatusClass)) +#define GKBD_IS_STATUS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GKBD_TYPE_STATUS)) +#define GKBD_IS_STATUS_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GKBD_TYPE_STATUS)) +#define GKBD_STATUS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GKBD_TYPE_STATUS, GkbdStatusClass)) + + struct _GkbdStatus { + GtkStatusIcon parent; + GkbdStatusPrivate *priv; + }; + + struct _GkbdStatusClass { + GtkNotebookClass parent_class; + }; + + extern GType gkbd_status_get_type (void); + + extern GtkStatusIcon *gkbd_status_new (void); + + extern void gkbd_status_reinit_ui (GkbdStatus * gki); + + extern void gkbd_status_set_angle (GkbdStatus * gki, + gdouble angle); + + extern XklEngine *gkbd_status_get_xkl_engine (void); + + extern gchar **gkbd_status_get_group_names (void); + + extern gchar *gkbd_status_get_image_filename (guint group); + + extern void + gkbd_status_set_tooltips_format (const gchar str[]); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/test/.gitignore b/test/.gitignore index 5ede48f..8a1b08b 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -1,4 +1,5 @@ .deps +gkbd-status-test gkbd-indicator-test gkbd-keyboard-drawing-test .libs diff --git a/test/Makefile.am b/test/Makefile.am index 896b851..81ccbb5 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,31 +1,25 @@ noinst_PROGRAMS = gkbd-indicator-test \ - gkbd-keyboard-drawing-test + gkbd-keyboard-drawing-test \ + gkbd-status-test -gkbd_indicator_test_CFLAGS= \ - $(WARN_CFLAGS) -I$(top_srcdir) -Wall \ - $(GTK_CFLAGS) \ - $(LIBGLADE_CFLAGS) \ - $(LIBXKLAVIER_CFLAGS) \ - -I$(top_srcdir)/intl \ - -DSYS_PLUGIN_DIR=\"$(libdir)/gnomekbd/\" \ - -DG_LOG_DOMAIN=\"GnomeKbdIndicatorTest\" \ - -DGNOMELOCALEDIR="\"$(datadir)/locale\"" \ - -DDATADIR=\"$(datadir)\" - -gkbd_indicator_test_LDFLAGS= \ - $(GTK_LIBS) \ - $(LIBGLADE_LIBS) \ - $(LIBXKLAVIER_LIBS) \ +common_CFLAGS = $(WARN_CFLAGS) -I$(top_srcdir) -Wall \ + $(GTK_CFLAGS) \ + $(LIBXKLAVIER_CFLAGS) \ + -DGNOMELOCALEDIR="\"$(datadir)/locale\"" + +common_LDFLAGS = $(GTK_LIBS) \ + $(LIBXKLAVIER_LIBS) \ $(top_builddir)/libgnomekbd/libgnomekbd.la \ $(top_builddir)/libgnomekbd/libgnomekbdui.la -gkbd_keyboard_drawing_test_CFLAGS= \ - $(WARN_CFLAGS) -I$(top_srcdir) \ - $(GTK_CFLAGS) $(GLIB_CFLAGS) +gkbd_indicator_test_CFLAGS=$(common_CFLAGS) -gkbd_keyboard_drawing_test_LDFLAGS= \ - $(GLIB_LIBS) \ - $(GTK_LIBS) \ - $(LIBXKLAVIER_LIBS) \ - $(top_builddir)/libgnomekbd/libgnomekbd.la \ - $(top_builddir)/libgnomekbd/libgnomekbdui.la +gkbd_indicator_test_LDFLAGS=$(common_LDFLAGS) + +gkbd_keyboard_drawing_test_CFLAGS=$(common_CFLAGS) + +gkbd_keyboard_drawing_test_LDFLAGS=$(common_LDFLAGS) + +gkbd_status_test_CFLAGS=$(common_CFLAGS) + +gkbd_status_test_LDFLAGS=$(common_LDFLAGS) diff --git a/test/gkbd-status-test.c b/test/gkbd-status-test.c new file mode 100644 index 0000000..3b2c365 --- /dev/null +++ b/test/gkbd-status-test.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org> + * + * 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 "config.h" + +#include "libxklavier/xklavier.h" +#include "libgnomekbd/gkbd-status.h" + +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> + +#include <gdk/gdk.h> +#include <gdk/gdkx.h> +#include <glib/gi18n.h> +#include <gtk/gtk.h> + +#include "X11/XKBlib.h" + +int +main (int argc, char **argv) +{ + GtkStatusIcon *icon; + + bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + + gtk_init (&argc, &argv); + + icon = gkbd_status_new (); + + gtk_main (); + + return 0; +} |