aboutsummaryrefslogtreecommitdiff
path: root/.pc/replace-deprecated-gtk.patch
diff options
context:
space:
mode:
Diffstat (limited to '.pc/replace-deprecated-gtk.patch')
-rw-r--r--.pc/replace-deprecated-gtk.patch/eggtrayicon.c380
-rw-r--r--.pc/replace-deprecated-gtk.patch/fbxkb.c538
2 files changed, 918 insertions, 0 deletions
diff --git a/.pc/replace-deprecated-gtk.patch/eggtrayicon.c b/.pc/replace-deprecated-gtk.patch/eggtrayicon.c
new file mode 100644
index 0000000..c167ed3
--- /dev/null
+++ b/.pc/replace-deprecated-gtk.patch/eggtrayicon.c
@@ -0,0 +1,380 @@
+/* eggtrayicon.c
+ *
+ * Contributed by Line72 <line72@line72.homelinux.com>
+ *
+ * Thanks to:
+ * Anders Carlsson <andersca@gnu.org>
+ *
+ */
+
+#include <string.h>
+#include <gdk/gdkx.h>
+#include "eggtrayicon.h"
+
+#define SYSTEM_TRAY_REQUEST_DOCK 0
+#define SYSTEM_TRAY_BEGIN_MESSAGE 1
+#define SYSTEM_TRAY_CANCEL_MESSAGE 2
+
+static GtkPlugClass *parent_class = NULL;
+
+static void egg_tray_icon_init (EggTrayIcon *icon);
+static void egg_tray_icon_class_init (EggTrayIconClass *klass);
+
+static void egg_tray_icon_unrealize (GtkWidget *widget);
+
+static void egg_tray_icon_update_manager_window (EggTrayIcon *icon);
+
+GType
+egg_tray_icon_get_type (void)
+{
+ static GType our_type = 0;
+
+ our_type = g_type_from_name("EggTrayIcon");
+
+ if (our_type == 0)
+ {
+ static const GTypeInfo our_info =
+ {
+ sizeof (EggTrayIconClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) egg_tray_icon_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (EggTrayIcon),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_tray_icon_init
+ };
+
+ our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, 0);
+ }
+ else if (parent_class == NULL) {
+ /* we're reheating the old class from a previous instance - engage ugly hack =( */
+ egg_tray_icon_class_init((EggTrayIconClass *)g_type_class_peek(our_type));
+ }
+
+ return our_type;
+}
+
+static void
+egg_tray_icon_init (EggTrayIcon *icon)
+{
+ icon->stamp = 1;
+
+ gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK);
+}
+
+static void
+egg_tray_icon_class_init (EggTrayIconClass *klass)
+{
+ GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ widget_class->unrealize = egg_tray_icon_unrealize;
+}
+
+static GdkFilterReturn
+egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data)
+{
+ EggTrayIcon *icon = user_data;
+ XEvent *xev = (XEvent *)xevent;
+
+ if (xev->xany.type == ClientMessage &&
+ xev->xclient.message_type == icon->manager_atom &&
+ xev->xclient.data.l[1] == icon->selection_atom)
+ {
+ egg_tray_icon_update_manager_window (icon);
+ }
+ else if (xev->xany.window == icon->manager_window)
+ {
+ if (xev->xany.type == DestroyNotify)
+ {
+ egg_tray_icon_update_manager_window (icon);
+ }
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+egg_tray_icon_unrealize (GtkWidget *widget)
+{
+ EggTrayIcon *icon = EGG_TRAY_ICON (widget);
+ GdkWindow *root_window;
+
+ if (icon->manager_window != None)
+ {
+ GdkWindow *gdkwin;
+
+#if HAVE_GTK_MULTIHEAD
+ gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (widget),
+ icon->manager_window);
+#else
+ gdkwin = gdk_window_lookup (icon->manager_window);
+#endif
+
+ gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+ }
+
+#if HAVE_GTK_MULTIHEAD
+ root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget));
+#else
+ root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ());
+#endif
+
+ gdk_window_remove_filter (root_window, egg_tray_icon_manager_filter, icon);
+
+ if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+ (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void
+egg_tray_icon_send_manager_message (EggTrayIcon *icon,
+ long message,
+ Window window,
+ long data1,
+ long data2,
+ long data3)
+{
+ XClientMessageEvent ev;
+ Display *display;
+
+ ev.type = ClientMessage;
+ ev.window = window;
+ ev.message_type = icon->system_tray_opcode_atom;
+ ev.format = 32;
+ ev.data.l[0] = gdk_x11_get_server_time (GTK_WIDGET (icon)->window);
+ ev.data.l[1] = message;
+ ev.data.l[2] = data1;
+ ev.data.l[3] = data2;
+ ev.data.l[4] = data3;
+
+#if HAVE_GTK_MULTIHEAD
+ display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+#else
+ display = gdk_x11_get_default_xdisplay();
+#endif
+
+ gdk_error_trap_push ();
+ XSendEvent (display,
+ icon->manager_window, False, NoEventMask, (XEvent *)&ev);
+ XSync (display, False);
+ gdk_error_trap_pop ();
+}
+
+static void
+egg_tray_icon_send_dock_request (EggTrayIcon *icon)
+{
+ egg_tray_icon_send_manager_message (icon,
+ SYSTEM_TRAY_REQUEST_DOCK,
+ icon->manager_window,
+ gtk_plug_get_id (GTK_PLUG (icon)),
+ 0, 0);
+}
+
+static void
+egg_tray_icon_update_manager_window (EggTrayIcon *icon)
+{
+ Display *xdisplay;
+
+#if HAVE_GTK_MULTIHEAD
+ xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+#else
+ xdisplay = gdk_x11_get_default_xdisplay();
+#endif
+
+ if (icon->manager_window != None)
+ {
+ GdkWindow *gdkwin;
+
+#if HAVE_GTK_MULTIHEAD
+ gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
+ icon->manager_window);
+#else
+ gdkwin = gdk_window_lookup (icon->manager_window);
+#endif
+
+ gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+ }
+
+ XGrabServer (xdisplay);
+
+ icon->manager_window = XGetSelectionOwner (xdisplay,
+ icon->selection_atom);
+
+ if (icon->manager_window != None)
+ XSelectInput (xdisplay,
+ icon->manager_window, StructureNotifyMask);
+
+ XUngrabServer (xdisplay);
+ XFlush (xdisplay);
+
+ if (icon->manager_window != None)
+ {
+ GdkWindow *gdkwin;
+
+#if HAVE_GTK_MULTIHEAD
+ gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
+ icon->manager_window);
+#else
+ gdkwin = gdk_window_lookup (icon->manager_window);
+#endif
+
+ gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+
+ /* Send a request that we'd like to dock */
+ egg_tray_icon_send_dock_request (icon);
+ }
+}
+
+EggTrayIcon *
+egg_tray_icon_new_for_xscreen (Screen *xscreen, const char *name)
+{
+ EggTrayIcon *icon;
+ char buffer[256];
+ GdkWindow *root_window;
+
+ g_return_val_if_fail (xscreen != NULL, NULL);
+
+ icon = g_object_new (EGG_TYPE_TRAY_ICON, NULL);
+ gtk_window_set_title (GTK_WINDOW (icon), name);
+
+#if HAVE_GTK_MULTIHEAD
+ /* FIXME: this code does not compile, screen is undefined. Now try
+ * getting the GdkScreen from xscreen (:. Dunno how to solve this
+ * (there is prolly some easy way I cant think of right now)
+ */
+ gtk_plug_construct_for_display (GTK_PLUG (icon),
+ gdk_screen_get_display (screen), 0);
+
+#else
+ gtk_plug_construct (GTK_PLUG (icon), 0);
+#endif
+
+ gtk_widget_realize (GTK_WIDGET (icon));
+
+
+ /* Now see if there's a manager window around */
+ g_snprintf (buffer, sizeof (buffer),
+ "_NET_SYSTEM_TRAY_S%d",
+ XScreenNumberOfScreen (xscreen));
+
+ icon->selection_atom = XInternAtom (DisplayOfScreen (xscreen),
+ buffer, False);
+
+ icon->manager_atom = XInternAtom (DisplayOfScreen (xscreen),
+ "MANAGER", False);
+
+ icon->system_tray_opcode_atom = XInternAtom (DisplayOfScreen (xscreen),
+ "_NET_SYSTEM_TRAY_OPCODE", False);
+
+ egg_tray_icon_update_manager_window (icon);
+
+#if HAVE_GTK_MULTIHEAD
+ root_window = gdk_screen_get_root_window (gtk_widget_get_screen (screen));
+#else
+ root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ());
+#endif
+
+ /* Add a root window filter so that we get changes on MANAGER */
+ gdk_window_add_filter (root_window,
+ egg_tray_icon_manager_filter, icon);
+
+ return icon;
+}
+
+#if HAVE_GTK_MULTIHEAD
+EggTrayIcon *
+egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name)
+{
+ EggTrayIcon *icon;
+ char buffer[256];
+
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+ return egg_tray_icon_new_for_xscreen (GDK_SCREEN_XSCREEN (screen), name);
+}
+#endif
+
+EggTrayIcon*
+egg_tray_icon_new (const gchar *name)
+{
+ return egg_tray_icon_new_for_xscreen (DefaultScreenOfDisplay (gdk_x11_get_default_xdisplay()), name);
+}
+
+guint
+egg_tray_icon_send_message (EggTrayIcon *icon,
+ gint timeout,
+ const gchar *message,
+ gint len)
+{
+ guint stamp;
+
+ g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0);
+ g_return_val_if_fail (timeout >= 0, 0);
+ g_return_val_if_fail (message != NULL, 0);
+
+ if (icon->manager_window == None)
+ return 0;
+
+ if (len < 0)
+ len = strlen (message);
+
+ stamp = icon->stamp++;
+
+ /* Get ready to send the message */
+ egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE,
+ (Window)gtk_plug_get_id (GTK_PLUG (icon)),
+ timeout, len, stamp);
+
+ /* Now to send the actual message */
+ gdk_error_trap_push ();
+ while (len > 0)
+ {
+ XClientMessageEvent ev;
+ Display *xdisplay;
+
+#if HAVE_GTK_MULTIHEAD
+ xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+#else
+ xdisplay = gdk_x11_get_default_xdisplay();
+#endif
+
+ ev.type = ClientMessage;
+ ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon));
+ ev.format = 8;
+ ev.message_type = XInternAtom (xdisplay,
+ "_NET_SYSTEM_TRAY_MESSAGE_DATA", False);
+ if (len > 20)
+ {
+ memcpy (&ev.data, message, 20);
+ len -= 20;
+ message += 20;
+ }
+ else
+ {
+ memcpy (&ev.data, message, len);
+ len = 0;
+ }
+
+ XSendEvent (xdisplay,
+ icon->manager_window, False, StructureNotifyMask, (XEvent *)&ev);
+ XSync (xdisplay, False);
+ }
+ gdk_error_trap_pop ();
+
+ return stamp;
+}
+
+void
+egg_tray_icon_cancel_message (EggTrayIcon *icon,
+ guint id)
+{
+ g_return_if_fail (EGG_IS_TRAY_ICON (icon));
+ g_return_if_fail (id > 0);
+
+ egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE,
+ (Window)gtk_plug_get_id (GTK_PLUG (icon)),
+ id, 0, 0);
+}
diff --git a/.pc/replace-deprecated-gtk.patch/fbxkb.c b/.pc/replace-deprecated-gtk.patch/fbxkb.c
new file mode 100644
index 0000000..482574b
--- /dev/null
+++ b/.pc/replace-deprecated-gtk.patch/fbxkb.c
@@ -0,0 +1,538 @@
+
+
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <locale.h>
+#include <string.h>
+#include <signal.h>
+
+#include <X11/Xlib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include <X11/XKBlib.h>
+
+#include "config.h"
+#include "eggtrayicon.h"
+#include "version.h"
+
+static gchar version[] = VERSION;
+
+
+//#define DEBUG
+#include "dbg.h"
+
+/******************************************************************
+ * TYPEDEFS *
+ ******************************************************************/
+typedef struct _kbd_info {
+ gchar *sym;
+ gchar *name;
+ GdkPixbuf *flag;
+} kbd_info;
+
+#define IMGPREFIX PREFIX "/share/fbxkb/images/"
+/******************************************************************
+ * GLOBAL VARSIABLES *
+ ******************************************************************/
+
+/* X11 common stuff */
+static Atom a_XKB_RULES_NAMES;
+static Display *dpy;
+static int xkb_event_type;
+
+/* internal state mashine */
+static int cur_group;
+static int ngroups;
+static GHashTable *sym2pix;
+static kbd_info group2info[XkbNumKbdGroups];
+static GdkPixbuf *zzflag;
+static int active;
+/* gtk gui */
+static GtkWidget *flag_menu;
+static GtkWidget *app_menu;
+static GtkWidget *docklet;
+static GtkWidget *image;
+static GtkWidget *about_dialog = NULL;
+/******************************************************************
+ * DECLARATION *
+ ******************************************************************/
+
+static int init();
+static void read_kbd_description();
+static void update_flag(int no);
+static GdkFilterReturn filter( XEvent *xev, GdkEvent *event, gpointer data);
+static void Xerror_handler(Display * d, XErrorEvent * ev);
+static GdkPixbuf *sym2flag(char *sym);
+static void flag_menu_create();
+static void flag_menu_destroy();
+static void flag_menu_activated(GtkWidget *widget, gpointer data);
+static void app_menu_create();
+static void app_menu_about(GtkWidget *widget, gpointer data);
+static void app_menu_exit(GtkWidget *widget, gpointer data);
+
+static int docklet_create();
+
+static int create_all();
+
+/******************************************************************
+ * CODE *
+ ******************************************************************/
+
+/******************************************************************
+ * gtk gui *
+ ******************************************************************/
+static void
+flag_menu_create()
+{
+ int i;
+ GdkPixbuf *flag;
+ GtkWidget *mi, *img;
+ //static GString *s = NULL;;
+
+ ENTER;
+ flag_menu = gtk_menu_new();
+ for (i = 0; i < ngroups; i++) {
+ mi = gtk_image_menu_item_new_with_label(
+ group2info[i].name ? group2info[i].name : group2info[i].sym);
+ g_signal_connect(G_OBJECT(mi), "activate", (GCallback)flag_menu_activated, GINT_TO_POINTER(i));
+ gtk_menu_shell_append (GTK_MENU_SHELL (flag_menu), mi);
+ gtk_widget_show (mi);
+ flag = sym2flag(group2info[i].sym);
+ img = gtk_image_new_from_pixbuf(flag);
+ gtk_widget_show(img);
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
+ }
+ RET();
+}
+
+static void
+flag_menu_destroy()
+{
+ if (flag_menu) {
+ gtk_widget_destroy(flag_menu);
+ flag_menu = NULL;
+ }
+}
+
+static void
+flag_menu_activated(GtkWidget *widget, gpointer data)
+{
+ int i;
+
+ ENTER;
+ i = GPOINTER_TO_INT(data);
+ DBG("asking %d group\n", i);
+ XkbLockGroup(dpy, XkbUseCoreKbd, i);
+ RET();
+}
+
+static void
+app_menu_create()
+{
+ GtkWidget *mi;
+
+ ENTER;
+ app_menu = gtk_menu_new();
+
+ mi = gtk_image_menu_item_new_from_stock(GTK_STOCK_DIALOG_INFO, NULL);
+ g_signal_connect(G_OBJECT(mi), "activate", (GCallback)app_menu_about, NULL);
+ gtk_menu_shell_append (GTK_MENU_SHELL (app_menu), mi);
+ gtk_widget_show (mi);
+
+
+ mi = gtk_menu_item_new ();
+ gtk_widget_show (mi);
+ gtk_menu_shell_append (GTK_MENU_SHELL (app_menu), mi);
+ gtk_widget_set_sensitive (mi, FALSE);
+
+ mi = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL);
+ g_signal_connect(G_OBJECT(mi), "activate", (GCallback)app_menu_exit, NULL);
+ gtk_menu_shell_append (GTK_MENU_SHELL (app_menu), mi);
+ gtk_widget_show (mi);
+ RET();
+
+}
+
+static void
+app_menu_about(GtkWidget *widget, gpointer data)
+{
+ ENTER;
+ if (!about_dialog) {
+ about_dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_CLOSE,
+ "fbxkb %s\nX11 Keyboard switcher\nAuthor: Anatoly Asviyan <aanatoly@users.sf.net>", version);
+ /* Destroy the dialog when the user responds to it (e.g. clicks a button) */
+ g_signal_connect_swapped (about_dialog, "response",
+ G_CALLBACK (gtk_widget_hide),
+ about_dialog);
+ }
+ gtk_widget_show (about_dialog);
+ RET();
+}
+
+
+static void
+app_menu_exit(GtkWidget *widget, gpointer data)
+{
+ ENTER;
+ exit(0);
+ RET();
+}
+
+
+static void docklet_embedded(GtkWidget *widget, void *data)
+{
+ ENTER;
+ RET();
+}
+
+static void docklet_destroyed(GtkWidget *widget, void *data)
+{
+ ENTER;
+ //g_object_unref(G_OBJECT(docklet));
+ docklet = NULL;
+ g_idle_add(create_all, NULL);
+ RET();
+}
+
+
+void docklet_clicked(GtkWidget *button, GdkEventButton *event, void *data)
+{
+ //GtkWidget *menu;
+ ENTER;
+ if (event->type != GDK_BUTTON_PRESS)
+ RET();
+
+ if (event->button == 1) {
+ int no;
+
+ no = (cur_group + 1) % ngroups;
+ DBG("no=%d\n", no);
+ XkbLockGroup(dpy, XkbUseCoreKbd, no);
+ } else if (event->button == 2) {
+ gtk_menu_popup(GTK_MENU(flag_menu), NULL, NULL, NULL, NULL, event->button, event->time);
+ } else if (event->button == 3) {
+ gtk_menu_popup(GTK_MENU(app_menu), NULL, NULL, NULL, NULL, event->button, event->time);
+ }
+ RET();
+}
+
+static int
+docklet_create()
+{
+ GtkWidget *box;
+
+ ENTER;
+ docklet = (GtkWidget*)egg_tray_icon_new("fbxkb");
+ box = gtk_event_box_new();
+ image = gtk_image_new();
+ //image = gtk_image_new();
+ g_signal_connect(G_OBJECT(docklet), "embedded", G_CALLBACK(docklet_embedded), NULL);
+ g_signal_connect(G_OBJECT(docklet), "destroy", G_CALLBACK(docklet_destroyed), NULL);
+ g_signal_connect(G_OBJECT(box), "button-press-event", G_CALLBACK(docklet_clicked), NULL);
+
+ gtk_container_set_border_width(GTK_CONTAINER(box), 0);
+
+ gtk_container_add(GTK_CONTAINER(box), image);
+ gtk_container_add(GTK_CONTAINER(docklet), box);
+ gtk_widget_show_all(GTK_WIDGET(docklet));
+
+ RET(1);
+}
+
+
+/******************************************************************
+ * internal state machine *
+ ******************************************************************/
+static gboolean
+my_str_equal (gchar *a, gchar *b)
+{
+ return (a[0] == b[0] && a[1] == b[1]);
+}
+
+
+static GdkPixbuf *
+sym2flag(char *sym)
+{
+ GdkPixbuf *flag;
+ static GString *s = NULL;
+
+ ENTER;
+ g_assert(sym != NULL && strlen(sym) > 1);
+ flag = g_hash_table_lookup(sym2pix, sym);
+ if (flag)
+ RET(flag);
+
+ if (!s)
+ s = g_string_new(IMGPREFIX "tt.png");
+ s->str[s->len-6] = sym[0];
+ s->str[s->len-5] = sym[1];
+ flag = gdk_pixbuf_new_from_file_at_size(s->str, 24, 24, NULL);
+ if (!flag)
+ RET(zzflag);
+ g_hash_table_insert(sym2pix, g_strdup(sym), flag);
+ RET(flag);
+}
+
+
+static void
+read_kbd_description()
+{
+ unsigned int mask;
+ XkbDescRec *kbd_desc_ptr;
+ XkbStateRec xkb_state;
+ Atom sym_name_atom;
+ int i;
+
+ ENTER;
+ // clean up
+ cur_group = ngroups = 0;
+ for (i = 0; i < XkbNumKbdGroups; i++) {
+ g_free(group2info[i].sym);
+ g_free(group2info[i].name);
+ /*
+ if (group2info[i].flag)
+ g_object_unref(G_OBJECT(group2info[i].flag));
+ */
+ }
+ bzero(group2info, sizeof(group2info));
+
+ // get kbd info
+ mask = XkbControlsMask | XkbServerMapMask;
+ kbd_desc_ptr = XkbAllocKeyboard();
+ if (!kbd_desc_ptr) {
+ ERR("can't alloc kbd info\n");
+ goto out_us;
+ }
+ kbd_desc_ptr->dpy = dpy;
+ if (XkbGetControls(dpy, XkbAllControlsMask, kbd_desc_ptr) != Success) {
+ ERR("can't get Xkb controls\n");
+ goto out;
+ }
+ ngroups = kbd_desc_ptr->ctrls->num_groups;
+ if (ngroups < 1)
+ goto out;
+ if (XkbGetState(dpy, XkbUseCoreKbd, &xkb_state) != Success) {
+ ERR("can't get Xkb state\n");
+ goto out;
+ }
+ cur_group = xkb_state.group;
+ DBG("cur_group = %d ngroups = %d\n", cur_group, ngroups);
+ g_assert(cur_group < ngroups);
+
+ if (XkbGetNames(dpy, XkbSymbolsNameMask, kbd_desc_ptr) != Success) {
+ ERR("can't get Xkb symbol description\n");
+ goto out;
+ }
+ if (XkbGetNames(dpy, XkbGroupNamesMask, kbd_desc_ptr) != Success)
+ ERR("Failed to get keyboard description\n");
+ g_assert(kbd_desc_ptr->names);
+ sym_name_atom = kbd_desc_ptr->names->symbols;
+
+ // parse kbd info
+ if (sym_name_atom != None) {
+ char *sym_name, *tmp, *tok;
+ int no;
+
+ sym_name = XGetAtomName(dpy, sym_name_atom);
+ if (!sym_name)
+ goto out;
+ /* to know how sym_name might look like do this:
+ * % xlsatoms | grep pc
+ * 150 pc/pc(pc101)+pc/us+pc/ru(phonetic):2+group(shift_toggle)
+ * 470 pc(pc105)+us+ru(phonetic):2+il(phonetic):3+group(shifts_toggle)+group(switch)
+ */
+ DBG("sym_name=%s\n", sym_name);
+ for (tok = strtok(sym_name, "+"); tok; tok = strtok(NULL, "+")) {
+ DBG("tok=%s\n", tok);
+ tmp = strchr(tok, ':');
+ if (tmp) {
+ if (sscanf(tmp+1, "%d", &no) != 1)
+ ERR("can't read kbd number\n");
+ no--;
+ *tmp = 0;
+ } else {
+ no = 0;
+ }
+ for (tmp = tok; isalpha(*tmp); tmp++);
+ *tmp = 0;
+
+ DBG("map=%s no=%d\n", tok, no);
+ if (!strcmp(tok, "pc") || (strlen(tok) != 2))
+ continue;
+
+ g_assert((no >= 0) && (no < ngroups));
+ if (group2info[no].sym != NULL) {
+ ERR("xkb group #%d is already defined\n", no);
+ }
+ group2info[no].sym = g_strdup(tok);
+ group2info[no].flag = sym2flag(tok);
+ group2info[no].name = XGetAtomName(dpy, kbd_desc_ptr->names->groups[no]);
+ }
+ XFree(sym_name);
+ }
+ out:
+ XkbFreeKeyboard(kbd_desc_ptr, 0, True);
+ // sanity check: group numbering must be continous
+ for (i = 0; (i < XkbNumKbdGroups) && (group2info[i].sym != NULL); i++);
+ if (i != ngroups) {
+ ERR("kbd group numbering is not continous\n");
+ ERR("run 'xlsatoms | grep pc' to know what hapends\n");
+ exit(1);
+ }
+ out_us:
+ //if no groups were defined just add default 'us' kbd group
+ if (!ngroups) {
+ ngroups = 1;
+ cur_group = 0;
+ group2info[0].sym = g_strdup("us");
+ group2info[0].flag = sym2flag("us");
+ group2info[0].name = NULL;
+ ERR("no kbd groups defined. adding default 'us' group\n");
+ }
+ RET();
+}
+
+
+
+static void update_flag(int no)
+{
+ kbd_info *k = &group2info[no];
+ ENTER;
+ g_assert(k != NULL);
+ DBG("k->sym=%s\n", k->sym);
+ gtk_image_set_from_pixbuf(GTK_IMAGE(image), k->flag);
+ RET();
+}
+
+
+
+static GdkFilterReturn
+filter( XEvent *xev, GdkEvent *event, gpointer data)
+{
+ ENTER;
+ if (!active)
+ RET(GDK_FILTER_CONTINUE);
+
+ if (xev->type == xkb_event_type) {
+ XkbEvent *xkbev = (XkbEvent *) xev;
+ DBG("XkbTypeEvent %d \n", xkbev->any.xkb_type);
+ if (xkbev->any.xkb_type == XkbStateNotify) {
+ DBG("XkbStateNotify: %d\n", xkbev->state.group);
+ cur_group = xkbev->state.group;
+ if (cur_group < ngroups)
+ update_flag(cur_group);
+ } else if (xkbev->any.xkb_type == XkbNewKeyboardNotify) {
+ DBG("XkbNewKeyboardNotify\n");
+ read_kbd_description();
+ //cur_group = 0;
+ update_flag(cur_group);
+ flag_menu_destroy();
+ flag_menu_create();
+ }
+ RET(GDK_FILTER_REMOVE);
+ }
+ RET(GDK_FILTER_CONTINUE);
+}
+
+static int
+init()
+{
+ int dummy;
+
+ ENTER;
+ sym2pix = g_hash_table_new(g_str_hash, (GEqualFunc) my_str_equal);
+ dpy = gdk_x11_get_default_xdisplay();
+ a_XKB_RULES_NAMES = XInternAtom(dpy, "_XKB_RULES_NAMES", False);
+ if (a_XKB_RULES_NAMES == None)
+ ERR("_XKB_RULES_NAMES - can't get this atom\n");
+
+ if (!XkbQueryExtension(dpy, &dummy, &xkb_event_type, &dummy, &dummy, &dummy))
+ RET(0);
+ DBG("xkb_event_type=%d\n", xkb_event_type);
+ XkbSelectEventDetails(dpy, XkbUseCoreKbd, XkbStateNotify,
+ XkbAllStateComponentsMask, XkbGroupStateMask);
+ gdk_window_add_filter(NULL, (GdkFilterFunc)filter, NULL);
+ zzflag = gdk_pixbuf_new_from_file_at_size(IMGPREFIX "zz.png", 24, 24, NULL);
+ RET(1);
+}
+
+#if 0
+
+
+static void
+app_menu_destroy()
+{
+ ENTER;
+ if (app_menu) {
+ gtk_widget_destroy(app_menu);
+ app_menu = NULL;
+ }
+ RET();
+}
+
+static void
+destroy_all()
+{
+ active = 0;
+ gdk_window_remove_filter(NULL, (GdkFilterFunc)filter, NULL);
+ XkbSelectEventDetails(dpy, XkbUseCoreKbd, XkbStateNotify,
+ XkbAllStateComponentsMask, 0UL);
+ flag_menu_destroy();
+ app_menu_destroy();
+}
+#endif
+
+static int
+create_all()
+{
+ ENTER;
+ read_kbd_description();
+ docklet_create();
+ flag_menu_create();
+ app_menu_create();
+ update_flag(cur_group);
+ active = 1;
+ RET(FALSE);// FALSE will remove us from idle func
+}
+
+int
+main(int argc, char *argv[], char *env[])
+{
+ ENTER;
+ setlocale(LC_CTYPE, "");
+ gtk_set_locale();
+ gtk_init(&argc, &argv);
+ XSetLocaleModifiers("");
+ XSetErrorHandler((XErrorHandler) Xerror_handler);
+
+ if (!init())
+ ERR("can't init. exiting\n");
+ create_all();
+ gtk_main ();
+ RET(0);
+}
+
+
+/********************************************************************/
+
+void
+Xerror_handler(Display * d, XErrorEvent * ev)
+{
+ char buf[256];
+
+ ENTER;
+ XGetErrorText(gdk_x11_get_default_xdisplay(), ev->error_code, buf, 256);
+ ERR( "fbxkb : X error: %s\n", buf);
+ RET();
+}
bgstack15