|
Packit |
88888e |
/*
|
|
Packit |
88888e |
* Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
|
|
Packit |
88888e |
*
|
|
Packit |
88888e |
* This library is free software; you can redistribute it and/or
|
|
Packit |
88888e |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
88888e |
* License as published by the Free Software Foundation; either
|
|
Packit |
88888e |
* version 2 of the License, or (at your option) any later version.
|
|
Packit |
88888e |
*
|
|
Packit |
88888e |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
88888e |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
88888e |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
88888e |
* Lesser General Public License for more details.
|
|
Packit |
88888e |
*
|
|
Packit |
88888e |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
88888e |
* License along with this library; if not, write to the
|
|
Packit |
88888e |
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
Packit |
88888e |
* Boston, MA 02111-1307, USA.
|
|
Packit |
88888e |
*/
|
|
Packit |
88888e |
#include <config.h>
|
|
Packit |
88888e |
|
|
Packit |
88888e |
#include <memory.h>
|
|
Packit |
88888e |
|
|
Packit |
88888e |
#include <cairo.h>
|
|
Packit |
88888e |
|
|
Packit |
88888e |
#include <gdk/gdkkeysyms.h>
|
|
Packit |
88888e |
#include <gdk/gdkx.h>
|
|
Packit |
88888e |
#include <glib/gi18n-lib.h>
|
|
Packit |
88888e |
|
|
Packit |
88888e |
#include <gkbd-status.h>
|
|
Packit |
88888e |
|
|
Packit |
88888e |
#include <gkbd-desktop-config.h>
|
|
Packit |
88888e |
#include <gkbd-indicator-config.h>
|
|
Packit |
88888e |
#include <gkbd-configuration.h>
|
|
Packit |
88888e |
|
|
Packit |
88888e |
typedef struct _gki_globals {
|
|
Packit |
88888e |
GkbdConfiguration *config;
|
|
Packit |
88888e |
|
|
Packit |
88888e |
gint current_width;
|
|
Packit |
88888e |
gint current_height;
|
|
Packit |
88888e |
int real_width;
|
|
Packit |
88888e |
|
|
Packit |
88888e |
GSList *icons; /* list of GdkPixbuf */
|
|
Packit |
88888e |
} gki_globals;
|
|
Packit |
88888e |
|
|
Packit |
88888e |
static gchar *settings_signal_names[] = {
|
|
Packit |
88888e |
"notify::gtk-theme-name",
|
|
Packit |
88888e |
"notify::gtk-key-theme-name",
|
|
Packit |
88888e |
"notify::gtk-font-name",
|
|
Packit |
88888e |
"notify::font-options",
|
|
Packit |
88888e |
};
|
|
Packit |
88888e |
|
|
Packit |
88888e |
struct _GkbdStatusPrivate {
|
|
Packit |
88888e |
gulong settings_signal_handlers[sizeof (settings_signal_names) /
|
|
Packit |
88888e |
sizeof (settings_signal_names[0])];
|
|
Packit |
88888e |
};
|
|
Packit |
88888e |
|
|
Packit |
88888e |
/* one instance for ALL widgets */
|
|
Packit |
88888e |
static gki_globals globals;
|
|
Packit |
88888e |
|
|
Packit |
88888e |
G_DEFINE_TYPE (GkbdStatus, gkbd_status, GTK_TYPE_STATUS_ICON)
|
|
Packit |
88888e |
|
|
Packit |
88888e |
typedef struct {
|
|
Packit |
88888e |
GtkWidget *tray_icon;
|
|
Packit |
88888e |
} GkbdStatusPrivHack;
|
|
Packit |
88888e |
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_global_init (void);
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_global_term (void);
|
|
Packit |
88888e |
static GdkPixbuf *
|
|
Packit |
88888e |
gkbd_status_prepare_drawing (GkbdStatus * gki, int group);
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_set_current_page_for_group (GkbdStatus * gki, int group);
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_set_current_page (GkbdStatus * gki);
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_reinit_globals (GkbdStatus * gki);
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_cleanup_icons (void);
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_fill_icons (GkbdStatus * gki);
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_set_tooltips (GkbdStatus * gki, const char *str);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
void
|
|
Packit |
88888e |
gkbd_status_set_tooltips (GkbdStatus * gki, const char *str)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
g_assert (str == NULL || g_utf8_validate (str, -1, NULL));
|
|
Packit |
88888e |
|
|
Packit |
88888e |
gtk_status_icon_set_tooltip_text (GTK_STATUS_ICON (gki), str);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
void
|
|
Packit |
88888e |
gkbd_status_cleanup_icons ()
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
while (globals.icons) {
|
|
Packit |
88888e |
if (globals.icons->data)
|
|
Packit |
88888e |
g_object_unref (G_OBJECT (globals.icons->data));
|
|
Packit |
88888e |
globals.icons =
|
|
Packit |
88888e |
g_slist_delete_link (globals.icons, globals.icons);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_fill_icons (GkbdStatus * gki)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
int grp;
|
|
Packit |
88888e |
int total_groups =
|
|
Packit |
88888e |
xkl_engine_get_num_groups (gkbd_configuration_get_xkl_engine
|
|
Packit |
88888e |
(globals.config));
|
|
Packit |
88888e |
|
|
Packit |
88888e |
for (grp = 0; grp < total_groups; grp++) {
|
|
Packit |
88888e |
GdkPixbuf *page = gkbd_status_prepare_drawing (gki, grp);
|
|
Packit |
88888e |
globals.icons = g_slist_append (globals.icons, page);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_activate (GkbdStatus * gki)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
xkl_debug (150, "Mouse button pressed on applet\n");
|
|
Packit |
88888e |
gkbd_configuration_lock_next_group (globals.config);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_render_cairo (GkbdStatusPrivHack * gkh, cairo_t * cr, int group)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
double r, g, b;
|
|
Packit |
88888e |
GdkRGBA *fg_color;
|
|
Packit |
88888e |
gchar *font_family;
|
|
Packit |
88888e |
int font_size;
|
|
Packit |
88888e |
PangoFontDescription *pfd;
|
|
Packit |
88888e |
PangoContext *pcc;
|
|
Packit |
88888e |
PangoLayout *pl;
|
|
Packit |
88888e |
int lwidth, lheight;
|
|
Packit |
88888e |
gchar *layout_name, *lbl_title;
|
|
Packit |
88888e |
cairo_font_options_t *fo;
|
|
Packit |
88888e |
static GHashTable *ln2cnt_map = NULL;
|
|
Packit |
88888e |
|
|
Packit |
88888e |
GkbdIndicatorConfig *ind_cfg =
|
|
Packit |
88888e |
gkbd_configuration_get_indicator_config (globals.config);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
xkl_debug (160, "Rendering cairo for group %d\n", group);
|
|
Packit |
88888e |
if (ind_cfg->background_color != NULL &&
|
|
Packit |
88888e |
ind_cfg->background_color[0] != 0) {
|
|
Packit |
88888e |
if (sscanf
|
|
Packit |
88888e |
(ind_cfg->background_color, "%lg %lg %lg", &r,
|
|
Packit |
88888e |
&g, &b) == 3) {
|
|
Packit |
88888e |
cairo_set_source_rgb (cr, r, g, b);
|
|
Packit |
88888e |
cairo_rectangle (cr, 0, 0, globals.current_width,
|
|
Packit |
88888e |
globals.current_height);
|
|
Packit |
88888e |
cairo_fill (cr);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
g_object_get (gkh->tray_icon, "fg-color", &fg_color, NULL);
|
|
Packit |
88888e |
cairo_set_source_rgb (cr, fg_color->red, fg_color->green, fg_color->blue);
|
|
Packit |
88888e |
gdk_rgba_free (fg_color);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
gkbd_indicator_config_get_font_for_widget (ind_cfg,
|
|
Packit |
88888e |
gkh->tray_icon,
|
|
Packit |
88888e |
&font_family,
|
|
Packit |
88888e |
&font_size);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
if (font_family != NULL && font_family[0] != 0) {
|
|
Packit |
88888e |
cairo_select_font_face (cr, font_family,
|
|
Packit |
88888e |
CAIRO_FONT_SLANT_NORMAL,
|
|
Packit |
88888e |
CAIRO_FONT_WEIGHT_NORMAL);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
pfd = pango_font_description_new ();
|
|
Packit |
88888e |
pango_font_description_set_family (pfd, font_family);
|
|
Packit |
88888e |
pango_font_description_set_style (pfd, PANGO_STYLE_NORMAL);
|
|
Packit |
88888e |
pango_font_description_set_weight (pfd, PANGO_WEIGHT_NORMAL);
|
|
Packit |
88888e |
pango_font_description_set_size (pfd,
|
|
Packit |
88888e |
ind_cfg->font_size * PANGO_SCALE);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
g_free (font_family);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
pcc = pango_cairo_create_context (cr);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
fo = cairo_font_options_copy (gdk_screen_get_font_options
|
|
Packit |
88888e |
(gdk_screen_get_default ()));
|
|
Packit |
88888e |
/* SUBPIXEL antialiasing gives bad results on in-memory images */
|
|
Packit |
88888e |
if (cairo_font_options_get_antialias (fo) ==
|
|
Packit |
88888e |
CAIRO_ANTIALIAS_SUBPIXEL)
|
|
Packit |
88888e |
cairo_font_options_set_antialias (fo,
|
|
Packit |
88888e |
CAIRO_ANTIALIAS_GRAY);
|
|
Packit |
88888e |
pango_cairo_context_set_font_options (pcc, fo);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
pl = pango_layout_new (pcc);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
layout_name =
|
|
Packit |
88888e |
gkbd_configuration_extract_layout_name (globals.config, group);
|
|
Packit |
88888e |
lbl_title =
|
|
Packit |
88888e |
gkbd_configuration_create_label_title (group, &ln2cnt_map,
|
|
Packit |
88888e |
layout_name);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
if (group + 1 ==
|
|
Packit |
88888e |
xkl_engine_get_num_groups (gkbd_configuration_get_xkl_engine
|
|
Packit |
88888e |
(globals.config))) {
|
|
Packit |
88888e |
g_hash_table_destroy (ln2cnt_map);
|
|
Packit |
88888e |
ln2cnt_map = NULL;
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
pango_layout_set_text (pl, lbl_title, -1);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
g_free (lbl_title);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
pango_layout_set_font_description (pl, pfd);
|
|
Packit |
88888e |
pango_layout_get_size (pl, &lwidth, &lheight);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
cairo_move_to (cr,
|
|
Packit |
88888e |
(globals.current_width - lwidth / PANGO_SCALE) / 2,
|
|
Packit |
88888e |
(globals.current_height -
|
|
Packit |
88888e |
lheight / PANGO_SCALE) / 2);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
pango_cairo_show_layout (cr, pl);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
pango_font_description_free (pfd);
|
|
Packit |
88888e |
g_object_unref (pl);
|
|
Packit |
88888e |
g_object_unref (pcc);
|
|
Packit |
88888e |
cairo_font_options_destroy (fo);
|
|
Packit |
88888e |
cairo_destroy (cr);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
globals.real_width = (lwidth / PANGO_SCALE) + 4;
|
|
Packit |
88888e |
if (globals.real_width > globals.current_width)
|
|
Packit |
88888e |
globals.real_width = globals.current_width;
|
|
Packit |
88888e |
if (globals.real_width < globals.current_height)
|
|
Packit |
88888e |
globals.real_width = globals.current_height;
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
static inline guint8
|
|
Packit |
88888e |
convert_color_channel (guint8 src, guint8 alpha)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
return alpha ? ((((guint) src) << 8) - src) / alpha : 0;
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
convert_bgra_to_rgba (guint8 const *src, guint8 * dst, int width,
|
|
Packit |
88888e |
int height, int new_width)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
int xoffset = width - new_width;
|
|
Packit |
88888e |
|
|
Packit |
88888e |
/* *4 */
|
|
Packit |
88888e |
int ptr_step = xoffset << 2;
|
|
Packit |
88888e |
|
|
Packit |
88888e |
int x, y;
|
|
Packit |
88888e |
|
|
Packit |
88888e |
/* / 2 * 4 */
|
|
Packit |
88888e |
src = src + ((xoffset >> 1) << 2);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
for (y = height; --y >= 0; src += ptr_step) {
|
|
Packit |
88888e |
for (x = new_width; --x >= 0;) {
|
|
Packit |
88888e |
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
|
Packit |
88888e |
dst[0] = convert_color_channel (src[2], src[3]);
|
|
Packit |
88888e |
dst[1] = convert_color_channel (src[1], src[3]);
|
|
Packit |
88888e |
dst[2] = convert_color_channel (src[0], src[3]);
|
|
Packit |
88888e |
dst[3] = src[3];
|
|
Packit |
88888e |
#else
|
|
Packit |
88888e |
dst[0] = convert_color_channel (src[1], src[0]);
|
|
Packit |
88888e |
dst[1] = convert_color_channel (src[2], src[0]);
|
|
Packit |
88888e |
dst[2] = convert_color_channel (src[3], src[0]);
|
|
Packit |
88888e |
dst[3] = src[0];
|
|
Packit |
88888e |
#endif
|
|
Packit |
88888e |
dst += 4;
|
|
Packit |
88888e |
src += 4;
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
static GdkPixbuf *
|
|
Packit |
88888e |
gkbd_status_prepare_drawing (GkbdStatus * gki, int group)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
GError *gerror = NULL;
|
|
Packit |
88888e |
char *image_filename;
|
|
Packit |
88888e |
GdkPixbuf *image;
|
|
Packit |
88888e |
|
|
Packit |
88888e |
if (globals.current_width == 0)
|
|
Packit |
88888e |
return NULL;
|
|
Packit |
88888e |
|
|
Packit |
88888e |
if (gkbd_configuration_if_flags_shown (globals.config)) {
|
|
Packit |
88888e |
|
|
Packit |
88888e |
image_filename =
|
|
Packit |
88888e |
gkbd_configuration_get_image_filename (globals.config,
|
|
Packit |
88888e |
group);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
image = gdk_pixbuf_new_from_file_at_size (image_filename,
|
|
Packit |
88888e |
globals.current_width,
|
|
Packit |
88888e |
globals.current_height,
|
|
Packit |
88888e |
&gerror);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
if (image == NULL) {
|
|
Packit |
88888e |
GtkWidget *dialog = gtk_message_dialog_new (NULL,
|
|
Packit |
88888e |
GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
Packit |
88888e |
GTK_MESSAGE_ERROR,
|
|
Packit |
88888e |
GTK_BUTTONS_OK,
|
|
Packit |
88888e |
_
|
|
Packit |
88888e |
("There was an error loading an image: %s"),
|
|
Packit |
88888e |
gerror
|
|
Packit |
88888e |
==
|
|
Packit |
88888e |
NULL ?
|
|
Packit |
88888e |
"Unknown"
|
|
Packit |
88888e |
:
|
|
Packit |
88888e |
gerror->message);
|
|
Packit |
88888e |
g_signal_connect (G_OBJECT (dialog), "response",
|
|
Packit |
88888e |
G_CALLBACK (gtk_widget_destroy),
|
|
Packit |
88888e |
NULL);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
gtk_window_set_resizable (GTK_WINDOW (dialog),
|
|
Packit |
88888e |
FALSE);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
gtk_widget_show (dialog);
|
|
Packit |
88888e |
g_error_free (gerror);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
return NULL;
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
xkl_debug (150,
|
|
Packit |
88888e |
"Image %d[%s] loaded -> %p[%dx%d], alpha: %d\n",
|
|
Packit |
88888e |
group, image_filename, image,
|
|
Packit |
88888e |
gdk_pixbuf_get_width (image),
|
|
Packit |
88888e |
gdk_pixbuf_get_height (image),
|
|
Packit |
88888e |
gdk_pixbuf_get_has_alpha (image));
|
|
Packit |
88888e |
|
|
Packit |
88888e |
return image;
|
|
Packit |
88888e |
} else {
|
|
Packit |
88888e |
cairo_surface_t *cs =
|
|
Packit |
88888e |
cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
|
Packit |
88888e |
globals.current_width,
|
|
Packit |
88888e |
globals.current_height);
|
|
Packit |
88888e |
unsigned char *cairo_data;
|
|
Packit |
88888e |
guchar *pixbuf_data;
|
|
Packit |
88888e |
gkbd_status_render_cairo ((GkbdStatusPrivHack *) GTK_STATUS_ICON (gki)->priv,
|
|
Packit |
88888e |
cairo_create (cs), group);
|
|
Packit |
88888e |
cairo_data = cairo_image_surface_get_data (cs);
|
|
Packit |
88888e |
#if 0
|
|
Packit |
88888e |
char pngfilename[20];
|
|
Packit |
88888e |
g_sprintf (pngfilename, "label%d.png", group);
|
|
Packit |
88888e |
cairo_surface_write_to_png (cs, pngfilename);
|
|
Packit |
88888e |
xkl_debug (150, "file %s is created\n", pngfilename);
|
|
Packit |
88888e |
#endif
|
|
Packit |
88888e |
pixbuf_data =
|
|
Packit |
88888e |
g_new0 (guchar,
|
|
Packit |
88888e |
4 * globals.real_width *
|
|
Packit |
88888e |
globals.current_height);
|
|
Packit |
88888e |
convert_bgra_to_rgba (cairo_data, pixbuf_data,
|
|
Packit |
88888e |
globals.current_width,
|
|
Packit |
88888e |
globals.current_height,
|
|
Packit |
88888e |
globals.real_width);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
cairo_surface_destroy (cs);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
image = gdk_pixbuf_new_from_data (pixbuf_data,
|
|
Packit |
88888e |
GDK_COLORSPACE_RGB,
|
|
Packit |
88888e |
TRUE,
|
|
Packit |
88888e |
8,
|
|
Packit |
88888e |
globals.real_width,
|
|
Packit |
88888e |
globals.current_height,
|
|
Packit |
88888e |
globals.real_width *
|
|
Packit |
88888e |
4,
|
|
Packit |
88888e |
(GdkPixbufDestroyNotify)
|
|
Packit |
88888e |
g_free, NULL);
|
|
Packit |
88888e |
xkl_debug (150,
|
|
Packit |
88888e |
"Image %d created -> %p[%dx%d], alpha: %d\n",
|
|
Packit |
88888e |
group, image, gdk_pixbuf_get_width (image),
|
|
Packit |
88888e |
gdk_pixbuf_get_height (image),
|
|
Packit |
88888e |
gdk_pixbuf_get_has_alpha (image));
|
|
Packit |
88888e |
|
|
Packit |
88888e |
return image;
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
return NULL;
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_update_tooltips (GkbdStatus * gki)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
gchar *buf =
|
|
Packit |
88888e |
gkbd_configuration_get_current_tooltip (globals.config);
|
|
Packit |
88888e |
if (buf != NULL) {
|
|
Packit |
88888e |
gkbd_status_set_tooltips (gki, buf);
|
|
Packit |
88888e |
g_free (buf);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_reinit_globals (GkbdStatus * gki)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
gkbd_status_cleanup_icons ();
|
|
Packit |
88888e |
gkbd_status_fill_icons (gki);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
void
|
|
Packit |
88888e |
gkbd_status_reinit_ui (GkbdStatus * gki)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
gkbd_status_set_current_page (gki);
|
|
Packit |
88888e |
/* To work around combined bugs in notification-area
|
|
Packit |
88888e |
* and GtkStatusIcon, reshow the icon here, to ensure
|
|
Packit |
88888e |
* size changes are picked up.
|
|
Packit |
88888e |
*/
|
|
Packit |
88888e |
gtk_status_icon_set_visible (GTK_STATUS_ICON (gki), FALSE);
|
|
Packit |
88888e |
gtk_status_icon_set_visible (GTK_STATUS_ICON (gki), TRUE);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
/* Should be called once for all widgets */
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_cfg_callback (GkbdConfiguration * configuration)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
GSList *objects;
|
|
Packit |
88888e |
xkl_debug (150, "Config changed: reinit ui\n");
|
|
Packit |
88888e |
objects = gkbd_configuration_get_all_objects (configuration);
|
|
Packit |
88888e |
if (objects)
|
|
Packit |
88888e |
gkbd_status_reinit_globals (objects->data);
|
|
Packit |
88888e |
ForAllObjects (configuration) {
|
|
Packit |
88888e |
gkbd_status_reinit_ui (GKBD_STATUS (gki));
|
|
Packit |
88888e |
} NextObject ()
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
/* Should be called once for all applets */
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_state_callback (GkbdConfiguration * configuration, gint group)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
xkl_debug (150, "Set page to group %d\n", group);
|
|
Packit |
88888e |
ForAllObjects (configuration) {
|
|
Packit |
88888e |
xkl_debug (150, "do repaint for icon %p\n", gki);
|
|
Packit |
88888e |
gkbd_status_set_current_page_for_group (GKBD_STATUS (gki),
|
|
Packit |
88888e |
group);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
NextObject ()
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
void
|
|
Packit |
88888e |
gkbd_status_set_current_page (GkbdStatus * gki)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
XklEngine *engine =
|
|
Packit |
88888e |
gkbd_configuration_get_xkl_engine (globals.config);
|
|
Packit |
88888e |
XklState *cur_state = xkl_engine_get_current_state (engine);
|
|
Packit |
88888e |
if (cur_state->group >= 0)
|
|
Packit |
88888e |
gkbd_status_set_current_page_for_group (gki,
|
|
Packit |
88888e |
cur_state->group);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
void
|
|
Packit |
88888e |
gkbd_status_set_current_page_for_group (GkbdStatus * gki, int group)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
GdkPixbuf *page =
|
|
Packit |
88888e |
GDK_PIXBUF (g_slist_nth_data (globals.icons, group));
|
|
Packit |
88888e |
xkl_debug (150, "Revalidating for group %d: %p\n", group, page);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
if (page == NULL) {
|
|
Packit |
88888e |
xkl_debug (0, "Page for group %d is not ready\n", group);
|
|
Packit |
88888e |
return;
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
gtk_status_icon_set_from_pixbuf (GTK_STATUS_ICON (gki), page);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
gkbd_status_update_tooltips (gki);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
/* Should be called once for all widgets */
|
|
Packit |
88888e |
static GdkFilterReturn
|
|
Packit |
88888e |
gkbd_status_filter_x_evt (GdkXEvent * xev, GdkEvent * event)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
XEvent *xevent = (XEvent *) xev;
|
|
Packit |
88888e |
XklEngine *engine =
|
|
Packit |
88888e |
gkbd_configuration_get_xkl_engine (globals.config);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
xkl_engine_filter_events (engine, xevent);
|
|
Packit |
88888e |
switch (xevent->type) {
|
|
Packit |
88888e |
case ReparentNotify:
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
XReparentEvent *rne = (XReparentEvent *) xev;
|
|
Packit |
88888e |
|
|
Packit |
88888e |
ForAllObjects (globals.config) {
|
|
Packit |
88888e |
guint32 xid =
|
|
Packit |
88888e |
gtk_status_icon_get_x11_window_id
|
|
Packit |
88888e |
(GTK_STATUS_ICON (gki));
|
|
Packit |
88888e |
|
|
Packit |
88888e |
/* compare the indicator's parent window with the even window */
|
|
Packit |
88888e |
if (xid == rne->window) {
|
|
Packit |
88888e |
/* if so - make it transparent... */
|
|
Packit |
88888e |
xkl_engine_set_window_transparent
|
|
Packit |
88888e |
(engine, rne->window, TRUE);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
NextObject ()}
|
|
Packit |
88888e |
break;
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
return GDK_FILTER_CONTINUE;
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
|
|
Packit |
88888e |
/* Should be called once for all widgets */
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_start_listen (void)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
gdk_window_add_filter (NULL, (GdkFilterFunc)
|
|
Packit |
88888e |
gkbd_status_filter_x_evt, NULL);
|
|
Packit |
88888e |
gdk_window_add_filter (gdk_get_default_root_window (),
|
|
Packit |
88888e |
(GdkFilterFunc) gkbd_status_filter_x_evt,
|
|
Packit |
88888e |
NULL);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
/* Should be called once for all widgets */
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_stop_listen (void)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
gdk_window_remove_filter (NULL, (GdkFilterFunc)
|
|
Packit |
88888e |
gkbd_status_filter_x_evt, NULL);
|
|
Packit |
88888e |
gdk_window_remove_filter
|
|
Packit |
88888e |
(gdk_get_default_root_window (),
|
|
Packit |
88888e |
(GdkFilterFunc) gkbd_status_filter_x_evt, NULL);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_size_changed (GkbdStatus * gki, gint size)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
xkl_debug (150, "Size changed to %d\n", size);
|
|
Packit |
88888e |
/* Ignore the initial size 200 that we get before
|
|
Packit |
88888e |
* we are embedded
|
|
Packit |
88888e |
*/
|
|
Packit |
88888e |
if (!gtk_status_icon_is_embedded (GTK_STATUS_ICON (gki)))
|
|
Packit |
88888e |
return;
|
|
Packit |
88888e |
if (globals.current_height != size) {
|
|
Packit |
88888e |
globals.current_height = size;
|
|
Packit |
88888e |
globals.current_width = size * 3 / 2;
|
|
Packit |
88888e |
gkbd_status_reinit_globals (gki);
|
|
Packit |
88888e |
gkbd_status_reinit_ui (gki);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_theme_changed (GtkSettings * settings, GParamSpec * pspec,
|
|
Packit |
88888e |
GkbdStatus * gki)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
xkl_debug (150, "Theme changed\n");
|
|
Packit |
88888e |
gkbd_indicator_config_refresh_style
|
|
Packit |
88888e |
(gkbd_configuration_get_indicator_config (globals.config));
|
|
Packit |
88888e |
gkbd_status_reinit_globals (gki);
|
|
Packit |
88888e |
gkbd_status_reinit_ui (gki);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_init (GkbdStatus * gki)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
int i;
|
|
Packit |
88888e |
|
|
Packit |
88888e |
if (!gkbd_configuration_if_any_object_exists (globals.config))
|
|
Packit |
88888e |
gkbd_status_global_init ();
|
|
Packit |
88888e |
|
|
Packit |
88888e |
gki->priv = g_new0 (GkbdStatusPrivate, 1);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
/* This should give Notification Area a hint about the order of icons */
|
|
Packit |
88888e |
gtk_status_icon_set_name (GTK_STATUS_ICON (gki), "keyboard");
|
|
Packit |
88888e |
|
|
Packit |
88888e |
xkl_debug (100, "The status icon startup process for %p started\n",
|
|
Packit |
88888e |
gki);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
if (gkbd_configuration_get_xkl_engine (globals.config) == NULL) {
|
|
Packit |
88888e |
gkbd_status_set_tooltips (gki,
|
|
Packit |
88888e |
_("XKB initialization error"));
|
|
Packit |
88888e |
return;
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
/* append AFTER all initialization work is finished */
|
|
Packit |
88888e |
gkbd_configuration_append_object (globals.config, G_OBJECT (gki));
|
|
Packit |
88888e |
|
|
Packit |
88888e |
g_signal_connect (gki, "size-changed",
|
|
Packit |
88888e |
G_CALLBACK (gkbd_status_size_changed), NULL);
|
|
Packit |
88888e |
g_signal_connect (gki, "activate",
|
|
Packit |
88888e |
G_CALLBACK (gkbd_status_activate), NULL);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
for (i = sizeof (settings_signal_names) /
|
|
Packit |
88888e |
sizeof (settings_signal_names[0]); --i >= 0;)
|
|
Packit |
88888e |
gki->priv->settings_signal_handlers[i] =
|
|
Packit |
88888e |
g_signal_connect_after (gtk_settings_get_default (),
|
|
Packit |
88888e |
settings_signal_names[i],
|
|
Packit |
88888e |
G_CALLBACK
|
|
Packit |
88888e |
(gkbd_status_theme_changed),
|
|
Packit |
88888e |
gki);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
xkl_debug (100,
|
|
Packit |
88888e |
"The status icon startup process for %p completed\n",
|
|
Packit |
88888e |
gki);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_finalize (GObject * obj)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
int i;
|
|
Packit |
88888e |
GkbdStatus *gki = GKBD_STATUS (obj);
|
|
Packit |
88888e |
xkl_debug (100,
|
|
Packit |
88888e |
"Starting the gnome-kbd-status widget shutdown process for %p\n",
|
|
Packit |
88888e |
gki);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
for (i = sizeof (settings_signal_names) /
|
|
Packit |
88888e |
sizeof (settings_signal_names[0]); --i >= 0;)
|
|
Packit |
88888e |
g_signal_handler_disconnect (gtk_settings_get_default (),
|
|
Packit |
88888e |
gki->
|
|
Packit |
88888e |
priv->settings_signal_handlers
|
|
Packit |
88888e |
[i]);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
/* remove BEFORE all termination work is finished */
|
|
Packit |
88888e |
gkbd_configuration_remove_object (globals.config, G_OBJECT (gki));
|
|
Packit |
88888e |
|
|
Packit |
88888e |
gkbd_status_cleanup_icons ();
|
|
Packit |
88888e |
|
|
Packit |
88888e |
xkl_debug (100,
|
|
Packit |
88888e |
"The instance of gnome-kbd-status successfully finalized\n");
|
|
Packit |
88888e |
|
|
Packit |
88888e |
g_free (gki->priv);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
G_OBJECT_CLASS (gkbd_status_parent_class)->finalize (obj);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
if (!gkbd_configuration_if_any_object_exists (globals.config))
|
|
Packit |
88888e |
gkbd_status_global_term ();
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_global_term (void)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
xkl_debug (100, "*** Last GkbdStatus instance *** \n");
|
|
Packit |
88888e |
gkbd_status_stop_listen ();
|
|
Packit |
88888e |
|
|
Packit |
88888e |
g_object_unref (globals.config);
|
|
Packit |
88888e |
globals.config = NULL;
|
|
Packit |
88888e |
|
|
Packit |
88888e |
xkl_debug (100, "*** Terminated globals *** \n");
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_class_init (GkbdStatusClass * klass)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
xkl_debug (100, "*** First GkbdStatus instance *** \n");
|
|
Packit |
88888e |
|
|
Packit |
88888e |
memset (&globals, 0, sizeof (globals));
|
|
Packit |
88888e |
|
|
Packit |
88888e |
/* Initing vtable */
|
|
Packit |
88888e |
object_class->finalize = gkbd_status_finalize;
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
static void
|
|
Packit |
88888e |
gkbd_status_global_init (void)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
globals.config = gkbd_configuration_get ();
|
|
Packit |
88888e |
|
|
Packit |
88888e |
g_signal_connect (globals.config, "group-changed",
|
|
Packit |
88888e |
G_CALLBACK (gkbd_status_state_callback), NULL);
|
|
Packit |
88888e |
g_signal_connect (globals.config, "changed",
|
|
Packit |
88888e |
G_CALLBACK (gkbd_status_cfg_callback), NULL);
|
|
Packit |
88888e |
|
|
Packit |
88888e |
gkbd_status_start_listen ();
|
|
Packit |
88888e |
|
|
Packit |
88888e |
xkl_debug (100, "*** Inited globals *** \n");
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
GtkStatusIcon *
|
|
Packit |
88888e |
gkbd_status_new (void)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
return
|
|
Packit |
88888e |
GTK_STATUS_ICON (g_object_new (gkbd_status_get_type (), NULL));
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
/**
|
|
Packit |
88888e |
* gkbd_status_get_xkl_engine:
|
|
Packit |
88888e |
*
|
|
Packit |
88888e |
* Returns: (transfer none): The engine shared by all GkbdStatus objects
|
|
Packit |
88888e |
*/
|
|
Packit |
88888e |
XklEngine *
|
|
Packit |
88888e |
gkbd_status_get_xkl_engine ()
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
return gkbd_configuration_get_xkl_engine (globals.config);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
/**
|
|
Packit |
88888e |
* gkbd_status_get_group_names:
|
|
Packit |
88888e |
*
|
|
Packit |
88888e |
* Returns: (transfer none) (array zero-terminated=1): List of group names
|
|
Packit |
88888e |
*/
|
|
Packit |
88888e |
gchar **
|
|
Packit |
88888e |
gkbd_status_get_group_names ()
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
return (gchar **)
|
|
Packit |
88888e |
gkbd_configuration_get_group_names (globals.config);
|
|
Packit |
88888e |
}
|
|
Packit |
88888e |
|
|
Packit |
88888e |
gchar *
|
|
Packit |
88888e |
gkbd_status_get_image_filename (guint group)
|
|
Packit |
88888e |
{
|
|
Packit |
88888e |
return gkbd_configuration_get_image_filename (globals.config,
|
|
Packit |
88888e |
group);
|
|
Packit |
88888e |
}
|