summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey V. Udaltsov <svu@src.gnome.org>2006-09-27 20:27:09 +0000
committerSergey V. Udaltsov <svu@src.gnome.org>2006-09-27 20:27:09 +0000
commit7699e660c678df45a7d0ce2edaec1611e210d583 (patch)
treea1e92bed7f668a851e276ec79a9bca846d70a2a1
downloadlibgnomekbd-7699e660c678df45a7d0ce2edaec1611e210d583.tar.gz
Initial revision
-rw-r--r--.anjuta/anjuta.session9
-rw-r--r--.anjuta/default.anjuta8
-rw-r--r--.anjuta/dock-layout.xml2
-rw-r--r--.tm_project2.cachebin0 -> 52012 bytes
-rw-r--r--AUTHORS1
-rw-r--r--ChangeLog0
-rw-r--r--ChangeLog.libgswitchit269
-rw-r--r--ChangeLog.libkbdraw295
-rw-r--r--Makefile.am18
-rw-r--r--NEWS0
-rw-r--r--README0
-rw-r--r--README.cvs1
-rwxr-xr-xautogen.sh25
-rw-r--r--capplet/Makefile.am47
-rw-r--r--capplet/gkbd-indicator-plugins-add.c190
-rw-r--r--capplet/gkbd-indicator-plugins-capplet.c380
-rw-r--r--capplet/gkbd-indicator-plugins-capplet.desktop.in.in15
-rw-r--r--capplet/gkbd-indicator-plugins-capplet.h62
-rw-r--r--capplet/gkbd-indicator-plugins.glade532
-rw-r--r--configure.in106
-rw-r--r--libgnomekbd.anjuta54
-rw-r--r--libgnomekbd.pc.in10
-rw-r--r--libgnomekbd/.indent.pro2
-rw-r--r--libgnomekbd/Makefile.am125
-rw-r--r--libgnomekbd/backup/Makefile718
-rw-r--r--libgnomekbd/backup/Makefile.am91
-rw-r--r--libgnomekbd/backup/gkb-config-private.h98
-rw-r--r--libgnomekbd/backup/gkb-config-registry.c166
-rw-r--r--libgnomekbd/backup/gkb-config-registry.h44
-rw-r--r--libgnomekbd/backup/gkb-config-registry.xml14
-rw-r--r--libgnomekbd/backup/gkb-desktop-config.c403
-rw-r--r--libgnomekbd/backup/gkb-desktop-config.h96
-rw-r--r--libgnomekbd/backup/gkb-indicator-config.c360
-rw-r--r--libgnomekbd/backup/gkb-indicator-config.h86
-rw-r--r--libgnomekbd/backup/gkb-indicator-marshal.list1
-rw-r--r--libgnomekbd/backup/gkb-indicator-plugin-manager.c391
-rw-r--r--libgnomekbd/backup/gkb-indicator-plugin-manager.h110
-rw-r--r--libgnomekbd/backup/gkb-indicator-plugin.h120
-rw-r--r--libgnomekbd/backup/gkb-indicator.c826
-rw-r--r--libgnomekbd/backup/gkb-indicator.h77
-rw-r--r--libgnomekbd/backup/gkb-keyboard-config.c822
-rw-r--r--libgnomekbd/backup/gkb-keyboard-config.h123
-rw-r--r--libgnomekbd/backup/gkb-keyboard-drawing-marshal.list2
-rw-r--r--libgnomekbd/backup/gkb-keyboard-drawing.c1845
-rw-r--r--libgnomekbd/backup/gkb-keyboard-drawing.h185
-rw-r--r--libgnomekbd/backup/gkb-util.c149
-rw-r--r--libgnomekbd/backup/gkb-util.h30
-rw-r--r--libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in193
-rw-r--r--libgnomekbd/gkbd-config-private.h99
-rw-r--r--libgnomekbd/gkbd-config-registry.c166
-rw-r--r--libgnomekbd/gkbd-config-registry.h44
-rw-r--r--libgnomekbd/gkbd-config-registry.xml14
-rw-r--r--libgnomekbd/gkbd-desktop-config.c400
-rw-r--r--libgnomekbd/gkbd-desktop-config.h97
-rw-r--r--libgnomekbd/gkbd-indicator-config.c361
-rw-r--r--libgnomekbd/gkbd-indicator-config.h89
-rw-r--r--libgnomekbd/gkbd-indicator-marshal.list1
-rw-r--r--libgnomekbd/gkbd-indicator-plugin-manager.c404
-rw-r--r--libgnomekbd/gkbd-indicator-plugin-manager.h113
-rw-r--r--libgnomekbd/gkbd-indicator-plugin.h122
-rw-r--r--libgnomekbd/gkbd-indicator.c825
-rw-r--r--libgnomekbd/gkbd-indicator.h77
-rw-r--r--libgnomekbd/gkbd-keyboard-config.c825
-rw-r--r--libgnomekbd/gkbd-keyboard-config.h120
-rw-r--r--libgnomekbd/gkbd-keyboard-drawing-marshal.list2
-rw-r--r--libgnomekbd/gkbd-keyboard-drawing.c1848
-rw-r--r--libgnomekbd/gkbd-keyboard-drawing.h189
-rw-r--r--libgnomekbd/gkbd-util.c148
-rw-r--r--libgnomekbd/gkbd-util.h30
-rw-r--r--libgnomekbdui.pc.in10
-rw-r--r--po/ChangeLog0
-rw-r--r--po/Makefile.in.in221
-rw-r--r--po/POTFILES.in12
-rw-r--r--po/ru.po169
-rw-r--r--test/.indent.pro2
-rw-r--r--test/Makefile.am45
-rw-r--r--test/gkbd-config-registry-server.c38
-rw-r--r--test/gkbd-indicator-test.c79
-rw-r--r--test/gkbd-keyboard-drawing-test.c286
79 files changed, 15937 insertions, 0 deletions
diff --git a/.anjuta/anjuta.session b/.anjuta/anjuta.session
new file mode 100644
index 0000000..40a96e3
--- /dev/null
+++ b/.anjuta/anjuta.session
@@ -0,0 +1,9 @@
+
+[Anjuta]
+Geometry=1120x755+10+25
+
+[File Loader]
+Files=file:///home/svu/CVS/libgnomekbd/capplet/gswitchit-plugins-app.h#30%%%file:///home/svu/CVS/libgnomekbd/capplet/gswitchit-plugins-app.c#394%%%file:///home/svu/CVS/libgnomekbd/capplet/gswitchit-plugins-add.c#173
+
+[Execution]
+Run in terminal=2
diff --git a/.anjuta/default.anjuta b/.anjuta/default.anjuta
new file mode 100644
index 0000000..3c61a54
--- /dev/null
+++ b/.anjuta/default.anjuta
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<anjuta>
+ <plugin name="GtkSourceview editor" mandatory="no">
+ <require group="Anjuta Plugin"
+ attribute="Location"
+ value="anjuta-sourceview:SourceviewPlugin"/>
+ </plugin>
+</anjuta>
diff --git a/.anjuta/dock-layout.xml b/.anjuta/dock-layout.xml
new file mode 100644
index 0000000..30defe8
--- /dev/null
+++ b/.anjuta/dock-layout.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<dock-layout><layout name="__default__"><dock name="__dock_1" floating="no" width="-1" height="-1" floatx="0" floaty="0"><paned orientation="vertical" locked="no" position="409"><placeholder name="ph_center" next-placement="center"/><paned orientation="horizontal" locked="no" position="453"><notebook orientation="vertical" locked="no" page="0"><item name="AnjutaFileManager" orientation="vertical" locked="no"><placeholder name="ph_left" next-placement="center"/></item><item name="AnjutaProjectManager" orientation="vertical" locked="no"/><item name="AnjutaSymbolBrowser" orientation="vertical" locked="no"/></notebook><notebook orientation="vertical" locked="no" page="0"><placeholder name="ph_right" next-placement="right"/><item name="AnjutaDocumentManager" orientation="vertical" locked="no"><placeholder name="ph_top" next-placement="center"/></item><item name="AnjutaTodoPlugin" orientation="vertical" locked="no"/></notebook></paned><item name="AnjutaMessageView" orientation="vertical" locked="no"><placeholder name="ph_bottom" next-placement="center"/></item></paned></dock></layout></dock-layout>
diff --git a/.tm_project2.cache b/.tm_project2.cache
new file mode 100644
index 0000000..35c9d12
--- /dev/null
+++ b/.tm_project2.cache
Binary files differ
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..8e9452b
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Email: svu@users.sourceforge.net
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ChangeLog
diff --git a/ChangeLog.libgswitchit b/ChangeLog.libgswitchit
new file mode 100644
index 0000000..4dc064b
--- /dev/null
+++ b/ChangeLog.libgswitchit
@@ -0,0 +1,269 @@
+2006-09-18 Sergey Udaltsov <svu@gnome.org>
+
+ * Makefile.am: one header should not be installed, one header should
+ be installed instead (for plugins to be built properly).
+
+2006-07-02 Sergey Udaltsov <svu@gnome.org>
+
+ * gnome-kbd-indicator.c: fix for gcc 2.95, #347611
+
+2006-07-02 Sergey Udaltsov <svu@gnome.org>
+
+ * gnome-kbd-indicator.c: using Unicode subscript for repeating
+ descriptions.
+
+2006-07-29 Sergey Udaltsov <svu@gnome.org>
+
+ * Makefile.am: fixed CLEANFILES, thanks to Davyd
+
+2006-07-11 Sebastien Bacher <seb128@debian.org>
+
+ * Makefile.am: specify srcdir where it's required
+
+2006-07-11 Sebastien Bacher <seb128@debian.org>
+
+ * Makefile.am:
+ make gswitchitinc_HEADERS list gswitchit-plugins-app.h
+
+2006-07-11 Sebastien Bacher <seb128@debian.org>
+
+ * Makefile.am:
+ make gswitchitinc_HEADERS list keyboard-config-registry.h
+
+2006-07-11 Sebastien Bacher <seb128@debian.org>
+
+ * Makefile.am: fixed type to gswitchit-plugins.h
+
+2006-07-10 Sergey Udaltsov <svu@gnome.org>
+
+ * keyboard-config-registry.c: made XML loading lazy. Thanks for the
+ idea, Ben
+
+2006-07-10 Sergey Udaltsov <svu@gnome.org>
+
+ * gswitchit-plugins-app.c: changing bonobo loop to glib loop
+
+2006-07-09 Sergey Udaltsov <svu@gnome.org>
+
+ * gnome-startup.*: Long unused startup stuff removed
+
+2006-07-08 Sergey Udaltsov <svu@gnome.org>
+
+ * gnome-kbd-indicator.c, gswitchit-applet-config.c,
+ gswitchit-config-private.h, gswitchit-config.c, gswitchit-config.h,
+ gswitchit-plugins-add.c, gswitchit-plugins-app.c,
+ gswitchit-plugins-app.h, gswitchit-plugins.glade, gswitchit-util.c,
+ gswitchit-util.h: Code restructuring, moving plugin management app to
+ libgswitchit
+
+2006-07-08 Sergey Udaltsov <svu@gnome.org>
+
+ * gnome-kbd-indicator.*: adding set_angle function
+
+2006-07-06 Sergey Udaltsov <svu@gnome.org>
+
+ Fixed build process, renaming files from '_' to '-'
+
+2006-07-05 Sergey Udaltsov <svu@gnome.org>
+
+ * Makefile.am,
+ gnome-kbd-indicator.c,
+ gswitchit_config.c,
+ gswitchit_config.h: Remote group names from DBUS are working
+
+2006-06-25 Sergey Udaltsov <svu@gnome.org>
+
+ The GKI widget is working, the libgswitchit API is changed
+ to the GNOME naming convention. Massive change in all GNOME
+ kbd-related sources.
+
+2006-06-23 Sergey Udaltsov <svu@gnome.org>
+
+ * gnome-kbd-indicator.[ch]: first version of the g-k-i widget
+ the development is in progress
+
+2006-05-27 Sergey Udaltsov <svu@gnome.org>
+
+ * gswitchit_config.[ch]: optimizing dealing with UTF8 descriptions -
+ changed GSList to NULL-terminated gchar **
+
+2006-04-22 Sergey Udaltsov <svu@gnome.org>
+
+ * gswitchit_config.[ch]: save/load preview window coords
+
+2006-04-20 Sergey Udaltsov <svu@gnome.org>
+
+ * gswitchit_config.c: added kbd config ToString function
+
+2006-04-20 Sergey Udaltsov <svu@gnome.org>
+
+ * *.c,*.h: update for new libxklavier API
+
+2006-01-03 Kristof Vansant <de_lupus@pandora.be>
+
+ Fixes #171668
+
+ * gswitchit_config.c:
+ * gnome-startup.[ch]: header cleanup.
+
+2005-12-06 Sergey V. Udaltsov <svu@gnome.org>
+
+ * gswitchit_plugin_manager.h,
+ gswitchit_plugin_manager.c: Small change in the plugin API:
+ the GroupChanged is called for every instance of the applet
+
+2005-11-14 Kjartan Maraas <kmaraas@gnome.org>
+
+ * gswitchit_config.c: (GSwitchItConfigLockPrevGroup):
+ Fix typo in function name.
+
+2005-09-14 Sergey V. Udaltsov <svu@gnome.org>
+
+ * gswitchit_plugin_manager.h,
+ gswitchit_plugin_manager.c: added ConfigChanged proxy
+
+2005-07-15 Mark McLoughlin <mark@skynet.ie>
+
+ Re-work the way some of the GConf keys are handled.
+ See bug #310513
+
+ * gswitchit_config.c:
+ (_GSwitchItKbdConfigLoadParams): kbdConfig->model can
+ be NULL.
+ (_GSwitchItKbdConfigSaveParams): if ->model, ->options or
+ ->layouts is NULL, unset the appropriate key.
+ (GSwitchItKbdConfigLoadFromGConf): ignore overrideSettings
+ and use the XKB default for any unset keys.
+ (GSwitchItKbdConfigSaveToGConf): ignore overrideSettings.
+ (GSwitchItKbdConfigModelSet): set ->model to NULL if the
+ GConf key contains an empty string.
+
+ * gswitchit_config.h: remove the overrideSettings member
+ from GSwitchItKbdConfig and add a kbdConfigDefault to
+ parameter to GSwitchItKbdConfigLoadFromGConf()
+
+2005-03-16 Sergey V. Udaltsov <svu@gnome.org>
+
+ * Makefile.am: removing -Werror
+
+2005-03-14 Pedro Villavicencio Garrido <pvillavi@gnome.org>
+
+ * gswitchit_config.c (GSwitchItAppletConfigLoadImages): use GtkMessageDialog instead of gnome_error_dialog.
+
+2005-03-16 Kjartan Maraas <kmaraas@gnome.org>
+
+ * gnome-startup.c: (gnome_startup_acquire_token):
+ Fix some compiler warnings wrt signedness.
+ * gswitchit_config.h:
+ * gswitchit_plugin_manager.c:
+ * gswitchit_util.c:
+ * gswitchit_util.h: Clean up headers.
+
+2005-01-12 Sergey Udaltsov <svu@gnome.org>
+
+ * gswitchit_config.h,
+ gswitchit_config.c: the listeners are inside the structs
+
+2005-01-08 Sergey Udaltsov <svu@gnome.org>
+
+ * gswitchit_config.h,
+ gswitchit_config.c: better names for the save/load functions
+
+2005-01-03 Dan Winship <danw@novell.com>
+
+ * gswitchit_util.c (GSwitchItLogAppender): Cast time_t to long to
+ match the printf format.
+
+2004-12-22 Sergey Udaltsov <svu@gnome.org>
+
+ * gswitchit_config.h,
+ gswitchit_config.c: can listen for the changes
+ in the general configuration
+
+2004-12-18 Sergey Udaltsov <svu@gnome.org>
+
+ * Makefile.am,
+ gswitchit_applet_config.h,
+ gswitchit_config.c,
+ gswitchit_config.h,
+ gswitchit_config_private.h,
+ gswitchit_plugin.h,
+ gswitchit_plugin_manager.c,
+ gswitchit_plugin_manager.h,
+ gswitchit_xkb_config.h,
+ gswitchit_xkb_config_private.h: massive redesign.
+ Three GSwitchIt*Config classes now - instead of two.
+ GConf entries changed.
+
+2004-12-08 Sergey Udaltsov <svu@gnome.org>
+
+ * gswitchit_applet_config.h,
+ gswitchit_config.c,
+ gswitchit_plugin_manager.c: changing fixed-size array to GSList.
+ Memleaks fixed.
+
+2004-10-03 Sergey Udaltsov <svu@gnome.org>
+
+ * gswitchit_config.c:
+ Removing a function which was never used.
+
+2004-06-29 Jody Goldberg <jody@gnome.org>
+
+ * gswitchit_config.c (GSwitchItXkbConfigInit) : s/g_error/g_warning/
+ (GSwitchItAppletConfigInit) : ditto.
+
+2004-04-15 Jody Goldberg <jody@gnome.org>
+
+ * Release 2.6.1
+
+2004-04-04 Sergey Udaltsov <svu@gnome.org>
+
+ * gswithit_config.c:
+ Better theme handling - deprecated GnomeIconTheme changed to
+ GtkIconTheme. Also now gswitchit applet allows local per-user
+ icons.
+
+2004-04-01 Jody Goldberg <jody@gnome.org>
+
+ * Release 2.6.0.3
+
+2004-03-30 Jody Goldberg <jody@gnome.org>
+
+ * Release 2.6.0.1
+
+2004-03-23 Jody Goldberg <jody@gnome.org>
+
+ * Release 2.6.0
+
+2004-03-11 Jody Goldberg <jody@gnome.org>
+
+ * Release 2.5.4
+
+2004-02-21 Dennis Smit <ds@nerds-incorporated.org>
+
+ * gswitchit_util.c, gswitchit_util.h (GSwitchItHelp):
+ Changed GtkWindow argument into a GtkWidget argument.
+
+ Updated to egg help and made multihead aware.
+
+2004-02-13 Jody Goldberg <jody@gnome.org>
+
+ * Release 2.5.3
+
+2004-01-14 Jody Goldberg <jody@gnome.org>
+
+ * Release 2.5.2
+
+2003-12-30 Jody Goldberg <jody@gnome.org>
+
+ * Release 2.5.1.1
+
+2003-12-30 Jody Goldberg <jody@gnome.org>
+
+ * Release 2.5.1
+
+2003-11-12 Jody Goldberg <jody@gnome.org>
+
+ * Makefile.am (EXTRA_DIST) : always dist gswitchit.pc.in to keep
+ automake happy. There is no significant downside to it.
+
diff --git a/ChangeLog.libkbdraw b/ChangeLog.libkbdraw
new file mode 100644
index 0000000..3f80b82
--- /dev/null
+++ b/ChangeLog.libkbdraw
@@ -0,0 +1,295 @@
+2005-10-07 Sergey V. Udaltsov <svu@gnome.org>
+
+ * src/keyboard-drawing.c: A bit of cleanup. No flipping any more at
+ all.
+
+2005-09-27 Sergey V. Udaltsov <svu@gnome.org>
+
+ * src/keyboard-drawing.c: Hack on flipping (const FALSE). Will fix it
+ properly next time.
+
+2005-08-24 Sergey V. Udaltsov <svu@gnome.org>
+
+ * src/keyboard-drawing.c: Do not use pangoxft any more - and the
+ text at least appears.
+
+2005-08-15 Sergey V. Udaltsov <svu@gnome.org>
+
+ * src/keyboard-drawing.c: fixing BAD bug with the stack variables,
+ I would kill the person doing (gint*)
+
+2005-08-14 Sergey V. Udaltsov <svu@gnome.org>
+
+ * autogen.sh, configure.ac: up2date
+
+2004-12-30 Sergey V. Udaltsov <svu@gnome.org>
+
+ * src/keyboard-drawing.c, src/keyboard-drawing.h,
+ tests/kbdraw.c: substantial architectural changes, introducing
+ struct KeyboardDrawingGroupLevel
+
+2004-10-28 Sergey V. Udaltsov <svu@gnome.org>
+
+ * src/keyboard-drawing.c, src/keyboard-drawing.h,
+ tests/kbdraw.c: Cleaning up the indicators handling.
+ Now indicators are handled properly on the off-screen keyboard.
+
+2004-10-24 Sergey V. Udaltsov <svu@gnome.org>
+
+ * src/keyboard-drawing.c, src/keyboard-drawing.h,
+ tests/kbdraw.c: tracking the modifiers
+
+2004-07-28 Sergey V. Udaltsov
+
+ * src/keyboard-drawing.c: prope handling of the "destroy" event
+
+2004-07-14 Sergey V. Udaltsov
+
+ * autogen.sh: make automake-1.8 friendly
+
+2004-03-26 Noah Levitt
+
+ * src/keyboard-drawing.c:
+ * src/keyboard-drawing.h:
+ * test/kbdraw.c: Fix up tracking functions and flags.
+
+ * src/keyboard-drawing.h: Reformat.
+
+2004-03-25 Noah Levitt
+
+ * test/kbdraw.c:
+ * src/keyboard-drawing.c: Fix code formatting.
+
+2004-03-25 Noah Levitt
+
+ * autogen.sh: Plagiarize gnome-common’s autogen.sh.
+
+2004-02-25 Sergey Oudaltsov
+
+ * test/kbdraw.c: two more options - track the group, track the
+ config
+
+2004-02-25 Sergey Oudaltsov
+
+ * src/: keyboard-drawing.c, keyboard-drawing.h: Now kbdraw can
+ track the group and configuration changes. Looks funny actually -
+ especially the groups > 0
+
+2004-02-24 Sergey Oudaltsov
+
+ * Makefile.am, configure.ac, src/Makefile.am, test/.cvsignore,
+ test/Makefile.am, test/kbdraw.c, src/kbdraw.c: now libkbdraw can
+ be inserted into other modules as static lib
+
+2003-11-18 Noah Levitt
+
+ * README: Add cvs info.
+
+ * configure.ac: Need to #include <X11/Xlib.h> before XKBlib.h for
+ Xfree86 3.3.6. (Mike Castle)
+
+2003-11-16 Noah Levitt
+
+ * configure.ac:
+ * kbdraw.pc.in:
+ * .cvsignore:
+ * Makefile.am: Add pkg-config kbdraw.pc file.
+
+2003-11-16 Noah Levitt
+
+ * src/keyboard-drawing.h: Update preprocessor define.
+
+ * configure.ac: Bump version number for release.
+
+ * README: New readme.
+
+2003-08-18 Noah Levitt
+
+ * src/Makefile.am: Add keyboard-marshal.list to EXTRA_DIST.
+
+2003-08-18 Noah Levitt
+
+ * src/kbdraw.c: Fix mistake parsing --levels.
+
+2003-08-13 Noah Levitt
+
+ * src/keyboard-drawing.c: With the last change, it would warn a bit
+ too often. Fixed.
+
+2003-08-13 Noah Levitt
+
+ * src/keyboard-drawing.[ch]: Check that the index returned by
+ XkbGetNamedIndicator is within range before using it.
+
+2003-08-09 Noah Levitt
+
+ * src/kbdraw.c:
+ * src/keyboard-drawing.c:
+ * src/keyboard-drawing.h: Draw only two shift levels. Command line
+ option to choose which ones.
+
+2003-08-09 Noah Levitt
+
+ * src/keyboard-drawing.c (keyboard_drawing_set_keyboard): Get
+ indicator information.
+
+ * src/keyboard_drawing.c (keyboard_drawing_init): Get only the
+ information needed, and use XkbGBN_* masks, since they seem to be what
+ it expects.
+
+2003-08-09 Noah Levitt
+
+ * src/kbdraw.c: Print a more detailed message about what was attempted
+ when keyboard_drawing_set_keyboard fails.
+
+2003-08-09 Noah Levitt
+
+ * src/keyboard-drawing.c: Draw logo doodads simplistically.
+
+2003-08-09 Noah Levitt
+
+ * src/keyboard-drawing.c: Remove debugging printfs.
+
+2003-08-09 Noah Levitt
+
+ * src/keyboard-drawing.c:
+ * src/keyboard-drawing.h: Color indicator doodads appropriately for
+ their state.
+
+2003-08-08 Noah Levitt
+
+ * src/keyboard-drawing: Changed my mind. Replace g_asserts with
+ g_critical. (g_assert can be disabled, anyway). Hopefully, we'll
+ survive a critical thing.
+
+2003-08-07 Noah Levitt
+
+ * src/keyboard-drawing.c: It's ok to die if the keyboard geometry says
+ the width or height of the keyboard is zero, but use an assertion
+ instead of getting a floating point exception.
+
+2003-08-07 Noah Levitt
+
+ * src/keyboard-drawing.c: Draw text doodads at the correct angle.
+
+2003-08-07 Noah Levitt
+
+ * src/kbdraw.c:
+ * src/keyboard-drawing.c:
+ * src/keyboard-drawing.h: Choose the keyboard you want to look at from
+ the command line (--symbols, --geometry).
+
+2003-08-07 Noah Levitt
+
+ * src/keyboard-drawing.c: Get keysyms from the keyboard description,
+ not from the server.
+
+2003-08-03 Noah Levitt
+
+ * src/keyboard-drawing.c: Fix bug freeing the old keyboard when
+ setting a new one.
+
+2003-08-02 Noah Levitt
+
+ * src/keyboard-drawing.c: Blank the widget if
+ keyboard_drawing_set_keyboard fails.
+
+2003-08-01 Noah Levitt
+
+ * src/keyboard-drawing.[ch]: Change keyboard_drawing_set_keybaord to
+ take an XkbComponentNamesRec so that we can manage the memory of the
+ XkbDescRec ourselves.
+
+2003-07-29 Noah Levitt
+
+ * configure.ac: Check for Xkb stuff.
+
+2003-07-29 Noah Levitt
+
+ * src/keyboard-drawing.c:
+ * src/keyboard-drawing.h: Add keyboard_drawing_set_keyboard.
+
+2003-07-29 Noah Levitt
+
+ * src/keyboard-drawing.h: Angle is signed.
+
+2003-07-26 Noah Levitt
+
+ * src/keyboard-drawing.c: Fix typo in keyboard_drawing_get_pixbuf.
+
+2003-07-26 Noah Levitt
+
+ * src/keyboard-drawing.c:
+ * src/keyboard-drawing.h: Add keyboard_drawing_get_pixbuf.
+
+2003-07-26 Noah Levitt
+
+ * src/keyboard-drawing.c: Position the second and subsequent lines of
+ rotated multi-line pango layouts correctly.
+
+2003-07-26 Noah Levitt
+
+ * src/.cvsignore:
+ * src/keyboard-marshal.list: Forgot to add this in the last commit.
+
+2003-07-26 Noah Levitt
+
+ * configure.ac:
+ * src/Makefile.am:
+ * src/kbdraw.c:
+ * src/keyboard-drawing.c:
+ * src/keyboard-drawing.h: Emit a signal "bad-keycode" when we get a
+ key event with a keycode that X doesn't think is on the keyboard.
+
+2003-07-26 Noah Levitt
+
+ * src/keyboard-drawing.c: Fix bug where string drawn at a different
+ angle than the previous string is messed up.
+
+2003-07-26 Noah Levitt
+
+ * src/keyboard-drawing.c: Redraw all the region that needs to be
+ redrawn when a key is pressed or released.
+
+2003-07-26 Noah Levitt
+
+ * src/keyboard-drawing.c: Draw a key even if we can't find a keycode
+ for it.
+
+2003-07-26 Noah Levitt
+
+ * src/keyboard-drawing.c: Position labels correctly within rotated
+ keys (well, most of the time).
+
+2003-07-26 Noah Levitt
+
+ * src/keyboard-drawing.c: Position rotated keys correctly.
+
+2003-07-26 Noah Levitt
+
+ * src/keyboard-drawing.c: Draw rotated keys rotated. (Still have to
+ position them and lots of other stuff.)
+
+2003-07-26 Noah Levitt
+
+ * MAINTAINERS: Add MAINTAINERS file.
+
+2003-07-26 Noah Levitt
+
+ * src/keyboard-drawing.c:
+ * src/keyboard-drawing.h: Remember the angle we're drawing text at, so
+ that we don't have to set it every time. Also, use the correct screen
+ everywhere instead of screen 0.
+
+2003-07-26 Noah Levitt
+
+ * .cvsignore:
+ * COPYING:
+ * Makefile.am:
+ * autogen.sh:
+ * configure.ac:
+ * src/.cvsignore:
+ * src/Makefile.am:
+ * src/kbdraw.c:
+ * src/keyboard-drawing.c:
+ * src/keyboard-drawing.h: Initial checkin.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..5aa859b
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,18 @@
+SUBDIRS = libgnomekbd test capplet po
+
+DISTCLEANFILES = \
+ intltool-extract \
+ intltool-merge \
+ intltool-update
+
+EXTRA_DIST = \
+ libgnomekbd.pc.in \
+ libgnomekbdui.pc.in \
+ intltool-extract.in \
+ intltool-merge.in \
+ intltool-update.in \
+ README.cvs \
+ ChangeLog.libkbdraw ChangeLog.libgswitchit
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libgnomekbd.pc libgnomekbdui.pc
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README
diff --git a/README.cvs b/README.cvs
new file mode 100644
index 0000000..49664ac
--- /dev/null
+++ b/README.cvs
@@ -0,0 +1 @@
+Please ask a maintainer before committing
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..a97b4a7
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+PKG_NAME="libgnomekbd"
+
+(test -f $srcdir/configure.in \
+ && test -f $srcdir/autogen.sh \
+ && test -d $srcdir/libgnomekbd) || {
+ echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
+ echo " top-level $PKG_NAME directory"
+ exit 1
+}
+
+DIE=0
+
+if ! which gnome-autogen.sh ; then
+ echo "You need to install the gnome-common module and make"
+ echo "sure the gnome-autogen.sh script is in your \$PATH."
+ exit 1
+fi
+
+REQUIRED_AUTOMAKE_VERSION=1.9 . gnome-autogen.sh
diff --git a/capplet/Makefile.am b/capplet/Makefile.am
new file mode 100644
index 0000000..f10bfd1
--- /dev/null
+++ b/capplet/Makefile.am
@@ -0,0 +1,47 @@
+bin_PROGRAMS = gkbd-indicator-plugins-capplet
+
+gladedir="$(pkgdatadir)/glade"
+glade_DATA = gkbd-indicator-plugins.glade
+
+@INTLTOOL_DESKTOP_RULE@
+
+desktopdir = $(datadir)/applications
+Desktop_in_files = gkbd-indicator-plugins-capplet.desktop.in
+desktop_DATA = $(Desktop_in_files:.desktop.in=.desktop)
+
+gkbd_indicator_plugins_capplet_CFLAGS = \
+ -I$(top_srcdir) -Wall -Werror \
+ $(LIBGLADE_CFLAGS) \
+ $(LIBGNOME_CFLAGS) \
+ $(LIBGNOMEUI_CFLAGS) \
+ $(LIBXKLAVIER_CFLAGS) \
+ -I$(top_srcdir)/intl \
+ -DSYS_PLUGIN_DIR=\"$(libdir)/gnomekbd/\" \
+ -DG_LOG_DOMAIN=\"GnomeKbdIndicatorPluginsCapplet\" \
+ -DPREFIX=\"$(prefix)\" \
+ -DGLADEDIR=\"$(gladedir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBDIR=\"$(libdir)\"
+
+gkbd_indicator_plugins_capplet_SOURCES = gkbd-indicator-plugins-capplet.c \
+ gkbd-indicator-plugins-add.c \
+ gkbd-indicator-plugins-capplet.h
+
+gkbd_indicator_plugins_capplet_LDFLAGS = -export-dynamic
+
+gkbd_indicator_plugins_capplet_LDADD = \
+ $(DBUS_LIBS) \
+ $(GCONF_LIBS) \
+ $(LIBGNOME_LIBS) \
+ $(LIBGNOMEUI_LIBS) \
+ $(LIBGLADE_LIBS) \
+ $(LIBXKLAVIER_LIBS) \
+ $(top_builddir)/libgnomekbd/libgnomekbd.la \
+ $(top_builddir)/libgnomekbd/libgnomekbdui.la
+
+EXTRA_DIST = gkbd-indicator-plugins-capplet.desktop.in.in \
+ $(glade_DATA)
+
+DISTCLEANFILES = $(desktop_DATA)
+
diff --git a/capplet/gkbd-indicator-plugins-add.c b/capplet/gkbd-indicator-plugins-add.c
new file mode 100644
index 0000000..f2930df
--- /dev/null
+++ b/capplet/gkbd-indicator-plugins-add.c
@@ -0,0 +1,190 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "gkbd-indicator-plugins-capplet.h"
+
+#include <string.h>
+#include <sys/stat.h>
+
+#include <gdk/gdkx.h>
+#include <glade/glade.h>
+#include <libbonobo.h>
+
+#include <libxklavier/xklavier.h>
+
+static void
+CappletAddAvailablePluginFunc (const char *fullPath,
+ GkbdIndicatorPluginManagerRecord * rec,
+ GkbdIndicatorPluginsCapplet * gipc)
+{
+ GtkListStore *availablePluginsModel;
+ GtkTreeIter iter;
+ const GkbdIndicatorPlugin *plugin = rec->plugin;
+
+ if (NULL !=
+ g_slist_find_custom (gipc->applet_cfg.enabled_plugins,
+ fullPath, (GCompareFunc) strcmp))
+ return;
+
+ availablePluginsModel =
+ GTK_LIST_STORE (g_object_get_data (G_OBJECT (gipc->capplet),
+ "gkbd_indicator_plugins_add.availablePluginsModel"));
+ if (availablePluginsModel == NULL)
+ return;
+
+ if (plugin != NULL)
+ {
+ gtk_list_store_append (availablePluginsModel, &iter);
+ gtk_list_store_set (availablePluginsModel, &iter,
+ NAME_COLUMN, plugin->name,
+ FULLPATH_COLUMN, fullPath, -1);
+ }
+}
+
+static void
+CappletFillAvailablePluginList (GtkTreeView *
+ availablePluginsList,
+ GkbdIndicatorPluginsCapplet * gipc)
+{
+ GtkListStore *availablePluginsModel =
+ GTK_LIST_STORE (gtk_tree_view_get_model
+ (GTK_TREE_VIEW (availablePluginsList)));
+ GSList *pluginPathNode = gipc->applet_cfg.enabled_plugins;
+ GHashTable *allPluginRecs = gipc->plugin_manager.all_plugin_recs;
+
+ gtk_list_store_clear (availablePluginsModel);
+ if (allPluginRecs == NULL)
+ return;
+
+ g_object_set_data (G_OBJECT (gipc->capplet),
+ "gkbd_indicator_plugins_add.availablePluginsModel",
+ availablePluginsModel);
+ g_hash_table_foreach (allPluginRecs,
+ (GHFunc) CappletAddAvailablePluginFunc, gipc);
+ g_object_set_data (G_OBJECT (gipc->capplet),
+ "gkbd_indicator_plugins_add.availablePluginsModel",
+ NULL);
+ pluginPathNode = g_slist_next (pluginPathNode);
+}
+
+static void
+CappletAvailablePluginsSelectionChanged (GtkTreeSelection *
+ selection,
+ GkbdIndicatorPluginsCapplet * gipc)
+{
+ GtkWidget *availablePluginsList =
+ GTK_WIDGET (gtk_tree_selection_get_tree_view (selection));
+ gboolean isAnythingSelected = FALSE;
+ GtkWidget *lblDescription =
+ GTK_WIDGET (g_object_get_data (G_OBJECT (gipc->capplet),
+ "gkbd_indicator_plugins_add.lblDescription"));
+
+ char *fullPath =
+ CappletGetSelectedPluginPath (GTK_TREE_VIEW (availablePluginsList),
+ gipc);
+ isAnythingSelected = fullPath != NULL;
+ gtk_label_set_text (GTK_LABEL (lblDescription),
+ g_strconcat ("<small><i>",
+ _("No description."),
+ "</i></small>", NULL));
+ gtk_label_set_use_markup (GTK_LABEL (lblDescription), TRUE);
+
+ if (fullPath != NULL)
+ {
+ const GkbdIndicatorPlugin *plugin =
+ gkbd_indicator_plugin_manager_get_plugin (&gipc->plugin_manager,
+ fullPath);
+ if (plugin != NULL && plugin->description != NULL)
+ gtk_label_set_text (GTK_LABEL (lblDescription),
+ g_strconcat ("<small><i>",
+ plugin->
+ description, "</i></small>", NULL));
+ gtk_label_set_use_markup (GTK_LABEL (lblDescription), TRUE);
+ }
+ gtk_widget_set_sensitive (GTK_WIDGET
+ (g_object_get_data
+ (G_OBJECT (gipc->capplet),
+ "gkbd_indicator_plugins_add.btnOK")),
+ isAnythingSelected);
+}
+
+void
+CappletEnablePlugin (GtkWidget * btnAdd, GkbdIndicatorPluginsCapplet * gipc)
+{
+ /* default domain! */
+ GladeXML *data = glade_xml_new (GLADEDIR "/gkbd-indicator-plugins.glade",
+ "gkbd_indicator_plugins_add", NULL);
+ GtkWidget *popup =
+ glade_xml_get_widget (data, "gkbd_indicator_plugins_add");
+ GtkWidget *availablePluginsList;
+ GtkTreeModel *availablePluginsModel;
+ GtkCellRenderer *renderer =
+ GTK_CELL_RENDERER (gtk_cell_renderer_text_new ());
+ GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (NULL,
+ renderer,
+ "text",
+ 0,
+ NULL);
+ GtkTreeSelection *selection;
+ gint response;
+ availablePluginsList = glade_xml_get_widget (data, "allPlugins");
+ availablePluginsModel =
+ GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (availablePluginsList),
+ availablePluginsModel);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (availablePluginsList), column);
+ selection =
+ gtk_tree_view_get_selection (GTK_TREE_VIEW (availablePluginsList));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+ CappletFillAvailablePluginList (GTK_TREE_VIEW (availablePluginsList), gipc);
+ g_signal_connect (G_OBJECT (selection), "changed",
+ G_CALLBACK
+ (CappletAvailablePluginsSelectionChanged), gipc);
+ g_object_set_data (G_OBJECT (gipc->capplet),
+ "gkbd_indicator_plugins_add.btnOK",
+ glade_xml_get_widget (data, "btnOK"));
+ g_object_set_data (G_OBJECT (gipc->capplet),
+ "gkbd_indicator_plugins_add.lblDescription",
+ glade_xml_get_widget (data, "lblDescription"));
+ CappletAvailablePluginsSelectionChanged (selection, gipc);
+ response = gtk_dialog_run (GTK_DIALOG (popup));
+ g_object_set_data (G_OBJECT (gipc->capplet),
+ "gkbd_indicator_plugins_add.lblDescription", NULL);
+ g_object_set_data (G_OBJECT (gipc->capplet),
+ "gkbd_indicator_plugins_add.btnOK", NULL);
+ gtk_widget_hide_all (popup);
+ if (response == GTK_RESPONSE_OK)
+ {
+ char *fullPath =
+ CappletGetSelectedPluginPath (GTK_TREE_VIEW (availablePluginsList),
+ gipc);
+ if (fullPath != NULL)
+ {
+ gkbd_indicator_plugin_manager_enable_plugin (&gipc->
+ plugin_manager,
+ &gipc->
+ applet_cfg.
+ enabled_plugins,
+ fullPath);
+ CappletFillActivePluginList (gipc);
+ g_free (fullPath);
+ gkbd_indicator_config_save_to_gconf (&gipc->applet_cfg);
+ }
+ }
+ gtk_widget_destroy (popup);
+}
diff --git a/capplet/gkbd-indicator-plugins-capplet.c b/capplet/gkbd-indicator-plugins-capplet.c
new file mode 100644
index 0000000..13761a8
--- /dev/null
+++ b/capplet/gkbd-indicator-plugins-capplet.c
@@ -0,0 +1,380 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "gkbd-indicator-plugins-capplet.h"
+
+#include <string.h>
+#include <sys/stat.h>
+
+#include <glib/gi18n.h>
+#include <gdk/gdkx.h>
+#include <glade/glade.h>
+#include <libgnomeui/gnome-ui-init.h>
+#include <libgnomeui/gnome-help.h>
+
+static GkbdKeyboardConfig initialSysKbdConfig;
+static GMainLoop *loop;
+
+extern void
+CappletFillActivePluginList (GkbdIndicatorPluginsCapplet * gipc)
+{
+ GtkWidget *activePlugins = CappletGetGladeWidget (gipc, "activePlugins");
+ GtkListStore *activePluginsModel =
+ GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (activePlugins)));
+ GSList *pluginPathNode = gipc->applet_cfg.enabled_plugins;
+ GHashTable *allPluginRecs = gipc->plugin_manager.all_plugin_recs;
+
+ gtk_list_store_clear (activePluginsModel);
+ if (allPluginRecs == NULL)
+ return;
+
+ while (pluginPathNode != NULL)
+ {
+ GtkTreeIter iter;
+ const char *fullPath = (const char *) pluginPathNode->data;
+ const GkbdIndicatorPlugin *plugin =
+ gkbd_indicator_plugin_manager_get_plugin (&gipc->plugin_manager,
+ fullPath);
+ if (plugin != NULL)
+ {
+ gtk_list_store_append (activePluginsModel, &iter);
+ gtk_list_store_set (activePluginsModel, &iter,
+ NAME_COLUMN, plugin->name,
+ FULLPATH_COLUMN, fullPath, -1);
+ }
+
+ pluginPathNode = g_slist_next (pluginPathNode);
+ }
+}
+
+static char *
+CappletGetSelectedActivePluginPath (GkbdIndicatorPluginsCapplet * gipc)
+{
+ GtkTreeView *pluginsList =
+ GTK_TREE_VIEW (CappletGetGladeWidget (gipc, "activePlugins"));
+ return CappletGetSelectedPluginPath (pluginsList, gipc);
+}
+
+char *
+CappletGetSelectedPluginPath (GtkTreeView * pluginsList,
+ GkbdIndicatorPluginsCapplet * gipc)
+{
+ GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (pluginsList));
+ GtkTreeSelection *selection =
+ gtk_tree_view_get_selection (GTK_TREE_VIEW (pluginsList));
+ GtkTreeIter selectedIter;
+
+ if (gtk_tree_selection_get_selected (selection, NULL, &selectedIter))
+ {
+ char *fullPath = NULL;
+
+ gtk_tree_model_get (model, &selectedIter,
+ FULLPATH_COLUMN, &fullPath, -1);
+ return fullPath;
+ }
+ return NULL;
+}
+
+static void
+CappletActivePluginsSelectionChanged (GtkTreeSelection *
+ selection,
+ GkbdIndicatorPluginsCapplet * gipc)
+{
+ GtkWidget *activePlugins = CappletGetGladeWidget (gipc, "activePlugins");
+ GtkTreeModel *model =
+ gtk_tree_view_get_model (GTK_TREE_VIEW (activePlugins));
+ GtkTreeIter selectedIter;
+ gboolean isAnythingSelected = FALSE;
+ gboolean isFirstSelected = FALSE;
+ gboolean isLastSelected = FALSE;
+ gboolean hasConfigurationUi = FALSE;
+ GtkWidget *btnRemove = CappletGetGladeWidget (gipc, "btnRemove");
+ GtkWidget *btnUp = CappletGetGladeWidget (gipc, "btnUp");
+ GtkWidget *btnDown = CappletGetGladeWidget (gipc, "btnDown");
+ GtkWidget *btnProperties = CappletGetGladeWidget (gipc, "btnProperties");
+ GtkWidget *lblDescription = CappletGetGladeWidget (gipc, "lblDescription");
+
+ gtk_label_set_text (GTK_LABEL (lblDescription),
+ g_strconcat ("<small><i>",
+ _("No description."),
+ "</i></small>", NULL));
+ gtk_label_set_use_markup (GTK_LABEL (lblDescription), TRUE);
+
+ if (gtk_tree_selection_get_selected (selection, NULL, &selectedIter))
+ {
+ int counter = gtk_tree_model_iter_n_children (model, NULL);
+ GtkTreePath *treePath = gtk_tree_model_get_path (model, &selectedIter);
+ gint *indices = gtk_tree_path_get_indices (treePath);
+ char *fullPath = CappletGetSelectedActivePluginPath (gipc);
+ const GkbdIndicatorPlugin *plugin =
+ gkbd_indicator_plugin_manager_get_plugin (&gipc->plugin_manager,
+ fullPath);
+
+ isAnythingSelected = TRUE;
+
+ isFirstSelected = indices[0] == 0;
+ isLastSelected = indices[0] == counter - 1;
+
+ if (plugin != NULL)
+ {
+ hasConfigurationUi =
+ (plugin->configure_properties_callback != NULL);
+ gtk_label_set_text (GTK_LABEL (lblDescription),
+ g_strconcat ("<small><i>",
+ plugin->
+ description,
+ "</i></small>", NULL));
+ gtk_label_set_use_markup (GTK_LABEL (lblDescription), TRUE);
+ }
+ g_free (fullPath);
+
+ gtk_tree_path_free (treePath);
+ }
+ gtk_widget_set_sensitive (btnRemove, isAnythingSelected);
+ gtk_widget_set_sensitive (btnUp, isAnythingSelected && !isFirstSelected);
+ gtk_widget_set_sensitive (btnDown, isAnythingSelected && !isLastSelected);
+ gtk_widget_set_sensitive (btnProperties, isAnythingSelected
+ && hasConfigurationUi);
+}
+
+static void
+CappletPromotePlugin (GtkWidget * btnUp, GkbdIndicatorPluginsCapplet * gipc)
+{
+ char *fullPath = CappletGetSelectedActivePluginPath (gipc);
+ if (fullPath != NULL)
+ {
+ gkbd_indicator_plugin_manager_promote_plugin (&gipc->
+ plugin_manager,
+ gipc->applet_cfg.
+ enabled_plugins,
+ fullPath);
+ g_free (fullPath);
+ CappletFillActivePluginList (gipc);
+ gkbd_indicator_config_save_to_gconf (&gipc->applet_cfg);
+ }
+}
+
+static void
+CappletDemotePlugin (GtkWidget * btnUp, GkbdIndicatorPluginsCapplet * gipc)
+{
+ char *fullPath = CappletGetSelectedActivePluginPath (gipc);
+ if (fullPath != NULL)
+ {
+ gkbd_indicator_plugin_manager_demote_plugin (&gipc->
+ plugin_manager,
+ gipc->applet_cfg.
+ enabled_plugins, fullPath);
+ g_free (fullPath);
+ CappletFillActivePluginList (gipc);
+ gkbd_indicator_config_save_to_gconf (&gipc->applet_cfg);
+ }
+}
+
+static void
+CappletDisablePlugin (GtkWidget * btnRemove,
+ GkbdIndicatorPluginsCapplet * gipc)
+{
+ char *fullPath = CappletGetSelectedActivePluginPath (gipc);
+ if (fullPath != NULL)
+ {
+ gkbd_indicator_plugin_manager_disable_plugin (&gipc->
+ plugin_manager,
+ &gipc->
+ applet_cfg.
+ enabled_plugins,
+ fullPath);
+ g_free (fullPath);
+ CappletFillActivePluginList (gipc);
+ gkbd_indicator_config_save_to_gconf (&gipc->applet_cfg);
+ }
+}
+
+static void
+CappletConfigurePlugin (GtkWidget * btnRemove,
+ GkbdIndicatorPluginsCapplet * gipc)
+{
+ char *fullPath = CappletGetSelectedActivePluginPath (gipc);
+ if (fullPath != NULL)
+ {
+ gkbd_indicator_plugin_manager_configure_plugin (&gipc->
+ plugin_manager,
+ &gipc->
+ plugin_container,
+ fullPath,
+ GTK_WINDOW
+ (gipc->capplet));
+ g_free (fullPath);
+ }
+}
+
+static void
+CappletResponse (GtkDialog * dialog, gint response)
+{
+ if (response == GTK_RESPONSE_HELP)
+ {
+ GError *error = NULL;
+ gnome_help_display_on_screen ("gkbd", "gkb-indicator-applet-plugins",
+ gtk_widget_get_screen (GTK_WIDGET
+ (dialog)), &error);
+ return;
+ }
+
+ g_main_loop_quit (loop);
+}
+
+static void
+CappletSetup (GkbdIndicatorPluginsCapplet * gipc)
+{
+ GladeXML *data;
+ GtkWidget *capplet;
+ GtkWidget *activePlugins;
+ GtkTreeModel *activePluginsModel;
+ GtkCellRenderer *renderer =
+ GTK_CELL_RENDERER (gtk_cell_renderer_text_new ());
+ GtkTreeViewColumn *column =
+ gtk_tree_view_column_new_with_attributes (NULL, renderer,
+ "text", 0,
+ NULL);
+ GtkTreeSelection *selection;
+ glade_gnome_init ();
+
+ gtk_window_set_default_icon_name ("gkbd-indicator_properties-capplet");
+
+ /* default domain! */
+ data =
+ glade_xml_new (GLADEDIR "/gkbd-indicator-plugins.glade",
+ "gkbd_indicator_plugins", NULL);
+ gipc->capplet = capplet =
+ glade_xml_get_widget (data, "gkbd_indicator_plugins");
+
+ gtk_object_set_data (GTK_OBJECT (capplet), "gladeData", data);
+ g_signal_connect_swapped (GTK_OBJECT (capplet),
+ "destroy", G_CALLBACK (g_object_unref), data);
+ g_signal_connect_swapped (G_OBJECT (capplet), "unrealize",
+ G_CALLBACK (g_main_loop_quit), loop);
+
+ g_signal_connect (GTK_OBJECT (capplet),
+ "response", G_CALLBACK (CappletResponse), NULL);
+
+ glade_xml_signal_connect_data (data, "on_btnUp_clicked",
+ GTK_SIGNAL_FUNC
+ (CappletPromotePlugin), gipc);
+ glade_xml_signal_connect_data (data,
+ "on_btnDown_clicked",
+ GTK_SIGNAL_FUNC (CappletDemotePlugin), gipc);
+ glade_xml_signal_connect_data (data,
+ "on_btnAdd_clicked",
+ GTK_SIGNAL_FUNC (CappletEnablePlugin), gipc);
+ glade_xml_signal_connect_data (data,
+ "on_btnRemove_clicked",
+ GTK_SIGNAL_FUNC
+ (CappletDisablePlugin), gipc);
+ glade_xml_signal_connect_data (data,
+ "on_btnProperties_clicked",
+ GTK_SIGNAL_FUNC
+ (CappletConfigurePlugin), gipc);
+
+ activePlugins = CappletGetGladeWidget (gipc, "activePlugins");
+ activePluginsModel =
+ GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (activePlugins), activePluginsModel);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (activePlugins), column);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (activePlugins));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+ g_signal_connect (G_OBJECT (selection), "changed",
+ G_CALLBACK (CappletActivePluginsSelectionChanged), gipc);
+ CappletFillActivePluginList (gipc);
+ CappletActivePluginsSelectionChanged (selection, gipc);
+ gtk_widget_show_all (capplet);
+}
+
+int
+main (int argc, char **argv)
+{
+ GkbdIndicatorPluginsCapplet gipc;
+
+ GError *gconf_error = NULL;
+ GConfClient *confClient;
+
+ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+ memset (&gipc, 0, sizeof (gipc));
+ gnome_program_init ("gkbd", VERSION,
+ LIBGNOMEUI_MODULE, argc, argv,
+ GNOME_PROGRAM_STANDARD_PROPERTIES, NULL);
+ if (!gconf_init (argc, argv, &gconf_error))
+ {
+ g_warning (_("Failed to init GConf: %s\n"), gconf_error->message);
+ g_error_free (gconf_error);
+ return 1;
+ }
+ gconf_error = NULL;
+ /*GkbdIndicatorInstallGlibLogAppender( ); */
+ gipc.engine = xkl_engine_get_instance (GDK_DISPLAY ());
+ gipc.config_registry = xkl_config_registry_get_instance (gipc.engine);
+
+ confClient = gconf_client_get_default ();
+ gkbd_indicator_plugin_container_init (&gipc.plugin_container, confClient);
+ g_object_unref (confClient);
+
+ gkbd_keyboard_config_init (&gipc.kbd_cfg, confClient, gipc.engine);
+ gkbd_keyboard_config_init (&initialSysKbdConfig, confClient, gipc.engine);
+
+ gkbd_indicator_config_init (&gipc.applet_cfg, confClient, gipc.engine);
+
+ gkbd_indicator_plugin_manager_init (&gipc.plugin_manager);
+
+ gkbd_keyboard_config_load_from_x_initial (&initialSysKbdConfig);
+ gkbd_keyboard_config_load_from_gconf (&gipc.kbd_cfg, &initialSysKbdConfig);
+
+ gkbd_indicator_config_load_from_gconf (&gipc.applet_cfg);
+
+ loop = g_main_loop_new (NULL, TRUE);
+
+ CappletSetup (&gipc);
+
+ g_main_loop_run (loop);
+
+ gkbd_indicator_plugin_manager_term (&gipc.plugin_manager);
+
+ gkbd_indicator_config_term (&gipc.applet_cfg);
+
+ gkbd_keyboard_config_term (&gipc.kbd_cfg);
+ gkbd_keyboard_config_term (&initialSysKbdConfig);
+
+ gkbd_indicator_plugin_container_term (&gipc.plugin_container);
+ g_object_unref (G_OBJECT (gipc.config_registry));
+ g_object_unref (G_OBJECT (gipc.engine));
+ return 0;
+}
+
+/* functions just for plugins - otherwise ldd is not happy */
+void
+gkbd_indicator_plugin_container_reinit_ui (GkbdIndicatorPluginContainer * pc)
+{
+}
+
+gchar **
+gkbd_indicator_plugin_load_localized_group_names (GkbdIndicatorPluginContainer
+ * pc)
+{
+ return
+ gkbd_desktop_config_load_group_descriptions_utf8 (&
+ (((GkbdIndicatorPluginsCapplet *) pc)->cfg), (((GkbdIndicatorPluginsCapplet *) pc)->config_registry));
+}
diff --git a/capplet/gkbd-indicator-plugins-capplet.desktop.in.in b/capplet/gkbd-indicator-plugins-capplet.desktop.in.in
new file mode 100644
index 0000000..f9e04df
--- /dev/null
+++ b/capplet/gkbd-indicator-plugins-capplet.desktop.in.in
@@ -0,0 +1,15 @@
+[Desktop Entry]
+Encoding=UTF-8
+_Name=Keyboard Indicator plugins
+_Comment=Enable/disable installed plugins
+Exec=gkbd-indicator-plugins-capplet
+Icon=gnome-dev-keyboard
+Terminal=false
+Type=Application
+StartupNotify=true
+Categories=Application;System;Settings;AdvancedSettings;
+OnlyShowIn=GNOME;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=libgnomekbd
+X-GNOME-Bugzilla-Component=keyboard indicator plugins capplet
+X-GNOME-Bugzilla-Version=@VERSION@
diff --git a/capplet/gkbd-indicator-plugins-capplet.h b/capplet/gkbd-indicator-plugins-capplet.h
new file mode 100644
index 0000000..f567801
--- /dev/null
+++ b/capplet/gkbd-indicator-plugins-capplet.h
@@ -0,0 +1,62 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GKBD_INDICATOR_PLUGINS_CAPPLET_H__
+#define __GKBD_INDICATOR_PLUGINS_CAPPLET_H__
+
+#include <glib-object.h>
+#include <gtk/gtkwidget.h>
+#include <glade/glade-xml.h>
+
+#include "libgnomekbd/gkbd-desktop-config.h"
+#include "libgnomekbd/gkbd-indicator-config.h"
+#include "libgnomekbd/gkbd-keyboard-config.h"
+
+#include "libgnomekbd/gkbd-indicator-plugin-manager.h"
+#include "libgnomekbd/gkbd-util.h"
+
+typedef struct _GkbdIndicatorPluginsCapplet
+{
+ GkbdIndicatorPluginContainer plugin_container;
+ GkbdDesktopConfig cfg;
+ GkbdIndicatorConfig applet_cfg;
+ GkbdKeyboardConfig kbd_cfg;
+ GkbdIndicatorPluginManager plugin_manager;
+ XklEngine *engine;
+ XklConfigRegistry *config_registry;
+
+ GtkWidget *capplet;
+} GkbdIndicatorPluginsCapplet;
+
+#define NAME_COLUMN 0
+#define FULLPATH_COLUMN 1
+
+#define CappletGetGladeWidget( gipc, name ) \
+ glade_xml_get_widget( \
+ GLADE_XML( g_object_get_data( G_OBJECT( (gipc)->capplet ), \
+ "gladeData" ) ), \
+ name )
+
+extern void CappletFillActivePluginList (GkbdIndicatorPluginsCapplet * gipc);
+
+extern char *CappletGetSelectedPluginPath (GtkTreeView * plugins_list,
+ GkbdIndicatorPluginsCapplet *
+ gipc);
+
+extern void CappletEnablePlugin (GtkWidget * btnAdd,
+ GkbdIndicatorPluginsCapplet * gipc);
+
+#endif
diff --git a/capplet/gkbd-indicator-plugins.glade b/capplet/gkbd-indicator-plugins.glade
new file mode 100644
index 0000000..9d3d2d1
--- /dev/null
+++ b/capplet/gkbd-indicator-plugins.glade
@@ -0,0 +1,532 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+<requires lib="gnome"/>
+
+<widget class="GtkDialog" id="gkbd_indicator_plugins">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Keyboard Indicator Plugins</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="has_separator">False</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">2</property>
+
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+ <child>
+ <widget class="GtkButton" id="btnClose">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Close the dialog</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-close</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">-7</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="btnHelp">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-help</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">-11</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox5">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">0</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Active _plugins:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">activePlugins</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="activePlugins">
+ <property name="width_request">160</property>
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">The list of active plugins</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">False</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment12">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">0</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox3">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label10">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="btnAdd">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Activate more plugins</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-add</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_btnAdd_clicked" last_modification_time="Tue, 29 Jul 2003 23:37:15 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="btnRemove">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Deactivate selected plugin</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-remove</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_btnRemove_clicked" last_modification_time="Tue, 29 Jul 2003 23:37:02 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="btnUp">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Increase the plugin priority</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-go-up</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_btnUp_clicked" last_modification_time="Tue, 29 Jul 2003 23:36:45 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="btnDown">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Decrease the plugin priority</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-go-down</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_btnDown_clicked" last_modification_time="Tue, 29 Jul 2003 23:36:30 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="btnProperties">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Configure the selected plugin</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-properties</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_btnProperties_clicked" last_modification_time="Tue, 29 Jul 2003 23:36:16 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label11">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="lblDescription">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">True</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkDialog" id="gkbd_indicator_plugins_add">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Add Plugin</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">True</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="has_separator">False</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox2">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">2</property>
+
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area2">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+ <child>
+ <widget class="GtkButton" id="helpbutton1">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-help</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">-11</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="cancelbutton1">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-cancel</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">-6</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="btnOK">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-ok</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">-5</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment13">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">0</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox4">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label18">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Available plugins:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">allPlugins</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="allPlugins">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">False</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="lblDescription">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">True</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+</glade-interface>
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..ab309f5
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,106 @@
+dnl ***************************************************************************
+dnl *** configure.in for GNOME-APPLETS ***
+dnl ***************************************************************************
+AC_INIT(libgnomekbd, 0.1)
+AC_PREREQ(2.59)
+
+AM_CONFIG_HEADER(config.h)
+AM_INIT_AUTOMAKE(1.8)
+AC_CONFIG_MACRO_DIR(m4)
+
+dnl ***************************************************************************
+dnl *** Minimum library versions for GNOME-APPLETS ***
+dnl ***************************************************************************
+DBUS_REQUIRED=0.92
+DBUS_GLIB_REQUIRED=0.34
+GCONF_REQUIRED=2.14.0
+GDK_REQUIRED=2.10.3
+GTK_REQUIRED=2.10.3
+LIBGLADE_REQUIRED=2.6.0
+LIBGNOME_REQUIRED=2.16.0
+LIBGNOMEUI_REQUIRED=2.16.0
+LIBXKLAVIER_REQUIRED=2.91
+dnl ***************************************************************************
+
+AM_MAINTAINER_MODE
+
+AC_PROG_INTLTOOL
+GNOME_COMPILE_WARNINGS
+
+AC_ISC_POSIX
+AC_PROG_CC
+AC_STDC_HEADERS
+AM_PROG_LIBTOOL
+
+GETTEXT_PACKAGE=libgnomekbd
+AC_SUBST(GETTEXT_PACKAGE)
+AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [Gettext package])
+
+ALL_LINGUAS="ru"
+
+AM_GLIB_GNU_GETTEXT
+
+GLIB_DEFINE_LOCALEDIR(GNOMELOCALEDIR)
+
+AC_CHECK_FUNCS(setlocale)
+
+PKG_CHECK_MODULES(DBUS, dbus-1 >= $DBUS_REQUIRED dbus-glib-1 >= $DBUS_GLIB_REQUIRED)
+
+AC_SUBST(DBUS_CFLAGS)
+AC_SUBST(DBUS_LIBS)
+
+PKG_CHECK_MODULES(GCONF, gconf-2.0 >= $GCONF_REQUIRED)
+
+AC_SUBST(GCONF_CFLAGS)
+AC_SUBST(GCONF_LIBS)
+
+PKG_CHECK_MODULES(GDK, gdk-2.0 >= $GDK_REQUIRED)
+
+AC_SUBST(GDK_CFLAGS)
+AC_SUBST(GDK_LIBS)
+
+PKG_CHECK_MODULES(GTK, gtk+-2.0 >= $GTK_REQUIRED gdk-x11-2.0 >= $GDK_REQUIRED)
+
+AC_SUBST(GTK_CFLAGS)
+AC_SUBST(GTK_LIBS)
+
+PKG_CHECK_MODULES(LIBXKLAVIER, libxklavier >= $LIBXKLAVIER_REQUIRED)
+
+AC_SUBST(LIBXKLAVIER_CFLAGS)
+AC_SUBST(LIBXKLAVIER_LIBS)
+
+PKG_CHECK_MODULES(LIBGLADE, libglade-2.0 >= $LIBGLADE_REQUIRED)
+
+AC_SUBST(LIBGLADE_CFLAGS)
+AC_SUBST(LIBGLADE_LIBS)
+
+PKG_CHECK_MODULES(LIBGNOME, libgnome-2.0 >= $LIBGNOME_REQUIRED)
+
+AC_SUBST(LIBGNOME_CFLAGS)
+AC_SUBST(LIBGNOME_LIBS)
+
+PKG_CHECK_MODULES(LIBGNOMEUI, libgnomeui-2.0 >= $LIBGNOMEUI_REQUIRED)
+
+AC_SUBST(LIBGNOMEUI_CFLAGS)
+AC_SUBST(LIBGNOMEUI_LIBS)
+
+AC_PATH_PROG(GCONFTOOL, gconftool-2, no)
+
+if test x"$GCONFTOOL" = xno; then
+ AC_MSG_ERROR([gconftool-2 executable not found in your path - should be installed with GConf])
+fi
+
+AM_GCONF_SOURCE_2
+
+AC_OUTPUT([
+Makefile
+libgnomekbd.pc
+libgnomekbdui.pc
+po/Makefile.in
+libgnomekbd/Makefile
+test/Makefile
+capplet/Makefile
+capplet/gkbd-indicator-plugins-capplet.desktop.in
+])
+
+
diff --git a/libgnomekbd.anjuta b/libgnomekbd.anjuta
new file mode 100644
index 0000000..b6a1551
--- /dev/null
+++ b/libgnomekbd.anjuta
@@ -0,0 +1,54 @@
+<?xml version="1.0"?>
+<anjuta>
+ <plugin name="GBF Project Manager"
+ url="http://anjuta.org/plugins/"
+ mandatory="yes">
+ <require group="Anjuta Plugin"
+ attribute="Interfaces"
+ value="IAnjutaProjectManager"/>
+ <require group="Project"
+ attribute="Supported-Project-Types"
+ value="automake"/>
+ </plugin>
+ <plugin name="Symbol Browser"
+ url="http://anjuta.org/plugins/"
+ mandatory="yes">
+ <require group="Anjuta Plugin"
+ attribute="Location"
+ value="anjuta-symbol-browser:SymbolBrowserPlugin"/>
+ </plugin>
+ <plugin name="Make Build System"
+ url="http://anjuta.org/plugins/"
+ mandatory="yes">
+ <require group="Anjuta Plugin"
+ attribute="Interfaces"
+ value="IAnjutaBuildable"/>
+ <require group="Build"
+ attribute="Supported-Build-Types"
+ value="make"/>
+ </plugin>
+ <plugin name="CVS Version Control System"
+ url="http://anjuta.org/plugins/"
+ mandatory="no">
+ <require group="Anjuta Plugin"
+ attribute="Interfaces"
+ value="IAnjutaVcs"/>
+ <require group="Version Control"
+ attribute="Supported-Vcs-Types"
+ value="cvs"/>
+ </plugin>
+ <plugin name="Task Manager"
+ url="http://anjuta.org/plugins/"
+ mandatory="no">
+ <require group="Anjuta Plugin"
+ attribute="Interfaces"
+ value="IAnjutaTodo"/>
+ </plugin>
+ <plugin name="Debug Manager"
+ url="http://anjuta.org/plugins/"
+ mandatory="no">
+ <require group="Anjuta Plugin"
+ attribute="Interfaces"
+ value="IAnjutaDebuggerManager"/>
+ </plugin>
+</anjuta>
diff --git a/libgnomekbd.pc.in b/libgnomekbd.pc.in
new file mode 100644
index 0000000..b981a96
--- /dev/null
+++ b/libgnomekbd.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libgnomekbd
+Description: GNOME keyboard shared library
+Version: @VERSION@
+Libs: -L${libdir} -lgnomekbd
+Cflags: -I${includedir}
diff --git a/libgnomekbd/.indent.pro b/libgnomekbd/.indent.pro
new file mode 100644
index 0000000..bdff074
--- /dev/null
+++ b/libgnomekbd/.indent.pro
@@ -0,0 +1,2 @@
+-kr -i8 -pcs -lps -psl
+
diff --git a/libgnomekbd/Makefile.am b/libgnomekbd/Makefile.am
new file mode 100644
index 0000000..01bb0cc
--- /dev/null
+++ b/libgnomekbd/Makefile.am
@@ -0,0 +1,125 @@
+lib_LTLIBRARIES = libgnomekbd.la libgnomekbdui.la
+
+common_CFLAGS = \
+ -I$(top_srcdir) -Wall -Werror \
+ $(GDK_CFLAGS) \
+ $(DBUS_CFLAGS) \
+ $(GCONF_CFLAGS) \
+ $(LIBGNOME_CFLAGS) \
+ $(LIBXKLAVIER_CFLAGS) \
+ -I$(top_srcdir)/intl \
+ -DSYS_PLUGIN_DIR=\"$(libdir)/gnomekbd/\" \
+ -DG_LOG_DOMAIN=\"GnomeKbdIndicator\" \
+ -DGLADEDIR=\"$(gladedir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBDIR=\"$(libdir)\"
+
+libgnomekbd_la_CFLAGS = $(common_CFLAGS)
+
+libgnomekbdui_la_CFLAGS = $(common_CFLAGS) \
+ $(GTK_CFLAGS)
+
+common_LDFLAGS = \
+ $(DBUS_LIBS) \
+ $(GDK_LIBS) \
+ $(GCONF_LIBS) \
+ $(LIBXKLAVIER_LIBS)
+
+libgnomekbd_la_LDFLAGS = $(common_LDFLAGS)
+
+libgnomekbdui_la_LDFLAGS = $(common_LDFLAGS) $(GTK_LIBS)
+
+libgnomekbd_la_SOURCES = \
+ gkbd-config-registry.c \
+ gkbd-desktop-config.c \
+ gkbd-keyboard-config.c \
+ gkbd-util.c
+
+libgnomekbdui_la_SOURCES = \
+ gkbd-indicator-config.c \
+ gkbd-indicator.c \
+ gkbd-indicator-marshal.c \
+ gkbd-indicator-plugin-manager.c \
+ gkbd-keyboard-drawing-marshal.c \
+ gkbd-keyboard-drawing.c
+
+BUILT_SOURCES = gkbd-indicator-marshal.c \
+ gkbd-indicator-marshal.h \
+ gkbd-config-registry-server.h \
+ gkbd-config-registry-client.h \
+ gkbd-keyboard-drawing-marshal.c \
+ gkbd-keyboard-drawing-marshal.h
+
+CLEANFILES = $(BUILT_SOURCES) $(schema_DATA)
+
+gnomekbdincdir = $(includedir)/libgnomekbd
+gnomekbdinc_HEADERS = \
+ gkbd-desktop-config.h \
+ gkbd-keyboard-config.h \
+ gkbd-config-registry-client.h \
+ gkbd-config-registry.h \
+ gkbd-indicator.h \
+ gkbd-indicator-config.h \
+ gkbd-indicator-plugin.h \
+ gkbd-keyboard-drawing.h \
+ gkbd-util.h
+
+@INTLTOOL_DESKTOP_RULE@
+
+@INTLTOOL_SCHEMAS_RULE@
+
+noinst_HEADERS = gkbd-indicator-plugin-manager.h \
+ $(extra_nih) \
+ gkbd-config-private.h \
+ gkbd-config-registry-server.h
+
+EXTRA_DIST = gkbd-indicator-marshal.list \
+ gkbd-keyboard-drawing-marshal.list \
+ gkbd-config-registry.xml \
+ $(glade_DATA) \
+ $(schema_in_files)
+
+GLIB_GENMARSHAL = $(shell pkg-config --variable=glib_genmarshal glib-2.0)
+
+gkbd-indicator-marshal.h: gkbd-indicator-marshal.list
+ $(GLIB_GENMARSHAL) --prefix=gkbd_indicator $(srcdir)/gkbd-indicator-marshal.list --header > $@
+
+gkbd-indicator-marshal.c: gkbd-indicator-marshal.h
+ $(GLIB_GENMARSHAL) --prefix=gkbd_indicator $(srcdir)/gkbd-indicator-marshal.list --body > $@
+
+gkbd-config-registry-server.h: gkbd-config-registry.xml
+ dbus-binding-tool --prefix=gkbd_config_registry --mode=glib-server $< > $@
+
+gkbd-config-registry-client.h: gkbd-config-registry.xml
+ dbus-binding-tool --prefix=gkbd_config_registry --mode=glib-client $< > $@
+
+gkbd-keyboard-drawing-marshal.h: gkbd-keyboard-drawing-marshal.list
+ ( $(GLIB_GENMARSHAL) --prefix=gkbd_keyboard_drawing $(srcdir)/gkbd-keyboard-drawing-marshal.list \
+ --header > gkbd-keyboard-drawing-marshal.tmp \
+ && mv gkbd-keyboard-drawing-marshal.tmp gkbd-keyboard-drawing-marshal.h ) \
+ || ( rm -f gkbd-keyboard-drawing-marshal.tmp && exit 1 )
+
+gkbd-keyboard-drawing-marshal.c: gkbd-keyboard-drawing-marshal.h
+ ( $(GLIB_GENMARSHAL) --prefix=gkbd_keyboard_drawing $(srcdir)/gkbd-keyboard-drawing-marshal.list \
+ --body > gkbd-keyboard-drawing-marshal.tmp \
+ && mv gkbd-keyboard-drawing-marshal.tmp gkbd-keyboard-drawing-marshal.c ) \
+ || ( rm -f gkbd-keyboard-drawing-marshal.tmp && exit 1 )
+
+schemadir = $(GCONF_SCHEMA_FILE_DIR)
+schema_in_files= desktop_gnome_peripherals_keyboard_xkb.schemas.in
+
+schema_DATA = $(schema_in_files:.schemas.in=.schemas)
+
+if GCONF_SCHEMAS_INSTALL
+# don't do this if we are building in eg. rpm
+install-data-local:
+ if test -z "$(DESTDIR)" ; then \
+ for p in $(schema_DATA) ; do \
+ GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $$p; \
+ done \
+ fi
+else
+install-data-local:
+endif
+
diff --git a/libgnomekbd/backup/Makefile b/libgnomekbd/backup/Makefile
new file mode 100644
index 0000000..3d83f1c
--- /dev/null
+++ b/libgnomekbd/backup/Makefile
@@ -0,0 +1,718 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# libgnomekbd/Makefile. Generated from Makefile.in by configure.
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+
+srcdir = .
+top_srcdir = ..
+
+pkgdatadir = $(datadir)/libgnomekbd
+pkglibdir = $(libdir)/libgnomekbd
+pkgincludedir = $(includedir)/libgnomekbd
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = /usr/bin/install -c
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = i686-pc-linux-gnu
+host_triplet = i686-pc-linux-gnu
+subdir = libgnomekbd
+DIST_COMMON = $(gnomekbdinc_HEADERS) $(noinst_HEADERS) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/intltool.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(gnomekbdincdir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libgnomekbd_la_LIBADD =
+am_libgnomekbd_la_OBJECTS = libgnomekbd_la-gkb-keyboard-config.lo \
+ libgnomekbd_la-gkb-desktop-config.lo \
+ libgnomekbd_la-gkb-indicator-config.lo \
+ libgnomekbd_la-gkb-util.lo libgnomekbd_la-gkb-indicator.lo \
+ libgnomekbd_la-gkb-indicator-marshal.lo \
+ libgnomekbd_la-gkb-indicator-plugin-manager.lo \
+ libgnomekbd_la-gkb-config-registry.lo \
+ libgnomekbd_la-gkb-keyboard-drawing-marshal.lo \
+ libgnomekbd_la-gkb-keyboard-drawing.lo
+libgnomekbd_la_OBJECTS = $(am_libgnomekbd_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libgnomekbd_la_SOURCES)
+DIST_SOURCES = $(libgnomekbd_la_SOURCES)
+gnomekbdincHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(gnomekbdinc_HEADERS) $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = ${SHELL} /home/svu/CVS/libgnomekbd/missing --run aclocal-1.9
+ALL_LINGUAS = ru
+AMDEP_FALSE = #
+AMDEP_TRUE =
+AMTAR = ${SHELL} /home/svu/CVS/libgnomekbd/missing --run tar
+AR = ar
+AUTOCONF = ${SHELL} /home/svu/CVS/libgnomekbd/missing --run autoconf
+AUTOHEADER = ${SHELL} /home/svu/CVS/libgnomekbd/missing --run autoheader
+AUTOMAKE = ${SHELL} /home/svu/CVS/libgnomekbd/missing --run automake-1.9
+AWK = gawk
+CATALOGS = ru.gmo
+CATOBJEXT = .gmo
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2
+CPP = gcc -E
+CPPFLAGS =
+CXX = g++
+CXXCPP = g++ -E
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2
+CYGPATH_W = echo
+DATADIRNAME = share
+DBUS_CFLAGS = -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include
+DBUS_LIBS = -ldbus-glib-1 -ldbus-1 -lglib-2.0
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+ECHO = echo
+ECHO_C =
+ECHO_N = -n
+ECHO_T =
+EGREP = /bin/grep -E
+EXEEXT =
+F77 =
+FFLAGS =
+GCONF_CFLAGS = -DORBIT2=1 -pthread -I/usr/include/gconf/2 -I/usr/include/orbit-2.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include
+GCONF_LIBS = -pthread -lgconf-2 -lORBit-2 -lm -lgmodule-2.0 -ldl -lgthread-2.0 -lglib-2.0
+GETTEXT_PACKAGE = libgnomekbd
+GMOFILES = ru.gmo
+GMSGFMT = /usr/bin/msgfmt
+GREP = /bin/grep
+GTK_CFLAGS = -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include
+GTK_LIBS = -lgtk-x11-2.0 -latk-1.0 -lgdk-x11-2.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lfontconfig -lXext -lXrender -lXinerama -lXi -lXrandr -lXcursor -lXfixes -lpango-1.0 -lcairo -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0 -lX11
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s
+INSTOBJEXT = .mo
+INTLLIBS =
+INTLTOOL_CAVES_RULE = %.caves: %.caves.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_DESKTOP_RULE = %.desktop: %.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_DIRECTORY_RULE = %.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_EXTRACT = $(top_builddir)/intltool-extract
+INTLTOOL_ICONV = /usr/bin/iconv
+INTLTOOL_KBD_RULE = %.kbd: %.kbd.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -m -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_KEYS_RULE = %.keys: %.keys.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_MERGE = $(top_builddir)/intltool-merge
+INTLTOOL_MSGFMT = /usr/bin/msgfmt
+INTLTOOL_MSGMERGE = /usr/bin/msgmerge
+INTLTOOL_OAF_RULE = %.oaf: %.oaf.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -p $(top_srcdir)/po $< $@
+INTLTOOL_PERL = /usr/bin/perl
+INTLTOOL_PONG_RULE = %.pong: %.pong.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_PROP_RULE = %.prop: %.prop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_SCHEMAS_RULE = %.schemas: %.schemas.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_SERVER_RULE = %.server: %.server.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_SERVICE_RULE = %.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_SHEET_RULE = %.sheet: %.sheet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_SOUNDLIST_RULE = %.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_THEME_RULE = %.theme: %.theme.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_UI_RULE = %.ui: %.ui.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_UPDATE = $(top_builddir)/intltool-update
+INTLTOOL_XAM_RULE = %.xam: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_XGETTEXT = /usr/bin/xgettext
+INTLTOOL_XML_NOMERGE_RULE = %.xml: %.xml.in $(INTLTOOL_MERGE) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u /tmp $< $@
+INTLTOOL_XML_RULE = %.xml: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+LDFLAGS =
+LIBGLADE_CFLAGS = -I/usr/include/libglade-2.0 -I/usr/include/gtk-2.0 -I/usr/include/libxml2 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include
+LIBGLADE_LIBS = -lglade-2.0 -lgtk-x11-2.0 -lxml2 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lfontconfig -lXext -lXrender -lXinerama -lXi -lXrandr -lXcursor -lXfixes -lpango-1.0 -lcairo -lX11 -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0
+LIBGNOMEUI_CFLAGS = -DORBIT2=1 -pthread -I/usr/include/libgnomeui-2.0 -I/usr/include/libgnome-2.0 -I/usr/include/libgnomecanvas-2.0 -I/usr/include/gtk-2.0 -I/usr/include/libart-2.0 -I/usr/include/gconf/2 -I/usr/include/libbonoboui-2.0 -I/usr/include/gnome-vfs-2.0 -I/usr/lib/gnome-vfs-2.0/include -I/usr/include/gnome-keyring-1 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/orbit-2.0 -I/usr/include/libbonobo-2.0 -I/usr/include/bonobo-activation-2.0 -I/usr/include/pango-1.0 -I/usr/include/freetype2 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/libxml2
+LIBGNOMEUI_LIBS = -pthread -lgnomeui-2 -lSM -lICE -lbonoboui-2 -lgnome-keyring -lxml2 -lgnomecanvas-2 -lgnome-2 -lpopt -lart_lgpl_2 -lpangoft2-1.0 -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lpangocairo-1.0 -lfontconfig -lXext -lXrender -lXinerama -lXi -lXrandr -lXcursor -lXfixes -lpango-1.0 -lcairo -lX11 -lbonobo-2 -lgnomevfs-2 -lbonobo-activation -lgconf-2 -lgobject-2.0 -lORBit-2 -lm -lgmodule-2.0 -ldl -lgthread-2.0 -lglib-2.0
+LIBGNOME_CFLAGS = -DORBIT2=1 -pthread -I/usr/include/libgnome-2.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/orbit-2.0 -I/usr/include/libbonobo-2.0 -I/usr/include/gconf/2 -I/usr/include/gnome-vfs-2.0 -I/usr/lib/gnome-vfs-2.0/include -I/usr/include/bonobo-activation-2.0
+LIBGNOME_LIBS = -pthread -lgnome-2 -lpopt -lbonobo-2 -lgnomevfs-2 -lbonobo-activation -lgconf-2 -lgobject-2.0 -lORBit-2 -lm -lgmodule-2.0 -ldl -lgthread-2.0 -lglib-2.0
+LIBOBJS =
+LIBS =
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LIBXKLAVIER_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/libxml2
+LIBXKLAVIER_LIBS = -lxklavier -lgobject-2.0 -lglib-2.0 -lxml2
+LN_S = ln -s
+LTLIBOBJS =
+MAINT =
+MAINTAINER_MODE_FALSE = #
+MAINTAINER_MODE_TRUE =
+MAKEINFO = ${SHELL} /home/svu/CVS/libgnomekbd/missing --run makeinfo
+MKINSTALLDIRS = ./mkinstalldirs
+MSGFMT = /usr/bin/msgfmt
+OBJEXT = o
+PACKAGE = libgnomekbd
+PACKAGE_BUGREPORT =
+PACKAGE_NAME = libgnomekbd
+PACKAGE_STRING = libgnomekbd 0.1
+PACKAGE_TARNAME = libgnomekbd
+PACKAGE_VERSION = 0.1
+PATH_SEPARATOR = :
+PKG_CONFIG = /usr/bin/pkg-config
+POFILES = ru.po
+POSUB = po
+PO_IN_DATADIR_FALSE =
+PO_IN_DATADIR_TRUE =
+RANLIB = ranlib
+SET_MAKE =
+SHELL = /bin/bash
+STRIP = strip
+USE_NLS = yes
+VERSION = 0.1
+WARN_CFLAGS = -Wall -Wmissing-prototypes
+XGETTEXT = /usr/bin/xgettext
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+ac_ct_F77 =
+am__fastdepCC_FALSE = #
+am__fastdepCC_TRUE =
+am__fastdepCXX_FALSE = #
+am__fastdepCXX_TRUE =
+am__include = include
+am__leading_dot = .
+am__quote =
+am__tar = ${AMTAR} chof - "$$tardir"
+am__untar = ${AMTAR} xf -
+bindir = ${exec_prefix}/bin
+build = i686-pc-linux-gnu
+build_alias =
+build_cpu = i686
+build_os = linux-gnu
+build_vendor = pc
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host = i686-pc-linux-gnu
+host_alias =
+host_cpu = i686
+host_os = linux-gnu
+host_vendor = pc
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = /home/svu/CVS/libgnomekbd/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${prefix}/share/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = mkdir -p --
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+sysconfdir = ${prefix}/etc
+target_alias =
+lib_LTLIBRARIES = libgnomekbd.la
+libgnomekbd_la_CFLAGS = \
+ -I$(top_srcdir) -Wall -Werror \
+ $(DBUS_CFLAGS) \
+ $(GTK_CFLAGS) \
+ $(GCONF_CFLAGS) \
+ $(LIBGNOME_CFLAGS) \
+ $(LIBXKLAVIER_CFLAGS) \
+ -I$(top_srcdir)/intl \
+ -DSYS_PLUGIN_DIR=\"$(libdir)/gnomekbd/\" \
+ -DG_LOG_DOMAIN=\"GnomeKbdIndicator\" \
+ -DGLADEDIR=\"$(gladedir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBDIR=\"$(libdir)\"
+
+libgnomekbd_la_LDFLAGS = \
+ $(GCONF_LIBS)
+
+libgnomekbd_la_SOURCES = gkb-keyboard-config.c \
+ gkb-desktop-config.c \
+ gkb-indicator-config.c \
+ gkb-util.c \
+ gkb-indicator.c \
+ gkb-indicator-marshal.c \
+ gkb-indicator-plugin-manager.c \
+ gkb-config-registry.c \
+ gkb-keyboard-drawing-marshal.c \
+ gkb-keyboard-drawing.c
+
+BUILT_SOURCES = gkb-indicator-marshal.c \
+ gkb-indicator-marshal.h \
+ gkb-config-registry-server.h \
+ gkb-config-registry-client.h \
+ gkb-keyboard-drawing-marshal.c \
+ gkb-keyboard-drawing-marshal.h
+
+CLEANFILES = \
+ $(BUILT_SOURCES)
+
+gnomekbdincdir = $(includedir)/libgnomekbd
+gnomekbdinc_HEADERS = \
+ gkb-desktop-config.h \
+ gkb-keyboard-config.h \
+ gkb-config-registry-client.h \
+ gkb-config-registry.h \
+ gkb-indicator.h \
+ gkb-indicator-config.h \
+ gkb-indicator-plugin.h \
+ gkb-keyboard-drawing.h \
+ gkb-util.h
+
+noinst_HEADERS = gkb-indicator-plugin-manager.h \
+ $(extra_nih) \
+ gkb-config-private.h \
+ gkb-config-registry-server.h
+
+EXTRA_DIST = gkb-indicator-marshal.list \
+ gkb-keyboard-drawing-marshal.list \
+ gkb-config-registry.xml \
+ $(glade_DATA)
+
+GLIB_GENMARSHAL = $(shell pkg-config --variable=glib_genmarshal glib-2.0)
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libgnomekbd/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu libgnomekbd/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libgnomekbd.la: $(libgnomekbd_la_OBJECTS) $(libgnomekbd_la_DEPENDENCIES)
+ $(LINK) -rpath $(libdir) $(libgnomekbd_la_LDFLAGS) $(libgnomekbd_la_OBJECTS) $(libgnomekbd_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+include ./$(DEPDIR)/libgnomekbd_la-gkb-config-registry.Plo
+include ./$(DEPDIR)/libgnomekbd_la-gkb-desktop-config.Plo
+include ./$(DEPDIR)/libgnomekbd_la-gkb-indicator-config.Plo
+include ./$(DEPDIR)/libgnomekbd_la-gkb-indicator-marshal.Plo
+include ./$(DEPDIR)/libgnomekbd_la-gkb-indicator-plugin-manager.Plo
+include ./$(DEPDIR)/libgnomekbd_la-gkb-indicator.Plo
+include ./$(DEPDIR)/libgnomekbd_la-gkb-keyboard-config.Plo
+include ./$(DEPDIR)/libgnomekbd_la-gkb-keyboard-drawing-marshal.Plo
+include ./$(DEPDIR)/libgnomekbd_la-gkb-keyboard-drawing.Plo
+include ./$(DEPDIR)/libgnomekbd_la-gkb-util.Plo
+
+.c.o:
+ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(COMPILE) -c $<
+
+.c.obj:
+ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+# source='$<' object='$@' libtool=yes \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(LTCOMPILE) -c -o $@ $<
+
+libgnomekbd_la-gkb-keyboard-config.lo: gkb-keyboard-config.c
+ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -MT libgnomekbd_la-gkb-keyboard-config.lo -MD -MP -MF "$(DEPDIR)/libgnomekbd_la-gkb-keyboard-config.Tpo" -c -o libgnomekbd_la-gkb-keyboard-config.lo `test -f 'gkb-keyboard-config.c' || echo '$(srcdir)/'`gkb-keyboard-config.c; \
+ then mv -f "$(DEPDIR)/libgnomekbd_la-gkb-keyboard-config.Tpo" "$(DEPDIR)/libgnomekbd_la-gkb-keyboard-config.Plo"; else rm -f "$(DEPDIR)/libgnomekbd_la-gkb-keyboard-config.Tpo"; exit 1; fi
+# source='gkb-keyboard-config.c' object='libgnomekbd_la-gkb-keyboard-config.lo' libtool=yes \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -c -o libgnomekbd_la-gkb-keyboard-config.lo `test -f 'gkb-keyboard-config.c' || echo '$(srcdir)/'`gkb-keyboard-config.c
+
+libgnomekbd_la-gkb-desktop-config.lo: gkb-desktop-config.c
+ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -MT libgnomekbd_la-gkb-desktop-config.lo -MD -MP -MF "$(DEPDIR)/libgnomekbd_la-gkb-desktop-config.Tpo" -c -o libgnomekbd_la-gkb-desktop-config.lo `test -f 'gkb-desktop-config.c' || echo '$(srcdir)/'`gkb-desktop-config.c; \
+ then mv -f "$(DEPDIR)/libgnomekbd_la-gkb-desktop-config.Tpo" "$(DEPDIR)/libgnomekbd_la-gkb-desktop-config.Plo"; else rm -f "$(DEPDIR)/libgnomekbd_la-gkb-desktop-config.Tpo"; exit 1; fi
+# source='gkb-desktop-config.c' object='libgnomekbd_la-gkb-desktop-config.lo' libtool=yes \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -c -o libgnomekbd_la-gkb-desktop-config.lo `test -f 'gkb-desktop-config.c' || echo '$(srcdir)/'`gkb-desktop-config.c
+
+libgnomekbd_la-gkb-indicator-config.lo: gkb-indicator-config.c
+ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -MT libgnomekbd_la-gkb-indicator-config.lo -MD -MP -MF "$(DEPDIR)/libgnomekbd_la-gkb-indicator-config.Tpo" -c -o libgnomekbd_la-gkb-indicator-config.lo `test -f 'gkb-indicator-config.c' || echo '$(srcdir)/'`gkb-indicator-config.c; \
+ then mv -f "$(DEPDIR)/libgnomekbd_la-gkb-indicator-config.Tpo" "$(DEPDIR)/libgnomekbd_la-gkb-indicator-config.Plo"; else rm -f "$(DEPDIR)/libgnomekbd_la-gkb-indicator-config.Tpo"; exit 1; fi
+# source='gkb-indicator-config.c' object='libgnomekbd_la-gkb-indicator-config.lo' libtool=yes \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -c -o libgnomekbd_la-gkb-indicator-config.lo `test -f 'gkb-indicator-config.c' || echo '$(srcdir)/'`gkb-indicator-config.c
+
+libgnomekbd_la-gkb-util.lo: gkb-util.c
+ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -MT libgnomekbd_la-gkb-util.lo -MD -MP -MF "$(DEPDIR)/libgnomekbd_la-gkb-util.Tpo" -c -o libgnomekbd_la-gkb-util.lo `test -f 'gkb-util.c' || echo '$(srcdir)/'`gkb-util.c; \
+ then mv -f "$(DEPDIR)/libgnomekbd_la-gkb-util.Tpo" "$(DEPDIR)/libgnomekbd_la-gkb-util.Plo"; else rm -f "$(DEPDIR)/libgnomekbd_la-gkb-util.Tpo"; exit 1; fi
+# source='gkb-util.c' object='libgnomekbd_la-gkb-util.lo' libtool=yes \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -c -o libgnomekbd_la-gkb-util.lo `test -f 'gkb-util.c' || echo '$(srcdir)/'`gkb-util.c
+
+libgnomekbd_la-gkb-indicator.lo: gkb-indicator.c
+ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -MT libgnomekbd_la-gkb-indicator.lo -MD -MP -MF "$(DEPDIR)/libgnomekbd_la-gkb-indicator.Tpo" -c -o libgnomekbd_la-gkb-indicator.lo `test -f 'gkb-indicator.c' || echo '$(srcdir)/'`gkb-indicator.c; \
+ then mv -f "$(DEPDIR)/libgnomekbd_la-gkb-indicator.Tpo" "$(DEPDIR)/libgnomekbd_la-gkb-indicator.Plo"; else rm -f "$(DEPDIR)/libgnomekbd_la-gkb-indicator.Tpo"; exit 1; fi
+# source='gkb-indicator.c' object='libgnomekbd_la-gkb-indicator.lo' libtool=yes \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -c -o libgnomekbd_la-gkb-indicator.lo `test -f 'gkb-indicator.c' || echo '$(srcdir)/'`gkb-indicator.c
+
+libgnomekbd_la-gkb-indicator-marshal.lo: gkb-indicator-marshal.c
+ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -MT libgnomekbd_la-gkb-indicator-marshal.lo -MD -MP -MF "$(DEPDIR)/libgnomekbd_la-gkb-indicator-marshal.Tpo" -c -o libgnomekbd_la-gkb-indicator-marshal.lo `test -f 'gkb-indicator-marshal.c' || echo '$(srcdir)/'`gkb-indicator-marshal.c; \
+ then mv -f "$(DEPDIR)/libgnomekbd_la-gkb-indicator-marshal.Tpo" "$(DEPDIR)/libgnomekbd_la-gkb-indicator-marshal.Plo"; else rm -f "$(DEPDIR)/libgnomekbd_la-gkb-indicator-marshal.Tpo"; exit 1; fi
+# source='gkb-indicator-marshal.c' object='libgnomekbd_la-gkb-indicator-marshal.lo' libtool=yes \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -c -o libgnomekbd_la-gkb-indicator-marshal.lo `test -f 'gkb-indicator-marshal.c' || echo '$(srcdir)/'`gkb-indicator-marshal.c
+
+libgnomekbd_la-gkb-indicator-plugin-manager.lo: gkb-indicator-plugin-manager.c
+ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -MT libgnomekbd_la-gkb-indicator-plugin-manager.lo -MD -MP -MF "$(DEPDIR)/libgnomekbd_la-gkb-indicator-plugin-manager.Tpo" -c -o libgnomekbd_la-gkb-indicator-plugin-manager.lo `test -f 'gkb-indicator-plugin-manager.c' || echo '$(srcdir)/'`gkb-indicator-plugin-manager.c; \
+ then mv -f "$(DEPDIR)/libgnomekbd_la-gkb-indicator-plugin-manager.Tpo" "$(DEPDIR)/libgnomekbd_la-gkb-indicator-plugin-manager.Plo"; else rm -f "$(DEPDIR)/libgnomekbd_la-gkb-indicator-plugin-manager.Tpo"; exit 1; fi
+# source='gkb-indicator-plugin-manager.c' object='libgnomekbd_la-gkb-indicator-plugin-manager.lo' libtool=yes \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -c -o libgnomekbd_la-gkb-indicator-plugin-manager.lo `test -f 'gkb-indicator-plugin-manager.c' || echo '$(srcdir)/'`gkb-indicator-plugin-manager.c
+
+libgnomekbd_la-gkb-config-registry.lo: gkb-config-registry.c
+ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -MT libgnomekbd_la-gkb-config-registry.lo -MD -MP -MF "$(DEPDIR)/libgnomekbd_la-gkb-config-registry.Tpo" -c -o libgnomekbd_la-gkb-config-registry.lo `test -f 'gkb-config-registry.c' || echo '$(srcdir)/'`gkb-config-registry.c; \
+ then mv -f "$(DEPDIR)/libgnomekbd_la-gkb-config-registry.Tpo" "$(DEPDIR)/libgnomekbd_la-gkb-config-registry.Plo"; else rm -f "$(DEPDIR)/libgnomekbd_la-gkb-config-registry.Tpo"; exit 1; fi
+# source='gkb-config-registry.c' object='libgnomekbd_la-gkb-config-registry.lo' libtool=yes \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -c -o libgnomekbd_la-gkb-config-registry.lo `test -f 'gkb-config-registry.c' || echo '$(srcdir)/'`gkb-config-registry.c
+
+libgnomekbd_la-gkb-keyboard-drawing-marshal.lo: gkb-keyboard-drawing-marshal.c
+ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -MT libgnomekbd_la-gkb-keyboard-drawing-marshal.lo -MD -MP -MF "$(DEPDIR)/libgnomekbd_la-gkb-keyboard-drawing-marshal.Tpo" -c -o libgnomekbd_la-gkb-keyboard-drawing-marshal.lo `test -f 'gkb-keyboard-drawing-marshal.c' || echo '$(srcdir)/'`gkb-keyboard-drawing-marshal.c; \
+ then mv -f "$(DEPDIR)/libgnomekbd_la-gkb-keyboard-drawing-marshal.Tpo" "$(DEPDIR)/libgnomekbd_la-gkb-keyboard-drawing-marshal.Plo"; else rm -f "$(DEPDIR)/libgnomekbd_la-gkb-keyboard-drawing-marshal.Tpo"; exit 1; fi
+# source='gkb-keyboard-drawing-marshal.c' object='libgnomekbd_la-gkb-keyboard-drawing-marshal.lo' libtool=yes \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -c -o libgnomekbd_la-gkb-keyboard-drawing-marshal.lo `test -f 'gkb-keyboard-drawing-marshal.c' || echo '$(srcdir)/'`gkb-keyboard-drawing-marshal.c
+
+libgnomekbd_la-gkb-keyboard-drawing.lo: gkb-keyboard-drawing.c
+ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -MT libgnomekbd_la-gkb-keyboard-drawing.lo -MD -MP -MF "$(DEPDIR)/libgnomekbd_la-gkb-keyboard-drawing.Tpo" -c -o libgnomekbd_la-gkb-keyboard-drawing.lo `test -f 'gkb-keyboard-drawing.c' || echo '$(srcdir)/'`gkb-keyboard-drawing.c; \
+ then mv -f "$(DEPDIR)/libgnomekbd_la-gkb-keyboard-drawing.Tpo" "$(DEPDIR)/libgnomekbd_la-gkb-keyboard-drawing.Plo"; else rm -f "$(DEPDIR)/libgnomekbd_la-gkb-keyboard-drawing.Tpo"; exit 1; fi
+# source='gkb-keyboard-drawing.c' object='libgnomekbd_la-gkb-keyboard-drawing.lo' libtool=yes \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnomekbd_la_CFLAGS) $(CFLAGS) -c -o libgnomekbd_la-gkb-keyboard-drawing.lo `test -f 'gkb-keyboard-drawing.c' || echo '$(srcdir)/'`gkb-keyboard-drawing.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+install-gnomekbdincHEADERS: $(gnomekbdinc_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(gnomekbdincdir)" || $(mkdir_p) "$(DESTDIR)$(gnomekbdincdir)"
+ @list='$(gnomekbdinc_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(gnomekbdincHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(gnomekbdincdir)/$$f'"; \
+ $(gnomekbdincHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(gnomekbdincdir)/$$f"; \
+ done
+
+uninstall-gnomekbdincHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(gnomekbdinc_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(gnomekbdincdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(gnomekbdincdir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(gnomekbdincdir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-gnomekbdincHEADERS
+
+install-exec-am: install-libLTLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-gnomekbdincHEADERS uninstall-info-am \
+ uninstall-libLTLIBRARIES
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-exec \
+ install-exec-am install-gnomekbdincHEADERS install-info \
+ install-info-am install-libLTLIBRARIES install-man \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-gnomekbdincHEADERS uninstall-info-am \
+ uninstall-libLTLIBRARIES
+
+
+%.desktop: %.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+
+gkb-indicator-marshal.h: gkb-indicator-marshal.list
+ $(GLIB_GENMARSHAL) --prefix=gkb_indicator $(srcdir)/gkb-indicator-marshal.list --header > $@
+
+gkb-indicator-marshal.c: gkb-indicator-marshal.h
+ $(GLIB_GENMARSHAL) --prefix=gkb_indicator $(srcdir)/gkb-indicator-marshal.list --body > $@
+
+gkb-config-registry-server.h: gkb-config-registry.xml
+ dbus-binding-tool --prefix=gkb_config_registry --mode=glib-server $< > $@
+
+gkb-config-registry-client.h: gkb-config-registry.xml
+ dbus-binding-tool --prefix=gkb_config_registry --mode=glib-client $< > $@
+
+gkb-keyboard-drawing-marshal.h: gkb-keyboard-drawing-marshal.list
+ ( $(GLIB_GENMARSHAL) --prefix=gkb_keyboard_drawing $(srcdir)/gkb-keyboard-drawing-marshal.list \
+ --header > gkb-keyboard-drawing-marshal.tmp \
+ && mv gkb-keyboard-drawing-marshal.tmp gkb-keyboard-drawing-marshal.h ) \
+ || ( rm -f gkb-keyboard-drawing-marshal.tmp && exit 1 )
+
+gkb-keyboard-drawing-marshal.c: gkb-keyboard-drawing-marshal.h
+ ( $(GLIB_GENMARSHAL) --prefix=gkb_keyboard_drawing $(srcdir)/gkb-keyboard-drawing-marshal.list \
+ --body > gkb-keyboard-drawing-marshal.tmp \
+ && mv gkb-keyboard-drawing-marshal.tmp gkb-keyboard-drawing-marshal.c ) \
+ || ( rm -f gkb-keyboard-drawing-marshal.tmp && exit 1 )
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libgnomekbd/backup/Makefile.am b/libgnomekbd/backup/Makefile.am
new file mode 100644
index 0000000..1052a86
--- /dev/null
+++ b/libgnomekbd/backup/Makefile.am
@@ -0,0 +1,91 @@
+lib_LTLIBRARIES = libgnomekbd.la
+
+libgnomekbd_la_CFLAGS = \
+ -I$(top_srcdir) -Wall -Werror \
+ $(DBUS_CFLAGS) \
+ $(GTK_CFLAGS) \
+ $(GCONF_CFLAGS) \
+ $(LIBGNOME_CFLAGS) \
+ $(LIBXKLAVIER_CFLAGS) \
+ -I$(top_srcdir)/intl \
+ -DSYS_PLUGIN_DIR=\"$(libdir)/gnomekbd/\" \
+ -DG_LOG_DOMAIN=\"GnomeKbdIndicator\" \
+ -DGLADEDIR=\"$(gladedir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBDIR=\"$(libdir)\"
+
+libgnomekbd_la_LDFLAGS = \
+ $(GCONF_LIBS)
+
+libgnomekbd_la_SOURCES = gkb-keyboard-config.c \
+ gkb-desktop-config.c \
+ gkb-indicator-config.c \
+ gkb-util.c \
+ gkb-indicator.c \
+ gkb-indicator-marshal.c \
+ gkb-indicator-plugin-manager.c \
+ gkb-config-registry.c \
+ gkb-keyboard-drawing-marshal.c \
+ gkb-keyboard-drawing.c
+
+BUILT_SOURCES = gkb-indicator-marshal.c \
+ gkb-indicator-marshal.h \
+ gkb-config-registry-server.h \
+ gkb-config-registry-client.h \
+ gkb-keyboard-drawing-marshal.c \
+ gkb-keyboard-drawing-marshal.h
+
+CLEANFILES = \
+ $(BUILT_SOURCES)
+
+gnomekbdincdir = $(includedir)/libgnomekbd
+gnomekbdinc_HEADERS = \
+ gkb-desktop-config.h \
+ gkb-keyboard-config.h \
+ gkb-config-registry-client.h \
+ gkb-config-registry.h \
+ gkb-indicator.h \
+ gkb-indicator-config.h \
+ gkb-indicator-plugin.h \
+ gkb-keyboard-drawing.h \
+ gkb-util.h
+
+@INTLTOOL_DESKTOP_RULE@
+
+noinst_HEADERS = gkb-indicator-plugin-manager.h \
+ $(extra_nih) \
+ gkb-config-private.h \
+ gkb-config-registry-server.h
+
+EXTRA_DIST = gkb-indicator-marshal.list \
+ gkb-keyboard-drawing-marshal.list \
+ gkb-config-registry.xml \
+ $(glade_DATA)
+
+GLIB_GENMARSHAL = $(shell pkg-config --variable=glib_genmarshal glib-2.0)
+
+gkb-indicator-marshal.h: gkb-indicator-marshal.list
+ $(GLIB_GENMARSHAL) --prefix=gkb_indicator $(srcdir)/gkb-indicator-marshal.list --header > $@
+
+gkb-indicator-marshal.c: gkb-indicator-marshal.h
+ $(GLIB_GENMARSHAL) --prefix=gkb_indicator $(srcdir)/gkb-indicator-marshal.list --body > $@
+
+gkb-config-registry-server.h: gkb-config-registry.xml
+ dbus-binding-tool --prefix=gkb_config_registry --mode=glib-server $< > $@
+
+gkb-config-registry-client.h: gkb-config-registry.xml
+ dbus-binding-tool --prefix=gkb_config_registry --mode=glib-client $< > $@
+
+gkb-keyboard-drawing-marshal.h: gkb-keyboard-drawing-marshal.list
+ ( $(GLIB_GENMARSHAL) --prefix=gkb_keyboard_drawing $(srcdir)/gkb-keyboard-drawing-marshal.list \
+ --header > gkb-keyboard-drawing-marshal.tmp \
+ && mv gkb-keyboard-drawing-marshal.tmp gkb-keyboard-drawing-marshal.h ) \
+ || ( rm -f gkb-keyboard-drawing-marshal.tmp && exit 1 )
+
+gkb-keyboard-drawing-marshal.c: gkb-keyboard-drawing-marshal.h
+ ( $(GLIB_GENMARSHAL) --prefix=gkb_keyboard_drawing $(srcdir)/gkb-keyboard-drawing-marshal.list \
+ --body > gkb-keyboard-drawing-marshal.tmp \
+ && mv gkb-keyboard-drawing-marshal.tmp gkb-keyboard-drawing-marshal.c ) \
+ || ( rm -f gkb-keyboard-drawing-marshal.tmp && exit 1 )
+
diff --git a/libgnomekbd/backup/gkb-config-private.h b/libgnomekbd/backup/gkb-config-private.h
new file mode 100644
index 0000000..a0afba4
--- /dev/null
+++ b/libgnomekbd/backup/gkb-config-private.h
@@ -0,0 +1,98 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GKB_CONFIG_PRIVATE_H__
+#define __GKB_CONFIG_PRIVATE_H__
+
+#include "libgnomekbd/gkb-desktop-config.h"
+#include "libgnomekbd/gkb-keyboard-config.h"
+
+#define GKB_CONFIG_KEY_PREFIX "/desktop/gnome/peripherals/keyboard"
+
+extern const gchar GKB_PREVIEW_CONFIG_DIR[];
+extern const gchar GKB_PREVIEW_CONFIG_KEY_X[];
+extern const gchar GKB_PREVIEW_CONFIG_KEY_Y[];
+extern const gchar GKB_PREVIEW_CONFIG_KEY_WIDTH[];
+extern const gchar GKB_PREVIEW_CONFIG_KEY_HEIGHT[];
+
+/**
+ * General config functions (private)
+ */
+extern void
+ gkb_desktop_config_add_listener (GConfClient * conf_client,
+ const gchar * key,
+ GConfClientNotifyFunc func,
+ gpointer user_data, int *pid);
+
+
+extern void
+ gkb_desktop_config_remove_listener (GConfClient * conf_client, int *pid);
+
+extern void gkb_keyboard_config_model_set (GkbKeyboardConfig *
+ kbd_config,
+ const gchar * model_name);
+
+extern void gkb_keyboard_config_layouts_reset (GkbKeyboardConfig *
+ kbd_config);
+extern void gkb_keyboard_config_layouts_add (GkbKeyboardConfig *
+ kbd_config,
+ const gchar * layout_name,
+ const gchar * variant_name);
+
+extern void gkb_keyboard_config_layouts_reset (GkbKeyboardConfig *
+ kbd_config);
+extern void gkb_keyboard_config_options_reset (GkbKeyboardConfig *
+ kbd_config);
+
+extern void gkb_keyboard_config_options_add (GkbKeyboardConfig *
+ kbd_config,
+ const gchar * group_name,
+ const gchar * option_name);
+extern gboolean gkb_keyboard_config_options_is_set (GkbKeyboardConfig *
+ kbd_config,
+ const gchar *
+ group_name,
+ const gchar *
+ option_name);
+
+extern gboolean gkb_keyboard_config_dump_settings (GkbKeyboardConfig *
+ kbd_config,
+ const char *file_name);
+
+extern void gkb_keyboard_config_start_listen (GkbKeyboardConfig *
+ kbd_config,
+ GConfClientNotifyFunc func,
+ gpointer user_data);
+
+extern void gkb_keyboard_config_stop_listen (GkbKeyboardConfig *
+ kbd_config);
+
+extern gboolean gkb_keyboard_config_get_lv_descriptions (XklConfigRegistry
+ * config_registry,
+ const gchar *
+ layout_name,
+ const gchar *
+ variant_name,
+ gchar **
+ layout_short_descr,
+ gchar **
+ layout_descr,
+ gchar **
+ variant_short_descr,
+ gchar **
+ variant_descr);
+
+#endif
diff --git a/libgnomekbd/backup/gkb-config-registry.c b/libgnomekbd/backup/gkb-config-registry.c
new file mode 100644
index 0000000..0f0b71d
--- /dev/null
+++ b/libgnomekbd/backup/gkb-config-registry.c
@@ -0,0 +1,166 @@
+#include <config.h>
+
+#include <gdk/gdkx.h>
+
+#include <gkb-config-registry.h>
+#include <gkb-config-registry-server.h>
+#include <gkb-keyboard-config.h>
+
+static GObjectClass *parent_class = NULL;
+
+gboolean
+ gkb_config_registry_get_current_descriptions_as_utf8
+ (GkbConfigRegistry * registry,
+ gchar *** short_layout_descriptions,
+ gchar *** long_layout_descriptions,
+ gchar *** short_variant_descriptions,
+ gchar *** long_variant_descriptions, GError ** error) {
+ XklConfigRec *xkl_config;
+ char **pl, **pv;
+ guint total_layouts;
+ gchar **sld, **lld, **svd, **lvd;
+
+ if (!registry->registry) {
+ registry->registry =
+ xkl_config_registry_get_instance (registry->engine);
+
+ xkl_config_registry_load (registry->registry);
+ }
+
+ if (!
+ (xkl_engine_get_features (registry->engine) &
+ XKLF_MULTIPLE_LAYOUTS_SUPPORTED))
+ return FALSE;
+
+ xkl_config = xkl_config_rec_new ();
+
+ if (!xkl_config_rec_get_from_server (xkl_config, registry->engine))
+ return FALSE;
+
+ pl = xkl_config->layouts;
+ pv = xkl_config->variants;
+ total_layouts = g_strv_length (xkl_config->layouts);
+ sld = *short_layout_descriptions =
+ g_new0 (char *, total_layouts + 1);
+ lld = *long_layout_descriptions =
+ g_new0 (char *, total_layouts + 1);
+ svd = *short_variant_descriptions =
+ g_new0 (char *, total_layouts + 1);
+ lvd = *long_variant_descriptions =
+ g_new0 (char *, total_layouts + 1);
+
+ while (pl != NULL && *pl != NULL) {
+ XklConfigItem item;
+
+ g_snprintf (item.name, sizeof item.name, "%s", *pl);
+ if (xkl_config_registry_find_layout
+ (registry->registry, &item)) {
+ *sld++ = g_strdup (item.short_description);
+ *lld++ = g_strdup (item.description);
+ } else {
+ *sld++ = g_strdup ("");
+ *lld++ = g_strdup ("");
+ }
+
+ if (*pv != NULL) {
+ g_snprintf (item.name, sizeof item.name, "%s",
+ *pv);
+ if (xkl_config_registry_find_variant
+ (registry->registry, *pl, &item)) {
+ *svd = g_strdup (item.short_description);
+ *lvd = g_strdup (item.description);
+ } else {
+ *svd++ = g_strdup ("");
+ *lvd++ = g_strdup ("");
+ }
+ } else {
+ *svd++ = g_strdup ("");
+ *lvd++ = g_strdup ("");
+ }
+
+ pl++;
+ pv++;
+ }
+ g_object_unref (G_OBJECT (xkl_config));
+
+ return TRUE;
+}
+
+G_DEFINE_TYPE (GkbConfigRegistry, gkb_config_registry, G_TYPE_OBJECT)
+static void
+finalize (GObject * object)
+{
+ GkbConfigRegistry *registry;
+
+ registry = GKB_CONFIG_REGISTRY (object);
+ if (registry->registry == NULL) {
+ return;
+ }
+
+ g_object_unref (registry->registry);
+ registry->registry = NULL;
+
+ g_object_unref (registry->engine);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gkb_config_registry_class_init (GkbConfigRegistryClass * klass)
+{
+ GError *error = NULL;
+ GObjectClass *object_class;
+
+ /* Init the DBus connection, per-klass */
+ klass->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (klass->connection == NULL) {
+ g_warning ("Unable to connect to dbus: %s",
+ error->message);
+ g_error_free (error);
+ return;
+ }
+
+ dbus_g_object_type_install_info (GKB_CONFIG_TYPE_REGISTRY,
+ &dbus_glib_gkb_config_registry_object_info);
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = finalize;
+
+ parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+gkb_config_registry_init (GkbConfigRegistry * registry)
+{
+ GError *error = NULL;
+ DBusGProxy *driver_proxy;
+ GkbConfigRegistryClass *klass =
+ GKB_CONFIG_REGISTRY_GET_CLASS (registry);
+ unsigned request_ret;
+
+ /* Register DBUS path */
+ dbus_g_connection_register_g_object (klass->connection,
+ "/org/gnome/GkbConfigRegistry",
+ G_OBJECT (registry));
+
+ /* Register the service name, the constant here are defined in dbus-glib-bindings.h */
+ driver_proxy = dbus_g_proxy_new_for_name (klass->connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+
+ if (!org_freedesktop_DBus_request_name
+ (driver_proxy, "org.gnome.GkbConfigRegistry", 0,
+ &request_ret, &error)) {
+ g_warning ("Unable to register service: %s",
+ error->message);
+ g_error_free (error);
+ }
+ g_object_unref (driver_proxy);
+
+ /* Init libxklavier stuff */
+ registry->engine = xkl_engine_get_instance (GDK_DISPLAY ());
+ /* Lazy initialization */
+ registry->registry = NULL;
+}
diff --git a/libgnomekbd/backup/gkb-config-registry.h b/libgnomekbd/backup/gkb-config-registry.h
new file mode 100644
index 0000000..cf6d524
--- /dev/null
+++ b/libgnomekbd/backup/gkb-config-registry.h
@@ -0,0 +1,44 @@
+#ifndef __GKB_CONFIG_REGISTRY_H__
+#define __GKB_CONFIG_REGISTRY_H__
+
+#include <dbus/dbus-glib-bindings.h>
+#include <libxklavier/xklavier.h>
+
+typedef struct GkbConfigRegistry GkbConfigRegistry;
+typedef struct GkbConfigRegistryClass GkbConfigRegistryClass;
+
+struct GkbConfigRegistry {
+ GObject parent;
+
+ XklEngine *engine;
+ XklConfigRegistry *registry;
+};
+
+struct GkbConfigRegistryClass {
+ GObjectClass parent;
+ DBusGConnection *connection;
+};
+
+#define GKB_CONFIG_TYPE_REGISTRY (gkb_config_registry_get_type ())
+#define GKB_CONFIG_REGISTRY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GKB_CONFIG_TYPE_REGISTRY, GkbConfigRegistry))
+#define GKB_CONFIG_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GKB_CONFIG_TYPE_REGISTRY, GkbConfigRegistryClass))
+#define GKB_IS_CONFIG_REGISTRY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GKB_CONFIG_TYPE_REGISTRY))
+#define GKB_IS_CONFIG_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GKB_CONFIG_TYPE_REGISTRY))
+#define GKB_CONFIG_REGISTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GKB_CONFIG_TYPE_REGISTRY, GkbConfigRegistryClass))
+
+
+/**
+ * DBUS server
+ */
+
+extern GType gkb_config_registry_get_type (void);
+
+extern gboolean
+ gkb_config_registry_get_current_descriptions_as_utf8
+ (GkbConfigRegistry * registry,
+ gchar *** short_layout_descriptions,
+ gchar *** long_layout_descriptions,
+ gchar *** short_variant_descriptions,
+ gchar *** long_variant_descriptions, GError ** error);
+
+#endif
diff --git a/libgnomekbd/backup/gkb-config-registry.xml b/libgnomekbd/backup/gkb-config-registry.xml
new file mode 100644
index 0000000..359d874
--- /dev/null
+++ b/libgnomekbd/backup/gkb-config-registry.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<node name="/org/gnome/GkbConfigRegistry">
+ <interface name="org.gnome.GkbConfigRegistry">
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="gkb_config_registry"/>
+ <method name="GetCurrentDescriptionsAsUtf8">
+ <arg type="as" name="shortLayoutDescriptions" direction="out" />
+ <arg type="as" name="longLayoutDescriptions" direction="out" />
+ <arg type="as" name="shortVariantDescriptions" direction="out" />
+ <arg type="as" name="longVariantDescriptions" direction="out" />
+ </method>
+ <!-- Add more methods/signals if you want -->
+ </interface>
+</node>
diff --git a/libgnomekbd/backup/gkb-desktop-config.c b/libgnomekbd/backup/gkb-desktop-config.c
new file mode 100644
index 0000000..fa88455
--- /dev/null
+++ b/libgnomekbd/backup/gkb-desktop-config.c
@@ -0,0 +1,403 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <X11/keysym.h>
+
+#include <glib/gi18n.h>
+#include <gdk/gdkx.h>
+#include <libgnome/gnome-program.h>
+
+#include <gkb-desktop-config.h>
+#include <gkb-config-private.h>
+
+#include <gkb-config-registry-client.h>
+
+/**
+ * GkbDesktopConfig
+ */
+#define GKB_DESKTOP_CONFIG_KEY_PREFIX GKB_CONFIG_KEY_PREFIX "/general"
+
+const gchar GKB_DESKTOP_CONFIG_DIR[] = GKB_DESKTOP_CONFIG_KEY_PREFIX;
+const gchar GKB_DESKTOP_CONFIG_KEY_DEFAULT_GROUP[] =
+ GKB_DESKTOP_CONFIG_KEY_PREFIX "/defaultGroup";
+const gchar GKB_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW[] =
+ GKB_DESKTOP_CONFIG_KEY_PREFIX "/groupPerWindow";
+const gchar GKB_DESKTOP_CONFIG_KEY_HANDLE_INDICATORS[] =
+ GKB_DESKTOP_CONFIG_KEY_PREFIX "/handleIndicators";
+const gchar GKB_DESKTOP_CONFIG_KEY_LAYOUT_NAMES_AS_GROUP_NAMES[]
+ = GKB_DESKTOP_CONFIG_KEY_PREFIX "/layoutNamesAsGroupNames";
+
+/**
+ * static common functions
+ */
+
+static gboolean
+gkb_desktop_config_get_remote_lv_descriptions_utf8 (gchar *** sld,
+ gchar *** lld,
+ gchar *** svd,
+ gchar *** lvd)
+{
+ DBusGProxy *proxy;
+ DBusGConnection *connection;
+ GError *error = NULL;
+
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (connection == NULL) {
+ g_warning ("Unable to connect to dbus: %s\n",
+ error->message);
+ g_error_free (error);
+ /* Basically here, there is a problem, since there is no dbus :) */
+ return False;
+ }
+
+/* This won't trigger activation! */
+ proxy = dbus_g_proxy_new_for_name (connection,
+ "org.gnome.GkbConfigRegistry",
+ "/org/gnome/GkbConfigRegistry",
+ "org.gnome.GkbConfigRegistry");
+
+/* The method call will trigger activation, more on that later */
+ if (!org_gnome_GkbConfigRegistry_get_current_descriptions_as_utf8
+ (proxy, sld, lld, svd, lvd, &error)) {
+ /* Method failed, the GError is set, let's warn everyone */
+ g_warning ("Woops remote method failed: %s",
+ error->message);
+ g_error_free (error);
+ return False;
+ }
+ return True;
+}
+
+void
+gkb_desktop_config_add_listener (GConfClient * conf_client,
+ const gchar * key,
+ GConfClientNotifyFunc func,
+ gpointer user_data, int *pid)
+{
+ GError *gerror = NULL;
+ xkl_debug (150, "Listening to [%s]\n", key);
+ *pid = gconf_client_notify_add (conf_client,
+ key, func, user_data, NULL,
+ &gerror);
+ if (0 == *pid) {
+ g_warning ("Error listening for configuration: [%s]\n",
+ gerror->message);
+ g_error_free (gerror);
+ }
+}
+
+void
+gkb_desktop_config_remove_listener (GConfClient * conf_client, int *pid)
+{
+ if (*pid != 0) {
+ gconf_client_notify_remove (conf_client, *pid);
+ *pid = 0;
+ }
+}
+
+/**
+ * extern GkbDesktopConfig config functions
+ */
+void
+gkb_desktop_config_init (GkbDesktopConfig * config,
+ GConfClient * conf_client, XklEngine * engine)
+{
+ GError *gerror = NULL;
+
+ memset (config, 0, sizeof (*config));
+ config->conf_client = conf_client;
+ config->engine = engine;
+ g_object_ref (config->conf_client);
+
+ gconf_client_add_dir (config->conf_client,
+ GKB_DESKTOP_CONFIG_DIR,
+ GCONF_CLIENT_PRELOAD_NONE, &gerror);
+ if (gerror != NULL) {
+ g_warning ("err: %s\n", gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+}
+
+void
+gkb_desktop_config_term (GkbDesktopConfig * config)
+{
+ g_object_unref (config->conf_client);
+ config->conf_client = NULL;
+}
+
+void
+gkb_desktop_config_load_from_gconf (GkbDesktopConfig * config)
+{
+ GError *gerror = NULL;
+
+ config->group_per_app =
+ gconf_client_get_bool (config->conf_client,
+ GKB_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ config->group_per_app = FALSE;
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ xkl_debug (150, "group_per_app: %d\n", config->group_per_app);
+
+ config->handle_indicators =
+ gconf_client_get_bool (config->conf_client,
+ GKB_DESKTOP_CONFIG_KEY_HANDLE_INDICATORS,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ config->handle_indicators = FALSE;
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ xkl_debug (150, "handle_indicators: %d\n",
+ config->handle_indicators);
+
+ config->layout_names_as_group_names =
+ gconf_client_get_bool (config->conf_client,
+ GKB_DESKTOP_CONFIG_KEY_LAYOUT_NAMES_AS_GROUP_NAMES,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ config->layout_names_as_group_names = TRUE;
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ xkl_debug (150, "layout_names_as_group_names: %d\n",
+ config->layout_names_as_group_names);
+
+ config->default_group =
+ gconf_client_get_int (config->conf_client,
+ GKB_DESKTOP_CONFIG_KEY_DEFAULT_GROUP,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ config->default_group = -1;
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+
+ if (config->default_group < -1
+ || config->default_group >=
+ xkl_engine_get_max_num_groups (config->engine))
+ config->default_group = -1;
+ xkl_debug (150, "default_group: %d\n", config->default_group);
+}
+
+void
+gkb_desktop_config_save_to_gconf (GkbDesktopConfig * config)
+{
+ GConfChangeSet *cs;
+ GError *gerror = NULL;
+
+ cs = gconf_change_set_new ();
+
+ gconf_change_set_set_bool (cs,
+ GKB_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW,
+ config->group_per_app);
+ gconf_change_set_set_bool (cs,
+ GKB_DESKTOP_CONFIG_KEY_HANDLE_INDICATORS,
+ config->handle_indicators);
+ gconf_change_set_set_bool (cs,
+ GKB_DESKTOP_CONFIG_KEY_LAYOUT_NAMES_AS_GROUP_NAMES,
+ config->layout_names_as_group_names);
+ gconf_change_set_set_int (cs,
+ GKB_DESKTOP_CONFIG_KEY_DEFAULT_GROUP,
+ config->default_group);
+
+ gconf_client_commit_change_set (config->conf_client, cs, TRUE,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error saving active configuration: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ gconf_change_set_unref (cs);
+}
+
+gboolean
+gkb_desktop_config_activate (GkbDesktopConfig * config)
+{
+ gboolean rv = TRUE;
+
+ xkl_engine_set_group_per_toplevel_window (config->engine,
+ config->group_per_app);
+ xkl_engine_set_indicators_handling (config->engine,
+ config->handle_indicators);
+ xkl_engine_set_default_group (config->engine,
+ config->default_group);
+
+ return rv;
+}
+
+void
+gkb_desktop_config_lock_next_group (GkbDesktopConfig * config)
+{
+ int group = xkl_engine_get_next_group (config->engine);
+ xkl_engine_lock_group (config->engine, group);
+}
+
+void
+gkb_desktop_config_lock_prev_group (GkbDesktopConfig * config)
+{
+ int group = xkl_engine_get_prev_group (config->engine);
+ xkl_engine_lock_group (config->engine, group);
+}
+
+void
+gkb_desktop_config_restore_group (GkbDesktopConfig * config)
+{
+ int group = xkl_engine_get_current_window_group (config->engine);
+ xkl_engine_lock_group (config->engine, group);
+}
+
+void
+gkb_desktop_config_start_listen (GkbDesktopConfig * config,
+ GConfClientNotifyFunc func,
+ gpointer user_data)
+{
+ gkb_desktop_config_add_listener (config->conf_client,
+ GKB_DESKTOP_CONFIG_DIR, func,
+ user_data,
+ &config->config_listener_id);
+}
+
+void
+gkb_desktop_config_stop_listen (GkbDesktopConfig * config)
+{
+ gkb_desktop_config_remove_listener (config->conf_client,
+ &config->config_listener_id);
+}
+
+gboolean
+gkb_desktop_config_load_remote_group_descriptions_utf8 (GkbDesktopConfig *
+ config,
+ gchar ***
+ short_group_names,
+ gchar ***
+ full_group_names)
+{
+ gchar **sld, **lld, **svd, **lvd;
+ gchar **psld, **plld, **plvd;
+ gchar **psgn, **pfgn;
+ gint total_descriptions;
+
+ if (!gkb_desktop_config_get_remote_lv_descriptions_utf8
+ (&sld, &lld, &svd, &lvd)) {
+ return False;
+ }
+
+ total_descriptions = g_strv_length (sld);
+
+ *short_group_names = psgn =
+ g_new0 (gchar *, total_descriptions + 1);
+ *full_group_names = pfgn =
+ g_new0 (gchar *, total_descriptions + 1);
+
+ plld = lld;
+ psld = sld;
+ plvd = lvd;
+ while (plld != NULL && *plld != NULL) {
+ *psgn++ = g_strdup (*psld++);
+ *pfgn++ = g_strdup (gkb_keyboard_config_format_full_layout
+ (*plld++, *plvd++));
+ }
+ g_strfreev (sld);
+ g_strfreev (lld);
+ g_strfreev (svd);
+ g_strfreev (lvd);
+
+ return True;
+}
+
+gchar **
+gkb_desktop_config_load_group_descriptions_utf8 (GkbDesktopConfig * config,
+ XklConfigRegistry *
+ config_registry)
+{
+ int i;
+ const gchar **native_names =
+ xkl_engine_get_groups_names (config->engine);
+ guint total_groups = xkl_engine_get_num_groups (config->engine);
+ guint total_layouts;
+ gchar **rv = g_new0 (char *, total_groups + 1);
+ gchar **current_descr = rv;
+
+ if ((xkl_engine_get_features (config->engine) &
+ XKLF_MULTIPLE_LAYOUTS_SUPPORTED)
+ && config->layout_names_as_group_names) {
+ XklConfigRec *xkl_config = xkl_config_rec_new ();
+ if (xkl_config_rec_get_from_server
+ (xkl_config, config->engine)) {
+ char **pl = xkl_config->layouts;
+ char **pv = xkl_config->variants;
+ i = total_groups;
+ while (pl != NULL && *pl != NULL && i >= 0) {
+ char *ls_descr;
+ char *l_descr;
+ char *vs_descr;
+ char *v_descr;
+ if (gkb_keyboard_config_get_lv_descriptions
+ (config_registry, *pl++, *pv++,
+ &ls_descr, &l_descr, &vs_descr,
+ &v_descr)) {
+ char *name_utf =
+ g_locale_to_utf8
+ (gkb_keyboard_config_format_full_layout
+ (l_descr, v_descr), -1, NULL,
+ NULL, NULL);
+ *current_descr++ = name_utf;
+ } else {
+ *current_descr++ = g_strdup ("");
+ }
+ }
+ }
+ g_object_unref (G_OBJECT (xkl_config));
+ /* Worst case - multiple layous - but SOME of them are multigrouped :(((
+ * We cannot do much - just add empty descriptions.
+ * The UI is going to be messy.
+ * Canadian layouts are famous for this sh.t. */
+ total_layouts = g_strv_length (rv);
+ if (total_layouts != total_groups) {
+ xkl_debug (0,
+ "The mismatch between "
+ "the number of groups: %d and number of layouts: %d\n",
+ total_groups, total_layouts);
+ current_descr = rv + total_layouts;
+ for (i = total_groups - total_layouts; --i >= 0;)
+ *current_descr++ = g_strdup ("");
+ }
+ }
+ total_layouts = g_strv_length (rv);
+ if (!total_layouts)
+ for (i = total_groups; --i >= 0;)
+ *current_descr++ = g_strdup (*native_names++);
+
+ return rv;
+}
diff --git a/libgnomekbd/backup/gkb-desktop-config.h b/libgnomekbd/backup/gkb-desktop-config.h
new file mode 100644
index 0000000..2cf27a0
--- /dev/null
+++ b/libgnomekbd/backup/gkb-desktop-config.h
@@ -0,0 +1,96 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GKB_DESKTOP_CONFIG_H__
+#define __GKB_DESKTOP_CONFIG_H__
+
+#include <X11/Xlib.h>
+
+#include <glib.h>
+#include <glib/gslist.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gconf/gconf-client.h>
+
+#include <libxklavier/xklavier.h>
+
+extern const gchar GKB_DESKTOP_CONFIG_DIR[];
+extern const gchar GKB_DESKTOP_CONFIG_KEY_DEFAULT_GROUP[];
+extern const gchar GKB_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW[];
+extern const gchar GKB_DESKTOP_CONFIG_KEY_HANDLE_INDICATORS[];
+extern const gchar GKB_DESKTOP_CONFIG_KEY_LAYOUT_NAMES_AS_GROUP_NAMES[];
+
+/*
+ * General configuration
+ */
+typedef struct _GkbDesktopConfig {
+ gint default_group;
+ gboolean group_per_app;
+ gboolean handle_indicators;
+ gboolean layout_names_as_group_names;
+
+ /* private, transient */
+ GConfClient *conf_client;
+ int config_listener_id;
+ XklEngine *engine;
+} GkbDesktopConfig;
+
+/**
+ * GkbDesktopConfig functions
+ */
+extern void gkb_desktop_config_init (GkbDesktopConfig * config,
+ GConfClient * conf_client,
+ XklEngine * engine);
+extern void gkb_desktop_config_term (GkbDesktopConfig * config);
+
+extern void gkb_desktop_config_load_from_gconf (GkbDesktopConfig * config);
+
+extern void gkb_desktop_config_save_to_gconf (GkbDesktopConfig * config);
+
+extern gboolean gkb_desktop_config_activate (GkbDesktopConfig * config);
+
+/* Affected by XKB and XKB/GConf configuration */
+extern gchar
+ ** gkb_desktop_config_load_group_descriptions_utf8 (GkbDesktopConfig *
+ config,
+ XklConfigRegistry *
+ config_registry);
+
+
+/* Using DBUS */
+extern gboolean
+gkb_desktop_config_load_remote_group_descriptions_utf8 (GkbDesktopConfig *
+ config,
+ gchar ***
+ short_group_names,
+ gchar ***
+ full_group_names);
+
+extern void gkb_desktop_config_lock_next_group (GkbDesktopConfig * config);
+
+extern void gkb_desktop_config_lock_prev_group (GkbDesktopConfig * config);
+
+extern void gkb_desktop_config_restore_group (GkbDesktopConfig * config);
+
+extern void gkb_desktop_config_start_listen (GkbDesktopConfig * config,
+ GConfClientNotifyFunc func,
+ gpointer user_data);
+
+extern void gkb_desktop_config_stop_listen (GkbDesktopConfig * config);
+
+#endif
diff --git a/libgnomekbd/backup/gkb-indicator-config.c b/libgnomekbd/backup/gkb-indicator-config.c
new file mode 100644
index 0000000..f90dadc
--- /dev/null
+++ b/libgnomekbd/backup/gkb-indicator-config.c
@@ -0,0 +1,360 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <X11/keysym.h>
+
+#include <glib/gi18n.h>
+#include <gdk/gdkx.h>
+#include <libgnome/gnome-program.h>
+
+#include <gkb-keyboard-config.h>
+#include <gkb-indicator-config.h>
+
+#include <gkb-config-private.h>
+
+#include <gkb-config-registry-client.h>
+
+/**
+ * GkbIndicatorConfig
+ */
+#define GKB_INDICATOR_CONFIG_KEY_PREFIX GKB_CONFIG_KEY_PREFIX "/indicator"
+
+const gchar GKB_INDICATOR_CONFIG_DIR[] = GKB_INDICATOR_CONFIG_KEY_PREFIX;
+const gchar GKB_INDICATOR_CONFIG_KEY_SHOW_FLAGS[] =
+ GKB_INDICATOR_CONFIG_KEY_PREFIX "/showFlags";
+const gchar GKB_INDICATOR_CONFIG_KEY_ENABLED_PLUGINS[] =
+ GKB_INDICATOR_CONFIG_KEY_PREFIX "/enabledPlugins";
+const gchar GKB_INDICATOR_CONFIG_KEY_SECONDARIES[] =
+ GKB_INDICATOR_CONFIG_KEY_PREFIX "/secondary";
+
+/**
+ * static applet config functions
+ */
+static void
+gkb_indicator_config_free_enabled_plugins (GkbIndicatorConfig * ind_config)
+{
+ GSList *plugin_node = ind_config->enabled_plugins;
+ if (plugin_node != NULL) {
+ do {
+ if (plugin_node->data != NULL) {
+ g_free (plugin_node->data);
+ plugin_node->data = NULL;
+ }
+ plugin_node = g_slist_next (plugin_node);
+ } while (plugin_node != NULL);
+ g_slist_free (ind_config->enabled_plugins);
+ ind_config->enabled_plugins = NULL;
+ }
+}
+
+/**
+ * extern applet kbdConfig functions
+ */
+void
+gkb_indicator_config_free_images (GkbIndicatorConfig * 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) {
+ gdk_pixbuf_unref (pi);
+ }
+ ind_config->images =
+ g_slist_remove_link (ind_config->images, img_node);
+ g_slist_free_1 (img_node);
+ }
+}
+
+char *
+gkb_indicator_config_get_images_file (GkbIndicatorConfig *
+ ind_config,
+ GkbKeyboardConfig *
+ kbd_config, int group)
+{
+ char *image_file = NULL;
+ GtkIconInfo *icon_info = NULL;
+
+ if (!ind_config->show_flags)
+ return NULL;
+
+ if ((kbd_config->layouts != NULL) &&
+ (g_slist_length (kbd_config->layouts) > group)) {
+ char *full_layout_name =
+ (char *) g_slist_nth_data (kbd_config->layouts, group);
+
+ if (full_layout_name != NULL) {
+ char *l, *v;
+ gkb_keyboard_config_split_items (full_layout_name,
+ &l, &v);
+ if (l != NULL) {
+ // probably there is something in theme?
+ icon_info = gtk_icon_theme_lookup_icon
+ (ind_config->icon_theme, l, 48, 0);
+ }
+ }
+ }
+ // fallback to the default value
+ if (icon_info == NULL) {
+ icon_info = gtk_icon_theme_lookup_icon
+ (ind_config->icon_theme, "stock_dialog-error", 48, 0);
+ }
+ if (icon_info != NULL) {
+ image_file =
+ g_strdup (gtk_icon_info_get_filename (icon_info));
+ gtk_icon_info_free (icon_info);
+ }
+
+ return image_file;
+}
+
+void
+gkb_indicator_config_load_images (GkbIndicatorConfig * ind_config,
+ GkbKeyboardConfig * kbd_config)
+{
+ int i;
+ ind_config->images = 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 =
+ gkb_indicator_config_get_images_file (ind_config,
+ kbd_config,
+ i);
+
+ 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
+gkb_indicator_config_init (GkbIndicatorConfig * ind_config,
+ GConfClient * conf_client, XklEngine * engine)
+{
+ GError *gerror = NULL;
+ gchar *sp, *datadir;
+
+ memset (ind_config, 0, sizeof (*ind_config));
+ ind_config->conf_client = conf_client;
+ ind_config->engine = engine;
+ g_object_ref (ind_config->conf_client);
+
+ gconf_client_add_dir (ind_config->conf_client,
+ GKB_INDICATOR_CONFIG_DIR,
+ GCONF_CLIENT_PRELOAD_NONE, &gerror);
+ if (gerror != NULL) {
+ g_warning ("err1:%s\n", gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+
+ ind_config->icon_theme = gtk_icon_theme_get_default ();
+
+ datadir =
+ gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_APP_DATADIR,
+ "", FALSE, NULL);
+ gtk_icon_theme_append_search_path (ind_config->icon_theme, sp =
+ g_build_filename (g_get_home_dir
+ (),
+ ".icons/flags",
+ NULL));
+ g_free (sp);
+
+ gtk_icon_theme_append_search_path (ind_config->icon_theme,
+ sp =
+ g_build_filename (datadir,
+ "pixmaps/flags",
+ NULL));
+ g_free (sp);
+
+ gtk_icon_theme_append_search_path (ind_config->icon_theme,
+ sp =
+ g_build_filename (datadir,
+ "icons/flags",
+ NULL));
+ g_free (sp);
+ g_free (datadir);
+}
+
+void
+gkb_indicator_config_term (GkbIndicatorConfig * ind_config)
+{
+#if 0
+ g_object_unref (G_OBJECT (ind_config->icon_theme));
+#endif
+ ind_config->icon_theme = NULL;
+
+ gkb_indicator_config_free_images (ind_config);
+
+ gkb_indicator_config_free_enabled_plugins (ind_config);
+ g_object_unref (ind_config->conf_client);
+ ind_config->conf_client = NULL;
+}
+
+void
+gkb_indicator_config_update_images (GkbIndicatorConfig *
+ ind_config,
+ GkbKeyboardConfig * kbd_config)
+{
+ gkb_indicator_config_free_images (ind_config);
+ gkb_indicator_config_load_images (ind_config, kbd_config);
+}
+
+void
+gkb_indicator_config_load_from_gconf (GkbIndicatorConfig * ind_config)
+{
+ GError *gerror = NULL;
+
+ ind_config->secondary_groups_mask =
+ gconf_client_get_int (ind_config->conf_client,
+ GKB_INDICATOR_CONFIG_KEY_SECONDARIES,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ ind_config->secondary_groups_mask = 0;
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+
+ ind_config->show_flags =
+ gconf_client_get_bool (ind_config->conf_client,
+ GKB_INDICATOR_CONFIG_KEY_SHOW_FLAGS,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error reading kbdConfiguration:%s\n",
+ gerror->message);
+ ind_config->show_flags = FALSE;
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+
+ gkb_indicator_config_free_enabled_plugins (ind_config);
+ ind_config->enabled_plugins =
+ gconf_client_get_list (ind_config->conf_client,
+ GKB_INDICATOR_CONFIG_KEY_ENABLED_PLUGINS,
+ GCONF_VALUE_STRING, &gerror);
+
+ if (gerror != NULL) {
+ g_warning ("Error reading kbd_configuration:%s\n",
+ gerror->message);
+ ind_config->enabled_plugins = NULL;
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+}
+
+void
+gkb_indicator_config_save_to_gconf (GkbIndicatorConfig * ind_config)
+{
+ GConfChangeSet *cs;
+ GError *gerror = NULL;
+
+ cs = gconf_change_set_new ();
+
+ gconf_change_set_set_int (cs,
+ GKB_INDICATOR_CONFIG_KEY_SECONDARIES,
+ ind_config->secondary_groups_mask);
+ gconf_change_set_set_bool (cs,
+ GKB_INDICATOR_CONFIG_KEY_SHOW_FLAGS,
+ ind_config->show_flags);
+ gconf_change_set_set_list (cs,
+ GKB_INDICATOR_CONFIG_KEY_ENABLED_PLUGINS,
+ GCONF_VALUE_STRING,
+ ind_config->enabled_plugins);
+
+ gconf_client_commit_change_set (ind_config->conf_client, cs,
+ TRUE, &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error saving configuration: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ gconf_change_set_unref (cs);
+}
+
+void
+gkb_indicator_config_activate (GkbIndicatorConfig * ind_config)
+{
+ xkl_engine_set_secondary_groups_mask (ind_config->engine,
+ ind_config->
+ secondary_groups_mask);
+}
+
+void
+gkb_indicator_config_start_listen (GkbIndicatorConfig *
+ ind_config,
+ GConfClientNotifyFunc func,
+ gpointer user_data)
+{
+ gkb_desktop_config_add_listener (ind_config->conf_client,
+ GKB_INDICATOR_CONFIG_DIR, func,
+ user_data,
+ &ind_config->config_listener_id);
+}
+
+void
+gkb_indicator_config_stop_listen (GkbIndicatorConfig * ind_config)
+{
+ gkb_desktop_config_remove_listener (ind_config->conf_client,
+ &ind_config->
+ config_listener_id);
+}
diff --git a/libgnomekbd/backup/gkb-indicator-config.h b/libgnomekbd/backup/gkb-indicator-config.h
new file mode 100644
index 0000000..ac838e0
--- /dev/null
+++ b/libgnomekbd/backup/gkb-indicator-config.h
@@ -0,0 +1,86 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GKB_INDICATOR_CONFIG_H__
+#define __GKB_INDICATOR_CONFIG_H__
+
+#include "libgnomekbd/gkb-keyboard-config.h"
+
+/*
+ * Indicator configuration
+ */
+typedef struct _GkbIndicatorConfig {
+ int secondary_groups_mask;
+ gboolean show_flags;
+
+ GSList *enabled_plugins;
+
+ /* private, transient */
+ GConfClient *conf_client;
+ GSList *images;
+ GtkIconTheme *icon_theme;
+ int config_listener_id;
+ XklEngine *engine;
+} GkbIndicatorConfig;
+
+/**
+ * GkbIndicatorConfig functions -
+ * some of them require GkbKeyboardConfig as well -
+ * for loading approptiate images
+ */
+extern void gkb_indicator_config_init (GkbIndicatorConfig *
+ applet_config,
+ GConfClient * conf_client,
+ XklEngine * engine);
+extern void gkb_indicator_config_term (GkbIndicatorConfig * applet_config);
+
+extern void gkb_indicator_config_load_from_gconf (GkbIndicatorConfig
+ * applet_config);
+extern void gkb_indicator_config_save_to_gconf (GkbIndicatorConfig *
+ applet_config);
+
+extern gchar
+ * gkb_indicator_config_get_images_file (GkbIndicatorConfig *
+ applet_config,
+ GkbKeyboardConfig *
+ kbd_config, int group);
+
+extern void gkb_indicator_config_load_images (GkbIndicatorConfig *
+ applet_config,
+ GkbKeyboardConfig *
+ kbd_config);
+extern void gkb_indicator_config_free_images (GkbIndicatorConfig *
+ applet_config);
+
+/* Should be updated on Indicator/GConf and Kbd/GConf configuration change */
+extern void gkb_indicator_config_update_images (GkbIndicatorConfig *
+ applet_config,
+ GkbKeyboardConfig *
+ kbd_config);
+
+/* Should be updated on Indicator/GConf configuration change */
+extern void gkb_indicator_config_activate (GkbIndicatorConfig *
+ applet_config);
+
+extern void gkb_indicator_config_start_listen (GkbIndicatorConfig *
+ applet_config,
+ GConfClientNotifyFunc
+ func, gpointer user_data);
+
+extern void gkb_indicator_config_stop_listen (GkbIndicatorConfig *
+ applet_config);
+
+#endif
diff --git a/libgnomekbd/backup/gkb-indicator-marshal.list b/libgnomekbd/backup/gkb-indicator-marshal.list
new file mode 100644
index 0000000..5b76282
--- /dev/null
+++ b/libgnomekbd/backup/gkb-indicator-marshal.list
@@ -0,0 +1 @@
+VOID:VOID
diff --git a/libgnomekbd/backup/gkb-indicator-plugin-manager.c b/libgnomekbd/backup/gkb-indicator-plugin-manager.c
new file mode 100644
index 0000000..5da7348
--- /dev/null
+++ b/libgnomekbd/backup/gkb-indicator-plugin-manager.c
@@ -0,0 +1,391 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <libxklavier/xklavier.h>
+
+#include <gkb-indicator-plugin-manager.h>
+
+#define FOREACH_INITED_PLUGIN() \
+{ \
+ GSList *prec; \
+ for( prec = manager->inited_plugin_recs; prec != NULL; prec = prec->next ) \
+ { \
+ const GkbIndicatorPlugin *plugin = \
+ ( ( GkbIndicatorPluginManagerRecord * ) ( prec->data ) )->plugin; \
+ if( plugin != NULL ) \
+ {
+
+#define NEXT_INITED_PLUGIN() \
+ } \
+ } \
+}
+
+static void
+gkb_indicator_plugin_manager_add_plugins_dir (GkbIndicatorPluginManager * manager,
+ const char *dirname)
+{
+ GDir *dir = g_dir_open (dirname, 0, NULL);
+ const gchar *filename;
+ if (dir == NULL)
+ return;
+
+ xkl_debug (100, "Scanning [%s]...\n", dirname);
+ while ((filename = g_dir_read_name (dir)) != NULL) {
+ gchar *full_path =
+ g_build_filename (dirname, filename, NULL);
+ xkl_debug (100, "Loading plugin module [%s]...\n",
+ full_path);
+ if (full_path != NULL) {
+ GModule *module = g_module_open (full_path, 0);
+ if (module != NULL) {
+ gpointer get_plugin_func;
+ if (g_module_symbol
+ (module, "GetPlugin",
+ &get_plugin_func)) {
+ const GkbIndicatorPlugin *plugin =
+ ((GkbIndicatorPluginGetPluginFunc)
+ get_plugin_func) ();
+ if (plugin != NULL) {
+ GkbIndicatorPluginManagerRecord
+ * rec =
+ g_new0
+ (GkbIndicatorPluginManagerRecord,
+ 1);
+ xkl_debug (100,
+ "Loaded plugin from [%s]: [%s]/[%s]...\n",
+ full_path,
+ plugin->name,
+ plugin->
+ description);
+ rec->full_path = full_path;
+ rec->module = module;
+ rec->plugin = plugin;
+ g_hash_table_insert
+ (manager->
+ all_plugin_recs,
+ full_path, rec);
+ continue;
+ }
+ } else
+ xkl_debug (0,
+ "Bad plugin: [%s]\n",
+ full_path);
+ g_module_close (module);
+ } else
+ xkl_debug (0, "Bad module: [%s], %s\n",
+ full_path, g_module_error ());
+ g_free (full_path);
+ }
+ }
+ g_dir_close (dir);
+}
+
+static void
+gkb_indicator_plugin_manager_load_all (GkbIndicatorPluginManager * manager)
+{
+ if (!g_module_supported ()) {
+ xkl_debug (0, "Modules are not supported - no plugins!\n");
+ return;
+ }
+ gkb_indicator_plugin_manager_add_plugins_dir (manager, SYS_PLUGIN_DIR);
+}
+
+static void
+gkb_indicator_plugin_manager_rec_term (GkbIndicatorPluginManagerRecord * rec,
+ void *user_data)
+{
+ const GkbIndicatorPlugin *plugin = rec->plugin;
+ if (plugin != NULL) {
+ xkl_debug (100, "Terminating plugin: [%s]...\n",
+ plugin->name);
+ if (plugin->term_callback)
+ (*plugin->term_callback) ();
+ }
+}
+
+static void
+gkb_indicator_plugin_manager_rec_destroy (GkbIndicatorPluginManagerRecord * rec)
+{
+ xkl_debug (100, "Unloading plugin: [%s]...\n", rec->plugin->name);
+
+ g_module_close (rec->module);
+ g_free (rec);
+}
+
+void
+gkb_indicator_plugin_manager_init (GkbIndicatorPluginManager * manager)
+{
+ manager->all_plugin_recs =
+ g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify)
+ gkb_indicator_plugin_manager_rec_destroy);
+ gkb_indicator_plugin_manager_load_all (manager);
+}
+
+void
+gkb_indicator_plugin_manager_term (GkbIndicatorPluginManager * manager)
+{
+ gkb_indicator_plugin_manager_term_initialized_plugins (manager);
+ if (manager->all_plugin_recs != NULL) {
+ g_hash_table_destroy (manager->all_plugin_recs);
+ manager->all_plugin_recs = NULL;
+ }
+}
+
+void
+gkb_indicator_plugin_manager_init_enabled_plugins (GkbIndicatorPluginManager *
+ manager,
+ GkbIndicatorPluginContainer
+ * pc,
+ GSList * enabled_plugins)
+{
+ GSList *plugin_name_node = enabled_plugins;
+ if (manager->all_plugin_recs == NULL)
+ return;
+ xkl_debug (100, "Initializing all enabled plugins...\n");
+ while (plugin_name_node != NULL) {
+ const char *full_path = plugin_name_node->data;
+ if (full_path != NULL) {
+ GkbIndicatorPluginManagerRecord *rec =
+ (GkbIndicatorPluginManagerRecord *)
+ g_hash_table_lookup (manager->all_plugin_recs,
+ full_path);
+
+ if (rec != NULL) {
+ const GkbIndicatorPlugin *plugin =
+ rec->plugin;
+ gboolean initialized = FALSE;
+ xkl_debug (100,
+ "Initializing plugin: [%s] from [%s]...\n",
+ plugin->name, full_path);
+ if (plugin->init_callback != NULL)
+ initialized =
+ (*plugin->init_callback) (pc);
+ else
+ initialized = TRUE;
+
+ manager->inited_plugin_recs =
+ g_slist_append (manager->
+ inited_plugin_recs,
+ rec);
+ xkl_debug (100,
+ "Plugin [%s] initialized: %d\n",
+ plugin->name, initialized);
+ }
+ }
+ plugin_name_node = g_slist_next (plugin_name_node);
+ }
+}
+
+void
+gkb_indicator_plugin_manager_term_initialized_plugins (GkbIndicatorPluginManager *
+ manager)
+{
+
+ if (manager->inited_plugin_recs == NULL)
+ return;
+ g_slist_foreach (manager->inited_plugin_recs,
+ (GFunc) gkb_indicator_plugin_manager_rec_term, NULL);
+ g_slist_free (manager->inited_plugin_recs);
+ manager->inited_plugin_recs = NULL;
+}
+
+void
+gkb_indicator_plugin_manager_toggle_plugins (GkbIndicatorPluginManager * manager,
+ GkbIndicatorPluginContainer * pc,
+ GSList * enabled_plugins)
+{
+ gkb_indicator_plugin_manager_term_initialized_plugins (manager);
+ gkb_indicator_plugin_manager_init_enabled_plugins (manager, pc,
+ enabled_plugins);
+}
+
+void
+gkb_indicator_plugin_manager_group_changed (GkbIndicatorPluginManager * manager,
+ GtkWidget * notebook,
+ int new_group)
+{
+ FOREACH_INITED_PLUGIN ();
+ if (plugin->group_changed_callback)
+ (*plugin->group_changed_callback) (notebook, new_group);
+ NEXT_INITED_PLUGIN ();
+}
+
+void
+gkb_indicator_plugin_manager_config_changed (GkbIndicatorPluginManager * manager,
+ GkbKeyboardConfig * from,
+ GkbKeyboardConfig * to)
+{
+ FOREACH_INITED_PLUGIN ();
+ if (plugin->config_changed_callback)
+ (*plugin->config_changed_callback) (from, to);
+ NEXT_INITED_PLUGIN ();
+}
+
+const GkbIndicatorPlugin *
+gkb_indicator_plugin_manager_get_plugin (GkbIndicatorPluginManager * manager,
+ const char *full_path)
+{
+ GkbIndicatorPluginManagerRecord *rec =
+ (GkbIndicatorPluginManagerRecord *) g_hash_table_lookup (manager->
+ all_plugin_recs,
+ full_path);
+ if (rec == NULL)
+ return NULL;
+ return rec->plugin;
+}
+
+void
+gkb_indicator_plugin_manager_promote_plugin (GkbIndicatorPluginManager * manager,
+ GSList * enabled_plugins,
+ const char *full_path)
+{
+ GSList *the_node = enabled_plugins;
+ GSList *prev_node = NULL;
+
+ while (the_node != NULL) {
+ if (!strcmp (the_node->data, full_path)) {
+ if (prev_node != NULL) {
+ char *tmp = (char *) prev_node->data;
+ prev_node->data = the_node->data;
+ the_node->data = tmp;
+ }
+ break;
+ }
+ prev_node = the_node;
+ the_node = g_slist_next (the_node);
+ }
+}
+
+void
+gkb_indicator_plugin_manager_demote_plugin (GkbIndicatorPluginManager * manager,
+ GSList * enabled_plugins,
+ const char *full_path)
+{
+ GSList *the_node = g_slist_find_custom (enabled_plugins, full_path,
+ (GCompareFunc) strcmp);
+ if (the_node != NULL) {
+ GSList *next_node = g_slist_next (the_node);
+ if (next_node != NULL) {
+ char *tmp = (char *) next_node->data;
+ next_node->data = the_node->data;
+ the_node->data = tmp;
+ }
+ }
+}
+
+void
+gkb_indicator_plugin_manager_enable_plugin (GkbIndicatorPluginManager * manager,
+ GSList ** enabled_plugins,
+ const char *full_path)
+{
+ if (NULL !=
+ gkb_indicator_plugin_manager_get_plugin (manager, full_path)) {
+ *enabled_plugins =
+ g_slist_append (*enabled_plugins,
+ (gpointer) g_strdup (full_path));
+ }
+}
+
+void
+gkb_indicator_plugin_manager_disable_plugin (GkbIndicatorPluginManager * manager,
+ GSList ** enabled_plugins,
+ const char *full_path)
+{
+ GSList *the_node =
+ g_slist_find_custom (*enabled_plugins, full_path,
+ (GCompareFunc) strcmp);
+ if (the_node != NULL) {
+ g_free (the_node->data);
+ *enabled_plugins =
+ g_slist_delete_link (*enabled_plugins, the_node);
+ }
+}
+
+int
+gkb_indicator_plugin_manager_window_created (GkbIndicatorPluginManager * manager,
+ Window win, Window parent)
+{
+ FOREACH_INITED_PLUGIN ();
+ if (plugin->window_created_callback) {
+ int group_to_assign =
+ (*plugin->window_created_callback) (win, parent);
+ if (group_to_assign != -1) {
+ xkl_debug (100,
+ "Plugin [%s] assigned group %d to new window %ld\n",
+ plugin->name, group_to_assign, win);
+ return group_to_assign;
+ }
+ }
+ NEXT_INITED_PLUGIN ();
+ return -1;
+}
+
+GtkWidget *
+gkb_indicator_plugin_manager_decorate_widget (GkbIndicatorPluginManager * manager,
+ GtkWidget * widget,
+ const gint group,
+ const char *group_description,
+ GkbKeyboardConfig * kbd_config)
+{
+ FOREACH_INITED_PLUGIN ();
+ if (plugin->decorate_widget_callback) {
+ GtkWidget *decorated_widget =
+ (*plugin->decorate_widget_callback) (widget, group,
+ group_description,
+ kbd_config);
+ if (decorated_widget != NULL) {
+ xkl_debug (100,
+ "Plugin [%s] decorated widget %p to %p\n",
+ plugin->name, widget, decorated_widget);
+ return decorated_widget;
+ }
+ }
+ NEXT_INITED_PLUGIN ();
+ return NULL;
+}
+
+void
+gkb_indicator_plugin_manager_configure_plugin (GkbIndicatorPluginManager *
+ manager,
+ GkbIndicatorPluginContainer *
+ pc, const char *full_path,
+ GtkWindow * parent)
+{
+ const GkbIndicatorPlugin *plugin =
+ gkb_indicator_plugin_manager_get_plugin (manager, full_path);
+ if (plugin->configure_properties_callback != NULL)
+ plugin->configure_properties_callback (pc, parent);
+}
+
+void
+gkb_indicator_plugin_container_init (GkbIndicatorPluginContainer * pc,
+ GConfClient * conf_client)
+{
+ pc->conf_client = conf_client;
+ g_object_ref (pc->conf_client);
+}
+
+void
+gkb_indicator_plugin_container_term (GkbIndicatorPluginContainer * pc)
+{
+ g_object_unref (pc->conf_client);
+}
diff --git a/libgnomekbd/backup/gkb-indicator-plugin-manager.h b/libgnomekbd/backup/gkb-indicator-plugin-manager.h
new file mode 100644
index 0000000..6ebfdf5
--- /dev/null
+++ b/libgnomekbd/backup/gkb-indicator-plugin-manager.h
@@ -0,0 +1,110 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GSWITCHIT_PLUGIN_MANAGER_H__
+#define __GSWITCHIT_PLUGIN_MANAGER_H__
+
+#include <gmodule.h>
+#include <libgnomekbd/gkb-indicator-plugin.h>
+
+typedef struct _GkbIndicatorPluginManager {
+ GHashTable *all_plugin_recs;
+ GSList *inited_plugin_recs;
+} GkbIndicatorPluginManager;
+
+typedef struct _GkbIndicatorPluginManagerRecord {
+ const char *full_path;
+ GModule *module;
+ const GkbIndicatorPlugin *plugin;
+} GkbIndicatorPluginManagerRecord;
+
+extern void
+ gkb_indicator_plugin_manager_init (GkbIndicatorPluginManager * manager);
+
+extern void
+ gkb_indicator_plugin_manager_term (GkbIndicatorPluginManager * manager);
+
+extern void
+ gkb_indicator_plugin_manager_init_enabled_plugins (GkbIndicatorPluginManager * manager,
+ GkbIndicatorPluginContainer
+ * pc,
+ GSList * enabled_plugins);
+
+extern void
+ gkb_indicator_plugin_manager_term_initialized_plugins (GkbIndicatorPluginManager * manager);
+
+extern void
+ gkb_indicator_plugin_manager_toggle_plugins (GkbIndicatorPluginManager * manager,
+ GkbIndicatorPluginContainer * pc,
+ GSList * enabled_plugins);
+
+extern const GkbIndicatorPlugin
+ * gkb_indicator_plugin_manager_get_plugin (GkbIndicatorPluginManager *
+ manager, const char *full_path);
+
+extern void
+ gkb_indicator_plugin_manager_promote_plugin (GkbIndicatorPluginManager * manager,
+ GSList * enabled_plugins,
+ const char *full_path);
+
+extern void
+ gkb_indicator_plugin_manager_demote_plugin (GkbIndicatorPluginManager * manager,
+ GSList * enabled_plugins,
+ const char *full_path);
+
+extern void
+ gkb_indicator_plugin_manager_enable_plugin (GkbIndicatorPluginManager * manager,
+ GSList ** enabled_plugins,
+ const char *full_path);
+
+extern void
+ gkb_indicator_plugin_manager_disable_plugin (GkbIndicatorPluginManager * manager,
+ GSList ** enabled_plugins,
+ const char *full_path);
+
+extern void
+ gkb_indicator_plugin_manager_configure_plugin (GkbIndicatorPluginManager * manager,
+ GkbIndicatorPluginContainer *
+ pc, const char *full_path,
+ GtkWindow * parent);
+
+// actual calling plugin notification methods
+
+extern void
+ gkb_indicator_plugin_manager_group_changed (GkbIndicatorPluginManager * manager,
+ GtkWidget * notebook,
+ int new_group);
+
+extern void
+ gkb_indicator_plugin_manager_config_changed (GkbIndicatorPluginManager * manager,
+ GkbKeyboardConfig * from,
+ GkbKeyboardConfig * to);
+
+extern int
+ gkb_indicator_plugin_manager_window_created (GkbIndicatorPluginManager * manager,
+ Window win, Window parent);
+
+extern GtkWidget
+ * gkb_indicator_plugin_manager_decorate_widget (GkbIndicatorPluginManager *
+ manager,
+ GtkWidget * widget,
+ const gint group,
+ const char
+ *group_description,
+ GkbKeyboardConfig *
+ config);
+
+#endif
diff --git a/libgnomekbd/backup/gkb-indicator-plugin.h b/libgnomekbd/backup/gkb-indicator-plugin.h
new file mode 100644
index 0000000..d7d8316
--- /dev/null
+++ b/libgnomekbd/backup/gkb-indicator-plugin.h
@@ -0,0 +1,120 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GKB_INDICATOR_PLUGIN_H__
+#define __GKB_INDICATOR_PLUGIN_H__
+
+#include <gtk/gtk.h>
+#include <gconf/gconf-client.h>
+#include <libgnomekbd/gkb-keyboard-config.h>
+
+#define MAX_LOCAL_NAME_BUF_LENGTH 512
+
+struct _GkbIndicatorPlugin;
+
+typedef struct _GkbIndicatorPluginContainer {
+ GConfClient *conf_client;
+} GkbIndicatorPluginContainer;
+
+typedef const struct _GkbIndicatorPlugin
+*(*GkbIndicatorPluginGetPluginFunc) (void);
+
+typedef gboolean (*GkbIndicatorPluginInitFunc) (GkbIndicatorPluginContainer
+ * pc);
+
+typedef void (*GkbIndicatorPluginGroupChangedFunc) (GtkWidget * notebook,
+ int new_group);
+
+typedef void (*GkbIndicatorPluginConfigChangedFunc) (const
+ GkbKeyboardConfig *
+ from,
+ const
+ GkbKeyboardConfig *
+ to);
+
+typedef int (*GkbIndicatorPluginWindowCreatedFunc) (const Window win,
+ const Window parent);
+
+typedef void (*GkbIndicatorPluginTermFunc) (void);
+
+typedef GtkWidget *(*GkbIndicatorPluginCreateWidget) (void);
+
+typedef GtkWidget *(*GkbIndicatorPluginDecorateWidget) (GtkWidget * widget,
+ const gint group,
+ const char
+ *group_description,
+ GkbKeyboardConfig *
+ config);
+
+typedef
+void (*GkbIndicatorPluginConfigureProperties) (GkbIndicatorPluginContainer
+ * pc, GtkWindow * parent);
+
+typedef struct _GkbIndicatorPlugin {
+ const char *name;
+
+ const char *description;
+
+// implemented
+ GkbIndicatorPluginInitFunc init_callback;
+
+// implemented
+ GkbIndicatorPluginTermFunc term_callback;
+
+// implemented
+ GkbIndicatorPluginConfigureProperties
+ configure_properties_callback;
+
+// implemented
+ GkbIndicatorPluginGroupChangedFunc group_changed_callback;
+
+// implemented
+ GkbIndicatorPluginWindowCreatedFunc window_created_callback;
+
+// implemented
+ GkbIndicatorPluginDecorateWidget decorate_widget_callback;
+
+// non implemented
+ GkbIndicatorPluginConfigChangedFunc config_changed_callback;
+
+// non implemented
+ GkbIndicatorPluginCreateWidget create_widget_callback;
+
+} GkbIndicatorPlugin;
+
+/**
+ * Functions accessible for plugins
+ */
+
+extern void gkb_indicator_plugin_container_init (GkbIndicatorPluginContainer *
+ pc,
+ GConfClient * conf_client);
+
+extern void gkb_indicator_plugin_container_term (GkbIndicatorPluginContainer *
+ pc);
+
+extern void
+ gkb_indicator_plugin_container_reinit_ui (GkbIndicatorPluginContainer * pc);
+
+extern guint gkb_indicator_plugin_get_num_groups (GkbIndicatorPluginContainer *
+ pc);
+
+extern gchar
+ **
+gkb_indicator_plugin_load_localized_group_names (GkbIndicatorPluginContainer *
+ pc);
+
+#endif
diff --git a/libgnomekbd/backup/gkb-indicator.c b/libgnomekbd/backup/gkb-indicator.c
new file mode 100644
index 0000000..4363b4b
--- /dev/null
+++ b/libgnomekbd/backup/gkb-indicator.c
@@ -0,0 +1,826 @@
+#include <memory.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gdk/gdkx.h>
+#include <glib/gi18n.h>
+
+#include <gkb-indicator.h>
+#include <gkb-indicator-marshal.h>
+
+#include <gkb-desktop-config.h>
+#include <gkb-indicator-config.h>
+
+#include <gkb-indicator-plugin-manager.h>
+
+#include <gkb-config-registry-client.h>
+
+typedef struct _gki_globals {
+ XklEngine *engine;
+
+ GkbDesktopConfig cfg;
+ GkbIndicatorConfig ind_cfg;
+ GkbKeyboardConfig kbd_cfg;
+
+ GkbIndicatorPluginContainer plugin_container;
+ GkbIndicatorPluginManager plugin_manager;
+
+ const gchar *tooltips_format;
+ gchar **full_group_names;
+ gchar **short_group_names;
+ GSList *widget_instances;
+} gki_globals;
+
+struct _GkbIndicatorPrivate {
+ 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) { \
+ GkbIndicator * gki = (GkbIndicator*)cur->data;
+#define NextIndicator() \
+ } \
+ }
+
+G_DEFINE_TYPE (GkbIndicator, gkb_indicator, GTK_TYPE_NOTEBOOK)
+
+static void
+gkb_indicator_global_init (void);
+static void
+gkb_indicator_global_term (void);
+static GtkWidget *
+gkb_indicator_prepare_drawing (GkbIndicator * gki, int group);
+static void
+gkb_indicator_set_current_page_for_group (GkbIndicator * gki, int group);
+static void
+gkb_indicator_set_current_page (GkbIndicator * gki);
+static void
+gkb_indicator_cleanup (GkbIndicator * gki);
+static void
+gkb_indicator_fill (GkbIndicator * gki);
+static void
+gkb_indicator_set_tooltips (GkbIndicator * gki, const char *str);
+
+void
+gkb_indicator_set_tooltips (GkbIndicator * gki, const char *str)
+{
+ GtkTooltips *tooltips;
+
+ if (str == NULL)
+ return;
+ tooltips = gtk_tooltips_new ();
+ g_object_ref (G_OBJECT (tooltips));
+ gtk_object_sink (GTK_OBJECT (tooltips));
+ g_object_set_data_full (G_OBJECT (gki), "tooltips",
+ tooltips, (GDestroyNotify) g_object_unref);
+ gtk_tooltips_set_tip (tooltips, GTK_WIDGET (gki), str, NULL);
+
+ if (gki->priv->set_parent_tooltips) {
+ GtkWidget *parent =
+ gtk_widget_get_parent (GTK_WIDGET (gki));
+ if (parent != NULL) {
+ gtk_tooltips_set_tip (tooltips,
+ GTK_WIDGET (parent), str,
+ NULL);
+ g_object_ref (G_OBJECT (tooltips));
+ g_object_set_data_full (G_OBJECT (parent),
+ "gnome-kbd-indicator.tooltips",
+ tooltips, (GDestroyNotify)
+ g_object_unref);
+ }
+ }
+ gtk_tooltips_enable (tooltips);
+}
+
+void
+gkb_indicator_cleanup (GkbIndicator * 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
+gkb_indicator_fill (GkbIndicator * 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;
+ page = gkb_indicator_prepare_drawing (gki, grp);
+
+ if (page == NULL)
+ page = gtk_label_new ("");
+
+ decorated_page =
+ gkb_indicator_plugin_manager_decorate_widget (&globals.
+ plugin_manager,
+ page, grp,
+ globals.
+ full_group_names
+ [grp],
+ &globals.
+ kbd_cfg);
+
+ page = decorated_page == NULL ? page : decorated_page;
+
+ gtk_notebook_append_page (notebook, page, NULL);
+ gtk_widget_show_all (page);
+ }
+}
+
+static gboolean
+gkb_indicator_key_pressed (GtkWidget *
+ widget, GdkEventKey * event, GkbIndicator * 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:
+ gkb_desktop_config_lock_next_group (&globals.cfg);
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+static gboolean
+gkb_indicator_button_pressed (GtkWidget *
+ widget,
+ GdkEventButton * event, GkbIndicator * gki)
+{
+ GtkWidget *img = gtk_bin_get_child (GTK_BIN (widget));
+ xkl_debug (150, "Flag img size %d x %d\n",
+ img->allocation.width, img->allocation.height);
+ if (event->button == 1 && event->type == GDK_BUTTON_PRESS) {
+ xkl_debug (150, "Mouse button pressed on applet\n");
+ gkb_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);
+ /* widget-to-image scales, X and Y */
+ double xwiratio = 1.0 * flag->allocation.width / iw;
+ double ywiratio = 1.0 * flag->allocation.height / ih;
+ double wiratio = xwiratio < ywiratio ? xwiratio : ywiratio;
+
+ /* scaled width and height */
+ int sw = iw * wiratio;
+ int sh = ih * wiratio;
+
+ /* offsets */
+ int ox = (flag->allocation.width - sw) >> 1;
+ int oy = (flag->allocation.height - sh) >> 1;
+
+ GdkPixbuf *scaled = gdk_pixbuf_scale_simple (image, sw, sh,
+ GDK_INTERP_HYPER);
+
+ gdk_draw_pixbuf (GDK_DRAWABLE (flag->window),
+ NULL,
+ scaled,
+ 0, 0,
+ ox, oy, sw, sh, GDK_RGB_DITHER_NORMAL, 0, 0);
+ g_object_unref (G_OBJECT (scaled));
+}
+
+static GtkWidget *
+gkb_indicator_prepare_drawing (GkbIndicator * gki, int group)
+{
+ gpointer pimage;
+ GdkPixbuf *image;
+ GtkWidget *ebox;
+
+ pimage = g_slist_nth_data (globals.ind_cfg.images, group);
+ ebox = gtk_event_box_new ();
+ if (globals.ind_cfg.show_flags) {
+ GtkWidget *flag;
+ if (pimage == NULL)
+ return NULL;
+ image = GDK_PIXBUF (pimage);
+ flag = gtk_drawing_area_new ();
+ g_signal_connect (G_OBJECT (flag),
+ "expose_event",
+ G_CALLBACK (flag_exposed), image);
+ gtk_container_add (GTK_CONTAINER (ebox), flag);
+ } else {
+ gpointer pcounter = NULL;
+ char *prev_layout_name = NULL, **ppln;
+ char *lbl_title = NULL;
+ int counter = 0;
+ char *layout_name = NULL;
+ XklConfigItem cfg_item;
+ GtkWidget *align, *label;
+ /**
+ * Map "short desciption" ->
+ * number of layouts in the configuration
+ * having this short description
+ */
+ static GHashTable *short_descrs = NULL;
+
+ if (group == 0)
+ short_descrs =
+ g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ if (xkl_engine_get_features (globals.engine) &
+ XKLF_MULTIPLE_LAYOUTS_SUPPORTED) {
+ char *full_layout_name =
+ (char *) g_slist_nth_data (globals.kbd_cfg.
+ layouts,
+ group);
+ char *variant_name;
+ if (!gkb_keyboard_config_split_items
+ (full_layout_name, &layout_name,
+ &variant_name))
+ /* just in case */
+ layout_name = g_strdup (full_layout_name);
+
+ g_snprintf (cfg_item.name,
+ sizeof (cfg_item.name), "%s",
+ layout_name);
+
+ if (globals.short_group_names != NULL) {
+ char *short_group_name =
+ globals.short_group_names[group];
+ if (short_group_name != NULL
+ && *short_group_name != '\0') {
+ layout_name =
+ g_strdup (short_group_name);
+ }
+ }
+ } else
+ layout_name =
+ g_strdup (globals.full_group_names[group]);
+
+ if (layout_name == NULL)
+ layout_name = g_strdup ("?");
+
+ /* Process layouts with repeating description */
+ ppln = &prev_layout_name;
+ if (g_hash_table_lookup_extended
+ (short_descrs, layout_name,
+ (gpointer *) ppln, &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 (short_descrs, layout_name,
+ GINT_TO_POINTER (counter + 1));
+
+ 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 == xkl_engine_get_num_groups (globals.engine)) {
+ g_hash_table_destroy (short_descrs);
+ short_descrs = 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 (gkb_indicator_button_pressed), gki);
+
+ g_signal_connect (G_OBJECT (gki),
+ "key_press_event",
+ G_CALLBACK (gkb_indicator_key_pressed), gki);
+
+ /* We have everything prepared for that size */
+
+ return ebox;
+}
+
+static void
+gkb_indicator_update_tooltips (GkbIndicator * gki)
+{
+ XklState *state = xkl_engine_get_current_state (globals.engine);
+ gchar *buf;
+ if (state == NULL || state->group < 0)
+ return;
+
+ buf = g_strdup_printf (globals.tooltips_format,
+ globals.full_group_names[state->group]);
+
+ gkb_indicator_set_tooltips (gki, buf);
+ g_free (buf);
+}
+
+static void
+gkb_indicator_parent_set (GtkWidget * gki, GtkWidget * previous_parent)
+{
+ gkb_indicator_update_tooltips (GKB_INDICATOR (gki));
+}
+
+
+void
+gkb_indicator_reinit_ui (GkbIndicator * gki)
+{
+ gkb_indicator_cleanup (gki);
+ gkb_indicator_fill (gki);
+
+ gkb_indicator_set_current_page (gki);
+
+ g_signal_emit_by_name (gki, "reinit-ui");
+}
+
+/* Should be called once for all widgets */
+static void
+gkb_indicator_cfg_changed (GConfClient * client,
+ guint cnxn_id, GConfEntry * entry)
+{
+ xkl_debug (100,
+ "General configuration changed in GConf - reiniting...\n");
+ gkb_desktop_config_load_from_gconf (&globals.cfg);
+ gkb_desktop_config_activate (&globals.cfg);
+ ForAllIndicators () {
+ gkb_indicator_reinit_ui (gki);
+ } NextIndicator ();
+}
+
+/* Should be called once for all widgets */
+static void
+gkb_indicator_ind_cfg_changed (GConfClient * client,
+ guint cnxn_id, GConfEntry * entry)
+{
+ xkl_debug (100,
+ "Applet configuration changed in GConf - reiniting...\n");
+ gkb_indicator_config_load_from_gconf (&globals.ind_cfg);
+ gkb_indicator_config_update_images (&globals.ind_cfg,
+ &globals.kbd_cfg);
+ gkb_indicator_config_activate (&globals.ind_cfg);
+
+ gkb_indicator_plugin_manager_toggle_plugins (&globals.plugin_manager,
+ &globals.plugin_container,
+ globals.ind_cfg.
+ enabled_plugins);
+
+ ForAllIndicators () {
+ gkb_indicator_reinit_ui (gki);
+ } NextIndicator ();
+}
+
+static void
+gkb_indicator_load_group_names (void)
+{
+ if (!gkb_desktop_config_load_remote_group_descriptions_utf8
+ (&globals.cfg, &globals.short_group_names,
+ &globals.full_group_names)) {
+ 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;
+ for (i = 0; lst; lst = lst->next) {
+ 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
+gkb_indicator_kbd_cfg_callback (GkbIndicator * gki)
+{
+ xkl_debug (100,
+ "XKB configuration changed on X Server - reiniting...\n");
+
+ gkb_keyboard_config_load_from_x_current (&globals.kbd_cfg);
+ gkb_indicator_config_update_images (&globals.ind_cfg,
+ &globals.kbd_cfg);
+
+ g_strfreev (globals.full_group_names);
+ g_strfreev (globals.short_group_names);
+ gkb_indicator_load_group_names ();
+
+ ForAllIndicators () {
+ gkb_indicator_reinit_ui (gki);
+ } NextIndicator ();
+}
+
+/* Should be called once for all applets */
+static void
+gkb_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 () {
+ gkb_indicator_plugin_manager_group_changed (&globals.
+ plugin_manager,
+ GTK_WIDGET
+ (gki),
+ group);
+ xkl_debug (200, "do repaint\n");
+ gkb_indicator_set_current_page_for_group
+ (gki, group);
+ }
+ NextIndicator ();
+ }
+}
+
+
+void
+gkb_indicator_set_current_page (GkbIndicator * gki)
+{
+ XklState *cur_state;
+ cur_state = xkl_engine_get_current_state (globals.engine);
+ if (cur_state->group >= 0)
+ gkb_indicator_set_current_page_for_group (gki,
+ cur_state->
+ group);
+}
+
+void
+gkb_indicator_set_current_page_for_group (GkbIndicator * gki, int group)
+{
+ xkl_debug (200, "Revalidating for group %d\n", group);
+
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (gki), group + 1);
+
+ gkb_indicator_update_tooltips (gki);
+}
+
+/* Should be called once for all widgets */
+static GdkFilterReturn
+gkb_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
+gkb_indicator_start_listen (void)
+{
+ gdk_window_add_filter (NULL, (GdkFilterFunc)
+ gkb_indicator_filter_x_evt, NULL);
+ gdk_window_add_filter (gdk_get_default_root_window (),
+ (GdkFilterFunc)
+ gkb_indicator_filter_x_evt, NULL);
+
+ xkl_engine_start_listen (globals.engine,
+ XKLL_TRACK_KEYBOARD_STATE);
+}
+
+/* Should be called once for all widgets */
+static void
+gkb_indicator_stop_listen (void)
+{
+ xkl_engine_stop_listen (globals.engine);
+
+ gdk_window_remove_filter (NULL, (GdkFilterFunc)
+ gkb_indicator_filter_x_evt, NULL);
+ gdk_window_remove_filter
+ (gdk_get_default_root_window (),
+ (GdkFilterFunc) gkb_indicator_filter_x_evt, NULL);
+}
+
+static gboolean
+gkb_indicator_scroll (GtkWidget * gki, GdkEventScroll * event)
+{
+ /* mouse wheel events should be ignored, otherwise funny effects appear */
+ return TRUE;
+}
+
+static void
+gkb_indicator_init (GkbIndicator * gki)
+{
+ GtkWidget *def_drawing;
+ GtkNotebook *notebook;
+
+ if (!g_slist_length (globals.widget_instances))
+ gkb_indicator_global_init ();
+
+ gki->priv = g_new0 (GkbIndicatorPrivate, 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) {
+ gkb_indicator_set_tooltips (gki,
+ _("XKB initialization error"));
+ return;
+ }
+
+ gkb_indicator_set_tooltips (gki, "");
+
+ gkb_indicator_fill (gki);
+ gkb_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
+gkb_indicator_finalize (GObject * obj)
+{
+ GkbIndicator *gki = GKB_INDICATOR (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);
+
+ gkb_indicator_cleanup (gki);
+
+ xkl_debug (100,
+ "The instance of gnome-kbd-indicator successfully finalized\n");
+
+ g_free (gki->priv);
+
+ G_OBJECT_CLASS (gkb_indicator_parent_class)->finalize (obj);
+
+ if (!g_slist_length (globals.widget_instances))
+ gkb_indicator_global_term ();
+}
+
+static void
+gkb_indicator_global_term (void)
+{
+ xkl_debug (100, "*** Last GkbIndicator instance *** \n");
+ gkb_indicator_stop_listen ();
+
+ gkb_desktop_config_stop_listen (&globals.cfg);
+ gkb_indicator_config_stop_listen (&globals.ind_cfg);
+
+ gkb_indicator_plugin_manager_term_initialized_plugins (&globals.
+ plugin_manager);
+ gkb_indicator_plugin_manager_term (&globals.plugin_manager);
+
+ gkb_indicator_config_term (&globals.ind_cfg);
+ gkb_keyboard_config_term (&globals.kbd_cfg);
+ gkb_desktop_config_term (&globals.cfg);
+
+ gkb_indicator_plugin_container_term (&globals.plugin_container);
+
+ g_object_unref (G_OBJECT (globals.engine));
+ globals.engine = NULL;
+ xkl_debug (100, "*** Terminated globals *** \n");
+}
+
+static void
+gkb_indicator_class_init (GkbIndicatorClass * klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ xkl_debug (100, "*** First GkbIndicator instance *** \n");
+
+ memset (&globals, 0, sizeof (globals));
+
+ /* Initing some global vars */
+ globals.tooltips_format = "%s";
+
+ /* Initing vtable */
+ object_class->finalize = gkb_indicator_finalize;
+
+ widget_class->scroll_event = gkb_indicator_scroll;
+ widget_class->parent_set = gkb_indicator_parent_set;
+
+ /* Signals */
+ g_signal_new ("reinit-ui", GKB_TYPE_INDICATOR,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GkbIndicatorClass, reinit_ui),
+ NULL, NULL, gkb_indicator_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+gkb_indicator_global_init (void)
+{
+ GConfClient *gconf_client;
+
+ 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 (gkb_indicator_state_callback), NULL);
+ g_signal_connect (globals.engine, "X-config-changed",
+ G_CALLBACK
+ (gkb_indicator_kbd_cfg_callback), NULL);
+
+ gkb_indicator_plugin_container_init (&globals.plugin_container,
+ gconf_client);
+
+ gkb_desktop_config_init (&globals.cfg, gconf_client,
+ globals.engine);
+ gkb_keyboard_config_init (&globals.kbd_cfg, gconf_client,
+ globals.engine);
+ gkb_indicator_config_init (&globals.ind_cfg, gconf_client,
+ globals.engine);
+
+ g_object_unref (gconf_client);
+
+ gkb_desktop_config_load_from_gconf (&globals.cfg);
+ gkb_desktop_config_activate (&globals.cfg);
+ gkb_keyboard_config_load_from_x_current (&globals.kbd_cfg);
+ gkb_indicator_config_load_from_gconf (&globals.ind_cfg);
+ gkb_indicator_config_update_images (&globals.ind_cfg,
+ &globals.kbd_cfg);
+ gkb_indicator_config_activate (&globals.ind_cfg);
+
+ gkb_indicator_load_group_names ();
+
+ gkb_indicator_plugin_manager_init (&globals.plugin_manager);
+ gkb_indicator_plugin_manager_init_enabled_plugins (&globals.
+ plugin_manager,
+ &globals.
+ plugin_container,
+ globals.
+ ind_cfg.
+ enabled_plugins);
+ gkb_desktop_config_start_listen (&globals.cfg,
+ (GConfClientNotifyFunc)
+ gkb_indicator_cfg_changed, NULL);
+ gkb_indicator_config_start_listen (&globals.ind_cfg,
+ (GConfClientNotifyFunc)
+ gkb_indicator_ind_cfg_changed,
+ NULL);
+ gkb_indicator_start_listen ();
+
+ xkl_debug (100, "*** Inited globals *** \n");
+}
+
+GtkWidget *
+gkb_indicator_new (void)
+{
+ return GTK_WIDGET (g_object_new (gkb_indicator_get_type (), NULL));
+}
+
+void
+gkb_indicator_set_parent_tooltips (GkbIndicator * gki, gboolean spt)
+{
+ gki->priv->set_parent_tooltips = spt;
+ gkb_indicator_update_tooltips (gki);
+}
+
+void
+gkb_indicator_set_tooltips_format (const gchar format[])
+{
+ globals.tooltips_format = format;
+ ForAllIndicators ()
+ gkb_indicator_update_tooltips (gki);
+ NextIndicator ()
+}
+
+XklEngine *
+gkb_indicator_get_xkl_engine ()
+{
+ return globals.engine;
+}
+
+gchar **
+gkb_indicator_get_group_names ()
+{
+ return globals.full_group_names;
+}
+
+gchar *
+gkb_indicator_get_image_filename (guint group)
+{
+ if (!globals.ind_cfg.show_flags)
+ return NULL;
+ return gkb_indicator_config_get_images_file (&globals.
+ ind_cfg,
+ &globals.
+ kbd_cfg, group);
+}
+
+gdouble
+gkb_indicator_get_max_width_height_ratio (void)
+{
+ gdouble rv = 0.0;
+ GSList *ip = globals.ind_cfg.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
+gkb_indicator_set_angle (GkbIndicator * gki, gdouble angle)
+{
+ gki->priv->angle = angle;
+}
+
+/* Plugin support */
+/* Preserve the plugin container functions during the linking */
+void
+gkb_indicator_plugin_container_reinit_ui (GkbIndicatorPluginContainer * pc)
+{
+ ForAllIndicators () {
+ gkb_indicator_reinit_ui (gki);
+ } NextIndicator ();
+}
+
+gchar **
+gkb_indicator_plugin_load_localized_group_names (GkbIndicatorPluginContainer *
+ pc)
+{
+ return globals.full_group_names;
+}
diff --git a/libgnomekbd/backup/gkb-indicator.h b/libgnomekbd/backup/gkb-indicator.h
new file mode 100644
index 0000000..07f6bfc
--- /dev/null
+++ b/libgnomekbd/backup/gkb-indicator.h
@@ -0,0 +1,77 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GKB_INDICATOR_H__
+#define __GKB_INDICATOR_H__
+
+#include <gtk/gtk.h>
+
+#include <libxklavier/xklavier.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef struct _GkbIndicator GkbIndicator;
+ typedef struct _GkbIndicatorPrivate GkbIndicatorPrivate;
+ typedef struct _GkbIndicatorClass GkbIndicatorClass;
+
+#define GKB_TYPE_INDICATOR (gkb_indicator_get_type ())
+#define GKB_INDICATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GKB_TYPE_INDICATOR, GkbIndicator))
+#define GKB_INDCATOR_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GKB_TYPE_INDICATOR, GkbIndicatorClass))
+#define GKB_IS_INDICATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GKB_TYPE_INDICATOR))
+#define GKB_IS_INDICATOR_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GKB_TYPE_INDICATOR))
+#define GKB_INDICATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GKB_TYPE_INDICATOR, GkbIndicatorClass))
+
+ struct _GkbIndicator {
+ GtkNotebook parent;
+ GkbIndicatorPrivate *priv;
+ };
+
+ struct _GkbIndicatorClass {
+ GtkNotebookClass parent_class;
+
+ void (*reinit_ui) (GkbIndicator * gki);
+ };
+
+ extern GType gkb_indicator_get_type (void);
+
+ extern GtkWidget *gkb_indicator_new (void);
+
+ extern void gkb_indicator_reinit_ui (GkbIndicator * gki);
+
+ extern void gkb_indicator_set_angle (GkbIndicator * gki,
+ gdouble angle);
+
+ extern XklEngine *gkb_indicator_get_xkl_engine (void);
+
+ extern gchar **gkb_indicator_get_group_names (void);
+
+ extern gchar *gkb_indicator_get_image_filename (guint group);
+
+ extern gdouble gkb_indicator_get_max_width_height_ratio (void);
+
+ extern void
+ gkb_indicator_set_parent_tooltips (GkbIndicator *
+ gki, gboolean ifset);
+
+ extern void
+ gkb_indicator_set_tooltips_format (const gchar str[]);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/libgnomekbd/backup/gkb-keyboard-config.c b/libgnomekbd/backup/gkb-keyboard-config.c
new file mode 100644
index 0000000..8a1ea3e
--- /dev/null
+++ b/libgnomekbd/backup/gkb-keyboard-config.c
@@ -0,0 +1,822 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <X11/keysym.h>
+
+#include <glib/gi18n.h>
+#include <gdk/gdkx.h>
+#include <libgnome/gnome-program.h>
+
+#include <gkb-keyboard-config.h>
+#include <gkb-config-private.h>
+
+#include <gkb-config-registry-client.h>
+
+/**
+ * GkbKeyboardConfig
+ */
+#define GKB_KEYBOARD_CONFIG_KEY_PREFIX GKB_CONFIG_KEY_PREFIX "/kbd"
+
+const gchar GKB_KEYBOARD_CONFIG_DIR[] = GKB_KEYBOARD_CONFIG_KEY_PREFIX;
+const gchar GKB_KEYBOARD_CONFIG_KEY_MODEL[] =
+ GKB_KEYBOARD_CONFIG_KEY_PREFIX "/model";
+const gchar GKB_KEYBOARD_CONFIG_KEY_LAYOUTS[] =
+ GKB_KEYBOARD_CONFIG_KEY_PREFIX "/layouts";
+const gchar GKB_KEYBOARD_CONFIG_KEY_OPTIONS[] =
+ GKB_KEYBOARD_CONFIG_KEY_PREFIX "/options";
+
+const gchar *GKB_KEYBOARD_CONFIG_ACTIVE[] = {
+ GKB_KEYBOARD_CONFIG_KEY_MODEL,
+ GKB_KEYBOARD_CONFIG_KEY_LAYOUTS,
+ GKB_KEYBOARD_CONFIG_KEY_OPTIONS
+};
+
+#define GKB_KEYBOARD_CONFIG_SYSBACKUP_KEY_PREFIX GKB_CONFIG_KEY_PREFIX "/kbd.sysbackup"
+
+const gchar GKB_KEYBOARD_CONFIG_SYSBACKUP_DIR[] =
+ GKB_KEYBOARD_CONFIG_SYSBACKUP_KEY_PREFIX;
+const gchar GKB_KEYBOARD_CONFIG_SYSBACKUP_KEY_MODEL[] =
+ GKB_KEYBOARD_CONFIG_SYSBACKUP_KEY_PREFIX "/model";
+const gchar GKB_KEYBOARD_CONFIG_SYSBACKUP_KEY_LAYOUTS[] =
+ GKB_KEYBOARD_CONFIG_SYSBACKUP_KEY_PREFIX "/layouts";
+const gchar GKB_KEYBOARD_CONFIG_SYSBACKUP_KEY_OPTIONS[] =
+ GKB_KEYBOARD_CONFIG_SYSBACKUP_KEY_PREFIX "/options";
+
+const gchar *GKB_KEYBOARD_CONFIG_SYSBACKUP[] = {
+ GKB_KEYBOARD_CONFIG_SYSBACKUP_KEY_MODEL,
+ GKB_KEYBOARD_CONFIG_SYSBACKUP_KEY_LAYOUTS,
+ GKB_KEYBOARD_CONFIG_SYSBACKUP_KEY_OPTIONS
+};
+
+/**
+ * static common functions
+ */
+static void
+gkb_keyboard_config_string_list_reset (GSList ** plist)
+{
+ while (*plist != NULL) {
+ GSList *p = *plist;
+ *plist = (*plist)->next;
+ g_free (p->data);
+ g_slist_free_1 (p);
+ }
+}
+
+static gboolean
+gslist_str_equal (GSList * l1, GSList * l2)
+{
+ if (l1 == l2)
+ return TRUE;
+ while (l1 != NULL && l2 != NULL) {
+ if ((l1->data != l2->data) &&
+ (l1->data != NULL) &&
+ (l2->data != NULL) &&
+ g_ascii_strcasecmp (l1->data, l2->data))
+ return False;
+
+ l1 = l1->next;
+ l2 = l2->next;
+ }
+ return (l1 == NULL && l2 == NULL);
+}
+
+gboolean
+gkb_keyboard_config_get_lv_descriptions (XklConfigRegistry *
+ config_registry,
+ const gchar * layout_name,
+ const gchar * variant_name,
+ gchar ** layout_short_descr,
+ gchar ** layout_descr,
+ gchar ** variant_short_descr,
+ gchar ** variant_descr)
+{
+ static XklConfigItem litem;
+ static XklConfigItem vitem;
+
+ layout_name = g_strdup (layout_name);
+
+ g_snprintf (litem.name, sizeof litem.name, "%s", layout_name);
+ if (xkl_config_registry_find_layout (config_registry, &litem)) {
+ *layout_short_descr = litem.short_description;
+ *layout_descr = litem.description;
+ } else
+ *layout_short_descr = *layout_descr = NULL;
+
+ if (variant_name != NULL) {
+ variant_name = g_strdup (variant_name);
+ g_snprintf (vitem.name, sizeof vitem.name, "%s",
+ variant_name);
+ if (xkl_config_registry_find_variant
+ (config_registry, layout_name, &vitem)) {
+ *variant_short_descr = vitem.short_description;
+ *variant_descr = vitem.description;
+ } else
+ *variant_short_descr = *variant_descr = NULL;
+
+ g_free ((char *) variant_name);
+ } else
+ *variant_descr = NULL;
+
+ g_free ((char *) layout_name);
+ return *layout_descr != NULL;
+}
+
+/**
+ * extern common functions
+ */
+const gchar *
+gkb_keyboard_config_merge_items (const gchar * parent, const gchar * child)
+{
+ static gchar buffer[XKL_MAX_CI_NAME_LENGTH * 2 - 1];
+ *buffer = '\0';
+ if (parent != NULL) {
+ if (strlen (parent) >= XKL_MAX_CI_NAME_LENGTH)
+ return NULL;
+ strcat (buffer, parent);
+ }
+ if (child != NULL) {
+ if (strlen (child) >= XKL_MAX_CI_NAME_LENGTH)
+ return NULL;
+ strcat (buffer, "\t");
+ strcat (buffer, child);
+ }
+ return buffer;
+}
+
+gboolean
+gkb_keyboard_config_split_items (const gchar * merged, gchar ** parent,
+ gchar ** child)
+{
+ static gchar pbuffer[XKL_MAX_CI_NAME_LENGTH];
+ static gchar cbuffer[XKL_MAX_CI_NAME_LENGTH];
+ int plen, clen;
+ const gchar *pos;
+ *parent = *child = NULL;
+
+ if (merged == NULL)
+ return FALSE;
+
+ pos = strchr (merged, '\t');
+ if (pos == NULL) {
+ plen = strlen (merged);
+ clen = 0;
+ } else {
+ plen = pos - merged;
+ clen = strlen (pos + 1);
+ if (clen >= XKL_MAX_CI_NAME_LENGTH)
+ return FALSE;
+ strcpy (*child = cbuffer, pos + 1);
+ }
+ if (plen >= XKL_MAX_CI_NAME_LENGTH)
+ return FALSE;
+ memcpy (*parent = pbuffer, merged, plen);
+ pbuffer[plen] = '\0';
+ return TRUE;
+}
+
+/**
+ * static GkbKeyboardConfig functions
+ */
+static void
+gkb_keyboard_config_options_add_full (GkbKeyboardConfig * kbd_config,
+ const gchar * full_option_name)
+{
+ kbd_config->options =
+ g_slist_append (kbd_config->options,
+ g_strdup (full_option_name));
+}
+
+static void
+gkb_keyboard_config_layouts_add_full (GkbKeyboardConfig * kbd_config,
+ const gchar * full_layout_name)
+{
+ kbd_config->layouts =
+ g_slist_append (kbd_config->layouts,
+ g_strdup (full_layout_name));
+}
+
+static void
+gkb_keyboard_config_copy_from_xkl_config (GkbKeyboardConfig * kbd_config,
+ XklConfigRec * pdata)
+{
+ char **p, **p1;
+ gkb_keyboard_config_model_set (kbd_config, pdata->model);
+ xkl_debug (150, "Loaded Kbd model: [%s]\n", pdata->model);
+
+ gkb_keyboard_config_layouts_reset (kbd_config);
+ p = pdata->layouts;
+ p1 = pdata->variants;
+ while (p != NULL && *p != NULL) {
+ if (*p1 == NULL || **p1 == '\0') {
+ xkl_debug (150, "Loaded Kbd layout: [%s]\n", *p);
+ gkb_keyboard_config_layouts_add_full (kbd_config,
+ *p);
+ } else {
+ char full_layout[XKL_MAX_CI_NAME_LENGTH * 2];
+ g_snprintf (full_layout, sizeof (full_layout),
+ "%s\t%s", *p, *p1);
+ xkl_debug (150,
+ "Loaded Kbd layout with variant: [%s]\n",
+ full_layout);
+ gkb_keyboard_config_layouts_add_full (kbd_config,
+ full_layout);
+ }
+ p++;
+ p1++;
+ }
+
+ gkb_keyboard_config_options_reset (kbd_config);
+ p = pdata->options;
+ while (p != NULL && *p != NULL) {
+ char group[XKL_MAX_CI_NAME_LENGTH];
+ char *option = *p;
+ char *delim =
+ (option != NULL) ? strchr (option, ':') : NULL;
+ int len;
+ if ((delim != NULL) &&
+ ((len = (delim - option)) < XKL_MAX_CI_NAME_LENGTH)) {
+ strncpy (group, option, len);
+ group[len] = 0;
+ xkl_debug (150, "Loaded Kbd option: [%s][%s]\n",
+ group, option);
+ gkb_keyboard_config_options_add (kbd_config,
+ group, option);
+ }
+ p++;
+ }
+}
+
+static void
+gkb_keyboard_config_copy_to_xkl_config (GkbKeyboardConfig * kbd_config,
+ XklConfigRec * pdata)
+{
+ int i;
+ int num_layouts, num_options;
+ pdata->model =
+ (kbd_config->model ==
+ NULL) ? NULL : g_strdup (kbd_config->model);
+
+ num_layouts =
+ (kbd_config->layouts ==
+ NULL) ? 0 : g_slist_length (kbd_config->layouts);
+ num_options =
+ (kbd_config->options ==
+ NULL) ? 0 : g_slist_length (kbd_config->options);
+
+ xkl_debug (150, "Taking %d layouts\n", num_layouts);
+ if (num_layouts != 0) {
+ GSList *the_layout = kbd_config->layouts;
+ char **p1 = pdata->layouts =
+ g_new0 (char *, num_layouts + 1);
+ char **p2 = pdata->variants =
+ g_new0 (char *, num_layouts + 1);
+ for (i = num_layouts; --i >= 0;) {
+ char *layout, *variant;
+ if (gkb_keyboard_config_split_items
+ (the_layout->data, &layout, &variant)
+ && variant != NULL) {
+ *p1 =
+ (layout ==
+ NULL) ? g_strdup ("") :
+ g_strdup (layout);
+ *p2 =
+ (variant ==
+ NULL) ? g_strdup ("") :
+ g_strdup (variant);
+ } else {
+ *p1 =
+ (the_layout->data ==
+ NULL) ? g_strdup ("") :
+ g_strdup (the_layout->data);
+ *p2 = g_strdup ("");
+ }
+ xkl_debug (150, "Adding [%s]/%p and [%s]/%p\n",
+ *p1 ? *p1 : "(nil)", *p1,
+ *p2 ? *p2 : "(nil)", *p2);
+ p1++;
+ p2++;
+ the_layout = the_layout->next;
+ }
+ }
+
+ if (num_options != 0) {
+ GSList *the_option = kbd_config->options;
+ char **p = pdata->options =
+ g_new0 (char *, num_options + 1);
+ for (i = num_options; --i >= 0;) {
+ char *group, *option;
+ if (gkb_keyboard_config_split_items
+ (the_option->data, &group, &option)
+ && option != NULL)
+ *(p++) = g_strdup (option);
+ else {
+ *(p++) = g_strdup ("");
+ xkl_debug (150, "Could not split [%s]\n",
+ the_option->data);
+ }
+ the_option = the_option->next;
+ }
+ }
+}
+
+static void
+gkb_keyboard_config_load_params (GkbKeyboardConfig * kbd_config,
+ const gchar * param_names[])
+{
+ GError *gerror = NULL;
+ gchar *pc;
+ GSList *pl;
+
+ pc = gconf_client_get_string (kbd_config->conf_client,
+ param_names[0], &gerror);
+ if (pc == NULL || gerror != NULL) {
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ g_error_free (gerror);
+ g_free (pc);
+ gerror = NULL;
+ }
+ gkb_keyboard_config_model_set (kbd_config, NULL);
+ } else {
+ gkb_keyboard_config_model_set (kbd_config, pc);
+ g_free (pc);
+ }
+ xkl_debug (150, "Loaded Kbd model: [%s]\n",
+ kbd_config->model ? kbd_config->model : "(null)");
+
+ gkb_keyboard_config_layouts_reset (kbd_config);
+
+ pl = gconf_client_get_list (kbd_config->conf_client,
+ param_names[1],
+ GCONF_VALUE_STRING, &gerror);
+ if (pl == NULL || gerror != NULL) {
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ }
+
+ while (pl != NULL) {
+ xkl_debug (150, "Loaded Kbd layout: [%s]\n", pl->data);
+ gkb_keyboard_config_layouts_add_full (kbd_config,
+ pl->data);
+ pl = pl->next;
+ }
+ gkb_keyboard_config_string_list_reset (&pl);
+
+ gkb_keyboard_config_options_reset (kbd_config);
+
+ pl = gconf_client_get_list (kbd_config->conf_client,
+ param_names[2],
+ GCONF_VALUE_STRING, &gerror);
+ if (pl == NULL || gerror != NULL) {
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ }
+
+ while (pl != NULL) {
+ xkl_debug (150, "Loaded Kbd option: [%s]\n", pl->data);
+ gkb_keyboard_config_options_add_full (kbd_config,
+ (const gchar *) pl->
+ data);
+ pl = pl->next;
+ }
+ gkb_keyboard_config_string_list_reset (&pl);
+}
+
+static void
+gkb_keyboard_config_save_params (GkbKeyboardConfig * kbd_config,
+ GConfChangeSet * cs,
+ const gchar * param_names[])
+{
+ GSList *pl;
+
+ if (kbd_config->model)
+ gconf_change_set_set_string (cs, param_names[0],
+ kbd_config->model);
+ else
+ gconf_change_set_unset (cs, param_names[0]);
+ xkl_debug (150, "Saved Kbd model: [%s]\n",
+ kbd_config->model ? kbd_config->model : "(null)");
+
+ if (kbd_config->layouts) {
+ pl = kbd_config->layouts;
+ while (pl != NULL) {
+ xkl_debug (150, "Saved Kbd layout: [%s]\n",
+ pl->data);
+ pl = pl->next;
+ }
+ gconf_change_set_set_list (cs,
+ param_names[1],
+ GCONF_VALUE_STRING,
+ kbd_config->layouts);
+ } else {
+ xkl_debug (150, "Saved Kbd layouts: []\n");
+ gconf_change_set_unset (cs, param_names[1]);
+ }
+
+ if (kbd_config->options) {
+ pl = kbd_config->options;
+ while (pl != NULL) {
+ xkl_debug (150, "Saved Kbd option: [%s]\n",
+ pl->data);
+ pl = pl->next;
+ }
+ gconf_change_set_set_list (cs,
+ param_names[2],
+ GCONF_VALUE_STRING,
+ kbd_config->options);
+ } else {
+ xkl_debug (150, "Saved Kbd options: []\n");
+ gconf_change_set_unset (cs, param_names[2]);
+ }
+}
+
+/**
+ * extern GkbKeyboardConfig config functions
+ */
+void
+gkb_keyboard_config_init (GkbKeyboardConfig * kbd_config,
+ GConfClient * conf_client, XklEngine * engine)
+{
+ GError *gerror = NULL;
+
+ memset (kbd_config, 0, sizeof (*kbd_config));
+ kbd_config->conf_client = conf_client;
+ kbd_config->engine = engine;
+ g_object_ref (kbd_config->conf_client);
+
+ gconf_client_add_dir (kbd_config->conf_client,
+ GKB_KEYBOARD_CONFIG_DIR,
+ GCONF_CLIENT_PRELOAD_NONE, &gerror);
+ if (gerror != NULL) {
+ g_warning ("err: %s\n", gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+}
+
+void
+gkb_keyboard_config_term (GkbKeyboardConfig * kbd_config)
+{
+ gkb_keyboard_config_model_set (kbd_config, NULL);
+
+ gkb_keyboard_config_layouts_reset (kbd_config);
+
+ g_object_unref (kbd_config->conf_client);
+ kbd_config->conf_client = NULL;
+}
+
+void
+gkb_keyboard_config_load_from_gconf (GkbKeyboardConfig * kbd_config,
+ GkbKeyboardConfig *
+ kbd_config_default)
+{
+ gkb_keyboard_config_load_params (kbd_config,
+ GKB_KEYBOARD_CONFIG_ACTIVE);
+
+ if (kbd_config_default != NULL) {
+ GSList *pl;
+
+ if (kbd_config->model == NULL)
+ kbd_config->model =
+ g_strdup (kbd_config_default->model);
+
+ if (kbd_config->layouts == NULL) {
+ pl = kbd_config_default->layouts;
+ while (pl != NULL) {
+ kbd_config->layouts =
+ g_slist_append (kbd_config->layouts,
+ g_strdup (pl->data));
+ pl = pl->next;
+ }
+ }
+
+ if (kbd_config->options == NULL) {
+ pl = kbd_config_default->options;
+ while (pl != NULL) {
+ kbd_config->options =
+ g_slist_append (kbd_config->options,
+ g_strdup (pl->data));
+ pl = pl->next;
+ }
+ }
+ }
+}
+
+void
+gkb_keyboard_config_load_from_gconf_backup (GkbKeyboardConfig * kbd_config)
+{
+ gkb_keyboard_config_load_params (kbd_config,
+ GKB_KEYBOARD_CONFIG_SYSBACKUP);
+}
+
+void
+gkb_keyboard_config_load_from_x_current (GkbKeyboardConfig * kbd_config)
+{
+ XklConfigRec *data = xkl_config_rec_new ();
+ if (xkl_config_rec_get_from_server (data, kbd_config->engine))
+ gkb_keyboard_config_copy_from_xkl_config (kbd_config,
+ data);
+ else
+ xkl_debug (150,
+ "Could not load keyboard config from server: [%s]\n",
+ xkl_get_last_error ());
+ g_object_unref (G_OBJECT (data));
+}
+
+void
+gkb_keyboard_config_load_from_x_initial (GkbKeyboardConfig * kbd_config)
+{
+ XklConfigRec *data = xkl_config_rec_new ();
+ if (xkl_config_rec_get_from_backup (data, kbd_config->engine))
+ gkb_keyboard_config_copy_from_xkl_config (kbd_config,
+ data);
+ else
+ xkl_debug (150,
+ "Could not load keyboard config from backup: [%s]\n",
+ xkl_get_last_error ());
+ g_object_unref (G_OBJECT (data));
+}
+
+gboolean
+gkb_keyboard_config_equals (GkbKeyboardConfig * kbd_config1,
+ GkbKeyboardConfig * kbd_config2)
+{
+ if (kbd_config1 == kbd_config2)
+ return True;
+ if ((kbd_config1->model != kbd_config2->model) &&
+ (kbd_config1->model != NULL) &&
+ (kbd_config2->model != NULL) &&
+ g_ascii_strcasecmp (kbd_config1->model, kbd_config2->model))
+ return False;
+ return gslist_str_equal (kbd_config1->layouts,
+ kbd_config2->layouts)
+ && gslist_str_equal (kbd_config1->options,
+ kbd_config2->options);
+}
+
+void
+gkb_keyboard_config_save_to_gconf (GkbKeyboardConfig * kbd_config)
+{
+ GConfChangeSet *cs;
+ GError *gerror = NULL;
+
+ cs = gconf_change_set_new ();
+
+ gkb_keyboard_config_save_params (kbd_config, cs,
+ GKB_KEYBOARD_CONFIG_ACTIVE);
+
+ gconf_client_commit_change_set (kbd_config->conf_client, cs, TRUE,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error saving active configuration: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ gconf_change_set_unref (cs);
+}
+
+void
+gkb_keyboard_config_save_to_gconf_backup (GkbKeyboardConfig * kbd_config)
+{
+ GConfChangeSet *cs;
+ GError *gerror = NULL;
+
+ cs = gconf_change_set_new ();
+
+ gkb_keyboard_config_save_params (kbd_config, cs,
+ GKB_KEYBOARD_CONFIG_SYSBACKUP);
+
+ gconf_client_commit_change_set (kbd_config->conf_client, cs, TRUE,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error saving backup configuration: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ gconf_change_set_unref (cs);
+}
+
+void
+gkb_keyboard_config_model_set (GkbKeyboardConfig * kbd_config,
+ const gchar * model_name)
+{
+ if (kbd_config->model != NULL)
+ g_free (kbd_config->model);
+ kbd_config->model =
+ (model_name == NULL
+ || model_name[0] == '\0') ? NULL : g_strdup (model_name);
+}
+
+void
+gkb_keyboard_config_layouts_add (GkbKeyboardConfig * kbd_config,
+ const gchar * layout_name,
+ const gchar * variant_name)
+{
+ const gchar *merged;
+ if (layout_name == NULL)
+ return;
+ merged =
+ gkb_keyboard_config_merge_items (layout_name, variant_name);
+ if (merged == NULL)
+ return;
+ gkb_keyboard_config_layouts_add_full (kbd_config, merged);
+}
+
+void
+gkb_keyboard_config_layouts_reset (GkbKeyboardConfig * kbd_config)
+{
+ gkb_keyboard_config_string_list_reset (&kbd_config->layouts);
+}
+
+void
+gkb_keyboard_config_options_reset (GkbKeyboardConfig * kbd_config)
+{
+ gkb_keyboard_config_string_list_reset (&kbd_config->options);
+}
+
+void
+gkb_keyboard_config_options_add (GkbKeyboardConfig * kbd_config,
+ const gchar * group_name,
+ const gchar * option_name)
+{
+ const gchar *merged;
+ if (group_name == NULL || option_name == NULL)
+ return;
+ merged = gkb_keyboard_config_merge_items (group_name, option_name);
+ if (merged == NULL)
+ return;
+ gkb_keyboard_config_options_add_full (kbd_config, merged);
+}
+
+gboolean
+gkb_keyboard_config_options_is_set (GkbKeyboardConfig * kbd_config,
+ const gchar * group_name,
+ const gchar * option_name)
+{
+ const gchar *merged =
+ gkb_keyboard_config_merge_items (group_name, option_name);
+ if (merged == NULL)
+ return FALSE;
+
+ return NULL != g_slist_find_custom (kbd_config->options, (gpointer)
+ merged, (GCompareFunc)
+ g_ascii_strcasecmp);
+}
+
+gboolean
+gkb_keyboard_config_activate (GkbKeyboardConfig * kbd_config)
+{
+ gboolean rv;
+ XklConfigRec *data = xkl_config_rec_new ();
+
+ gkb_keyboard_config_copy_to_xkl_config (kbd_config, data);
+ rv = xkl_config_rec_activate (data, kbd_config->engine);
+ g_object_unref (G_OBJECT (data));
+
+ return rv;
+}
+
+void
+gkb_keyboard_config_start_listen (GkbKeyboardConfig * kbd_config,
+ GConfClientNotifyFunc func,
+ gpointer user_data)
+{
+ gkb_desktop_config_add_listener (kbd_config->conf_client,
+ GKB_KEYBOARD_CONFIG_DIR, func,
+ user_data,
+ &kbd_config->config_listener_id);
+}
+
+void
+gkb_keyboard_config_stop_listen (GkbKeyboardConfig * kbd_config)
+{
+ gkb_desktop_config_remove_listener (kbd_config->conf_client,
+ &kbd_config->
+ config_listener_id);
+}
+
+gboolean
+gkb_keyboard_config_get_descriptions (XklConfigRegistry * config_registry,
+ const gchar * name,
+ gchar ** layout_short_descr,
+ gchar ** layout_descr,
+ gchar ** variant_short_descr,
+ gchar ** variant_descr)
+{
+ char *layout_name = NULL, *variant_name = NULL;
+ if (!gkb_keyboard_config_split_items
+ (name, &layout_name, &variant_name))
+ return FALSE;
+ return gkb_keyboard_config_get_lv_descriptions (config_registry,
+ layout_name,
+ variant_name,
+ layout_short_descr,
+ layout_descr,
+ variant_short_descr,
+ variant_descr);
+}
+
+const gchar *
+gkb_keyboard_config_format_full_layout (const gchar * layout_descr,
+ const gchar * variant_descr)
+{
+ static gchar full_descr[XKL_MAX_CI_DESC_LENGTH * 2];
+ if (variant_descr == NULL)
+ g_snprintf (full_descr, sizeof (full_descr), "%s",
+ layout_descr);
+ else
+ g_snprintf (full_descr, sizeof (full_descr), "%s %s",
+ layout_descr, variant_descr);
+ return full_descr;
+}
+
+gchar *
+gkb_keyboard_config_to_string (const GkbKeyboardConfig * config)
+{
+ gchar *layouts = NULL, *options = NULL;
+ GString *buffer = g_string_new (NULL);
+
+ GSList *iter;
+ gint count;
+ gchar *result;
+
+ if (config->layouts) {
+ /* g_slist_length is "expensive", so we determinate the length on the fly */
+ for (iter = config->layouts, count = 0; iter;
+ iter = iter->next, ++count) {
+ if (buffer->len)
+ g_string_append (buffer, " ");
+
+ g_string_append (buffer,
+ (const gchar *) iter->data);
+ }
+
+ /* TRANS: The count is related to the number of options. The %s format specifier should not be modified,
+ * left "as is". */
+ layouts =
+ g_strdup_printf (ngettext
+ ("layout \"%s\"", "layouts \"%s\"",
+ count), buffer->str);
+ g_string_truncate (buffer, 0);
+ }
+ if (config->options) {
+ /* g_slist_length is "expensive", so we determinate the length on the fly */
+ for (iter = config->options, count = 0; iter;
+ iter = iter->next, ++count) {
+ if (buffer->len)
+ g_string_append (buffer, " ");
+
+ g_string_append (buffer,
+ (const gchar *) iter->data);
+ }
+
+ /* TRANS: The count is related to the number of options. The %s format specifier should not be modified,
+ * left "as is". */
+ options =
+ g_strdup_printf (ngettext
+ ("option \"%s\"", "options \"%s\"",
+ count), buffer->str);
+ g_string_truncate (buffer, 0);
+ }
+
+ g_string_free (buffer, TRUE);
+
+ result =
+ g_strdup_printf (_("model \"%s\", %s and %s"), config->model,
+ layouts ? layouts : _("no layout"),
+ options ? options : _("no options"));
+
+ g_free (options);
+ g_free (layouts);
+
+ return result;
+}
diff --git a/libgnomekbd/backup/gkb-keyboard-config.h b/libgnomekbd/backup/gkb-keyboard-config.h
new file mode 100644
index 0000000..b833b23
--- /dev/null
+++ b/libgnomekbd/backup/gkb-keyboard-config.h
@@ -0,0 +1,123 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GKB_KEYBOARD_CONFIG_H__
+#define __GKB_KEYBOARD_CONFIG_H__
+
+#include <X11/Xlib.h>
+
+#include <glib.h>
+#include <glib/gslist.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gconf/gconf-client.h>
+
+#include <libxklavier/xklavier.h>
+
+extern const gchar GKB_KEYBOARD_CONFIG_DIR[];
+extern const gchar GKB_KEYBOARD_CONFIG_KEY_MODEL[];
+extern const gchar GKB_KEYBOARD_CONFIG_KEY_LAYOUTS[];
+extern const gchar GKB_KEYBOARD_CONFIG_KEY_OPTIONS[];
+
+/*
+ * Keyboard Configuration
+ */
+typedef struct _GkbKeyboardConfig {
+ gchar *model;
+ GSList *layouts;
+ GSList *options;
+
+ /* private, transient */
+ GConfClient *conf_client;
+ int config_listener_id;
+ XklEngine *engine;
+} GkbKeyboardConfig;
+
+/**
+ * GkbKeyboardConfig functions
+ */
+extern void gkb_keyboard_config_init (GkbKeyboardConfig * kbd_config,
+ GConfClient * conf_client,
+ XklEngine * engine);
+extern void gkb_keyboard_config_term (GkbKeyboardConfig * kbd_config);
+
+extern void gkb_keyboard_config_load_from_gconf (GkbKeyboardConfig *
+ kbd_config,
+ GkbKeyboardConfig *
+ kbd_config_default);
+
+extern void gkb_keyboard_config_save_to_gconf (GkbKeyboardConfig *
+ kbd_config);
+
+extern void gkb_keyboard_config_load_from_gconf_backup (GkbKeyboardConfig
+ * kbd_config);
+
+extern void gkb_keyboard_config_save_to_gconf_backup (GkbKeyboardConfig *
+ kbd_config);
+
+extern void gkb_keyboard_config_load_from_x_initial (GkbKeyboardConfig *
+ kbd_config);
+
+extern void gkb_keyboard_config_load_from_x_current (GkbKeyboardConfig *
+ kbd_config);
+
+extern void gkb_keyboard_config_start_listen (GkbKeyboardConfig *
+ kbd_config,
+ GConfClientNotifyFunc func,
+ gpointer user_data);
+
+extern void gkb_keyboard_config_stop_listen (GkbKeyboardConfig *
+ kbd_config);
+
+extern gboolean gkb_keyboard_config_equals (GkbKeyboardConfig *
+ kbd_config1,
+ GkbKeyboardConfig *
+ kbd_config2);
+
+extern gboolean gkb_keyboard_config_activate (GkbKeyboardConfig *
+ kbd_config);
+
+extern const gchar *gkb_keyboard_config_merge_items (const gchar * parent,
+ const gchar * child);
+
+extern gboolean gkb_keyboard_config_split_items (const gchar * merged,
+ gchar ** parent,
+ gchar ** child);
+
+extern gboolean gkb_keyboard_config_get_descriptions (XklConfigRegistry *
+ config_registry,
+ const gchar * name,
+ gchar **
+ layout_short_descr,
+ gchar **
+ layout_descr,
+ gchar **
+ variant_short_descr,
+ gchar **
+ variant_descr);
+
+extern const gchar *gkb_keyboard_config_format_full_layout (const gchar
+ *
+ layout_descr,
+ const gchar *
+ variant_descr);
+
+extern gchar *gkb_keyboard_config_to_string (const GkbKeyboardConfig *
+ config);
+
+#endif
diff --git a/libgnomekbd/backup/gkb-keyboard-drawing-marshal.list b/libgnomekbd/backup/gkb-keyboard-drawing-marshal.list
new file mode 100644
index 0000000..88a875f
--- /dev/null
+++ b/libgnomekbd/backup/gkb-keyboard-drawing-marshal.list
@@ -0,0 +1,2 @@
+# $Id$
+VOID:UINT
diff --git a/libgnomekbd/backup/gkb-keyboard-drawing.c b/libgnomekbd/backup/gkb-keyboard-drawing.c
new file mode 100644
index 0000000..3ec085e
--- /dev/null
+++ b/libgnomekbd/backup/gkb-keyboard-drawing.c
@@ -0,0 +1,1845 @@
+/* $Id$ */
+/*
+ * keyboard-drawing.c: implementation of a gtk+ widget that is a drawing of
+ * the keyboard of the default display
+ *
+ * Copyright (c) 2004 Noah Levitt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkkeysyms.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBgeom.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <math.h>
+
+#include <gkb-keyboard-drawing.h>
+#include <gkb-keyboard-drawing-marshal.h>
+
+#define noKBDRAW_DEBUG
+
+enum {
+ BAD_KEYCODE = 0,
+ NUM_SIGNALS
+};
+
+static guint gkb_keyboard_drawing_signals[NUM_SIGNALS] = { 0 };
+
+static void gkb_keyboard_drawing_set_mods (GkbKeyboardDrawing * drawing,
+ guint mods);
+
+static gint
+xkb_to_pixmap_coord (GkbKeyboardDrawing * drawing, gint n)
+{
+ return n * drawing->scale_numerator / drawing->scale_denominator;
+}
+
+/* angle is in tenths of a degree; coordinates can be anything as (xkb,
+ * pixels, pango) as long as they are all the same */
+static void
+rotate_coordinate (gint origin_x,
+ gint origin_y,
+ gint x,
+ gint y, gint angle, gint * rotated_x, gint * rotated_y)
+{
+ *rotated_x =
+ origin_x + (x - origin_x) * cos (M_PI * angle / 1800.0) - (y -
+ origin_y)
+ * sin (M_PI * angle / 1800.0);
+ *rotated_y =
+ origin_y + (x - origin_x) * sin (M_PI * angle / 1800.0) + (y -
+ origin_y)
+ * cos (M_PI * angle / 1800.0);
+}
+
+static void
+draw_polygon (GkbKeyboardDrawing * drawing,
+ GdkColor * fill_color,
+ gint xkb_x,
+ gint xkb_y, XkbPointRec * xkb_points, guint num_points)
+{
+ GtkStateType state = GTK_WIDGET_STATE (GTK_WIDGET (drawing));
+ GdkGC *gc;
+ GdkPoint *points;
+ gboolean filled;
+ gint i;
+
+ if (drawing->pixmap == NULL)
+ return;
+
+ if (fill_color) {
+ gc = gdk_gc_new (GTK_WIDGET (drawing)->window);
+ gdk_gc_set_rgb_fg_color (gc, fill_color);
+ filled = TRUE;
+ } else {
+ gc = GTK_WIDGET (drawing)->style->dark_gc[state];
+ filled = FALSE;
+ }
+
+ points = g_new (GdkPoint, num_points);
+
+ for (i = 0; i < num_points; i++) {
+ points[i].x =
+ xkb_to_pixmap_coord (drawing, xkb_x + xkb_points[i].x);
+ points[i].y =
+ xkb_to_pixmap_coord (drawing, xkb_y + xkb_points[i].y);
+ }
+
+ gdk_draw_polygon (drawing->pixmap, gc, filled, points, num_points);
+
+ g_free (points);
+ if (fill_color)
+ g_object_unref (gc);
+}
+
+/* x, y, width, height are in the xkb coordinate system */
+static void
+draw_rectangle (GkbKeyboardDrawing * drawing,
+ GdkColor * fill_color,
+ gint angle,
+ gint xkb_x, gint xkb_y, gint xkb_width, gint xkb_height)
+{
+ if (drawing->pixmap == NULL)
+ return;
+
+ if (angle == 0) {
+ GtkStateType state =
+ GTK_WIDGET_STATE (GTK_WIDGET (drawing));
+ gint x, y, width, height;
+ gboolean filled;
+ GdkGC *gc;
+
+ if (fill_color) {
+ gc = gdk_gc_new (GTK_WIDGET (drawing)->window);
+ gdk_gc_set_rgb_fg_color (gc, fill_color);
+ filled = TRUE;
+ } else {
+ gc = GTK_WIDGET (drawing)->style->dark_gc[state];
+ filled = FALSE;
+ }
+
+ x = xkb_to_pixmap_coord (drawing, xkb_x);
+ y = xkb_to_pixmap_coord (drawing, xkb_y);
+ width =
+ xkb_to_pixmap_coord (drawing, xkb_x + xkb_width) - x;
+ height =
+ xkb_to_pixmap_coord (drawing, xkb_y + xkb_height) - y;
+
+ gdk_draw_rectangle (drawing->pixmap, gc, filled, x, y,
+ width, height);
+
+ if (fill_color)
+ g_object_unref (gc);
+ } else {
+ XkbPointRec points[4];
+ gint x, y;
+
+ points[0].x = xkb_x;
+ points[0].y = xkb_y;
+ rotate_coordinate (xkb_x, xkb_y, xkb_x + xkb_width, xkb_y,
+ angle, &x, &y);
+ points[1].x = x;
+ points[1].y = y;
+ rotate_coordinate (xkb_x, xkb_y, xkb_x + xkb_width,
+ xkb_y + xkb_height, angle, &x, &y);
+ points[2].x = x;
+ points[2].y = y;
+ rotate_coordinate (xkb_x, xkb_y, xkb_x, xkb_y + xkb_height,
+ angle, &x, &y);
+ points[3].x = x;
+ points[3].y = y;
+
+ /* the points we've calculated are relative to 0,0 */
+ draw_polygon (drawing, fill_color, 0, 0, points, 4);
+ }
+}
+
+static void
+draw_outline (GkbKeyboardDrawing * drawing,
+ XkbOutlineRec * outline,
+ GdkColor * color, gint angle, gint origin_x, gint origin_y)
+{
+#ifdef KBDRAW_DEBUG
+ printf ("num_points in %p: %d\n", outline, outline->num_points);
+#endif
+
+ if (outline->num_points == 1) {
+ if (color)
+ draw_rectangle (drawing, color, angle, origin_x,
+ origin_y, outline->points[0].x,
+ outline->points[0].y);
+
+#ifdef KBDRAW_DEBUG
+ printf ("points:%p\n", outline->points);
+ printf ("pointsxy:%d %d\n", outline->points[0].x,
+ outline->points[0].y);
+#endif
+
+ draw_rectangle (drawing, NULL, angle, origin_x, origin_y,
+ outline->points[0].x,
+ outline->points[0].y);
+ } else if (outline->num_points == 2) {
+ gint rotated_x0, rotated_y0;
+
+ rotate_coordinate (origin_x, origin_y,
+ origin_x + outline->points[0].x,
+ origin_y + outline->points[0].y,
+ angle, &rotated_x0, &rotated_y0);
+ if (color)
+ draw_rectangle (drawing, color, angle, rotated_x0,
+ rotated_y0, outline->points[1].x,
+ outline->points[1].y);
+
+ draw_rectangle (drawing, NULL, angle, rotated_x0,
+ rotated_y0, outline->points[1].x,
+ outline->points[1].y);
+ } else {
+ if (color)
+ draw_polygon (drawing, color, origin_x, origin_y,
+ outline->points,
+ outline->num_points);
+
+ draw_polygon (drawing, NULL, origin_x, origin_y,
+ outline->points, outline->num_points);
+ }
+}
+
+/* see PSColorDef in xkbprint */
+static gboolean
+parse_xkb_color_spec (gchar * colorspec, GdkColor * color)
+{
+ glong level;
+
+ if (g_ascii_strcasecmp (colorspec, "black") == 0) {
+ color->red = 0;
+ color->green = 0;
+ color->blue = 0;
+ } else if (g_ascii_strcasecmp (colorspec, "white") == 0) {
+ color->red = 65535;
+ color->green = 65535;
+ color->blue = 65535;
+ } else if (g_ascii_strncasecmp (colorspec, "grey", 4) == 0 ||
+ g_ascii_strncasecmp (colorspec, "gray", 4) == 0) {
+ level = strtol (colorspec + 4, NULL, 10);
+
+ color->red = 65535 - 65535 * level / 100;
+ color->green = 65535 - 65535 * level / 100;
+ color->blue = 65535 - 65535 * level / 100;
+ } else if (g_ascii_strcasecmp (colorspec, "red") == 0) {
+ color->red = 65535;
+ color->green = 0;
+ color->blue = 0;
+ } else if (g_ascii_strcasecmp (colorspec, "green") == 0) {
+ color->red = 0;
+ color->green = 65535;
+ color->blue = 0;
+ } else if (g_ascii_strcasecmp (colorspec, "blue") == 0) {
+ color->red = 0;
+ color->green = 0;
+ color->blue = 65535;
+ } else if (g_ascii_strncasecmp (colorspec, "red", 3) == 0) {
+ level = strtol (colorspec + 3, NULL, 10);
+
+ color->red = 65535 * level / 100;
+ color->green = 0;
+ color->blue = 0;
+ } else if (g_ascii_strncasecmp (colorspec, "green", 5) == 0) {
+ level = strtol (colorspec + 5, NULL, 10);
+
+ color->red = 0;
+ color->green = 65535 * level / 100;;
+ color->blue = 0;
+ } else if (g_ascii_strncasecmp (colorspec, "blue", 4) == 0) {
+ level = strtol (colorspec + 4, NULL, 10);
+
+ color->red = 0;
+ color->green = 0;
+ color->blue = 65535 * level / 100;
+ } else
+ return FALSE;
+
+ return TRUE;
+}
+
+
+static guint
+find_keycode (GkbKeyboardDrawing * drawing, gchar * key_name)
+{
+ guint i;
+
+ if (!drawing->xkb)
+ return (gint) (-1);
+
+ for (i = drawing->xkb->min_key_code;
+ i <= drawing->xkb->max_key_code; i++) {
+ if (drawing->xkb->names->keys[i].name[0] == key_name[0]
+ && drawing->xkb->names->keys[i].name[1] == key_name[1]
+ && drawing->xkb->names->keys[i].name[2] == key_name[2]
+ && drawing->xkb->names->keys[i].name[3] == key_name[3])
+ return i;
+ }
+
+ return (guint) (-1);
+}
+
+
+static void
+fit_width (GkbKeyboardDrawing * drawing, gint width)
+{
+ PangoRectangle logical_rect;
+ gint old_size;
+
+ pango_layout_get_extents (drawing->layout, NULL, &logical_rect);
+
+ if (logical_rect.width > 0 && logical_rect.width > width) {
+ old_size =
+ pango_font_description_get_size (drawing->font_desc);
+ pango_font_description_set_size (drawing->font_desc,
+ old_size * width /
+ logical_rect.width);
+ pango_layout_set_font_description (drawing->layout,
+ drawing->font_desc);
+ }
+}
+
+static void
+set_key_label_in_layout (GkbKeyboardDrawing * drawing,
+ PangoLayout * layout, guint keyval)
+{
+ gchar buf[5];
+ gunichar uc;
+
+ switch (keyval) {
+ case GDK_Scroll_Lock:
+ pango_layout_set_text (layout, "Scroll\nLock", -1);
+ break;
+
+ case GDK_space:
+ pango_layout_set_text (layout, "", -1);
+ break;
+
+ case GDK_Sys_Req:
+ pango_layout_set_text (layout, "Sys Rq", -1);
+ break;
+
+ case GDK_Page_Up:
+ pango_layout_set_text (layout, "Page\nUp", -1);
+ break;
+
+ case GDK_Page_Down:
+ pango_layout_set_text (layout, "Page\nDown", -1);
+ break;
+
+ case GDK_Num_Lock:
+ pango_layout_set_text (layout, "Num\nLock", -1);
+ break;
+
+ case GDK_KP_Page_Up:
+ pango_layout_set_text (layout, "Pg Up", -1);
+ break;
+
+ case GDK_KP_Page_Down:
+ pango_layout_set_text (layout, "Pg Dn", -1);
+ break;
+
+ case GDK_KP_Home:
+ pango_layout_set_text (layout, "Home", -1);
+ break;
+
+ case GDK_KP_Left:
+ pango_layout_set_text (layout, "Left", -1);
+ break;
+
+ case GDK_KP_End:
+ pango_layout_set_text (layout, "End", -1);
+ break;
+
+ case GDK_KP_Up:
+ pango_layout_set_text (layout, "Up", -1);
+ break;
+
+ case GDK_KP_Begin:
+ pango_layout_set_text (layout, "Begin", -1);
+ break;
+
+ case GDK_KP_Right:
+ pango_layout_set_text (layout, "Right", -1);
+ break;
+
+ case GDK_KP_Enter:
+ pango_layout_set_text (layout, "Enter", -1);
+ break;
+
+ case GDK_KP_Down:
+ pango_layout_set_text (layout, "Down", -1);
+ break;
+
+ case GDK_KP_Insert:
+ pango_layout_set_text (layout, "Ins", -1);
+ break;
+
+ case GDK_KP_Delete:
+ pango_layout_set_text (layout, "Del", -1);
+ break;
+
+ case GDK_dead_grave:
+ pango_layout_set_text (layout, "ˋ", -1);
+ break;
+
+ case GDK_dead_acute:
+ pango_layout_set_text (layout, "ˊ", -1);
+ break;
+
+ case GDK_dead_circumflex:
+ pango_layout_set_text (layout, "ˆ", -1);
+ break;
+
+ case GDK_dead_tilde:
+ pango_layout_set_text (layout, "~", -1);
+ break;
+
+ case GDK_dead_macron:
+ pango_layout_set_text (layout, "ˉ", -1);
+ break;
+
+ case GDK_dead_breve:
+ pango_layout_set_text (layout, "˘", -1);
+ break;
+
+ case GDK_dead_abovedot:
+ pango_layout_set_text (layout, "˙", -1);
+ break;
+
+ case GDK_dead_diaeresis:
+ pango_layout_set_text (layout, "¨", -1);
+ break;
+
+ case GDK_dead_abovering:
+ pango_layout_set_text (layout, "˚", -1);
+ break;
+
+ case GDK_dead_doubleacute:
+ pango_layout_set_text (layout, "˝", -1);
+ break;
+
+ case GDK_dead_caron:
+ pango_layout_set_text (layout, "ˇ", -1);
+ break;
+
+ case GDK_dead_cedilla:
+ pango_layout_set_text (layout, "¸", -1);
+ break;
+
+ case GDK_dead_ogonek:
+ pango_layout_set_text (layout, "˛", -1);
+ break;
+
+ /* case GDK_dead_iota:
+ * case GDK_dead_voiced_sound:
+ * case GDK_dead_semivoiced_sound: */
+
+ case GDK_dead_belowdot:
+ pango_layout_set_text (layout, " ̣", -1);
+ break;
+
+ case GDK_horizconnector:
+ pango_layout_set_text (layout, "horiz\nconn", -1);
+ break;
+
+ case GDK_Mode_switch:
+ pango_layout_set_text (layout, "AltGr", -1);
+ break;
+
+ case GDK_Multi_key:
+ pango_layout_set_text (layout, "Compose", -1);
+ break;
+
+ default:
+ uc = gdk_keyval_to_unicode (keyval);
+ if (uc != 0 && g_unichar_isgraph (uc)) {
+ buf[g_unichar_to_utf8 (uc, buf)] = '\0';
+ pango_layout_set_text (layout, buf, -1);
+ } else {
+ gchar *name = gdk_keyval_name (keyval);
+ if (name)
+ pango_layout_set_text (layout, name, -1);
+ else
+ pango_layout_set_text (layout, "", -1);
+ }
+ }
+}
+
+
+static void
+draw_layout (GkbKeyboardDrawing * drawing,
+ gint angle, gint x, gint y, PangoLayout * layout)
+{
+ GtkStateType state = GTK_WIDGET_STATE (GTK_WIDGET (drawing));
+ PangoLayoutLine *line;
+ gint x_off, y_off;
+ gint i;
+
+ if (drawing->pixmap == NULL)
+ return;
+
+ if (angle != drawing->angle) {
+ PangoMatrix matrix = PANGO_MATRIX_INIT;
+ pango_matrix_rotate (&matrix, -angle / 10.0);
+ pango_context_set_matrix (gtk_widget_get_pango_context
+ (GTK_WIDGET (drawing)), &matrix);
+ pango_layout_context_changed (drawing->layout);
+ drawing->angle = angle;
+ }
+
+ i = 0;
+ y_off = 0;
+ for (line = pango_layout_get_line (drawing->layout, i);
+ line != NULL;
+ line = pango_layout_get_line (drawing->layout, ++i)) {
+ GSList *runp;
+ PangoRectangle line_extents;
+
+ x_off = 0;
+
+ for (runp = line->runs; runp != NULL; runp = runp->next) {
+ PangoGlyphItem *run = runp->data;
+ gint j;
+
+ for (j = 0; j < run->glyphs->num_glyphs; j++) {
+ PangoGlyphGeometry *geometry;
+ gint xx, yy;
+
+ geometry =
+ &run->glyphs->glyphs[j].geometry;
+
+ rotate_coordinate (0, 0, x_off, y_off,
+ angle, &xx, &yy);
+ geometry->x_offset -= x_off - xx;
+ geometry->y_offset -= y_off - yy;
+
+ x_off += geometry->width;
+ }
+ }
+
+ pango_layout_line_get_extents (line, NULL, &line_extents);
+ y_off +=
+ line_extents.height +
+ pango_layout_get_spacing (drawing->layout);
+ }
+
+ gdk_draw_layout (drawing->pixmap,
+ GTK_WIDGET (drawing)->style->text_gc[state], x, y,
+ drawing->layout);
+}
+
+static void
+draw_key_label_helper (GkbKeyboardDrawing * drawing,
+ KeySym keysym,
+ gint angle,
+ GkbKeyboardDrawingGroupLevelPosition glp,
+ gint x,
+ gint y, gint width, gint height, gint padding)
+{
+ gint old_size;
+ gint label_x, label_y, label_max_width, ycell;
+
+ if (keysym == 0)
+ return;
+#ifdef KBDRAW_DEBUG
+ printf ("keysym: %04X(%c) at glp: %d\n",
+ (unsigned) keysym, (char) keysym, (int) glp);
+#endif
+
+ switch (glp) {
+ case GKB_KEYBOARD_DRAWING_POS_TOPLEFT:
+ case GKB_KEYBOARD_DRAWING_POS_BOTTOMLEFT:
+ {
+ ycell = glp == GKB_KEYBOARD_DRAWING_POS_BOTTOMLEFT;
+
+ rotate_coordinate (x, y, x + padding,
+ y + padding + (height -
+ 2 * padding) *
+ ycell * 4 / 7, angle, &label_x,
+ &label_y);
+ label_max_width =
+ PANGO_SCALE * (width - 2 * padding);
+ break;
+ }
+ case GKB_KEYBOARD_DRAWING_POS_TOPRIGHT:
+ case GKB_KEYBOARD_DRAWING_POS_BOTTOMRIGHT:
+ {
+ ycell =
+ glp == GKB_KEYBOARD_DRAWING_POS_BOTTOMRIGHT;
+
+ rotate_coordinate (x, y,
+ x + padding + (width -
+ 2 * padding) *
+ 4 / 7,
+ y + padding + (height -
+ 2 * padding) *
+ ycell * 4 / 7, angle, &label_x,
+ &label_y);
+ label_max_width =
+ PANGO_SCALE * ((width - 2 * padding) -
+ (width - 2 * padding) * 4 / 7);
+ break;
+ }
+ default:
+ return;
+ }
+ set_key_label_in_layout (drawing, drawing->layout, keysym);
+
+ old_size = pango_font_description_get_size (drawing->font_desc);
+ fit_width (drawing, label_max_width);
+
+ draw_layout (drawing, angle, label_x, label_y, drawing->layout);
+
+ if (pango_font_description_get_size (drawing->font_desc) !=
+ old_size) {
+ pango_font_description_set_size (drawing->font_desc,
+ old_size);
+ pango_layout_set_font_description (drawing->layout,
+ drawing->font_desc);
+ }
+}
+
+static void
+draw_key_label (GkbKeyboardDrawing * drawing,
+ guint keycode,
+ gint angle,
+ gint xkb_origin_x,
+ gint xkb_origin_y, gint xkb_width, gint xkb_height)
+{
+ gint x, y, width, height;
+ gint padding;
+ gint g, l, glp;
+
+ if (!drawing->xkb)
+ return;
+
+ padding = 23 * drawing->scale_numerator / drawing->scale_denominator; /* 2.3mm */
+
+ x = xkb_to_pixmap_coord (drawing, xkb_origin_x);
+ y = xkb_to_pixmap_coord (drawing, xkb_origin_y);
+ width =
+ xkb_to_pixmap_coord (drawing, xkb_origin_x + xkb_width) - x;
+ height =
+ xkb_to_pixmap_coord (drawing, xkb_origin_y + xkb_height) - y;
+
+ for (glp = GKB_KEYBOARD_DRAWING_POS_TOPLEFT;
+ glp < GKB_KEYBOARD_DRAWING_POS_TOTAL; glp++) {
+ if (drawing->groupLevels[glp] == NULL)
+ continue;
+ g = drawing->groupLevels[glp]->group;
+ l = drawing->groupLevels[glp]->level;
+
+ if (g < 0 || g >= XkbKeyNumGroups (drawing->xkb, keycode))
+ continue;
+ if (l < 0
+ || l >= XkbKeyGroupWidth (drawing->xkb, keycode, g))
+ continue;
+
+ if (drawing->track_modifiers) {
+ uint mods_rtrn;
+ KeySym keysym;
+
+ if (XkbTranslateKeyCode (drawing->xkb, keycode,
+ XkbBuildCoreState
+ (drawing->mods, g),
+ &mods_rtrn, &keysym)) {
+ draw_key_label_helper (drawing, keysym,
+ angle, glp, x, y,
+ width, height,
+ padding);
+ /* reverse y order */
+ }
+ } else {
+ KeySym keysym;
+
+ keysym =
+ XkbKeySymEntry (drawing->xkb, keycode, l, g);
+
+ draw_key_label_helper (drawing, keysym, angle, glp,
+ x, y, width, height,
+ padding);
+ /* reverse y order */
+ }
+ }
+}
+
+/* groups are from 0-3 */
+static void
+draw_key (GkbKeyboardDrawing * drawing, GkbKeyboardDrawingKey * key)
+{
+ XkbShapeRec *shape;
+ GdkColor *color;
+ gint i;
+
+ if (!drawing->xkb)
+ return;
+
+#ifdef KBDRAW_DEBUG
+ printf ("shape: %p (%p + %d)\n",
+ drawing->xkb->geom->shapes + key->xkbkey->shape_ndx,
+ drawing->xkb->geom->shapes, key->xkbkey->shape_ndx);
+#endif
+
+ shape = drawing->xkb->geom->shapes + key->xkbkey->shape_ndx;
+
+ if (key->pressed)
+ color =
+ &(GTK_WIDGET (drawing)->style->
+ base[GTK_STATE_SELECTED]);
+ else
+ color = drawing->colors + key->xkbkey->color_ndx;
+
+#ifdef KBDRAW_DEBUG
+ printf ("outlines: %p(%d)\n", shape->outlines,
+ shape->num_outlines);
+#endif
+
+ for (i = 0; i < 1 /* shape->num_outlines */ ; i++)
+ draw_outline (drawing, shape->outlines + i, color,
+ key->angle, key->origin_x, key->origin_y);
+
+ draw_key_label (drawing, key->keycode, key->angle, key->origin_x,
+ key->origin_y, shape->bounds.x2, shape->bounds.y2);
+}
+
+static void
+invalidate_region (GkbKeyboardDrawing * drawing,
+ gdouble angle,
+ gint origin_x, gint origin_y, XkbShapeRec * shape)
+{
+ GdkPoint points[4];
+ gint x_min, x_max, y_min, y_max;
+ gint x, y, width, height;
+ gint xx, yy;
+
+ rotate_coordinate (0, 0, 0, 0, angle, &xx, &yy);
+ points[0].x = xx;
+ points[0].y = yy;
+ rotate_coordinate (0, 0, shape->bounds.x2, 0, angle, &xx, &yy);
+ points[1].x = xx;
+ points[1].y = yy;
+ rotate_coordinate (0, 0, shape->bounds.x2, shape->bounds.y2, angle,
+ &xx, &yy);
+ points[2].x = xx;
+ points[2].y = yy;
+ rotate_coordinate (0, 0, 0, shape->bounds.y2, angle, &xx, &yy);
+ points[3].x = xx;
+ points[3].y = yy;
+
+ x_min =
+ MIN (MIN (points[0].x, points[1].x),
+ MIN (points[2].x, points[3].x));
+ x_max =
+ MAX (MAX (points[0].x, points[1].x),
+ MAX (points[2].x, points[3].x));
+ y_min =
+ MIN (MIN (points[0].y, points[1].y),
+ MIN (points[2].y, points[3].y));
+ y_max =
+ MAX (MAX (points[0].y, points[1].y),
+ MAX (points[2].y, points[3].y));
+
+ x = xkb_to_pixmap_coord (drawing, origin_x + x_min) - 6;
+ y = xkb_to_pixmap_coord (drawing, origin_y + y_min) - 6;
+ width = xkb_to_pixmap_coord (drawing, x_max - x_min) + 12;
+ height = xkb_to_pixmap_coord (drawing, y_max - y_min) + 12;
+
+ gtk_widget_queue_draw_area (GTK_WIDGET (drawing), x, y, width,
+ height);
+}
+
+static void
+invalidate_indicator_doodad_region (GkbKeyboardDrawing * drawing,
+ GkbKeyboardDrawingDoodad * doodad)
+{
+ if (!drawing->xkb)
+ return;
+
+ invalidate_region (drawing,
+ doodad->angle,
+ doodad->origin_x +
+ doodad->doodad->indicator.left,
+ doodad->origin_y +
+ doodad->doodad->indicator.top,
+ &drawing->xkb->geom->shapes[doodad->doodad->
+ indicator.
+ shape_ndx]);
+}
+
+static void
+invalidate_key_region (GkbKeyboardDrawing * drawing,
+ GkbKeyboardDrawingKey * key)
+{
+ if (!drawing->xkb)
+ return;
+
+ invalidate_region (drawing,
+ key->angle,
+ key->origin_x,
+ key->origin_y,
+ &drawing->xkb->geom->shapes[key->xkbkey->
+ shape_ndx]);
+}
+
+static void
+draw_text_doodad (GkbKeyboardDrawing * drawing,
+ GkbKeyboardDrawingDoodad * doodad,
+ XkbTextDoodadRec * text_doodad)
+{
+ gint x, y;
+ if (!drawing->xkb)
+ return;
+
+ x = xkb_to_pixmap_coord (drawing,
+ doodad->origin_x + text_doodad->left);
+ y = xkb_to_pixmap_coord (drawing,
+ doodad->origin_y + text_doodad->top);
+
+ pango_layout_set_text (drawing->layout, text_doodad->text, -1);
+ draw_layout (drawing, doodad->angle, x, y, drawing->layout);
+}
+
+static void
+draw_indicator_doodad (GkbKeyboardDrawing * drawing,
+ GkbKeyboardDrawingDoodad * doodad,
+ XkbIndicatorDoodadRec * indicator_doodad)
+{
+ GdkColor *color;
+ XkbShapeRec *shape;
+ gint i;
+
+ if (!drawing->xkb)
+ return;
+
+ shape = drawing->xkb->geom->shapes + indicator_doodad->shape_ndx;
+
+ color = drawing->colors + (doodad->on ?
+ indicator_doodad->on_color_ndx :
+ indicator_doodad->off_color_ndx);
+
+ for (i = 0; i < 1; i++)
+ draw_outline (drawing, shape->outlines + i, color,
+ doodad->angle,
+ doodad->origin_x + indicator_doodad->left,
+ doodad->origin_y + indicator_doodad->top);
+}
+
+static void
+draw_shape_doodad (GkbKeyboardDrawing * drawing,
+ GkbKeyboardDrawingDoodad * doodad,
+ XkbShapeDoodadRec * shape_doodad)
+{
+ XkbShapeRec *shape;
+ GdkColor *color;
+ gint i;
+
+ if (!drawing->xkb)
+ return;
+
+ shape = drawing->xkb->geom->shapes + shape_doodad->shape_ndx;
+ color = drawing->colors + shape_doodad->color_ndx;
+
+ for (i = 0; i < shape->num_outlines; i++)
+ draw_outline (drawing, shape->outlines + i, color,
+ doodad->angle,
+ doodad->origin_x + shape_doodad->left,
+ doodad->origin_y + shape_doodad->top);
+}
+
+static void
+draw_doodad (GkbKeyboardDrawing * drawing,
+ GkbKeyboardDrawingDoodad * doodad)
+{
+ switch (doodad->doodad->any.type) {
+ case XkbOutlineDoodad:
+ case XkbSolidDoodad:
+ draw_shape_doodad (drawing, doodad,
+ &doodad->doodad->shape);
+ break;
+
+ case XkbTextDoodad:
+ draw_text_doodad (drawing, doodad, &doodad->doodad->text);
+ break;
+
+ case XkbIndicatorDoodad:
+ draw_indicator_doodad (drawing, doodad,
+ &doodad->doodad->indicator);
+ break;
+
+ case XkbLogoDoodad:
+ /* g_print ("draw_doodad: logo: %s\n", doodad->doodad->logo.logo_name); */
+ /* XkbLogoDoodadRec is essentially a subclass of XkbShapeDoodadRec */
+ draw_shape_doodad (drawing, doodad,
+ &doodad->doodad->shape);
+ break;
+ }
+}
+
+static void
+draw_keyboard_item (GkbKeyboardDrawingItem * item,
+ GkbKeyboardDrawing * drawing)
+{
+ if (!drawing->xkb)
+ return;
+
+ switch (item->type) {
+ case GKB_KEYBOARD_DRAWING_ITEM_TYPE_KEY:
+ draw_key (drawing, (GkbKeyboardDrawingKey *) item);
+ break;
+
+ case GKB_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD:
+ draw_doodad (drawing, (GkbKeyboardDrawingDoodad *) item);
+ break;
+ }
+}
+
+static void
+draw_keyboard (GkbKeyboardDrawing * drawing)
+{
+ GtkStateType state = GTK_WIDGET_STATE (GTK_WIDGET (drawing));
+ gint pixw, pixh;
+
+ if (!drawing->xkb)
+ return;
+
+ pixw = GTK_WIDGET (drawing)->allocation.width;
+ pixh = GTK_WIDGET (drawing)->allocation.height;
+
+ drawing->pixmap =
+ gdk_pixmap_new (GTK_WIDGET (drawing)->window, pixw, pixh, -1);
+
+ /* blank background */
+ gdk_draw_rectangle (drawing->pixmap,
+ GTK_WIDGET (drawing)->style->base_gc[state],
+ TRUE, 0, 0, pixw, pixh);
+
+ if (drawing->xkb == NULL)
+ return;
+
+#ifdef KBDRAW_DEBUG
+ printf ("mods: %d\n", drawing->mods);
+#endif
+
+ g_list_foreach (drawing->keyboard_items,
+ (GFunc) draw_keyboard_item, drawing);
+}
+
+static void
+alloc_pango_layout (GkbKeyboardDrawing * drawing)
+{
+ PangoContext *context =
+ gtk_widget_get_pango_context (GTK_WIDGET (drawing));
+ drawing->layout = pango_layout_new (context);
+}
+
+static void
+free_pango_layout (GkbKeyboardDrawing * drawing)
+{
+ g_object_unref (G_OBJECT (drawing->layout));
+ drawing->layout = NULL;
+}
+
+static gboolean
+expose_event (GtkWidget * widget,
+ GdkEventExpose * event, GkbKeyboardDrawing * drawing)
+{
+ GtkStateType state = GTK_WIDGET_STATE (GTK_WIDGET (drawing));
+
+ if (!drawing->xkb)
+ return FALSE;
+
+ if (drawing->pixmap == NULL)
+ draw_keyboard (drawing);
+
+ gdk_draw_drawable (widget->window,
+ widget->style->fg_gc[state],
+ drawing->pixmap,
+ event->area.x, event->area.y,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+ if (GTK_WIDGET_HAS_FOCUS (widget))
+ gtk_paint_focus (widget->style, widget->window,
+ GTK_WIDGET_STATE (widget), &event->area,
+ widget, "keyboard-drawing",
+ 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ return FALSE;
+}
+
+static void
+size_allocate (GtkWidget * widget,
+ GtkAllocation * allocation, GkbKeyboardDrawing * drawing)
+{
+ if (!drawing->xkb)
+ return;
+
+ if (drawing->pixmap) {
+ g_object_unref (drawing->pixmap);
+ drawing->pixmap = NULL;
+ }
+
+ if (drawing->xkb->geom->width_mm <= 0
+ || drawing->xkb->geom->height_mm <= 0) {
+ g_critical
+ ("keyboard geometry reports width or height as zero!");
+ return;
+ }
+
+ if (allocation->width * drawing->xkb->geom->height_mm <
+ allocation->height * drawing->xkb->geom->width_mm) {
+ drawing->scale_numerator = allocation->width;
+ drawing->scale_denominator = drawing->xkb->geom->width_mm;
+ } else {
+ drawing->scale_numerator = allocation->height;
+ drawing->scale_denominator = drawing->xkb->geom->height_mm;
+ }
+
+ pango_font_description_set_size (drawing->font_desc,
+ 36000 * drawing->scale_numerator /
+ drawing->scale_denominator);
+ pango_layout_set_spacing (drawing->layout,
+ -8000 * drawing->scale_numerator /
+ drawing->scale_denominator);
+ pango_layout_set_font_description (drawing->layout,
+ drawing->font_desc);
+}
+
+static gint
+key_event (GtkWidget * widget,
+ GdkEventKey * event, GkbKeyboardDrawing * drawing)
+{
+ GkbKeyboardDrawingKey *key;
+ if (!drawing->xkb)
+ return FALSE;
+
+ key = drawing->keys + event->hardware_keycode;
+
+ if (event->hardware_keycode > drawing->xkb->max_key_code ||
+ event->hardware_keycode < drawing->xkb->min_key_code ||
+ key->xkbkey == NULL) {
+ g_signal_emit (drawing,
+ gkb_keyboard_drawing_signals[BAD_KEYCODE],
+ 0, event->hardware_keycode);
+ return TRUE;
+ }
+
+ if ((event->type == GDK_KEY_PRESS && key->pressed) ||
+ (event->type == GDK_KEY_RELEASE && !key->pressed))
+ return TRUE;
+ /* otherwise this event changes the state we believed we had before */
+
+ key->pressed = (event->type == GDK_KEY_PRESS);
+
+ draw_key (drawing, key);
+
+ invalidate_key_region (drawing, key);
+
+ return TRUE;
+}
+
+static gint
+button_press_event (GtkWidget * widget,
+ GdkEventButton * event, GkbKeyboardDrawing * drawing)
+{
+ if (!drawing->xkb)
+ return FALSE;
+
+ gtk_widget_grab_focus (widget);
+ return FALSE;
+}
+
+static gboolean
+unpress_keys (GkbKeyboardDrawing * drawing)
+{
+ gint i;
+
+ if (!drawing->xkb)
+ return FALSE;
+
+ for (i = drawing->xkb->min_key_code;
+ i <= drawing->xkb->max_key_code; i++)
+ if (drawing->keys[i].pressed) {
+ drawing->keys[i].pressed = FALSE;
+ draw_key (drawing, drawing->keys + i);
+ invalidate_key_region (drawing, drawing->keys + i);
+ }
+
+ return FALSE;
+}
+
+static gint
+focus_event (GtkWidget * widget,
+ GdkEventFocus * event, GkbKeyboardDrawing * drawing)
+{
+ if (event->in && drawing->timeout > 0) {
+ g_source_remove (drawing->timeout);
+ drawing->timeout = 0;
+ } else
+ drawing->timeout =
+ g_timeout_add (120, (GSourceFunc) unpress_keys,
+ drawing);
+
+ return FALSE;
+}
+
+static gint
+compare_keyboard_item_priorities (GkbKeyboardDrawingItem * a,
+ GkbKeyboardDrawingItem * b)
+{
+ if (a->priority > b->priority)
+ return 1;
+ else if (a->priority < b->priority)
+ return -1;
+ else
+ return 0;
+}
+
+static void
+init_indicator_doodad (GkbKeyboardDrawing * drawing,
+ XkbDoodadRec * xkbdoodad,
+ GkbKeyboardDrawingDoodad * doodad)
+{
+ if (!drawing->xkb)
+ return;
+
+ if (xkbdoodad->any.type == XkbIndicatorDoodad) {
+ gint index;
+ Atom iname = 0;
+ Atom sname = xkbdoodad->indicator.name;
+ unsigned long phys_indicators =
+ drawing->xkb->indicators->phys_indicators;
+ Atom *pind = drawing->xkb->names->indicators;
+
+#ifdef KBDRAW_DEBUG
+ printf ("Looking for %d[%s]\n",
+ (int) sname, XGetAtomName (drawing->display,
+ sname));
+#endif
+
+ for (index = 0; index < XkbNumIndicators; index++) {
+ iname = *pind++;
+ /* name matches and it is real */
+ if (iname == sname
+ && (phys_indicators & (1 << index)))
+ break;
+ if (iname == 0)
+ break;
+ }
+ if (iname == 0)
+ g_warning ("Could not find indicator %d [%s]\n",
+ (int) sname,
+ XGetAtomName (drawing->display, sname));
+ else {
+#ifdef KBDRAW_DEBUG
+ printf ("Found in xkbdesc as %d\n", index);
+#endif
+ drawing->physical_indicators[index] = doodad;
+ /* Trying to obtain the real state, but if fail - just assume OFF */
+ if (!XkbGetNamedIndicator
+ (drawing->display, sname, NULL, &doodad->on,
+ NULL, NULL))
+ doodad->on = 0;
+ }
+ }
+}
+
+static void
+init_keys_and_doodads (GkbKeyboardDrawing * drawing)
+{
+ gint i, j, k;
+ gint x, y;
+
+ if (!drawing->xkb)
+ return;
+
+ for (i = 0; i < drawing->xkb->geom->num_doodads; i++) {
+ XkbDoodadRec *xkbdoodad = drawing->xkb->geom->doodads + i;
+ GkbKeyboardDrawingDoodad *doodad =
+ g_new (GkbKeyboardDrawingDoodad, 1);
+
+ doodad->type = GKB_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD;
+ doodad->origin_x = 0;
+ doodad->origin_y = 0;
+ doodad->angle = 0;
+ doodad->priority = xkbdoodad->any.priority * 256 * 256;
+ doodad->doodad = xkbdoodad;
+
+ init_indicator_doodad (drawing, xkbdoodad, doodad);
+
+ drawing->keyboard_items =
+ g_list_append (drawing->keyboard_items, doodad);
+ }
+
+ for (i = 0; i < drawing->xkb->geom->num_sections; i++) {
+#ifdef KBDRAW_DEBUG
+ printf ("initing section %d\n", i);
+#endif
+ XkbSectionRec *section = drawing->xkb->geom->sections + i;
+ guint priority;
+
+ x = section->left;
+ y = section->top;
+ priority = section->priority * 256 * 256;
+
+ for (j = 0; j < section->num_rows; j++) {
+ XkbRowRec *row = section->rows + j;
+
+#ifdef KBDRAW_DEBUG
+ printf (" initing row %d\n", j);
+#endif
+ x = section->left + row->left;
+ y = section->top + row->top;
+
+ for (k = 0; k < row->num_keys; k++) {
+ XkbKeyRec *xkbkey = row->keys + k;
+ GkbKeyboardDrawingKey *key;
+ XkbShapeRec *shape =
+ drawing->xkb->geom->shapes +
+ xkbkey->shape_ndx;
+ guint keycode = find_keycode (drawing,
+ xkbkey->name.
+ name);
+
+#ifdef KBDRAW_DEBUG
+ printf
+ (" initing key %d, shape: %p(%p + %d), code: %d\n",
+ k, shape, drawing->xkb->geom->shapes,
+ xkbkey->shape_ndx, keycode);
+#endif
+ if (row->vertical)
+ y += xkbkey->gap;
+ else
+ x += xkbkey->gap;
+
+ if (keycode >= drawing->xkb->min_key_code
+ && keycode <=
+ drawing->xkb->max_key_code)
+ key = drawing->keys + keycode;
+ else {
+ g_warning
+ ("key %4.4s: keycode = %u; not in range %d..%d\n",
+ xkbkey->name.name, keycode,
+ drawing->xkb->min_key_code,
+ drawing->xkb->max_key_code);
+
+ key =
+ g_new0 (GkbKeyboardDrawingKey,
+ 1);
+ }
+
+ key->type =
+ GKB_KEYBOARD_DRAWING_ITEM_TYPE_KEY;
+ key->xkbkey = xkbkey;
+ key->angle = section->angle;
+ rotate_coordinate (section->left,
+ section->top, x, y,
+ section->angle,
+ &key->origin_x,
+ &key->origin_y);
+ key->priority = priority;
+ key->keycode = keycode;
+
+ drawing->keyboard_items =
+ g_list_append (drawing->keyboard_items,
+ key);
+
+ if (row->vertical)
+ y += shape->bounds.y2;
+ else
+ x += shape->bounds.x2;
+
+ priority++;
+ }
+ }
+
+ for (j = 0; j < section->num_doodads; j++) {
+ XkbDoodadRec *xkbdoodad = section->doodads + j;
+ GkbKeyboardDrawingDoodad *doodad =
+ g_new (GkbKeyboardDrawingDoodad, 1);
+
+ doodad->type =
+ GKB_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD;
+ doodad->origin_x = x;
+ doodad->origin_y = y;
+ doodad->angle = section->angle;
+ doodad->priority =
+ priority + xkbdoodad->any.priority;
+ doodad->doodad = xkbdoodad;
+
+ init_indicator_doodad (drawing, xkbdoodad, doodad);
+
+ drawing->keyboard_items =
+ g_list_append (drawing->keyboard_items,
+ doodad);
+ }
+ }
+
+ drawing->keyboard_items = g_list_sort (drawing->keyboard_items,
+ (GCompareFunc)
+ compare_keyboard_item_priorities);
+}
+
+static void
+init_colors (GkbKeyboardDrawing * drawing)
+{
+ gboolean result;
+ gint i;
+
+ if (!drawing->xkb)
+ return;
+
+ drawing->colors = g_new (GdkColor, drawing->xkb->geom->num_colors);
+
+ for (i = 0; i < drawing->xkb->geom->num_colors; i++) {
+ result =
+ parse_xkb_color_spec (drawing->xkb->geom->colors[i].
+ spec, drawing->colors + i);
+
+ if (!result)
+ g_warning
+ ("init_colors: unable to parse color %s\n",
+ drawing->xkb->geom->colors[i].spec);
+ }
+}
+
+static void
+free_cdik ( /*colors doodads indicators keys */
+ GkbKeyboardDrawing * drawing)
+{
+ GList *itemp;
+
+ if (!drawing->xkb)
+ return;
+
+ for (itemp = drawing->keyboard_items; itemp; itemp = itemp->next) {
+ GkbKeyboardDrawingItem *item = itemp->data;
+ GkbKeyboardDrawingKey *key;
+
+ switch (item->type) {
+ case GKB_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD:
+ g_free (item);
+ break;
+
+ case GKB_KEYBOARD_DRAWING_ITEM_TYPE_KEY:
+ key = (GkbKeyboardDrawingKey *) item;
+ if (key->keycode < drawing->xkb->min_key_code ||
+ key->keycode > drawing->xkb->max_key_code)
+ g_free (key);
+ /* otherwise it's part of the array */
+ break;
+ }
+ }
+
+ g_list_free (drawing->keyboard_items);
+ drawing->keyboard_items = NULL;
+
+ g_free (drawing->keys);
+ g_free (drawing->colors);
+}
+
+static void
+alloc_cdik (GkbKeyboardDrawing * drawing)
+{
+ drawing->physical_indicators_size =
+ drawing->xkb->indicators->phys_indicators + 1;
+ drawing->physical_indicators =
+ g_new0 (GkbKeyboardDrawingDoodad *,
+ drawing->physical_indicators_size);
+ drawing->keys =
+ g_new0 (GkbKeyboardDrawingKey, drawing->xkb->max_key_code + 1);
+}
+
+static GdkFilterReturn
+xkb_state_notify_event_filter (GdkXEvent * gdkxev,
+ GdkEvent * event,
+ GkbKeyboardDrawing * drawing)
+{
+#define group_change_mask (XkbGroupStateMask | XkbGroupBaseMask | XkbGroupLatchMask | XkbGroupLockMask)
+#define modifier_change_mask (XkbModifierStateMask | XkbModifierBaseMask | XkbModifierLatchMask | XkbModifierLockMask)
+
+ if (!drawing->xkb)
+ return GDK_FILTER_CONTINUE;
+
+ if (((XEvent *) gdkxev)->type == drawing->xkb_event_type) {
+ XkbEvent *kev = (XkbEvent *) gdkxev;
+ switch (kev->any.xkb_type) {
+ case XkbStateNotify:
+ if (((kev->state.changed & modifier_change_mask) &&
+ drawing->track_modifiers)) {
+ free_cdik (drawing);
+ if (drawing->track_modifiers)
+ gkb_keyboard_drawing_set_mods
+ (drawing,
+ kev->state.compat_state);
+ drawing->keys =
+ g_new0 (GkbKeyboardDrawingKey,
+ drawing->xkb->max_key_code +
+ 1);
+ size_allocate (GTK_WIDGET (drawing),
+ &(GTK_WIDGET (drawing)->
+ allocation), drawing);
+
+ init_keys_and_doodads (drawing);
+ init_colors (drawing);
+ }
+ break;
+
+ case XkbIndicatorStateNotify:
+ {
+ /* Good question: should we track indicators when the keyboard is
+ NOT really taken from the screen */
+ XkbIndicatorNotifyEvent *iev =
+ &((XkbEvent *) gdkxev)->indicators;
+ gint i;
+
+ for (i = 0;
+ i <=
+ drawing->xkb->indicators->
+ phys_indicators; i++)
+ if (drawing->
+ physical_indicators[i] != NULL
+ && (iev->changed & 1 << i)) {
+ gint state =
+ (iev->
+ state & 1 << i) !=
+ FALSE;
+
+ if ((state
+ && !drawing->
+ physical_indicators
+ [i]->on) || (!state
+ &&
+ drawing->
+ physical_indicators
+ [i]->
+ on)) {
+ drawing->
+ physical_indicators
+ [i]->on =
+ state;
+ draw_doodad
+ (drawing,
+ drawing->
+ physical_indicators
+ [i]);
+ invalidate_indicator_doodad_region
+ (drawing,
+ drawing->
+ physical_indicators
+ [i]);
+ }
+ }
+ }
+ break;
+
+ case XkbIndicatorMapNotify:
+ case XkbControlsNotify:
+ case XkbNamesNotify:
+ case XkbNewKeyboardNotify:
+ {
+ XkbStateRec state;
+ memset (&state, 0, sizeof (state));
+ XkbGetState (drawing->display,
+ XkbUseCoreKbd, &state);
+ if (drawing->track_modifiers)
+ gkb_keyboard_drawing_set_mods
+ (drawing, state.compat_state);
+ if (drawing->track_config)
+ gkb_keyboard_drawing_set_keyboard
+ (drawing, NULL);
+ }
+ break;
+ }
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+destroy (GkbKeyboardDrawing * drawing)
+{
+ free_pango_layout (drawing);
+ gdk_window_remove_filter (NULL, (GdkFilterFunc)
+ xkb_state_notify_event_filter, drawing);
+ if (drawing->timeout > 0) {
+ g_source_remove (drawing->timeout);
+ drawing->timeout = 0;
+ }
+
+ g_object_unref (drawing->pixmap);
+}
+
+static void
+style_changed (GkbKeyboardDrawing * drawing)
+{
+ pango_layout_context_changed (drawing->layout);
+}
+
+static void
+gkb_keyboard_drawing_init (GkbKeyboardDrawing * drawing)
+{
+ gint opcode = 0, error = 0, major = 1, minor = 0;
+ gint mask;
+
+ drawing->display =
+ GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ printf ("dpy: %p\n", drawing->display);
+
+ if (!XkbQueryExtension
+ (drawing->display, &opcode, &drawing->xkb_event_type, &error,
+ &major, &minor))
+ g_critical
+ ("XkbQueryExtension failed! Stuff probably won't work.");
+
+ printf ("evt/error/major/minor: %d/%d/%d/%d\n",
+ drawing->xkb_event_type, error, major, minor);
+
+ /* XXX: this stuff probably doesn't matter.. also, gdk_screen_get_default can fail */
+ if (gtk_widget_has_screen (GTK_WIDGET (drawing)))
+ drawing->screen_num =
+ gdk_screen_get_number (gtk_widget_get_screen
+ (GTK_WIDGET (drawing)));
+ else
+ drawing->screen_num =
+ gdk_screen_get_number (gdk_screen_get_default ());
+
+ drawing->pixmap = NULL;
+ alloc_pango_layout (drawing);
+
+ drawing->font_desc =
+ pango_font_description_copy (GTK_WIDGET (drawing)->style->
+ font_desc);
+ drawing->keyboard_items = NULL;
+ drawing->colors = NULL;
+ drawing->angle = 0;
+ drawing->scale_numerator = 1;
+ drawing->scale_denominator = 1;
+
+ drawing->track_modifiers = 0;
+ drawing->track_config = 0;
+
+ gtk_widget_set_double_buffered (GTK_WIDGET (drawing), FALSE);
+
+ /* XXX: XkbClientMapMask | XkbIndicatorMapMask | XkbNamesMask | XkbGeometryMask */
+ drawing->xkb = XkbGetKeyboard (drawing->display,
+ XkbGBN_GeometryMask |
+ XkbGBN_KeyNamesMask |
+ XkbGBN_OtherNamesMask |
+ XkbGBN_SymbolsMask |
+ XkbGBN_IndicatorMapMask,
+ XkbUseCoreKbd);
+ if (drawing->xkb == NULL) {
+ g_critical
+ ("XkbGetKeyboard failed to get keyboard from the server!");
+ return;
+ }
+
+ XkbGetNames (drawing->display, XkbAllNamesMask, drawing->xkb);
+
+ drawing->xkbOnDisplay = TRUE;
+
+ alloc_cdik (drawing);
+
+ XkbSelectEventDetails (drawing->display, XkbUseCoreKbd,
+ XkbIndicatorStateNotify,
+ drawing->xkb->indicators->phys_indicators,
+ drawing->xkb->indicators->phys_indicators);
+
+ mask =
+ (XkbStateNotifyMask | XkbNamesNotifyMask |
+ XkbControlsNotifyMask | XkbIndicatorMapNotifyMask |
+ XkbNewKeyboardNotifyMask);
+ XkbSelectEvents (drawing->display, XkbUseCoreKbd, mask, mask);
+
+ mask = XkbGroupStateMask | XkbModifierStateMask;
+ XkbSelectEventDetails (drawing->display, XkbUseCoreKbd,
+ XkbStateNotify, mask, mask);
+
+ mask = (XkbGroupNamesMask | XkbIndicatorNamesMask);
+ XkbSelectEventDetails (drawing->display, XkbUseCoreKbd,
+ XkbNamesNotify, mask, mask);
+ init_keys_and_doodads (drawing);
+ init_colors (drawing);
+
+ /* required to get key events */
+ GTK_WIDGET_SET_FLAGS (GTK_WIDGET (drawing), GTK_CAN_FOCUS);
+
+ gtk_widget_set_events (GTK_WIDGET (drawing),
+ GDK_EXPOSURE_MASK | GDK_KEY_PRESS_MASK |
+ GDK_KEY_RELEASE_MASK | GDK_BUTTON_PRESS_MASK
+ | GDK_FOCUS_CHANGE_MASK);
+ g_signal_connect (G_OBJECT (drawing), "expose-event",
+ G_CALLBACK (expose_event), drawing);
+ g_signal_connect (G_OBJECT (drawing), "key-press-event",
+ G_CALLBACK (key_event), drawing);
+ g_signal_connect (G_OBJECT (drawing), "key-release-event",
+ G_CALLBACK (key_event), drawing);
+ g_signal_connect (G_OBJECT (drawing), "button-press-event",
+ G_CALLBACK (button_press_event), drawing);
+ g_signal_connect (G_OBJECT (drawing), "focus-out-event",
+ G_CALLBACK (focus_event), drawing);
+ g_signal_connect (G_OBJECT (drawing), "focus-in-event",
+ G_CALLBACK (focus_event), drawing);
+ g_signal_connect (G_OBJECT (drawing), "size-allocate",
+ G_CALLBACK (size_allocate), drawing);
+ g_signal_connect (G_OBJECT (drawing), "destroy",
+ G_CALLBACK (destroy), drawing);
+ g_signal_connect (G_OBJECT (drawing), "style-set",
+ G_CALLBACK (style_changed), drawing);
+
+ gdk_window_add_filter (NULL, (GdkFilterFunc)
+ xkb_state_notify_event_filter, drawing);
+}
+
+GtkWidget *
+gkb_keyboard_drawing_new (void)
+{
+ return
+ GTK_WIDGET (g_object_new
+ (gkb_keyboard_drawing_get_type (), NULL));
+}
+
+static void
+gkb_keyboard_drawing_class_init (GkbKeyboardDrawingClass * klass)
+{
+ klass->bad_keycode = NULL;
+
+ gkb_keyboard_drawing_signals[BAD_KEYCODE] =
+ g_signal_new ("bad-keycode", gkb_keyboard_drawing_get_type (),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GkbKeyboardDrawingClass,
+ bad_keycode), NULL, NULL,
+ gkb_keyboard_drawing_VOID__UINT, G_TYPE_NONE, 1,
+ G_TYPE_UINT);
+}
+
+GType
+gkb_keyboard_drawing_get_type (void)
+{
+ static GType gkb_keyboard_drawing_type = 0;
+
+ if (!gkb_keyboard_drawing_type) {
+ static const GTypeInfo gkb_keyboard_drawing_info = {
+ sizeof (GkbKeyboardDrawingClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) gkb_keyboard_drawing_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GkbKeyboardDrawing),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gkb_keyboard_drawing_init,
+ };
+
+ gkb_keyboard_drawing_type =
+ g_type_register_static (GTK_TYPE_DRAWING_AREA,
+ "GkbKeyboardDrawing",
+ &gkb_keyboard_drawing_info, 0);
+ }
+
+ return gkb_keyboard_drawing_type;
+}
+
+void
+gkb_keyboard_drawing_set_mods (GkbKeyboardDrawing * drawing, guint mods)
+{
+#ifdef KBDRAW_DEBUG
+ printf ("set_mods: %d\n", mods);
+#endif
+ if (mods != drawing->mods) {
+ drawing->mods = mods;
+ gtk_widget_queue_draw (GTK_WIDGET (drawing));
+ }
+}
+
+/* returns a pixbuf with the keyboard drawing at the current pixel size
+ * (which can then be saved to disk, etc) */
+GdkPixbuf *
+gkb_keyboard_drawing_get_pixbuf (GkbKeyboardDrawing * drawing)
+{
+ if (drawing->pixmap == NULL)
+ draw_keyboard (drawing);
+
+ return gdk_pixbuf_get_from_drawable (NULL, drawing->pixmap, NULL,
+ 0, 0, 0, 0,
+ xkb_to_pixmap_coord (drawing,
+ drawing->
+ xkb->
+ geom->
+ width_mm),
+ xkb_to_pixmap_coord (drawing,
+ drawing->
+ xkb->
+ geom->
+ height_mm));
+}
+
+gboolean
+gkb_keyboard_drawing_set_keyboard (GkbKeyboardDrawing * drawing,
+ XkbComponentNamesRec * names)
+{
+ free_cdik (drawing);
+ if (drawing->xkb)
+ XkbFreeKeyboard (drawing->xkb, 0, TRUE); /* free_all = TRUE */
+ drawing->xkb = NULL;
+
+ if (names) {
+ drawing->xkb =
+ XkbGetKeyboardByName (drawing->display, XkbUseCoreKbd,
+ names, 0,
+ XkbGBN_GeometryMask |
+ XkbGBN_KeyNamesMask |
+ XkbGBN_OtherNamesMask |
+ XkbGBN_ClientSymbolsMask |
+ XkbGBN_IndicatorMapMask, FALSE);
+ drawing->xkbOnDisplay = FALSE;
+ } else {
+ drawing->xkb = XkbGetKeyboard (drawing->display,
+ XkbGBN_GeometryMask |
+ XkbGBN_KeyNamesMask |
+ XkbGBN_OtherNamesMask |
+ XkbGBN_SymbolsMask |
+ XkbGBN_IndicatorMapMask,
+ XkbUseCoreKbd);
+ XkbGetNames (drawing->display, XkbAllNamesMask,
+ drawing->xkb);
+ drawing->xkbOnDisplay = TRUE;
+ }
+
+ if (drawing->xkb == NULL)
+ return FALSE;
+
+ alloc_cdik (drawing);
+
+ init_keys_and_doodads (drawing);
+ init_colors (drawing);
+
+ size_allocate (GTK_WIDGET (drawing),
+ &(GTK_WIDGET (drawing)->allocation), drawing);
+ gtk_widget_queue_draw (GTK_WIDGET (drawing));
+
+ return TRUE;
+}
+
+G_CONST_RETURN gchar *
+gkb_keyboard_drawing_get_keycodes (GkbKeyboardDrawing * drawing)
+{
+ if (!drawing->xkb || drawing->xkb->names->keycodes <= 0)
+ return NULL;
+ else
+ return XGetAtomName (drawing->display,
+ drawing->xkb->names->keycodes);
+}
+
+G_CONST_RETURN gchar *
+gkb_keyboard_drawing_get_geometry (GkbKeyboardDrawing * drawing)
+{
+ if (!drawing->xkb || drawing->xkb->names->geometry <= 0)
+ return NULL;
+ else
+ return XGetAtomName (drawing->display,
+ drawing->xkb->names->geometry);
+}
+
+G_CONST_RETURN gchar *
+gkb_keyboard_drawing_get_symbols (GkbKeyboardDrawing * drawing)
+{
+ if (!drawing->xkb || drawing->xkb->names->symbols <= 0)
+ return NULL;
+ else
+ return XGetAtomName (drawing->display,
+ drawing->xkb->names->symbols);
+}
+
+G_CONST_RETURN gchar *
+gkb_keyboard_drawing_get_types (GkbKeyboardDrawing * drawing)
+{
+ if (!drawing->xkb || drawing->xkb->names->types <= 0)
+ return NULL;
+ else
+ return XGetAtomName (drawing->display,
+ drawing->xkb->names->types);
+}
+
+G_CONST_RETURN gchar *
+gkb_keyboard_drawing_get_compat (GkbKeyboardDrawing * drawing)
+{
+ if (!drawing->xkb || drawing->xkb->names->compat <= 0)
+ return NULL;
+ else
+ return XGetAtomName (drawing->display,
+ drawing->xkb->names->compat);
+}
+
+void
+gkb_keyboard_drawing_set_track_modifiers (GkbKeyboardDrawing * drawing,
+ gboolean enable)
+{
+ if (enable) {
+ XkbStateRec state;
+ drawing->track_modifiers = 1;
+ memset (&state, 0, sizeof (state));
+ XkbGetState (drawing->display, XkbUseCoreKbd, &state);
+ gkb_keyboard_drawing_set_mods (drawing,
+ state.compat_state);
+ } else
+ drawing->track_modifiers = 0;
+}
+
+void
+gkb_keyboard_drawing_set_track_config (GkbKeyboardDrawing * drawing,
+ gboolean enable)
+{
+ if (enable)
+ drawing->track_config = 1;
+ else
+ drawing->track_config = 0;
+}
+
+void
+gkb_keyboard_drawing_set_groups_levels (GkbKeyboardDrawing * drawing,
+ GkbKeyboardDrawingGroupLevel *
+ groupLevels[])
+{
+#ifdef KBDRAW_DEBUG
+ printf ("set_group_levels [topLeft]: %d %d \n",
+ groupLevels[GKB_KEYBOARD_DRAWING_POS_TOPLEFT]->group,
+ groupLevels[GKB_KEYBOARD_DRAWING_POS_TOPLEFT]->level);
+ printf ("set_group_levels [topRight]: %d %d \n",
+ groupLevels[GKB_KEYBOARD_DRAWING_POS_TOPRIGHT]->group,
+ groupLevels[GKB_KEYBOARD_DRAWING_POS_TOPRIGHT]->level);
+ printf ("set_group_levels [bottomLeft]: %d %d \n",
+ groupLevels[GKB_KEYBOARD_DRAWING_POS_BOTTOMLEFT]->group,
+ groupLevels[GKB_KEYBOARD_DRAWING_POS_BOTTOMLEFT]->level);
+ printf ("set_group_levels [bottomRight]: %d %d \n",
+ groupLevels[GKB_KEYBOARD_DRAWING_POS_BOTTOMRIGHT]->group,
+ groupLevels[GKB_KEYBOARD_DRAWING_POS_BOTTOMRIGHT]->level);
+#endif
+ drawing->groupLevels = groupLevels;
+
+ gtk_widget_queue_draw (GTK_WIDGET (drawing));
+}
diff --git a/libgnomekbd/backup/gkb-keyboard-drawing.h b/libgnomekbd/backup/gkb-keyboard-drawing.h
new file mode 100644
index 0000000..253de33
--- /dev/null
+++ b/libgnomekbd/backup/gkb-keyboard-drawing.h
@@ -0,0 +1,185 @@
+/* $Id$ */
+/*
+ * keyboard-drawing.h: header file for a gtk+ widget that is a drawing of
+ * the keyboard of the default display
+ *
+ * Copyright (c) 2003 Noah Levitt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef GKB_KEYBOARD_DRAWING_H
+#define GKB_KEYBOARD_DRAWING_H 1
+
+#include <gtk/gtk.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBgeom.h>
+
+G_BEGIN_DECLS
+#define GKB_KEYBOARD_DRAWING(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), gkb_keyboard_drawing_get_type (), \
+ GkbKeyboardDrawing))
+#define GKB_KEYBOARD_DRAWING_CLASS(clazz) (G_TYPE_CHECK_CLASS_CAST ((clazz), gkb_keyboard_drawing_get_type () \
+ GkbKeyboardDrawingClass))
+#define GKB_IS_KEYBOARD_DRAWING(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), gkb_keyboard_drawing_get_type ())
+typedef struct _GkbKeyboardDrawing GkbKeyboardDrawing;
+typedef struct _GkbKeyboardDrawingClass GkbKeyboardDrawingClass;
+
+typedef struct _GkbKeyboardDrawingItem GkbKeyboardDrawingItem;
+typedef struct _GkbKeyboardDrawingKey GkbKeyboardDrawingKey;
+typedef struct _GkbKeyboardDrawingDoodad GkbKeyboardDrawingDoodad;
+typedef struct _GkbKeyboardDrawingGroupLevel GkbKeyboardDrawingGroupLevel;
+
+typedef enum {
+ GKB_KEYBOARD_DRAWING_ITEM_TYPE_KEY,
+ GKB_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD
+} GkbKeyboardDrawingItemType;
+
+typedef enum {
+ GKB_KEYBOARD_DRAWING_POS_TOPLEFT,
+ GKB_KEYBOARD_DRAWING_POS_TOPRIGHT,
+ GKB_KEYBOARD_DRAWING_POS_BOTTOMLEFT,
+ GKB_KEYBOARD_DRAWING_POS_BOTTOMRIGHT,
+ GKB_KEYBOARD_DRAWING_POS_TOTAL,
+ GKB_KEYBOARD_DRAWING_POS_FIRST = GKB_KEYBOARD_DRAWING_POS_TOPLEFT,
+ GKB_KEYBOARD_DRAWING_POS_LAST =
+ GKB_KEYBOARD_DRAWING_POS_BOTTOMRIGHT,
+} GkbKeyboardDrawingGroupLevelPosition;
+
+/* units are in xkb form */
+struct _GkbKeyboardDrawingItem {
+ /*< private > */
+
+ GkbKeyboardDrawingItemType type;
+ gint origin_x;
+ gint origin_y;
+ gint angle;
+ guint priority;
+};
+
+/* units are in xkb form */
+struct _GkbKeyboardDrawingKey {
+ /*< private > */
+
+ GkbKeyboardDrawingItemType type;
+ gint origin_x;
+ gint origin_y;
+ gint angle;
+ guint priority;
+
+ XkbKeyRec *xkbkey;
+ gboolean pressed;
+ guint keycode;
+};
+
+/* units are in xkb form */
+struct _GkbKeyboardDrawingDoodad {
+ /*< private > */
+
+ GkbKeyboardDrawingItemType type;
+ gint origin_x;
+ gint origin_y;
+ gint angle;
+ guint priority;
+
+ XkbDoodadRec *doodad;
+ gboolean on; /* for indicator doodads */
+};
+
+struct _GkbKeyboardDrawingGroupLevel {
+ gint group;
+ gint level;
+};
+
+struct _GkbKeyboardDrawing {
+ /*< private > */
+
+ GtkDrawingArea parent;
+
+ GdkPixmap *pixmap;
+ XkbDescRec *xkb;
+ gboolean xkbOnDisplay;
+
+ gint angle; /* current angle pango is set to draw at, in tenths of a degree */
+ PangoLayout *layout;
+ PangoFontDescription *font_desc;
+
+ gint scale_numerator;
+ gint scale_denominator;
+
+ GkbKeyboardDrawingKey *keys;
+
+ /* list of stuff to draw in priority order */
+ GList *keyboard_items;
+
+ GdkColor *colors;
+
+ guint timeout;
+
+ GkbKeyboardDrawingGroupLevel **groupLevels;
+
+ guint mods;
+
+ Display *display;
+ gint screen_num;
+
+ gint xkb_event_type;
+
+ GkbKeyboardDrawingDoodad **physical_indicators;
+ gint physical_indicators_size;
+
+ guint track_config:1;
+ guint track_modifiers:1;
+};
+
+struct _GkbKeyboardDrawingClass {
+ GtkDrawingAreaClass parent_class;
+
+ /* we send this signal when the user presses a key that "doesn't exist"
+ * according to the keyboard geometry; it probably means their xkb
+ * configuration is incorrect */
+ void (*bad_keycode) (GkbKeyboardDrawing * drawing, guint keycode);
+};
+
+GType gkb_keyboard_drawing_get_type (void);
+GtkWidget *gkb_keyboard_drawing_new (void);
+
+GdkPixbuf *gkb_keyboard_drawing_get_pixbuf (GkbKeyboardDrawing *
+ kbdrawing);
+gboolean gkb_keyboard_drawing_set_keyboard (GkbKeyboardDrawing * kbdrawing,
+ XkbComponentNamesRec * names);
+
+G_CONST_RETURN gchar *gkb_keyboard_drawing_get_keycodes (GkbKeyboardDrawing
+ * kbdrawing);
+G_CONST_RETURN gchar *gkb_keyboard_drawing_get_geometry (GkbKeyboardDrawing
+ * kbdrawing);
+G_CONST_RETURN gchar *gkb_keyboard_drawing_get_symbols (GkbKeyboardDrawing
+ * kbdrawing);
+G_CONST_RETURN gchar *gkb_keyboard_drawing_get_types (GkbKeyboardDrawing *
+ kbdrawing);
+G_CONST_RETURN gchar *gkb_keyboard_drawing_get_compat (GkbKeyboardDrawing *
+ kbdrawing);
+
+void gkb_keyboard_drawing_set_track_modifiers (GkbKeyboardDrawing *
+ kbdrawing, gboolean enable);
+void gkb_keyboard_drawing_set_track_config (GkbKeyboardDrawing * kbdrawing,
+ gboolean enable);
+
+void gkb_keyboard_drawing_set_groups_levels (GkbKeyboardDrawing *
+ kbdrawing,
+ GkbKeyboardDrawingGroupLevel *
+ groupLevels[]);
+
+G_END_DECLS
+#endif /* #ifndef GKB_KEYBOARD_DRAWING_H */
diff --git a/libgnomekbd/backup/gkb-util.c b/libgnomekbd/backup/gkb-util.c
new file mode 100644
index 0000000..845e0bf
--- /dev/null
+++ b/libgnomekbd/backup/gkb-util.c
@@ -0,0 +1,149 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <gkb-util.h>
+
+#include <time.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtkmessagedialog.h>
+
+#include <libxklavier/xklavier.h>
+
+#include <gconf/gconf-client.h>
+
+#include <gkb-config-private.h>
+
+static void
+gkb_log_appender (const char file[], const char function[],
+ int level, const char format[], va_list args)
+{
+ time_t now = time (NULL);
+ g_log (NULL, G_LOG_LEVEL_DEBUG, "[%08ld,%03d,%s:%s/] \t",
+ (long) now, level, file, function);
+ g_logv (NULL, G_LOG_LEVEL_DEBUG, format, args);
+}
+
+void
+gkb_install_glib_log_appender (void)
+{
+ xkl_set_log_appender (gkb_log_appender);
+}
+
+#define GKB_PREVIEW_CONFIG_KEY_PREFIX GKB_CONFIG_KEY_PREFIX "/preview"
+
+const gchar GKB_PREVIEW_CONFIG_DIR[] = GKB_PREVIEW_CONFIG_KEY_PREFIX;
+const gchar GKB_PREVIEW_CONFIG_KEY_X[] =
+ GKB_PREVIEW_CONFIG_KEY_PREFIX "/x";
+const gchar GKB_PREVIEW_CONFIG_KEY_Y[] =
+ GKB_PREVIEW_CONFIG_KEY_PREFIX "/y";
+const gchar GKB_PREVIEW_CONFIG_KEY_WIDTH[] =
+ GKB_PREVIEW_CONFIG_KEY_PREFIX "/width";
+const gchar GKB_PREVIEW_CONFIG_KEY_HEIGHT[] =
+ GKB_PREVIEW_CONFIG_KEY_PREFIX "/height";
+
+GdkRectangle *
+gkb_preview_load_position (void)
+{
+ GError *gerror = NULL;
+ GdkRectangle *rv = NULL;
+ gint x, y, w, h;
+ GConfClient *conf_client = gconf_client_get_default ();
+
+ if (conf_client == NULL)
+ return NULL;
+
+ x = gconf_client_get_int (conf_client,
+ GKB_PREVIEW_CONFIG_KEY_X, &gerror);
+ if (gerror != NULL) {
+ xkl_debug (0, "Error getting the preview x: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ g_object_unref (G_OBJECT (conf_client));
+ return NULL;
+ }
+
+ y = gconf_client_get_int (conf_client,
+ GKB_PREVIEW_CONFIG_KEY_Y, &gerror);
+ if (gerror != NULL) {
+ xkl_debug (0, "Error getting the preview y: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ g_object_unref (G_OBJECT (conf_client));
+ return NULL;
+ }
+
+ w = gconf_client_get_int (conf_client,
+ GKB_PREVIEW_CONFIG_KEY_WIDTH, &gerror);
+ if (gerror != NULL) {
+ xkl_debug (0, "Error getting the preview width: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ g_object_unref (G_OBJECT (conf_client));
+ return NULL;
+ }
+
+ h = gconf_client_get_int (conf_client,
+ GKB_PREVIEW_CONFIG_KEY_HEIGHT, &gerror);
+ if (gerror != NULL) {
+ xkl_debug (0, "Error getting the preview height: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ g_object_unref (G_OBJECT (conf_client));
+ return NULL;
+ }
+
+ g_object_unref (G_OBJECT (conf_client));
+
+ // default values should be just ignored
+ if (x == -1 || y == -1 || w == -1 || h == -1)
+ return NULL;
+
+ rv = g_new (GdkRectangle, 1);
+ rv->x = x;
+ rv->y = y;
+ rv->width = w;
+ rv->height = h;
+ return rv;
+}
+
+void
+gkb_preview_save_position (GdkRectangle * rect)
+{
+ GConfClient *conf_client = gconf_client_get_default ();
+ GConfChangeSet *cs;
+ GError *gerror = NULL;
+
+ cs = gconf_change_set_new ();
+
+ gconf_change_set_set_int (cs, GKB_PREVIEW_CONFIG_KEY_X, rect->x);
+ gconf_change_set_set_int (cs, GKB_PREVIEW_CONFIG_KEY_Y, rect->y);
+ gconf_change_set_set_int (cs, GKB_PREVIEW_CONFIG_KEY_WIDTH,
+ rect->width);
+ gconf_change_set_set_int (cs, GKB_PREVIEW_CONFIG_KEY_HEIGHT,
+ rect->height);
+
+ gconf_client_commit_change_set (conf_client, cs, TRUE, &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error saving preview configuration: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ }
+ gconf_change_set_unref (cs);
+ g_object_unref (G_OBJECT (conf_client));
+}
diff --git a/libgnomekbd/backup/gkb-util.h b/libgnomekbd/backup/gkb-util.h
new file mode 100644
index 0000000..e441656
--- /dev/null
+++ b/libgnomekbd/backup/gkb-util.h
@@ -0,0 +1,30 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GKB_UTIL_H__
+#define __GKB_UTIL_H__
+
+#include <glib.h>
+#include <gtk/gtkwidget.h>
+
+extern void gkb_install_glib_log_appender (void);
+
+extern GdkRectangle *gkb_preview_load_position (void);
+
+extern void gkb_preview_save_position (GdkRectangle * rect);
+
+
+#endif
diff --git a/libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in b/libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in
new file mode 100644
index 0000000..1a917e6
--- /dev/null
+++ b/libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in
@@ -0,0 +1,193 @@
+<?xml version="1.0"?>
+<gconfschemafile>
+ <schemalist>
+ <schema>
+ <key>/schemas/desktop/gnome/peripherals/keyboard/kbd/overrideSettings</key>
+ <applyto>/desktop/gnome/peripherals/keyboard/kbd/overrideSettings</applyto>
+ <owner>gnome</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Keyboard settings in gconf will be overridden from the system ASAP (deprecated)</short>
+ <long>Very soon, keyboard settings in gconf will be overridden (from the system configuration)
+ This key has been deprecated since GNOME 2.12, please unset the model, layouts and
+ options keys to get the default system configuration.</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/gnome/peripherals/keyboard/kbd/model</key>
+ <applyto>/desktop/gnome/peripherals/keyboard/kbd/model</applyto>
+ <owner>gnome</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>Keyboard model</short>
+ <long>keyboard model</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/gnome/peripherals/keyboard/kbd/layouts</key>
+ <applyto>/desktop/gnome/peripherals/keyboard/kbd/layouts</applyto>
+ <owner>gnome</owner>
+ <type>list</type>
+ <list_type>string</list_type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Keyboard layout</short>
+ <long>keyboard layout</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/gnome/peripherals/keyboard/kbd/options</key>
+ <applyto>/desktop/gnome/peripherals/keyboard/kbd/options</applyto>
+ <owner>gnome</owner>
+ <type>list</type>
+ <list_type>string</list_type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Keyboard options</short>
+ <long>Keyboard options</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/gnome/peripherals/keyboard/general/update_handlers</key>
+ <applyto>/desktop/gnome/peripherals/keyboard/general/update_handlers</applyto>
+ <owner>gnome</owner>
+ <type>list</type>
+ <list_type>string</list_type>
+ <default>[]</default>
+ <locale name="C">
+ <short>Keyboard Update Handlers</short>
+ <long>A collection of scripts to run whenever the keyboard state is
+ reloaded. Useful for re-applying xmodmap based adjustments</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/gnome/peripherals/keyboard/general/known_file_list</key>
+ <applyto>/desktop/gnome/peripherals/keyboard/general/known_file_list</applyto>
+ <owner>gnome</owner>
+ <type>list</type>
+ <list_type>string</list_type>
+ <default>[]</default>
+ <locale name="C">
+ <short>modmap file list</short>
+ <long>A list of modmap files available in the $HOME directory.</long>
+ </locale>
+ </schema>
+
+
+ <schema>
+ <key>/schemas/desktop/gnome/peripherals/keyboard/general/defaultGroup</key>
+ <applyto>/desktop/gnome/peripherals/keyboard/general/defaultGroup</applyto>
+ <owner>gnome</owner>
+ <type>int</type>
+ <default>-1</default>
+ <locale name="C">
+ <short>Default group, assigned on window creation</short>
+ <long>Default group, assigned on window creation</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/gnome/peripherals/keyboard/general/groupPerWindow</key>
+ <applyto>/desktop/gnome/peripherals/keyboard/general/groupPerWindow</applyto>
+ <owner>gnome</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Keep and manage separate group per window</short>
+ <long>Keep and manage separate group per window</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/gnome/peripherals/keyboard/general/handleIndicators</key>
+ <applyto>/desktop/gnome/peripherals/keyboard/general/handleIndicators</applyto>
+ <owner>gnome</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Save/restore indicators together with layout groups</short>
+ <long>Save/restore indicators together with layout groups</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/gnome/peripherals/keyboard/general/layoutNamesAsGroupNames</key>
+ <applyto>/desktop/gnome/peripherals/keyboard/general/layoutNamesAsGroupNames</applyto>
+ <owner>gnome</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Show layout names instead of group names</short>
+ <long>Show layout names instead of group names (only for versions of XFree supporting multiple layouts)</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/gnome/peripherals/keyboard/general/disable_sysconfig_changed_warning</key>
+ <applyto>/desktop/gnome/peripherals/keyboard/general/disable_sysconfig_changed_warning</applyto>
+ <owner>gnome</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Suppress the "X sysconfig changed" warning message</short>
+ <long>Suppress the "X sysconfig changed" warning message</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/gswitchit/preview/x</key>
+ <applyto>/apps/gswitchit/preview/x</applyto>
+ <owner>gnome</owner>
+ <type>int</type>
+ <default>-1</default>
+ <locale name="C">
+ <short>The Keyboard Preview, X offset</short>
+ <long>The Keyboard Preview, X offset</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/gswitchit/preview/y</key>
+ <applyto>/apps/gswitchit/preview/y</applyto>
+ <owner>gnome</owner>
+ <type>int</type>
+ <default>-1</default>
+ <locale name="C">
+ <short>The Keyboard Preview, Y offset</short>
+ <long>The Keyboard Preview, Y offset</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/gswitchit/preview/width</key>
+ <applyto>/apps/gswitchit/preview/width</applyto>
+ <owner>gnome</owner>
+ <type>int</type>
+ <default>-1</default>
+ <locale name="C">
+ <short>The Keyboard Preview, width</short>
+ <long>The Keyboard Preview, width</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/gswitchit/preview/height</key>
+ <applyto>/apps/gswitchit/preview/height</applyto>
+ <owner>gnome</owner>
+ <type>int</type>
+ <default>-1</default>
+ <locale name="C">
+ <short>The Keyboard Preview, height</short>
+ <long>The Keyboard Preview, height</long>
+ </locale>
+ </schema>
+
+ </schemalist>
+</gconfschemafile>
diff --git a/libgnomekbd/gkbd-config-private.h b/libgnomekbd/gkbd-config-private.h
new file mode 100644
index 0000000..998a34b
--- /dev/null
+++ b/libgnomekbd/gkbd-config-private.h
@@ -0,0 +1,99 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GKBD_CONFIG_PRIVATE_H__
+#define __GKBD_CONFIG_PRIVATE_H__
+
+#include "libgnomekbd/gkbd-desktop-config.h"
+#include "libgnomekbd/gkbd-keyboard-config.h"
+
+#define GKBD_CONFIG_KEY_PREFIX "/desktop/gnome/peripherals/keyboard"
+
+extern const gchar GKBD_PREVIEW_CONFIG_DIR[];
+extern const gchar GKBD_PREVIEW_CONFIG_KEY_X[];
+extern const gchar GKBD_PREVIEW_CONFIG_KEY_Y[];
+extern const gchar GKBD_PREVIEW_CONFIG_KEY_WIDTH[];
+extern const gchar GKBD_PREVIEW_CONFIG_KEY_HEIGHT[];
+
+/**
+ * General config functions (private)
+ */
+extern void
+ gkbd_desktop_config_add_listener (GConfClient * conf_client,
+ const gchar * key,
+ GConfClientNotifyFunc func,
+ gpointer user_data, int *pid);
+
+
+extern void
+ gkbd_desktop_config_remove_listener (GConfClient * conf_client, int *pid);
+
+extern void gkbd_keyboard_config_model_set (GkbdKeyboardConfig *
+ kbd_config,
+ const gchar * model_name);
+
+extern void gkbd_keyboard_config_layouts_reset (GkbdKeyboardConfig *
+ kbd_config);
+extern void gkbd_keyboard_config_layouts_add (GkbdKeyboardConfig *
+ kbd_config,
+ const gchar * layout_name,
+ const gchar * variant_name);
+
+extern void gkbd_keyboard_config_layouts_reset (GkbdKeyboardConfig *
+ kbd_config);
+extern void gkbd_keyboard_config_options_reset (GkbdKeyboardConfig *
+ kbd_config);
+
+extern void gkbd_keyboard_config_options_add (GkbdKeyboardConfig *
+ kbd_config,
+ const gchar * group_name,
+ const gchar * option_name);
+extern gboolean gkbd_keyboard_config_options_is_set (GkbdKeyboardConfig *
+ kbd_config,
+ const gchar *
+ group_name,
+ const gchar *
+ option_name);
+
+extern gboolean gkbd_keyboard_config_dump_settings (GkbdKeyboardConfig *
+ kbd_config,
+ const char *file_name);
+
+extern void gkbd_keyboard_config_start_listen (GkbdKeyboardConfig *
+ kbd_config,
+ GConfClientNotifyFunc func,
+ gpointer user_data);
+
+extern void gkbd_keyboard_config_stop_listen (GkbdKeyboardConfig *
+ kbd_config);
+
+extern gboolean gkbd_keyboard_config_get_lv_descriptions (XklConfigRegistry
+ *
+ config_registry,
+ const gchar *
+ layout_name,
+ const gchar *
+ variant_name,
+ gchar **
+ layout_short_descr,
+ gchar **
+ layout_descr,
+ gchar **
+ variant_short_descr,
+ gchar **
+ variant_descr);
+
+#endif
diff --git a/libgnomekbd/gkbd-config-registry.c b/libgnomekbd/gkbd-config-registry.c
new file mode 100644
index 0000000..60dce84
--- /dev/null
+++ b/libgnomekbd/gkbd-config-registry.c
@@ -0,0 +1,166 @@
+#include <config.h>
+
+#include <X11/Xlib.h>
+
+#include <gkbd-config-registry.h>
+#include <gkbd-config-registry-server.h>
+#include <gkbd-keyboard-config.h>
+
+static GObjectClass *parent_class = NULL;
+
+gboolean
+ gkbd_config_registry_get_current_descriptions_as_utf8
+ (GkbdConfigRegistry * registry,
+ gchar *** short_layout_descriptions,
+ gchar *** long_layout_descriptions,
+ gchar *** short_variant_descriptions,
+ gchar *** long_variant_descriptions, GError ** error) {
+ XklConfigRec *xkl_config;
+ char **pl, **pv;
+ guint total_layouts;
+ gchar **sld, **lld, **svd, **lvd;
+
+ if (!registry->registry) {
+ registry->registry =
+ xkl_config_registry_get_instance (registry->engine);
+
+ xkl_config_registry_load (registry->registry);
+ }
+
+ if (!
+ (xkl_engine_get_features (registry->engine) &
+ XKLF_MULTIPLE_LAYOUTS_SUPPORTED))
+ return FALSE;
+
+ xkl_config = xkl_config_rec_new ();
+
+ if (!xkl_config_rec_get_from_server (xkl_config, registry->engine))
+ return FALSE;
+
+ pl = xkl_config->layouts;
+ pv = xkl_config->variants;
+ total_layouts = g_strv_length (xkl_config->layouts);
+ sld = *short_layout_descriptions =
+ g_new0 (char *, total_layouts + 1);
+ lld = *long_layout_descriptions =
+ g_new0 (char *, total_layouts + 1);
+ svd = *short_variant_descriptions =
+ g_new0 (char *, total_layouts + 1);
+ lvd = *long_variant_descriptions =
+ g_new0 (char *, total_layouts + 1);
+
+ while (pl != NULL && *pl != NULL) {
+ XklConfigItem item;
+
+ g_snprintf (item.name, sizeof item.name, "%s", *pl);
+ if (xkl_config_registry_find_layout
+ (registry->registry, &item)) {
+ *sld++ = g_strdup (item.short_description);
+ *lld++ = g_strdup (item.description);
+ } else {
+ *sld++ = g_strdup ("");
+ *lld++ = g_strdup ("");
+ }
+
+ if (*pv != NULL) {
+ g_snprintf (item.name, sizeof item.name, "%s",
+ *pv);
+ if (xkl_config_registry_find_variant
+ (registry->registry, *pl, &item)) {
+ *svd = g_strdup (item.short_description);
+ *lvd = g_strdup (item.description);
+ } else {
+ *svd++ = g_strdup ("");
+ *lvd++ = g_strdup ("");
+ }
+ } else {
+ *svd++ = g_strdup ("");
+ *lvd++ = g_strdup ("");
+ }
+
+ pl++;
+ pv++;
+ }
+ g_object_unref (G_OBJECT (xkl_config));
+
+ return TRUE;
+}
+
+G_DEFINE_TYPE (GkbdConfigRegistry, gkbd_config_registry, G_TYPE_OBJECT)
+static void
+finalize (GObject * object)
+{
+ GkbdConfigRegistry *registry;
+
+ registry = GKBD_CONFIG_REGISTRY (object);
+ if (registry->registry == NULL) {
+ return;
+ }
+
+ g_object_unref (registry->registry);
+ registry->registry = NULL;
+
+ g_object_unref (registry->engine);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gkbd_config_registry_class_init (GkbdConfigRegistryClass * klass)
+{
+ GError *error = NULL;
+ GObjectClass *object_class;
+
+ /* Init the DBus connection, per-klass */
+ klass->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (klass->connection == NULL) {
+ g_warning ("Unable to connect to dbus: %s",
+ error->message);
+ g_error_free (error);
+ return;
+ }
+
+ dbus_g_object_type_install_info (GKBD_CONFIG_TYPE_REGISTRY,
+ &dbus_glib_gkbd_config_registry_object_info);
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = finalize;
+
+ parent_class = g_type_class_peek_parent (klass);
+}
+
+static void
+gkbd_config_registry_init (GkbdConfigRegistry * registry)
+{
+ GError *error = NULL;
+ DBusGProxy *driver_proxy;
+ GkbdConfigRegistryClass *klass =
+ GKBD_CONFIG_REGISTRY_GET_CLASS (registry);
+ unsigned request_ret;
+
+ /* Register DBUS path */
+ dbus_g_connection_register_g_object (klass->connection,
+ "/org/gnome/GkbdConfigRegistry",
+ G_OBJECT (registry));
+
+ /* Register the service name, the constant here are defined in dbus-glib-bindings.h */
+ driver_proxy = dbus_g_proxy_new_for_name (klass->connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+
+ if (!org_freedesktop_DBus_request_name
+ (driver_proxy, "org.gnome.GkbdConfigRegistry", 0,
+ &request_ret, &error)) {
+ g_warning ("Unable to register service: %s",
+ error->message);
+ g_error_free (error);
+ }
+ g_object_unref (driver_proxy);
+
+ /* Init libxklavier stuff */
+ registry->engine = xkl_engine_get_instance (XOpenDisplay (NULL));
+ /* Lazy initialization */
+ registry->registry = NULL;
+}
diff --git a/libgnomekbd/gkbd-config-registry.h b/libgnomekbd/gkbd-config-registry.h
new file mode 100644
index 0000000..c55f5f0
--- /dev/null
+++ b/libgnomekbd/gkbd-config-registry.h
@@ -0,0 +1,44 @@
+#ifndef __GKBD_CONFIG_REGISTRY_H__
+#define __GKBD_CONFIG_REGISTRY_H__
+
+#include <dbus/dbus-glib-bindings.h>
+#include <libxklavier/xklavier.h>
+
+typedef struct GkbdConfigRegistry GkbdConfigRegistry;
+typedef struct GkbdConfigRegistryClass GkbdConfigRegistryClass;
+
+struct GkbdConfigRegistry {
+ GObject parent;
+
+ XklEngine *engine;
+ XklConfigRegistry *registry;
+};
+
+struct GkbdConfigRegistryClass {
+ GObjectClass parent;
+ DBusGConnection *connection;
+};
+
+#define GKBD_CONFIG_TYPE_REGISTRY (gkbd_config_registry_get_type ())
+#define GKBD_CONFIG_REGISTRY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GKBD_CONFIG_TYPE_REGISTRY, GkbdConfigRegistry))
+#define GKBD_CONFIG_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GKBD_CONFIG_TYPE_REGISTRY, GkbdConfigRegistryClass))
+#define GKBD_IS_CONFIG_REGISTRY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GKBD_CONFIG_TYPE_REGISTRY))
+#define GKBD_IS_CONFIG_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GKBD_CONFIG_TYPE_REGISTRY))
+#define GKBD_CONFIG_REGISTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GKBD_CONFIG_TYPE_REGISTRY, GkbdConfigRegistryClass))
+
+
+/**
+ * DBUS server
+ */
+
+extern GType gkbd_config_registry_get_type (void);
+
+extern gboolean
+ gkbd_config_registry_get_current_descriptions_as_utf8
+ (GkbdConfigRegistry * registry,
+ gchar *** short_layout_descriptions,
+ gchar *** long_layout_descriptions,
+ gchar *** short_variant_descriptions,
+ gchar *** long_variant_descriptions, GError ** error);
+
+#endif
diff --git a/libgnomekbd/gkbd-config-registry.xml b/libgnomekbd/gkbd-config-registry.xml
new file mode 100644
index 0000000..32c4380
--- /dev/null
+++ b/libgnomekbd/gkbd-config-registry.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<node name="/org/gnome/GkbdConfigRegistry">
+ <interface name="org.gnome.GkbdConfigRegistry">
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="gkbd_config_registry"/>
+ <method name="GetCurrentDescriptionsAsUtf8">
+ <arg type="as" name="shortLayoutDescriptions" direction="out" />
+ <arg type="as" name="longLayoutDescriptions" direction="out" />
+ <arg type="as" name="shortVariantDescriptions" direction="out" />
+ <arg type="as" name="longVariantDescriptions" direction="out" />
+ </method>
+ <!-- Add more methods/signals if you want -->
+ </interface>
+</node>
diff --git a/libgnomekbd/gkbd-desktop-config.c b/libgnomekbd/gkbd-desktop-config.c
new file mode 100644
index 0000000..06db6eb
--- /dev/null
+++ b/libgnomekbd/gkbd-desktop-config.c
@@ -0,0 +1,400 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <X11/keysym.h>
+
+#include <glib/gi18n.h>
+#include <libgnome/gnome-program.h>
+
+#include <gkbd-desktop-config.h>
+#include <gkbd-config-private.h>
+
+#include <gkbd-config-registry-client.h>
+
+/**
+ * GkbdDesktopConfig
+ */
+#define GKBD_DESKTOP_CONFIG_KEY_PREFIX GKBD_CONFIG_KEY_PREFIX "/general"
+
+const gchar GKBD_DESKTOP_CONFIG_DIR[] = GKBD_DESKTOP_CONFIG_KEY_PREFIX;
+const gchar GKBD_DESKTOP_CONFIG_KEY_DEFAULT_GROUP[] =
+ GKBD_DESKTOP_CONFIG_KEY_PREFIX "/defaultGroup";
+const gchar GKBD_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW[] =
+ GKBD_DESKTOP_CONFIG_KEY_PREFIX "/groupPerWindow";
+const gchar GKBD_DESKTOP_CONFIG_KEY_HANDLE_INDICATORS[] =
+ GKBD_DESKTOP_CONFIG_KEY_PREFIX "/handleIndicators";
+const gchar GKBD_DESKTOP_CONFIG_KEY_LAYOUT_NAMES_AS_GROUP_NAMES[]
+ = GKBD_DESKTOP_CONFIG_KEY_PREFIX "/layoutNamesAsGroupNames";
+
+/**
+ * static common functions
+ */
+
+static gboolean
+gkbd_desktop_config_get_remote_lv_descriptions_utf8 (gchar *** sld,
+ gchar *** lld,
+ gchar *** svd,
+ gchar *** lvd)
+{
+ DBusGProxy *proxy;
+ DBusGConnection *connection;
+ GError *error = NULL;
+
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (connection == NULL) {
+ g_warning ("Unable to connect to dbus: %s\n",
+ error->message);
+ g_error_free (error);
+ /* Basically here, there is a problem, since there is no dbus :) */
+ return False;
+ }
+
+/* This won't trigger activation! */
+ proxy = dbus_g_proxy_new_for_name (connection,
+ "org.gnome.GkbdConfigRegistry",
+ "/org/gnome/GkbdConfigRegistry",
+ "org.gnome.GkbdConfigRegistry");
+
+/* The method call will trigger activation, more on that later */
+ if (!org_gnome_GkbdConfigRegistry_get_current_descriptions_as_utf8
+ (proxy, sld, lld, svd, lvd, &error)) {
+ /* Method failed, the GError is set, let's warn everyone */
+ g_warning ("Woops remote method failed: %s",
+ error->message);
+ g_error_free (error);
+ return False;
+ }
+ return True;
+}
+
+void
+gkbd_desktop_config_add_listener (GConfClient * conf_client,
+ const gchar * key,
+ GConfClientNotifyFunc func,
+ gpointer user_data, int *pid)
+{
+ GError *gerror = NULL;
+ xkl_debug (150, "Listening to [%s]\n", key);
+ *pid = gconf_client_notify_add (conf_client,
+ key, func, user_data, NULL,
+ &gerror);
+ if (0 == *pid) {
+ g_warning ("Error listening for configuration: [%s]\n",
+ gerror->message);
+ g_error_free (gerror);
+ }
+}
+
+void
+gkbd_desktop_config_remove_listener (GConfClient * conf_client, int *pid)
+{
+ if (*pid != 0) {
+ gconf_client_notify_remove (conf_client, *pid);
+ *pid = 0;
+ }
+}
+
+/**
+ * extern GkbdDesktopConfig config functions
+ */
+void
+gkbd_desktop_config_init (GkbdDesktopConfig * config,
+ GConfClient * conf_client, XklEngine * engine)
+{
+ GError *gerror = NULL;
+
+ memset (config, 0, sizeof (*config));
+ config->conf_client = conf_client;
+ config->engine = engine;
+ g_object_ref (config->conf_client);
+
+ gconf_client_add_dir (config->conf_client,
+ GKBD_DESKTOP_CONFIG_DIR,
+ GCONF_CLIENT_PRELOAD_NONE, &gerror);
+ if (gerror != NULL) {
+ g_warning ("err: %s\n", gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+}
+
+void
+gkbd_desktop_config_term (GkbdDesktopConfig * config)
+{
+ g_object_unref (config->conf_client);
+ config->conf_client = NULL;
+}
+
+void
+gkbd_desktop_config_load_from_gconf (GkbdDesktopConfig * config)
+{
+ GError *gerror = NULL;
+
+ config->group_per_app =
+ gconf_client_get_bool (config->conf_client,
+ GKBD_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ config->group_per_app = FALSE;
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ xkl_debug (150, "group_per_app: %d\n", config->group_per_app);
+
+ config->handle_indicators =
+ gconf_client_get_bool (config->conf_client,
+ GKBD_DESKTOP_CONFIG_KEY_HANDLE_INDICATORS,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ config->handle_indicators = FALSE;
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ xkl_debug (150, "handle_indicators: %d\n",
+ config->handle_indicators);
+
+ config->layout_names_as_group_names =
+ gconf_client_get_bool (config->conf_client,
+ GKBD_DESKTOP_CONFIG_KEY_LAYOUT_NAMES_AS_GROUP_NAMES,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ config->layout_names_as_group_names = TRUE;
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ xkl_debug (150, "layout_names_as_group_names: %d\n",
+ config->layout_names_as_group_names);
+
+ config->default_group =
+ gconf_client_get_int (config->conf_client,
+ GKBD_DESKTOP_CONFIG_KEY_DEFAULT_GROUP,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ config->default_group = -1;
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+
+ if (config->default_group < -1
+ || config->default_group >=
+ xkl_engine_get_max_num_groups (config->engine))
+ config->default_group = -1;
+ xkl_debug (150, "default_group: %d\n", config->default_group);
+}
+
+void
+gkbd_desktop_config_save_to_gconf (GkbdDesktopConfig * config)
+{
+ GConfChangeSet *cs;
+ GError *gerror = NULL;
+
+ cs = gconf_change_set_new ();
+
+ gconf_change_set_set_bool (cs,
+ GKBD_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW,
+ config->group_per_app);
+ gconf_change_set_set_bool (cs,
+ GKBD_DESKTOP_CONFIG_KEY_HANDLE_INDICATORS,
+ config->handle_indicators);
+ gconf_change_set_set_bool (cs,
+ GKBD_DESKTOP_CONFIG_KEY_LAYOUT_NAMES_AS_GROUP_NAMES,
+ config->layout_names_as_group_names);
+ gconf_change_set_set_int (cs,
+ GKBD_DESKTOP_CONFIG_KEY_DEFAULT_GROUP,
+ config->default_group);
+
+ gconf_client_commit_change_set (config->conf_client, cs, TRUE,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error saving active configuration: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ gconf_change_set_unref (cs);
+}
+
+gboolean
+gkbd_desktop_config_activate (GkbdDesktopConfig * config)
+{
+ gboolean rv = TRUE;
+
+ xkl_engine_set_group_per_toplevel_window (config->engine,
+ config->group_per_app);
+ xkl_engine_set_indicators_handling (config->engine,
+ config->handle_indicators);
+ xkl_engine_set_default_group (config->engine,
+ config->default_group);
+
+ return rv;
+}
+
+void
+gkbd_desktop_config_lock_next_group (GkbdDesktopConfig * config)
+{
+ int group = xkl_engine_get_next_group (config->engine);
+ xkl_engine_lock_group (config->engine, group);
+}
+
+void
+gkbd_desktop_config_lock_prev_group (GkbdDesktopConfig * config)
+{
+ int group = xkl_engine_get_prev_group (config->engine);
+ xkl_engine_lock_group (config->engine, group);
+}
+
+void
+gkbd_desktop_config_restore_group (GkbdDesktopConfig * config)
+{
+ int group = xkl_engine_get_current_window_group (config->engine);
+ xkl_engine_lock_group (config->engine, group);
+}
+
+void
+gkbd_desktop_config_start_listen (GkbdDesktopConfig * config,
+ GConfClientNotifyFunc func,
+ gpointer user_data)
+{
+ gkbd_desktop_config_add_listener (config->conf_client,
+ GKBD_DESKTOP_CONFIG_DIR, func,
+ user_data,
+ &config->config_listener_id);
+}
+
+void
+gkbd_desktop_config_stop_listen (GkbdDesktopConfig * config)
+{
+ gkbd_desktop_config_remove_listener (config->conf_client,
+ &config->config_listener_id);
+}
+
+gboolean
+gkbd_desktop_config_load_remote_group_descriptions_utf8 (GkbdDesktopConfig
+ * config,
+ gchar ***
+ short_group_names,
+ gchar ***
+ full_group_names)
+{
+ gchar **sld, **lld, **svd, **lvd;
+ gchar **psld, **plld, **plvd;
+ gchar **psgn, **pfgn;
+ gint total_descriptions;
+
+ if (!gkbd_desktop_config_get_remote_lv_descriptions_utf8
+ (&sld, &lld, &svd, &lvd)) {
+ return False;
+ }
+
+ total_descriptions = g_strv_length (sld);
+
+ *short_group_names = psgn =
+ g_new0 (gchar *, total_descriptions + 1);
+ *full_group_names = pfgn =
+ g_new0 (gchar *, total_descriptions + 1);
+
+ plld = lld;
+ psld = sld;
+ plvd = lvd;
+ while (plld != NULL && *plld != NULL) {
+ *psgn++ = g_strdup (*psld++);
+ *pfgn++ = g_strdup (gkbd_keyboard_config_format_full_layout
+ (*plld++, *plvd++));
+ }
+ g_strfreev (sld);
+ g_strfreev (lld);
+ g_strfreev (svd);
+ g_strfreev (lvd);
+
+ return True;
+}
+
+gchar **
+gkbd_desktop_config_load_group_descriptions_utf8 (GkbdDesktopConfig *
+ config,
+ XklConfigRegistry *
+ config_registry)
+{
+ int i;
+ const gchar **native_names =
+ xkl_engine_get_groups_names (config->engine);
+ guint total_groups = xkl_engine_get_num_groups (config->engine);
+ guint total_layouts;
+ gchar **rv = g_new0 (char *, total_groups + 1);
+ gchar **current_descr = rv;
+
+ if ((xkl_engine_get_features (config->engine) &
+ XKLF_MULTIPLE_LAYOUTS_SUPPORTED)
+ && config->layout_names_as_group_names) {
+ XklConfigRec *xkl_config = xkl_config_rec_new ();
+ if (xkl_config_rec_get_from_server
+ (xkl_config, config->engine)) {
+ char **pl = xkl_config->layouts;
+ char **pv = xkl_config->variants;
+ i = total_groups;
+ while (pl != NULL && *pl != NULL && i >= 0) {
+ char *ls_descr;
+ char *l_descr;
+ char *vs_descr;
+ char *v_descr;
+ if (gkbd_keyboard_config_get_lv_descriptions (config_registry, *pl++, *pv++, &ls_descr, &l_descr, &vs_descr, &v_descr)) {
+ char *name_utf =
+ g_locale_to_utf8
+ (gkbd_keyboard_config_format_full_layout
+ (l_descr, v_descr), -1, NULL,
+ NULL, NULL);
+ *current_descr++ = name_utf;
+ } else {
+ *current_descr++ = g_strdup ("");
+ }
+ }
+ }
+ g_object_unref (G_OBJECT (xkl_config));
+ /* Worst case - multiple layous - but SOME of them are multigrouped :(((
+ * We cannot do much - just add empty descriptions.
+ * The UI is going to be messy.
+ * Canadian layouts are famous for this sh.t. */
+ total_layouts = g_strv_length (rv);
+ if (total_layouts != total_groups) {
+ xkl_debug (0,
+ "The mismatch between "
+ "the number of groups: %d and number of layouts: %d\n",
+ total_groups, total_layouts);
+ current_descr = rv + total_layouts;
+ for (i = total_groups - total_layouts; --i >= 0;)
+ *current_descr++ = g_strdup ("");
+ }
+ }
+ total_layouts = g_strv_length (rv);
+ if (!total_layouts)
+ for (i = total_groups; --i >= 0;)
+ *current_descr++ = g_strdup (*native_names++);
+
+ return rv;
+}
diff --git a/libgnomekbd/gkbd-desktop-config.h b/libgnomekbd/gkbd-desktop-config.h
new file mode 100644
index 0000000..3ca5519
--- /dev/null
+++ b/libgnomekbd/gkbd-desktop-config.h
@@ -0,0 +1,97 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GKBD_DESKTOP_CONFIG_H__
+#define __GKBD_DESKTOP_CONFIG_H__
+
+#include <X11/Xlib.h>
+
+#include <glib.h>
+#include <glib/gslist.h>
+
+#include <gconf/gconf-client.h>
+
+#include <libxklavier/xklavier.h>
+
+extern const gchar GKBD_DESKTOP_CONFIG_DIR[];
+extern const gchar GKBD_DESKTOP_CONFIG_KEY_DEFAULT_GROUP[];
+extern const gchar GKBD_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW[];
+extern const gchar GKBD_DESKTOP_CONFIG_KEY_HANDLE_INDICATORS[];
+extern const gchar GKBD_DESKTOP_CONFIG_KEY_LAYOUT_NAMES_AS_GROUP_NAMES[];
+
+/*
+ * General configuration
+ */
+typedef struct _GkbdDesktopConfig {
+ gint default_group;
+ gboolean group_per_app;
+ gboolean handle_indicators;
+ gboolean layout_names_as_group_names;
+
+ /* private, transient */
+ GConfClient *conf_client;
+ int config_listener_id;
+ XklEngine *engine;
+} GkbdDesktopConfig;
+
+/**
+ * GkbdDesktopConfig functions
+ */
+extern void gkbd_desktop_config_init (GkbdDesktopConfig * config,
+ GConfClient * conf_client,
+ XklEngine * engine);
+extern void gkbd_desktop_config_term (GkbdDesktopConfig * config);
+
+extern void gkbd_desktop_config_load_from_gconf (GkbdDesktopConfig *
+ config);
+
+extern void gkbd_desktop_config_save_to_gconf (GkbdDesktopConfig * config);
+
+extern gboolean gkbd_desktop_config_activate (GkbdDesktopConfig * config);
+
+/* Affected by XKB and XKB/GConf configuration */
+extern gchar
+ **
+gkbd_desktop_config_load_group_descriptions_utf8 (GkbdDesktopConfig *
+ config,
+ XklConfigRegistry *
+ config_registry);
+
+
+/* Using DBUS */
+extern gboolean
+gkbd_desktop_config_load_remote_group_descriptions_utf8 (GkbdDesktopConfig
+ * config,
+ gchar ***
+ short_group_names,
+ gchar ***
+ full_group_names);
+
+extern void gkbd_desktop_config_lock_next_group (GkbdDesktopConfig *
+ config);
+
+extern void gkbd_desktop_config_lock_prev_group (GkbdDesktopConfig *
+ config);
+
+extern void gkbd_desktop_config_restore_group (GkbdDesktopConfig * config);
+
+extern void gkbd_desktop_config_start_listen (GkbdDesktopConfig * config,
+ GConfClientNotifyFunc func,
+ gpointer user_data);
+
+extern void gkbd_desktop_config_stop_listen (GkbdDesktopConfig * config);
+
+#endif
diff --git a/libgnomekbd/gkbd-indicator-config.c b/libgnomekbd/gkbd-indicator-config.c
new file mode 100644
index 0000000..381c671
--- /dev/null
+++ b/libgnomekbd/gkbd-indicator-config.c
@@ -0,0 +1,361 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <X11/keysym.h>
+
+#include <glib/gi18n.h>
+#include <gdk/gdkx.h>
+#include <libgnome/gnome-program.h>
+
+#include <gkbd-keyboard-config.h>
+#include <gkbd-indicator-config.h>
+
+#include <gkbd-config-private.h>
+
+#include <gkbd-config-registry-client.h>
+
+/**
+ * GkbdIndicatorConfig
+ */
+#define GKBD_INDICATOR_CONFIG_KEY_PREFIX GKBD_CONFIG_KEY_PREFIX "/indicator"
+
+const gchar GKBD_INDICATOR_CONFIG_DIR[] = GKBD_INDICATOR_CONFIG_KEY_PREFIX;
+const gchar GKBD_INDICATOR_CONFIG_KEY_SHOW_FLAGS[] =
+ GKBD_INDICATOR_CONFIG_KEY_PREFIX "/showFlags";
+const gchar GKBD_INDICATOR_CONFIG_KEY_ENABLED_PLUGINS[] =
+ GKBD_INDICATOR_CONFIG_KEY_PREFIX "/enabledPlugins";
+const gchar GKBD_INDICATOR_CONFIG_KEY_SECONDARIES[] =
+ GKBD_INDICATOR_CONFIG_KEY_PREFIX "/secondary";
+
+/**
+ * static applet config functions
+ */
+static void
+gkbd_indicator_config_free_enabled_plugins (GkbdIndicatorConfig *
+ ind_config)
+{
+ GSList *plugin_node = ind_config->enabled_plugins;
+ if (plugin_node != NULL) {
+ do {
+ if (plugin_node->data != NULL) {
+ g_free (plugin_node->data);
+ plugin_node->data = NULL;
+ }
+ plugin_node = g_slist_next (plugin_node);
+ } while (plugin_node != NULL);
+ g_slist_free (ind_config->enabled_plugins);
+ ind_config->enabled_plugins = NULL;
+ }
+}
+
+/**
+ * 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) {
+ gdk_pixbuf_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,
+ GkbdKeyboardConfig *
+ kbd_config, int group)
+{
+ char *image_file = NULL;
+ GtkIconInfo *icon_info = NULL;
+
+ if (!ind_config->show_flags)
+ return NULL;
+
+ if ((kbd_config->layouts != NULL) &&
+ (g_slist_length (kbd_config->layouts) > group)) {
+ char *full_layout_name =
+ (char *) g_slist_nth_data (kbd_config->layouts, group);
+
+ if (full_layout_name != NULL) {
+ char *l, *v;
+ gkbd_keyboard_config_split_items (full_layout_name,
+ &l, &v);
+ if (l != NULL) {
+ // probably there is something in theme?
+ icon_info = gtk_icon_theme_lookup_icon
+ (ind_config->icon_theme, l, 48, 0);
+ }
+ }
+ }
+ // fallback to the default value
+ if (icon_info == NULL) {
+ icon_info = gtk_icon_theme_lookup_icon
+ (ind_config->icon_theme, "stock_dialog-error", 48, 0);
+ }
+ if (icon_info != NULL) {
+ image_file =
+ g_strdup (gtk_icon_info_get_filename (icon_info));
+ gtk_icon_info_free (icon_info);
+ }
+
+ return image_file;
+}
+
+void
+gkbd_indicator_config_load_images (GkbdIndicatorConfig * ind_config,
+ GkbdKeyboardConfig * kbd_config)
+{
+ int i;
+ ind_config->images = 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);
+
+ 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_init (GkbdIndicatorConfig * ind_config,
+ GConfClient * conf_client, XklEngine * engine)
+{
+ GError *gerror = NULL;
+ gchar *sp, *datadir;
+
+ memset (ind_config, 0, sizeof (*ind_config));
+ ind_config->conf_client = conf_client;
+ ind_config->engine = engine;
+ g_object_ref (ind_config->conf_client);
+
+ gconf_client_add_dir (ind_config->conf_client,
+ GKBD_INDICATOR_CONFIG_DIR,
+ GCONF_CLIENT_PRELOAD_NONE, &gerror);
+ if (gerror != NULL) {
+ g_warning ("err1:%s\n", gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+
+ ind_config->icon_theme = gtk_icon_theme_get_default ();
+
+ datadir =
+ gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_APP_DATADIR,
+ "", FALSE, NULL);
+ gtk_icon_theme_append_search_path (ind_config->icon_theme, sp =
+ g_build_filename (g_get_home_dir
+ (),
+ ".icons/flags",
+ NULL));
+ g_free (sp);
+
+ gtk_icon_theme_append_search_path (ind_config->icon_theme,
+ sp =
+ g_build_filename (datadir,
+ "pixmaps/flags",
+ NULL));
+ g_free (sp);
+
+ gtk_icon_theme_append_search_path (ind_config->icon_theme,
+ sp =
+ g_build_filename (datadir,
+ "icons/flags",
+ NULL));
+ g_free (sp);
+ g_free (datadir);
+}
+
+void
+gkbd_indicator_config_term (GkbdIndicatorConfig * ind_config)
+{
+#if 0
+ g_object_unref (G_OBJECT (ind_config->icon_theme));
+#endif
+ ind_config->icon_theme = NULL;
+
+ gkbd_indicator_config_free_images (ind_config);
+
+ gkbd_indicator_config_free_enabled_plugins (ind_config);
+ g_object_unref (ind_config->conf_client);
+ ind_config->conf_client = NULL;
+}
+
+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;
+
+ ind_config->secondary_groups_mask =
+ gconf_client_get_int (ind_config->conf_client,
+ GKBD_INDICATOR_CONFIG_KEY_SECONDARIES,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ ind_config->secondary_groups_mask = 0;
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+
+ ind_config->show_flags =
+ gconf_client_get_bool (ind_config->conf_client,
+ GKBD_INDICATOR_CONFIG_KEY_SHOW_FLAGS,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error reading kbdConfiguration:%s\n",
+ gerror->message);
+ ind_config->show_flags = FALSE;
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+
+ gkbd_indicator_config_free_enabled_plugins (ind_config);
+ ind_config->enabled_plugins =
+ gconf_client_get_list (ind_config->conf_client,
+ GKBD_INDICATOR_CONFIG_KEY_ENABLED_PLUGINS,
+ GCONF_VALUE_STRING, &gerror);
+
+ if (gerror != NULL) {
+ g_warning ("Error reading kbd_configuration:%s\n",
+ gerror->message);
+ ind_config->enabled_plugins = NULL;
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+}
+
+void
+gkbd_indicator_config_save_to_gconf (GkbdIndicatorConfig * ind_config)
+{
+ GConfChangeSet *cs;
+ GError *gerror = NULL;
+
+ cs = gconf_change_set_new ();
+
+ gconf_change_set_set_int (cs,
+ GKBD_INDICATOR_CONFIG_KEY_SECONDARIES,
+ ind_config->secondary_groups_mask);
+ gconf_change_set_set_bool (cs,
+ GKBD_INDICATOR_CONFIG_KEY_SHOW_FLAGS,
+ ind_config->show_flags);
+ gconf_change_set_set_list (cs,
+ GKBD_INDICATOR_CONFIG_KEY_ENABLED_PLUGINS,
+ GCONF_VALUE_STRING,
+ ind_config->enabled_plugins);
+
+ gconf_client_commit_change_set (ind_config->conf_client, cs,
+ TRUE, &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error saving configuration: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ gconf_change_set_unref (cs);
+}
+
+void
+gkbd_indicator_config_activate (GkbdIndicatorConfig * ind_config)
+{
+ xkl_engine_set_secondary_groups_mask (ind_config->engine,
+ ind_config->
+ secondary_groups_mask);
+}
+
+void
+gkbd_indicator_config_start_listen (GkbdIndicatorConfig *
+ ind_config,
+ GConfClientNotifyFunc func,
+ gpointer user_data)
+{
+ gkbd_desktop_config_add_listener (ind_config->conf_client,
+ GKBD_INDICATOR_CONFIG_DIR, func,
+ user_data,
+ &ind_config->config_listener_id);
+}
+
+void
+gkbd_indicator_config_stop_listen (GkbdIndicatorConfig * ind_config)
+{
+ gkbd_desktop_config_remove_listener (ind_config->conf_client,
+ &ind_config->
+ config_listener_id);
+}
diff --git a/libgnomekbd/gkbd-indicator-config.h b/libgnomekbd/gkbd-indicator-config.h
new file mode 100644
index 0000000..e497e0e
--- /dev/null
+++ b/libgnomekbd/gkbd-indicator-config.h
@@ -0,0 +1,89 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GKBD_INDICATOR_CONFIG_H__
+#define __GKBD_INDICATOR_CONFIG_H__
+
+#include <gtk/gtk.h>
+
+#include "libgnomekbd/gkbd-keyboard-config.h"
+
+/*
+ * Indicator configuration
+ */
+typedef struct _GkbdIndicatorConfig {
+ int secondary_groups_mask;
+ gboolean show_flags;
+
+ GSList *enabled_plugins;
+
+ /* private, transient */
+ GConfClient *conf_client;
+ GSList *images;
+ GtkIconTheme *icon_theme;
+ int config_listener_id;
+ XklEngine *engine;
+} GkbdIndicatorConfig;
+
+/**
+ * GkbdIndicatorConfig functions -
+ * some of them require GkbdKeyboardConfig as well -
+ * for loading approptiate images
+ */
+extern void gkbd_indicator_config_init (GkbdIndicatorConfig *
+ applet_config,
+ GConfClient * conf_client,
+ XklEngine * engine);
+extern void gkbd_indicator_config_term (GkbdIndicatorConfig *
+ applet_config);
+
+extern void gkbd_indicator_config_load_from_gconf (GkbdIndicatorConfig
+ * applet_config);
+extern void gkbd_indicator_config_save_to_gconf (GkbdIndicatorConfig *
+ applet_config);
+
+extern gchar
+ * gkbd_indicator_config_get_images_file (GkbdIndicatorConfig *
+ applet_config,
+ 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);
+
+/* Should be updated on Indicator/GConf configuration change */
+extern void gkbd_indicator_config_activate (GkbdIndicatorConfig *
+ applet_config);
+
+extern void gkbd_indicator_config_start_listen (GkbdIndicatorConfig *
+ applet_config,
+ GConfClientNotifyFunc
+ func, gpointer user_data);
+
+extern void gkbd_indicator_config_stop_listen (GkbdIndicatorConfig *
+ applet_config);
+
+#endif
diff --git a/libgnomekbd/gkbd-indicator-marshal.list b/libgnomekbd/gkbd-indicator-marshal.list
new file mode 100644
index 0000000..5b76282
--- /dev/null
+++ b/libgnomekbd/gkbd-indicator-marshal.list
@@ -0,0 +1 @@
+VOID:VOID
diff --git a/libgnomekbd/gkbd-indicator-plugin-manager.c b/libgnomekbd/gkbd-indicator-plugin-manager.c
new file mode 100644
index 0000000..e59ef77
--- /dev/null
+++ b/libgnomekbd/gkbd-indicator-plugin-manager.c
@@ -0,0 +1,404 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <libxklavier/xklavier.h>
+
+#include <gkbd-indicator-plugin-manager.h>
+
+#define FOREACH_INITED_PLUGIN() \
+{ \
+ GSList *prec; \
+ for( prec = manager->inited_plugin_recs; prec != NULL; prec = prec->next ) \
+ { \
+ const GkbdIndicatorPlugin *plugin = \
+ ( ( GkbdIndicatorPluginManagerRecord * ) ( prec->data ) )->plugin; \
+ if( plugin != NULL ) \
+ {
+
+#define NEXT_INITED_PLUGIN() \
+ } \
+ } \
+}
+
+static void
+gkbd_indicator_plugin_manager_add_plugins_dir (GkbdIndicatorPluginManager *
+ manager,
+ const char *dirname)
+{
+ GDir *dir = g_dir_open (dirname, 0, NULL);
+ const gchar *filename;
+ if (dir == NULL)
+ return;
+
+ xkl_debug (100, "Scanning [%s]...\n", dirname);
+ while ((filename = g_dir_read_name (dir)) != NULL) {
+ gchar *full_path =
+ g_build_filename (dirname, filename, NULL);
+ xkl_debug (100, "Loading plugin module [%s]...\n",
+ full_path);
+ if (full_path != NULL) {
+ GModule *module = g_module_open (full_path, 0);
+ if (module != NULL) {
+ gpointer get_plugin_func;
+ if (g_module_symbol
+ (module, "GetPlugin",
+ &get_plugin_func)) {
+ const GkbdIndicatorPlugin *plugin =
+ ((GkbdIndicatorPluginGetPluginFunc)
+ get_plugin_func) ();
+ if (plugin != NULL) {
+ GkbdIndicatorPluginManagerRecord
+ * rec =
+ g_new0
+ (GkbdIndicatorPluginManagerRecord,
+ 1);
+ xkl_debug (100,
+ "Loaded plugin from [%s]: [%s]/[%s]...\n",
+ full_path,
+ plugin->name,
+ plugin->
+ description);
+ rec->full_path = full_path;
+ rec->module = module;
+ rec->plugin = plugin;
+ g_hash_table_insert
+ (manager->
+ all_plugin_recs,
+ full_path, rec);
+ continue;
+ }
+ } else
+ xkl_debug (0,
+ "Bad plugin: [%s]\n",
+ full_path);
+ g_module_close (module);
+ } else
+ xkl_debug (0, "Bad module: [%s], %s\n",
+ full_path, g_module_error ());
+ g_free (full_path);
+ }
+ }
+ g_dir_close (dir);
+}
+
+static void
+gkbd_indicator_plugin_manager_load_all (GkbdIndicatorPluginManager *
+ manager)
+{
+ if (!g_module_supported ()) {
+ xkl_debug (0, "Modules are not supported - no plugins!\n");
+ return;
+ }
+ gkbd_indicator_plugin_manager_add_plugins_dir (manager,
+ SYS_PLUGIN_DIR);
+}
+
+static void
+gkbd_indicator_plugin_manager_rec_term (GkbdIndicatorPluginManagerRecord *
+ rec, void *user_data)
+{
+ const GkbdIndicatorPlugin *plugin = rec->plugin;
+ if (plugin != NULL) {
+ xkl_debug (100, "Terminating plugin: [%s]...\n",
+ plugin->name);
+ if (plugin->term_callback)
+ (*plugin->term_callback) ();
+ }
+}
+
+static void
+gkbd_indicator_plugin_manager_rec_destroy (GkbdIndicatorPluginManagerRecord
+ * rec)
+{
+ xkl_debug (100, "Unloading plugin: [%s]...\n", rec->plugin->name);
+
+ g_module_close (rec->module);
+ g_free (rec);
+}
+
+void
+gkbd_indicator_plugin_manager_init (GkbdIndicatorPluginManager * manager)
+{
+ manager->all_plugin_recs =
+ g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify)
+ gkbd_indicator_plugin_manager_rec_destroy);
+ gkbd_indicator_plugin_manager_load_all (manager);
+}
+
+void
+gkbd_indicator_plugin_manager_term (GkbdIndicatorPluginManager * manager)
+{
+ gkbd_indicator_plugin_manager_term_initialized_plugins (manager);
+ if (manager->all_plugin_recs != NULL) {
+ g_hash_table_destroy (manager->all_plugin_recs);
+ manager->all_plugin_recs = NULL;
+ }
+}
+
+void
+ gkbd_indicator_plugin_manager_init_enabled_plugins
+ (GkbdIndicatorPluginManager * manager,
+ GkbdIndicatorPluginContainer * pc, GSList * enabled_plugins) {
+ GSList *plugin_name_node = enabled_plugins;
+ if (manager->all_plugin_recs == NULL)
+ return;
+ xkl_debug (100, "Initializing all enabled plugins...\n");
+ while (plugin_name_node != NULL) {
+ const char *full_path = plugin_name_node->data;
+ if (full_path != NULL) {
+ GkbdIndicatorPluginManagerRecord *rec =
+ (GkbdIndicatorPluginManagerRecord *)
+ g_hash_table_lookup (manager->all_plugin_recs,
+ full_path);
+
+ if (rec != NULL) {
+ const GkbdIndicatorPlugin *plugin =
+ rec->plugin;
+ gboolean initialized = FALSE;
+ xkl_debug (100,
+ "Initializing plugin: [%s] from [%s]...\n",
+ plugin->name, full_path);
+ if (plugin->init_callback != NULL)
+ initialized =
+ (*plugin->init_callback) (pc);
+ else
+ initialized = TRUE;
+
+ manager->inited_plugin_recs =
+ g_slist_append (manager->
+ inited_plugin_recs,
+ rec);
+ xkl_debug (100,
+ "Plugin [%s] initialized: %d\n",
+ plugin->name, initialized);
+ }
+ }
+ plugin_name_node = g_slist_next (plugin_name_node);
+ }
+}
+
+void
+ gkbd_indicator_plugin_manager_term_initialized_plugins
+ (GkbdIndicatorPluginManager * manager) {
+
+ if (manager->inited_plugin_recs == NULL)
+ return;
+ g_slist_foreach (manager->inited_plugin_recs,
+ (GFunc) gkbd_indicator_plugin_manager_rec_term,
+ NULL);
+ g_slist_free (manager->inited_plugin_recs);
+ manager->inited_plugin_recs = NULL;
+}
+
+void
+gkbd_indicator_plugin_manager_toggle_plugins (GkbdIndicatorPluginManager *
+ manager,
+ GkbdIndicatorPluginContainer
+ * pc,
+ GSList * enabled_plugins)
+{
+ gkbd_indicator_plugin_manager_term_initialized_plugins (manager);
+ gkbd_indicator_plugin_manager_init_enabled_plugins (manager, pc,
+ enabled_plugins);
+}
+
+void
+gkbd_indicator_plugin_manager_group_changed (GkbdIndicatorPluginManager *
+ manager, GtkWidget * notebook,
+ int new_group)
+{
+ FOREACH_INITED_PLUGIN ();
+ if (plugin->group_changed_callback)
+ (*plugin->group_changed_callback) (notebook, new_group);
+ NEXT_INITED_PLUGIN ();
+}
+
+void
+gkbd_indicator_plugin_manager_config_changed (GkbdIndicatorPluginManager *
+ manager,
+ GkbdKeyboardConfig * from,
+ GkbdKeyboardConfig * to)
+{
+ FOREACH_INITED_PLUGIN ();
+ if (plugin->config_changed_callback)
+ (*plugin->config_changed_callback) (from, to);
+ NEXT_INITED_PLUGIN ();
+}
+
+const GkbdIndicatorPlugin *
+gkbd_indicator_plugin_manager_get_plugin (GkbdIndicatorPluginManager *
+ manager, const char *full_path)
+{
+ GkbdIndicatorPluginManagerRecord *rec =
+ (GkbdIndicatorPluginManagerRecord *)
+ g_hash_table_lookup (manager->all_plugin_recs,
+ full_path);
+ if (rec == NULL)
+ return NULL;
+ return rec->plugin;
+}
+
+void
+gkbd_indicator_plugin_manager_promote_plugin (GkbdIndicatorPluginManager *
+ manager,
+ GSList * enabled_plugins,
+ const char *full_path)
+{
+ GSList *the_node = enabled_plugins;
+ GSList *prev_node = NULL;
+
+ while (the_node != NULL) {
+ if (!strcmp (the_node->data, full_path)) {
+ if (prev_node != NULL) {
+ char *tmp = (char *) prev_node->data;
+ prev_node->data = the_node->data;
+ the_node->data = tmp;
+ }
+ break;
+ }
+ prev_node = the_node;
+ the_node = g_slist_next (the_node);
+ }
+}
+
+void
+gkbd_indicator_plugin_manager_demote_plugin (GkbdIndicatorPluginManager *
+ manager,
+ GSList * enabled_plugins,
+ const char *full_path)
+{
+ GSList *the_node = g_slist_find_custom (enabled_plugins, full_path,
+ (GCompareFunc) strcmp);
+ if (the_node != NULL) {
+ GSList *next_node = g_slist_next (the_node);
+ if (next_node != NULL) {
+ char *tmp = (char *) next_node->data;
+ next_node->data = the_node->data;
+ the_node->data = tmp;
+ }
+ }
+}
+
+void
+gkbd_indicator_plugin_manager_enable_plugin (GkbdIndicatorPluginManager *
+ manager,
+ GSList ** enabled_plugins,
+ const char *full_path)
+{
+ if (NULL !=
+ gkbd_indicator_plugin_manager_get_plugin (manager,
+ full_path)) {
+ *enabled_plugins =
+ g_slist_append (*enabled_plugins,
+ (gpointer) g_strdup (full_path));
+ }
+}
+
+void
+gkbd_indicator_plugin_manager_disable_plugin (GkbdIndicatorPluginManager *
+ manager,
+ GSList ** enabled_plugins,
+ const char *full_path)
+{
+ GSList *the_node =
+ g_slist_find_custom (*enabled_plugins, full_path,
+ (GCompareFunc) strcmp);
+ if (the_node != NULL) {
+ g_free (the_node->data);
+ *enabled_plugins =
+ g_slist_delete_link (*enabled_plugins, the_node);
+ }
+}
+
+int
+gkbd_indicator_plugin_manager_window_created (GkbdIndicatorPluginManager *
+ manager, Window win,
+ Window parent)
+{
+ FOREACH_INITED_PLUGIN ();
+ if (plugin->window_created_callback) {
+ int group_to_assign =
+ (*plugin->window_created_callback) (win, parent);
+ if (group_to_assign != -1) {
+ xkl_debug (100,
+ "Plugin [%s] assigned group %d to new window %ld\n",
+ plugin->name, group_to_assign, win);
+ return group_to_assign;
+ }
+ }
+ NEXT_INITED_PLUGIN ();
+ return -1;
+}
+
+GtkWidget *
+gkbd_indicator_plugin_manager_decorate_widget (GkbdIndicatorPluginManager *
+ manager, GtkWidget * widget,
+ const gint group,
+ const char
+ *group_description,
+ GkbdKeyboardConfig *
+ kbd_config)
+{
+ FOREACH_INITED_PLUGIN ();
+ if (plugin->decorate_widget_callback) {
+ GtkWidget *decorated_widget =
+ (*plugin->decorate_widget_callback) (widget, group,
+ group_description,
+ kbd_config);
+ if (decorated_widget != NULL) {
+ xkl_debug (100,
+ "Plugin [%s] decorated widget %p to %p\n",
+ plugin->name, widget, decorated_widget);
+ return decorated_widget;
+ }
+ }
+ NEXT_INITED_PLUGIN ();
+ return NULL;
+}
+
+void
+gkbd_indicator_plugin_manager_configure_plugin (GkbdIndicatorPluginManager
+ * manager,
+ GkbdIndicatorPluginContainer
+ * pc,
+ const char *full_path,
+ GtkWindow * parent)
+{
+ const GkbdIndicatorPlugin *plugin =
+ gkbd_indicator_plugin_manager_get_plugin (manager, full_path);
+ if (plugin->configure_properties_callback != NULL)
+ plugin->configure_properties_callback (pc, parent);
+}
+
+void
+gkbd_indicator_plugin_container_init (GkbdIndicatorPluginContainer * pc,
+ GConfClient * conf_client)
+{
+ pc->conf_client = conf_client;
+ g_object_ref (pc->conf_client);
+}
+
+void
+gkbd_indicator_plugin_container_term (GkbdIndicatorPluginContainer * pc)
+{
+ g_object_unref (pc->conf_client);
+}
diff --git a/libgnomekbd/gkbd-indicator-plugin-manager.h b/libgnomekbd/gkbd-indicator-plugin-manager.h
new file mode 100644
index 0000000..2d25cd3
--- /dev/null
+++ b/libgnomekbd/gkbd-indicator-plugin-manager.h
@@ -0,0 +1,113 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GSWITCHIT_PLUGIN_MANAGER_H__
+#define __GSWITCHIT_PLUGIN_MANAGER_H__
+
+#include <gmodule.h>
+#include <libgnomekbd/gkbd-indicator-plugin.h>
+
+typedef struct _GkbdIndicatorPluginManager {
+ GHashTable *all_plugin_recs;
+ GSList *inited_plugin_recs;
+} GkbdIndicatorPluginManager;
+
+typedef struct _GkbdIndicatorPluginManagerRecord {
+ const char *full_path;
+ GModule *module;
+ const GkbdIndicatorPlugin *plugin;
+} GkbdIndicatorPluginManagerRecord;
+
+extern void
+ gkbd_indicator_plugin_manager_init (GkbdIndicatorPluginManager * manager);
+
+extern void
+ gkbd_indicator_plugin_manager_term (GkbdIndicatorPluginManager * manager);
+
+extern void
+ gkbd_indicator_plugin_manager_init_enabled_plugins (GkbdIndicatorPluginManager * manager,
+ GkbdIndicatorPluginContainer
+ * pc,
+ GSList *
+ enabled_plugins);
+
+extern void
+ gkbd_indicator_plugin_manager_term_initialized_plugins (GkbdIndicatorPluginManager * manager);
+
+extern void
+ gkbd_indicator_plugin_manager_toggle_plugins (GkbdIndicatorPluginManager * manager,
+ GkbdIndicatorPluginContainer
+ * pc,
+ GSList * enabled_plugins);
+
+extern const GkbdIndicatorPlugin
+ *
+gkbd_indicator_plugin_manager_get_plugin (GkbdIndicatorPluginManager *
+ manager, const char *full_path);
+
+extern void
+ gkbd_indicator_plugin_manager_promote_plugin (GkbdIndicatorPluginManager * manager,
+ GSList * enabled_plugins,
+ const char *full_path);
+
+extern void
+ gkbd_indicator_plugin_manager_demote_plugin (GkbdIndicatorPluginManager * manager,
+ GSList * enabled_plugins,
+ const char *full_path);
+
+extern void
+ gkbd_indicator_plugin_manager_enable_plugin (GkbdIndicatorPluginManager * manager,
+ GSList ** enabled_plugins,
+ const char *full_path);
+
+extern void
+ gkbd_indicator_plugin_manager_disable_plugin (GkbdIndicatorPluginManager * manager,
+ GSList ** enabled_plugins,
+ const char *full_path);
+
+extern void
+ gkbd_indicator_plugin_manager_configure_plugin (GkbdIndicatorPluginManager * manager,
+ GkbdIndicatorPluginContainer
+ * pc,
+ const char *full_path,
+ GtkWindow * parent);
+
+// actual calling plugin notification methods
+
+extern void
+ gkbd_indicator_plugin_manager_group_changed (GkbdIndicatorPluginManager * manager,
+ GtkWidget * notebook,
+ int new_group);
+
+extern void
+ gkbd_indicator_plugin_manager_config_changed (GkbdIndicatorPluginManager * manager,
+ GkbdKeyboardConfig * from,
+ GkbdKeyboardConfig * to);
+
+extern int
+ gkbd_indicator_plugin_manager_window_created (GkbdIndicatorPluginManager * manager,
+ Window win, Window parent);
+
+extern GtkWidget
+ *
+gkbd_indicator_plugin_manager_decorate_widget (GkbdIndicatorPluginManager *
+ manager, GtkWidget * widget,
+ const gint group, const char
+ *group_description,
+ GkbdKeyboardConfig *
+ config);
+
+#endif
diff --git a/libgnomekbd/gkbd-indicator-plugin.h b/libgnomekbd/gkbd-indicator-plugin.h
new file mode 100644
index 0000000..fd2c0bb
--- /dev/null
+++ b/libgnomekbd/gkbd-indicator-plugin.h
@@ -0,0 +1,122 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GKBD_INDICATOR_PLUGIN_H__
+#define __GKBD_INDICATOR_PLUGIN_H__
+
+#include <gtk/gtk.h>
+#include <gconf/gconf-client.h>
+#include <libgnomekbd/gkbd-keyboard-config.h>
+
+#define MAX_LOCAL_NAME_BUF_LENGTH 512
+
+struct _GkbdIndicatorPlugin;
+
+typedef struct _GkbdIndicatorPluginContainer {
+ GConfClient *conf_client;
+} GkbdIndicatorPluginContainer;
+
+typedef const struct _GkbdIndicatorPlugin
+*(*GkbdIndicatorPluginGetPluginFunc) (void);
+
+typedef
+ gboolean (*GkbdIndicatorPluginInitFunc) (GkbdIndicatorPluginContainer *
+ pc);
+
+typedef void (*GkbdIndicatorPluginGroupChangedFunc) (GtkWidget * notebook,
+ int new_group);
+
+typedef void (*GkbdIndicatorPluginConfigChangedFunc) (const
+ GkbdKeyboardConfig *
+ from,
+ const
+ GkbdKeyboardConfig *
+ to);
+
+typedef int (*GkbdIndicatorPluginWindowCreatedFunc) (const Window win,
+ const Window parent);
+
+typedef void (*GkbdIndicatorPluginTermFunc) (void);
+
+typedef GtkWidget *(*GkbdIndicatorPluginCreateWidget) (void);
+
+typedef GtkWidget *(*GkbdIndicatorPluginDecorateWidget) (GtkWidget *
+ widget,
+ const gint group,
+ const char
+ *group_description,
+ GkbdKeyboardConfig
+ * config);
+
+typedef
+void (*GkbdIndicatorPluginConfigureProperties)
+ (GkbdIndicatorPluginContainer * pc, GtkWindow * parent);
+
+typedef struct _GkbdIndicatorPlugin {
+ const char *name;
+
+ const char *description;
+
+// implemented
+ GkbdIndicatorPluginInitFunc init_callback;
+
+// implemented
+ GkbdIndicatorPluginTermFunc term_callback;
+
+// implemented
+ GkbdIndicatorPluginConfigureProperties
+ configure_properties_callback;
+
+// implemented
+ GkbdIndicatorPluginGroupChangedFunc group_changed_callback;
+
+// implemented
+ GkbdIndicatorPluginWindowCreatedFunc window_created_callback;
+
+// implemented
+ GkbdIndicatorPluginDecorateWidget decorate_widget_callback;
+
+// non implemented
+ GkbdIndicatorPluginConfigChangedFunc config_changed_callback;
+
+// non implemented
+ GkbdIndicatorPluginCreateWidget create_widget_callback;
+
+} GkbdIndicatorPlugin;
+
+/**
+ * Functions accessible for plugins
+ */
+
+extern void
+ gkbd_indicator_plugin_container_init (GkbdIndicatorPluginContainer * pc,
+ GConfClient * conf_client);
+
+extern void
+ gkbd_indicator_plugin_container_term (GkbdIndicatorPluginContainer * pc);
+
+extern void
+ gkbd_indicator_plugin_container_reinit_ui (GkbdIndicatorPluginContainer * pc);
+
+extern guint
+gkbd_indicator_plugin_get_num_groups (GkbdIndicatorPluginContainer * pc);
+
+extern gchar
+ **
+ gkbd_indicator_plugin_load_localized_group_names
+ (GkbdIndicatorPluginContainer * pc);
+
+#endif
diff --git a/libgnomekbd/gkbd-indicator.c b/libgnomekbd/gkbd-indicator.c
new file mode 100644
index 0000000..04d6265
--- /dev/null
+++ b/libgnomekbd/gkbd-indicator.c
@@ -0,0 +1,825 @@
+#include <memory.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gdk/gdkx.h>
+#include <glib/gi18n.h>
+
+#include <gkbd-indicator.h>
+#include <gkbd-indicator-marshal.h>
+
+#include <gkbd-desktop-config.h>
+#include <gkbd-indicator-config.h>
+
+#include <gkbd-indicator-plugin-manager.h>
+
+#include <gkbd-config-registry-client.h>
+
+typedef struct _gki_globals {
+ XklEngine *engine;
+
+ GkbdDesktopConfig cfg;
+ GkbdIndicatorConfig ind_cfg;
+ GkbdKeyboardConfig kbd_cfg;
+
+ GkbdIndicatorPluginContainer plugin_container;
+ GkbdIndicatorPluginManager plugin_manager;
+
+ const gchar *tooltips_format;
+ gchar **full_group_names;
+ gchar **short_group_names;
+ GSList *widget_instances;
+} gki_globals;
+
+struct _GkbdIndicatorPrivate {
+ 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) { \
+ GkbdIndicator * gki = (GkbdIndicator*)cur->data;
+#define NextIndicator() \
+ } \
+ }
+
+G_DEFINE_TYPE (GkbdIndicator, gkbd_indicator, GTK_TYPE_NOTEBOOK)
+
+static void
+gkbd_indicator_global_init (void);
+static void
+gkbd_indicator_global_term (void);
+static GtkWidget *
+gkbd_indicator_prepare_drawing (GkbdIndicator * gki, int group);
+static void
+gkbd_indicator_set_current_page_for_group (GkbdIndicator * gki, int group);
+static void
+gkbd_indicator_set_current_page (GkbdIndicator * gki);
+static void
+gkbd_indicator_cleanup (GkbdIndicator * gki);
+static void
+gkbd_indicator_fill (GkbdIndicator * gki);
+static void
+gkbd_indicator_set_tooltips (GkbdIndicator * gki, const char *str);
+
+void
+gkbd_indicator_set_tooltips (GkbdIndicator * gki, const char *str)
+{
+ GtkTooltips *tooltips;
+
+ if (str == NULL)
+ return;
+ tooltips = gtk_tooltips_new ();
+ g_object_ref (G_OBJECT (tooltips));
+ gtk_object_sink (GTK_OBJECT (tooltips));
+ g_object_set_data_full (G_OBJECT (gki), "tooltips",
+ tooltips, (GDestroyNotify) g_object_unref);
+ gtk_tooltips_set_tip (tooltips, GTK_WIDGET (gki), str, NULL);
+
+ if (gki->priv->set_parent_tooltips) {
+ GtkWidget *parent =
+ gtk_widget_get_parent (GTK_WIDGET (gki));
+ if (parent != NULL) {
+ gtk_tooltips_set_tip (tooltips,
+ GTK_WIDGET (parent), str,
+ NULL);
+ g_object_ref (G_OBJECT (tooltips));
+ g_object_set_data_full (G_OBJECT (parent),
+ "gnome-kbd-indicator.tooltips",
+ tooltips, (GDestroyNotify)
+ g_object_unref);
+ }
+ }
+ gtk_tooltips_enable (tooltips);
+}
+
+void
+gkbd_indicator_cleanup (GkbdIndicator * 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
+gkbd_indicator_fill (GkbdIndicator * 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;
+ page = gkbd_indicator_prepare_drawing (gki, grp);
+
+ if (page == NULL)
+ page = gtk_label_new ("");
+
+ decorated_page =
+ gkbd_indicator_plugin_manager_decorate_widget
+ (&globals.plugin_manager, page, grp,
+ globals.full_group_names[grp], &globals.kbd_cfg);
+
+ page = decorated_page == NULL ? page : decorated_page;
+
+ gtk_notebook_append_page (notebook, page, NULL);
+ gtk_widget_show_all (page);
+ }
+}
+
+static gboolean
+gkbd_indicator_key_pressed (GtkWidget *
+ widget, GdkEventKey * event,
+ GkbdIndicator * 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:
+ gkbd_desktop_config_lock_next_group (&globals.cfg);
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+static gboolean
+gkbd_indicator_button_pressed (GtkWidget *
+ widget,
+ GdkEventButton * event, GkbdIndicator * gki)
+{
+ GtkWidget *img = gtk_bin_get_child (GTK_BIN (widget));
+ xkl_debug (150, "Flag img size %d x %d\n",
+ img->allocation.width, img->allocation.height);
+ if (event->button == 1 && event->type == GDK_BUTTON_PRESS) {
+ xkl_debug (150, "Mouse button pressed on applet\n");
+ gkbd_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);
+ /* widget-to-image scales, X and Y */
+ double xwiratio = 1.0 * flag->allocation.width / iw;
+ double ywiratio = 1.0 * flag->allocation.height / ih;
+ double wiratio = xwiratio < ywiratio ? xwiratio : ywiratio;
+
+ /* scaled width and height */
+ int sw = iw * wiratio;
+ int sh = ih * wiratio;
+
+ /* offsets */
+ int ox = (flag->allocation.width - sw) >> 1;
+ int oy = (flag->allocation.height - sh) >> 1;
+
+ GdkPixbuf *scaled = gdk_pixbuf_scale_simple (image, sw, sh,
+ GDK_INTERP_HYPER);
+
+ gdk_draw_pixbuf (GDK_DRAWABLE (flag->window),
+ NULL,
+ scaled,
+ 0, 0,
+ ox, oy, sw, sh, GDK_RGB_DITHER_NORMAL, 0, 0);
+ g_object_unref (G_OBJECT (scaled));
+}
+
+static GtkWidget *
+gkbd_indicator_prepare_drawing (GkbdIndicator * gki, int group)
+{
+ gpointer pimage;
+ GdkPixbuf *image;
+ GtkWidget *ebox;
+
+ pimage = g_slist_nth_data (globals.ind_cfg.images, group);
+ ebox = gtk_event_box_new ();
+ if (globals.ind_cfg.show_flags) {
+ GtkWidget *flag;
+ if (pimage == NULL)
+ return NULL;
+ image = GDK_PIXBUF (pimage);
+ flag = gtk_drawing_area_new ();
+ g_signal_connect (G_OBJECT (flag),
+ "expose_event",
+ G_CALLBACK (flag_exposed), image);
+ gtk_container_add (GTK_CONTAINER (ebox), flag);
+ } else {
+ gpointer pcounter = NULL;
+ char *prev_layout_name = NULL, **ppln;
+ char *lbl_title = NULL;
+ int counter = 0;
+ char *layout_name = NULL;
+ XklConfigItem cfg_item;
+ GtkWidget *align, *label;
+ /**
+ * Map "short desciption" ->
+ * number of layouts in the configuration
+ * having this short description
+ */
+ static GHashTable *short_descrs = NULL;
+
+ if (group == 0)
+ short_descrs =
+ g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ if (xkl_engine_get_features (globals.engine) &
+ XKLF_MULTIPLE_LAYOUTS_SUPPORTED) {
+ char *full_layout_name =
+ (char *) g_slist_nth_data (globals.kbd_cfg.
+ layouts,
+ group);
+ char *variant_name;
+ if (!gkbd_keyboard_config_split_items
+ (full_layout_name, &layout_name,
+ &variant_name))
+ /* just in case */
+ layout_name = g_strdup (full_layout_name);
+
+ g_snprintf (cfg_item.name,
+ sizeof (cfg_item.name), "%s",
+ layout_name);
+
+ if (globals.short_group_names != NULL) {
+ char *short_group_name =
+ globals.short_group_names[group];
+ if (short_group_name != NULL
+ && *short_group_name != '\0') {
+ layout_name =
+ g_strdup (short_group_name);
+ }
+ }
+ } else
+ layout_name =
+ g_strdup (globals.full_group_names[group]);
+
+ if (layout_name == NULL)
+ layout_name = g_strdup ("?");
+
+ /* Process layouts with repeating description */
+ ppln = &prev_layout_name;
+ if (g_hash_table_lookup_extended
+ (short_descrs, layout_name,
+ (gpointer *) ppln, &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 (short_descrs, layout_name,
+ GINT_TO_POINTER (counter + 1));
+
+ 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 == xkl_engine_get_num_groups (globals.engine)) {
+ g_hash_table_destroy (short_descrs);
+ short_descrs = 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 (gkbd_indicator_button_pressed), gki);
+
+ g_signal_connect (G_OBJECT (gki),
+ "key_press_event",
+ G_CALLBACK (gkbd_indicator_key_pressed), gki);
+
+ /* We have everything prepared for that size */
+
+ return ebox;
+}
+
+static void
+gkbd_indicator_update_tooltips (GkbdIndicator * gki)
+{
+ XklState *state = xkl_engine_get_current_state (globals.engine);
+ gchar *buf;
+ if (state == NULL || state->group < 0)
+ return;
+
+ buf = g_strdup_printf (globals.tooltips_format,
+ globals.full_group_names[state->group]);
+
+ gkbd_indicator_set_tooltips (gki, buf);
+ g_free (buf);
+}
+
+static void
+gkbd_indicator_parent_set (GtkWidget * gki, GtkWidget * previous_parent)
+{
+ gkbd_indicator_update_tooltips (GKBD_INDICATOR (gki));
+}
+
+
+void
+gkbd_indicator_reinit_ui (GkbdIndicator * gki)
+{
+ gkbd_indicator_cleanup (gki);
+ gkbd_indicator_fill (gki);
+
+ gkbd_indicator_set_current_page (gki);
+
+ g_signal_emit_by_name (gki, "reinit-ui");
+}
+
+/* Should be called once for all widgets */
+static void
+gkbd_indicator_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_indicator_reinit_ui (gki);
+ } NextIndicator ();
+}
+
+/* Should be called once for all widgets */
+static void
+gkbd_indicator_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_update_images (&globals.ind_cfg,
+ &globals.kbd_cfg);
+ gkbd_indicator_config_activate (&globals.ind_cfg);
+
+ gkbd_indicator_plugin_manager_toggle_plugins (&globals.
+ plugin_manager,
+ &globals.
+ plugin_container,
+ globals.ind_cfg.
+ enabled_plugins);
+
+ ForAllIndicators () {
+ gkbd_indicator_reinit_ui (gki);
+ } NextIndicator ();
+}
+
+static void
+gkbd_indicator_load_group_names (void)
+{
+ if (!gkbd_desktop_config_load_remote_group_descriptions_utf8
+ (&globals.cfg, &globals.short_group_names,
+ &globals.full_group_names)) {
+ 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;
+ for (i = 0; lst; lst = lst->next) {
+ 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_indicator_kbd_cfg_callback (GkbdIndicator * gki)
+{
+ xkl_debug (100,
+ "XKB configuration changed on X Server - reiniting...\n");
+
+ gkbd_keyboard_config_load_from_x_current (&globals.kbd_cfg);
+ gkbd_indicator_config_update_images (&globals.ind_cfg,
+ &globals.kbd_cfg);
+
+ g_strfreev (globals.full_group_names);
+ g_strfreev (globals.short_group_names);
+ gkbd_indicator_load_group_names ();
+
+ ForAllIndicators () {
+ gkbd_indicator_reinit_ui (gki);
+ } NextIndicator ();
+}
+
+/* Should be called once for all applets */
+static void
+gkbd_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 () {
+ gkbd_indicator_plugin_manager_group_changed
+ (&globals.plugin_manager, GTK_WIDGET (gki),
+ group);
+ xkl_debug (200, "do repaint\n");
+ gkbd_indicator_set_current_page_for_group
+ (gki, group);
+ }
+ NextIndicator ();
+ }
+}
+
+
+void
+gkbd_indicator_set_current_page (GkbdIndicator * gki)
+{
+ XklState *cur_state;
+ 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);
+}
+
+void
+gkbd_indicator_set_current_page_for_group (GkbdIndicator * gki, int group)
+{
+ xkl_debug (200, "Revalidating for group %d\n", group);
+
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (gki), group + 1);
+
+ gkbd_indicator_update_tooltips (gki);
+}
+
+/* Should be called once for all widgets */
+static GdkFilterReturn
+gkbd_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
+gkbd_indicator_start_listen (void)
+{
+ gdk_window_add_filter (NULL, (GdkFilterFunc)
+ gkbd_indicator_filter_x_evt, NULL);
+ gdk_window_add_filter (gdk_get_default_root_window (),
+ (GdkFilterFunc)
+ gkbd_indicator_filter_x_evt, NULL);
+
+ xkl_engine_start_listen (globals.engine,
+ XKLL_TRACK_KEYBOARD_STATE);
+}
+
+/* Should be called once for all widgets */
+static void
+gkbd_indicator_stop_listen (void)
+{
+ xkl_engine_stop_listen (globals.engine);
+
+ gdk_window_remove_filter (NULL, (GdkFilterFunc)
+ gkbd_indicator_filter_x_evt, NULL);
+ gdk_window_remove_filter
+ (gdk_get_default_root_window (),
+ (GdkFilterFunc) gkbd_indicator_filter_x_evt, NULL);
+}
+
+static gboolean
+gkbd_indicator_scroll (GtkWidget * gki, GdkEventScroll * event)
+{
+ /* mouse wheel events should be ignored, otherwise funny effects appear */
+ return TRUE;
+}
+
+static void
+gkbd_indicator_init (GkbdIndicator * gki)
+{
+ GtkWidget *def_drawing;
+ GtkNotebook *notebook;
+
+ if (!g_slist_length (globals.widget_instances))
+ gkbd_indicator_global_init ();
+
+ gki->priv = g_new0 (GkbdIndicatorPrivate, 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) {
+ gkbd_indicator_set_tooltips (gki,
+ _
+ ("XKB initialization error"));
+ return;
+ }
+
+ gkbd_indicator_set_tooltips (gki, "");
+
+ gkbd_indicator_fill (gki);
+ gkbd_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
+gkbd_indicator_finalize (GObject * obj)
+{
+ GkbdIndicator *gki = GKBD_INDICATOR (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_indicator_cleanup (gki);
+
+ xkl_debug (100,
+ "The instance of gnome-kbd-indicator successfully finalized\n");
+
+ g_free (gki->priv);
+
+ G_OBJECT_CLASS (gkbd_indicator_parent_class)->finalize (obj);
+
+ if (!g_slist_length (globals.widget_instances))
+ gkbd_indicator_global_term ();
+}
+
+static void
+gkbd_indicator_global_term (void)
+{
+ xkl_debug (100, "*** Last GkbdIndicator instance *** \n");
+ gkbd_indicator_stop_listen ();
+
+ gkbd_desktop_config_stop_listen (&globals.cfg);
+ gkbd_indicator_config_stop_listen (&globals.ind_cfg);
+
+ gkbd_indicator_plugin_manager_term_initialized_plugins (&globals.
+ plugin_manager);
+ gkbd_indicator_plugin_manager_term (&globals.plugin_manager);
+
+ gkbd_indicator_config_term (&globals.ind_cfg);
+ gkbd_keyboard_config_term (&globals.kbd_cfg);
+ gkbd_desktop_config_term (&globals.cfg);
+
+ gkbd_indicator_plugin_container_term (&globals.plugin_container);
+
+ g_object_unref (G_OBJECT (globals.engine));
+ globals.engine = NULL;
+ xkl_debug (100, "*** Terminated globals *** \n");
+}
+
+static void
+gkbd_indicator_class_init (GkbdIndicatorClass * klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ xkl_debug (100, "*** First GkbdIndicator instance *** \n");
+
+ memset (&globals, 0, sizeof (globals));
+
+ /* Initing some global vars */
+ globals.tooltips_format = "%s";
+
+ /* Initing vtable */
+ object_class->finalize = gkbd_indicator_finalize;
+
+ widget_class->scroll_event = gkbd_indicator_scroll;
+ widget_class->parent_set = gkbd_indicator_parent_set;
+
+ /* Signals */
+ g_signal_new ("reinit-ui", GKBD_TYPE_INDICATOR,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GkbdIndicatorClass, reinit_ui),
+ NULL, NULL, gkbd_indicator_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+gkbd_indicator_global_init (void)
+{
+ GConfClient *gconf_client;
+
+ 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_indicator_state_callback),
+ NULL);
+ g_signal_connect (globals.engine, "X-config-changed",
+ G_CALLBACK (gkbd_indicator_kbd_cfg_callback),
+ NULL);
+
+ gkbd_indicator_plugin_container_init (&globals.plugin_container,
+ gconf_client);
+
+ 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);
+ gkbd_keyboard_config_load_from_x_current (&globals.kbd_cfg);
+ gkbd_indicator_config_load_from_gconf (&globals.ind_cfg);
+ gkbd_indicator_config_update_images (&globals.ind_cfg,
+ &globals.kbd_cfg);
+ gkbd_indicator_config_activate (&globals.ind_cfg);
+
+ gkbd_indicator_load_group_names ();
+
+ gkbd_indicator_plugin_manager_init (&globals.plugin_manager);
+ gkbd_indicator_plugin_manager_init_enabled_plugins (&globals.
+ plugin_manager,
+ &globals.
+ plugin_container,
+ globals.
+ ind_cfg.
+ enabled_plugins);
+ gkbd_desktop_config_start_listen (&globals.cfg,
+ (GConfClientNotifyFunc)
+ gkbd_indicator_cfg_changed,
+ NULL);
+ gkbd_indicator_config_start_listen (&globals.ind_cfg,
+ (GConfClientNotifyFunc)
+ gkbd_indicator_ind_cfg_changed,
+ NULL);
+ gkbd_indicator_start_listen ();
+
+ xkl_debug (100, "*** Inited globals *** \n");
+}
+
+GtkWidget *
+gkbd_indicator_new (void)
+{
+ return
+ GTK_WIDGET (g_object_new (gkbd_indicator_get_type (), NULL));
+}
+
+void
+gkbd_indicator_set_parent_tooltips (GkbdIndicator * gki, gboolean spt)
+{
+ gki->priv->set_parent_tooltips = spt;
+ gkbd_indicator_update_tooltips (gki);
+}
+
+void
+gkbd_indicator_set_tooltips_format (const gchar format[])
+{
+ globals.tooltips_format = format;
+ ForAllIndicators ()
+ gkbd_indicator_update_tooltips (gki);
+ NextIndicator ()
+}
+
+XklEngine *
+gkbd_indicator_get_xkl_engine ()
+{
+ return globals.engine;
+}
+
+gchar **
+gkbd_indicator_get_group_names ()
+{
+ return globals.full_group_names;
+}
+
+gchar *
+gkbd_indicator_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);
+}
+
+gdouble
+gkbd_indicator_get_max_width_height_ratio (void)
+{
+ gdouble rv = 0.0;
+ GSList *ip = globals.ind_cfg.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
+gkbd_indicator_set_angle (GkbdIndicator * gki, gdouble angle)
+{
+ gki->priv->angle = angle;
+}
+
+/* Plugin support */
+/* Preserve the plugin container functions during the linking */
+void
+gkbd_indicator_plugin_container_reinit_ui (GkbdIndicatorPluginContainer *
+ pc)
+{
+ ForAllIndicators () {
+ gkbd_indicator_reinit_ui (gki);
+ } NextIndicator ();
+}
+
+gchar **gkbd_indicator_plugin_load_localized_group_names
+ (GkbdIndicatorPluginContainer * pc) {
+ return globals.full_group_names;
+}
diff --git a/libgnomekbd/gkbd-indicator.h b/libgnomekbd/gkbd-indicator.h
new file mode 100644
index 0000000..8cd2e33
--- /dev/null
+++ b/libgnomekbd/gkbd-indicator.h
@@ -0,0 +1,77 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GKBD_INDICATOR_H__
+#define __GKBD_INDICATOR_H__
+
+#include <gtk/gtk.h>
+
+#include <libxklavier/xklavier.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef struct _GkbdIndicator GkbdIndicator;
+ typedef struct _GkbdIndicatorPrivate GkbdIndicatorPrivate;
+ typedef struct _GkbdIndicatorClass GkbdIndicatorClass;
+
+#define GKBD_TYPE_INDICATOR (gkbd_indicator_get_type ())
+#define GKBD_INDICATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GKBD_TYPE_INDICATOR, GkbdIndicator))
+#define GKBD_INDCATOR_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GKBD_TYPE_INDICATOR, GkbdIndicatorClass))
+#define GKBD_IS_INDICATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GKBD_TYPE_INDICATOR))
+#define GKBD_IS_INDICATOR_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GKBD_TYPE_INDICATOR))
+#define GKBD_INDICATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GKBD_TYPE_INDICATOR, GkbdIndicatorClass))
+
+ struct _GkbdIndicator {
+ GtkNotebook parent;
+ GkbdIndicatorPrivate *priv;
+ };
+
+ struct _GkbdIndicatorClass {
+ GtkNotebookClass parent_class;
+
+ void (*reinit_ui) (GkbdIndicator * gki);
+ };
+
+ extern GType gkbd_indicator_get_type (void);
+
+ extern GtkWidget *gkbd_indicator_new (void);
+
+ extern void gkbd_indicator_reinit_ui (GkbdIndicator * gki);
+
+ extern void gkbd_indicator_set_angle (GkbdIndicator * gki,
+ gdouble angle);
+
+ extern XklEngine *gkbd_indicator_get_xkl_engine (void);
+
+ extern gchar **gkbd_indicator_get_group_names (void);
+
+ extern gchar *gkbd_indicator_get_image_filename (guint group);
+
+ extern gdouble gkbd_indicator_get_max_width_height_ratio (void);
+
+ extern void
+ gkbd_indicator_set_parent_tooltips (GkbdIndicator *
+ gki, gboolean ifset);
+
+ extern void
+ gkbd_indicator_set_tooltips_format (const gchar str[]);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/libgnomekbd/gkbd-keyboard-config.c b/libgnomekbd/gkbd-keyboard-config.c
new file mode 100644
index 0000000..126cbc8
--- /dev/null
+++ b/libgnomekbd/gkbd-keyboard-config.c
@@ -0,0 +1,825 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <X11/keysym.h>
+
+#include <glib/gi18n.h>
+//#include <gdk/gdkx.h>
+#include <libgnome/gnome-program.h>
+
+#include <gkbd-keyboard-config.h>
+#include <gkbd-config-private.h>
+
+#include <gkbd-config-registry-client.h>
+
+/**
+ * GkbdKeyboardConfig
+ */
+#define GKBD_KEYBOARD_CONFIG_KEY_PREFIX GKBD_CONFIG_KEY_PREFIX "/kbd"
+
+const gchar GKBD_KEYBOARD_CONFIG_DIR[] = GKBD_KEYBOARD_CONFIG_KEY_PREFIX;
+const gchar GKBD_KEYBOARD_CONFIG_KEY_MODEL[] =
+ GKBD_KEYBOARD_CONFIG_KEY_PREFIX "/model";
+const gchar GKBD_KEYBOARD_CONFIG_KEY_LAYOUTS[] =
+ GKBD_KEYBOARD_CONFIG_KEY_PREFIX "/layouts";
+const gchar GKBD_KEYBOARD_CONFIG_KEY_OPTIONS[] =
+ GKBD_KEYBOARD_CONFIG_KEY_PREFIX "/options";
+
+const gchar *GKBD_KEYBOARD_CONFIG_ACTIVE[] = {
+ GKBD_KEYBOARD_CONFIG_KEY_MODEL,
+ GKBD_KEYBOARD_CONFIG_KEY_LAYOUTS,
+ GKBD_KEYBOARD_CONFIG_KEY_OPTIONS
+};
+
+#define GKBD_KEYBOARD_CONFIG_SYSBACKUP_KEY_PREFIX GKBD_CONFIG_KEY_PREFIX "/kbd.sysbackup"
+
+const gchar GKBD_KEYBOARD_CONFIG_SYSBACKUP_DIR[] =
+ GKBD_KEYBOARD_CONFIG_SYSBACKUP_KEY_PREFIX;
+const gchar GKBD_KEYBOARD_CONFIG_SYSBACKUP_KEY_MODEL[] =
+ GKBD_KEYBOARD_CONFIG_SYSBACKUP_KEY_PREFIX "/model";
+const gchar GKBD_KEYBOARD_CONFIG_SYSBACKUP_KEY_LAYOUTS[] =
+ GKBD_KEYBOARD_CONFIG_SYSBACKUP_KEY_PREFIX "/layouts";
+const gchar GKBD_KEYBOARD_CONFIG_SYSBACKUP_KEY_OPTIONS[] =
+ GKBD_KEYBOARD_CONFIG_SYSBACKUP_KEY_PREFIX "/options";
+
+const gchar *GKBD_KEYBOARD_CONFIG_SYSBACKUP[] = {
+ GKBD_KEYBOARD_CONFIG_SYSBACKUP_KEY_MODEL,
+ GKBD_KEYBOARD_CONFIG_SYSBACKUP_KEY_LAYOUTS,
+ GKBD_KEYBOARD_CONFIG_SYSBACKUP_KEY_OPTIONS
+};
+
+/**
+ * static common functions
+ */
+static void
+gkbd_keyboard_config_string_list_reset (GSList ** plist)
+{
+ while (*plist != NULL) {
+ GSList *p = *plist;
+ *plist = (*plist)->next;
+ g_free (p->data);
+ g_slist_free_1 (p);
+ }
+}
+
+static gboolean
+gslist_str_equal (GSList * l1, GSList * l2)
+{
+ if (l1 == l2)
+ return TRUE;
+ while (l1 != NULL && l2 != NULL) {
+ if ((l1->data != l2->data) &&
+ (l1->data != NULL) &&
+ (l2->data != NULL) &&
+ g_ascii_strcasecmp (l1->data, l2->data))
+ return False;
+
+ l1 = l1->next;
+ l2 = l2->next;
+ }
+ return (l1 == NULL && l2 == NULL);
+}
+
+gboolean
+gkbd_keyboard_config_get_lv_descriptions (XklConfigRegistry *
+ config_registry,
+ const gchar * layout_name,
+ const gchar * variant_name,
+ gchar ** layout_short_descr,
+ gchar ** layout_descr,
+ gchar ** variant_short_descr,
+ gchar ** variant_descr)
+{
+ static XklConfigItem litem;
+ static XklConfigItem vitem;
+
+ layout_name = g_strdup (layout_name);
+
+ g_snprintf (litem.name, sizeof litem.name, "%s", layout_name);
+ if (xkl_config_registry_find_layout (config_registry, &litem)) {
+ *layout_short_descr = litem.short_description;
+ *layout_descr = litem.description;
+ } else
+ *layout_short_descr = *layout_descr = NULL;
+
+ if (variant_name != NULL) {
+ variant_name = g_strdup (variant_name);
+ g_snprintf (vitem.name, sizeof vitem.name, "%s",
+ variant_name);
+ if (xkl_config_registry_find_variant
+ (config_registry, layout_name, &vitem)) {
+ *variant_short_descr = vitem.short_description;
+ *variant_descr = vitem.description;
+ } else
+ *variant_short_descr = *variant_descr = NULL;
+
+ g_free ((char *) variant_name);
+ } else
+ *variant_descr = NULL;
+
+ g_free ((char *) layout_name);
+ return *layout_descr != NULL;
+}
+
+/**
+ * extern common functions
+ */
+const gchar *
+gkbd_keyboard_config_merge_items (const gchar * parent,
+ const gchar * child)
+{
+ static gchar buffer[XKL_MAX_CI_NAME_LENGTH * 2 - 1];
+ *buffer = '\0';
+ if (parent != NULL) {
+ if (strlen (parent) >= XKL_MAX_CI_NAME_LENGTH)
+ return NULL;
+ strcat (buffer, parent);
+ }
+ if (child != NULL) {
+ if (strlen (child) >= XKL_MAX_CI_NAME_LENGTH)
+ return NULL;
+ strcat (buffer, "\t");
+ strcat (buffer, child);
+ }
+ return buffer;
+}
+
+gboolean
+gkbd_keyboard_config_split_items (const gchar * merged, gchar ** parent,
+ gchar ** child)
+{
+ static gchar pbuffer[XKL_MAX_CI_NAME_LENGTH];
+ static gchar cbuffer[XKL_MAX_CI_NAME_LENGTH];
+ int plen, clen;
+ const gchar *pos;
+ *parent = *child = NULL;
+
+ if (merged == NULL)
+ return FALSE;
+
+ pos = strchr (merged, '\t');
+ if (pos == NULL) {
+ plen = strlen (merged);
+ clen = 0;
+ } else {
+ plen = pos - merged;
+ clen = strlen (pos + 1);
+ if (clen >= XKL_MAX_CI_NAME_LENGTH)
+ return FALSE;
+ strcpy (*child = cbuffer, pos + 1);
+ }
+ if (plen >= XKL_MAX_CI_NAME_LENGTH)
+ return FALSE;
+ memcpy (*parent = pbuffer, merged, plen);
+ pbuffer[plen] = '\0';
+ return TRUE;
+}
+
+/**
+ * static GkbdKeyboardConfig functions
+ */
+static void
+gkbd_keyboard_config_options_add_full (GkbdKeyboardConfig * kbd_config,
+ const gchar * full_option_name)
+{
+ kbd_config->options =
+ g_slist_append (kbd_config->options,
+ g_strdup (full_option_name));
+}
+
+static void
+gkbd_keyboard_config_layouts_add_full (GkbdKeyboardConfig * kbd_config,
+ const gchar * full_layout_name)
+{
+ kbd_config->layouts =
+ g_slist_append (kbd_config->layouts,
+ g_strdup (full_layout_name));
+}
+
+static void
+gkbd_keyboard_config_copy_from_xkl_config (GkbdKeyboardConfig * kbd_config,
+ XklConfigRec * pdata)
+{
+ char **p, **p1;
+ gkbd_keyboard_config_model_set (kbd_config, pdata->model);
+ xkl_debug (150, "Loaded Kbd model: [%s]\n", pdata->model);
+
+ gkbd_keyboard_config_layouts_reset (kbd_config);
+ p = pdata->layouts;
+ p1 = pdata->variants;
+ while (p != NULL && *p != NULL) {
+ if (*p1 == NULL || **p1 == '\0') {
+ xkl_debug (150, "Loaded Kbd layout: [%s]\n", *p);
+ gkbd_keyboard_config_layouts_add_full (kbd_config,
+ *p);
+ } else {
+ char full_layout[XKL_MAX_CI_NAME_LENGTH * 2];
+ g_snprintf (full_layout, sizeof (full_layout),
+ "%s\t%s", *p, *p1);
+ xkl_debug (150,
+ "Loaded Kbd layout with variant: [%s]\n",
+ full_layout);
+ gkbd_keyboard_config_layouts_add_full (kbd_config,
+ full_layout);
+ }
+ p++;
+ p1++;
+ }
+
+ gkbd_keyboard_config_options_reset (kbd_config);
+ p = pdata->options;
+ while (p != NULL && *p != NULL) {
+ char group[XKL_MAX_CI_NAME_LENGTH];
+ char *option = *p;
+ char *delim =
+ (option != NULL) ? strchr (option, ':') : NULL;
+ int len;
+ if ((delim != NULL) &&
+ ((len = (delim - option)) < XKL_MAX_CI_NAME_LENGTH)) {
+ strncpy (group, option, len);
+ group[len] = 0;
+ xkl_debug (150, "Loaded Kbd option: [%s][%s]\n",
+ group, option);
+ gkbd_keyboard_config_options_add (kbd_config,
+ group, option);
+ }
+ p++;
+ }
+}
+
+static void
+gkbd_keyboard_config_copy_to_xkl_config (GkbdKeyboardConfig * kbd_config,
+ XklConfigRec * pdata)
+{
+ int i;
+ int num_layouts, num_options;
+ pdata->model =
+ (kbd_config->model ==
+ NULL) ? NULL : g_strdup (kbd_config->model);
+
+ num_layouts =
+ (kbd_config->layouts ==
+ NULL) ? 0 : g_slist_length (kbd_config->layouts);
+ num_options =
+ (kbd_config->options ==
+ NULL) ? 0 : g_slist_length (kbd_config->options);
+
+ xkl_debug (150, "Taking %d layouts\n", num_layouts);
+ if (num_layouts != 0) {
+ GSList *the_layout = kbd_config->layouts;
+ char **p1 = pdata->layouts =
+ g_new0 (char *, num_layouts + 1);
+ char **p2 = pdata->variants =
+ g_new0 (char *, num_layouts + 1);
+ for (i = num_layouts; --i >= 0;) {
+ char *layout, *variant;
+ if (gkbd_keyboard_config_split_items
+ (the_layout->data, &layout, &variant)
+ && variant != NULL) {
+ *p1 =
+ (layout ==
+ NULL) ? g_strdup ("") :
+ g_strdup (layout);
+ *p2 =
+ (variant ==
+ NULL) ? g_strdup ("") :
+ g_strdup (variant);
+ } else {
+ *p1 =
+ (the_layout->data ==
+ NULL) ? g_strdup ("") :
+ g_strdup (the_layout->data);
+ *p2 = g_strdup ("");
+ }
+ xkl_debug (150, "Adding [%s]/%p and [%s]/%p\n",
+ *p1 ? *p1 : "(nil)", *p1,
+ *p2 ? *p2 : "(nil)", *p2);
+ p1++;
+ p2++;
+ the_layout = the_layout->next;
+ }
+ }
+
+ if (num_options != 0) {
+ GSList *the_option = kbd_config->options;
+ char **p = pdata->options =
+ g_new0 (char *, num_options + 1);
+ for (i = num_options; --i >= 0;) {
+ char *group, *option;
+ if (gkbd_keyboard_config_split_items
+ (the_option->data, &group, &option)
+ && option != NULL)
+ *(p++) = g_strdup (option);
+ else {
+ *(p++) = g_strdup ("");
+ xkl_debug (150, "Could not split [%s]\n",
+ the_option->data);
+ }
+ the_option = the_option->next;
+ }
+ }
+}
+
+static void
+gkbd_keyboard_config_load_params (GkbdKeyboardConfig * kbd_config,
+ const gchar * param_names[])
+{
+ GError *gerror = NULL;
+ gchar *pc;
+ GSList *pl;
+
+ pc = gconf_client_get_string (kbd_config->conf_client,
+ param_names[0], &gerror);
+ if (pc == NULL || gerror != NULL) {
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ g_error_free (gerror);
+ g_free (pc);
+ gerror = NULL;
+ }
+ gkbd_keyboard_config_model_set (kbd_config, NULL);
+ } else {
+ gkbd_keyboard_config_model_set (kbd_config, pc);
+ g_free (pc);
+ }
+ xkl_debug (150, "Loaded Kbd model: [%s]\n",
+ kbd_config->model ? kbd_config->model : "(null)");
+
+ gkbd_keyboard_config_layouts_reset (kbd_config);
+
+ pl = gconf_client_get_list (kbd_config->conf_client,
+ param_names[1],
+ GCONF_VALUE_STRING, &gerror);
+ if (pl == NULL || gerror != NULL) {
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ }
+
+ while (pl != NULL) {
+ xkl_debug (150, "Loaded Kbd layout: [%s]\n", pl->data);
+ gkbd_keyboard_config_layouts_add_full (kbd_config,
+ pl->data);
+ pl = pl->next;
+ }
+ gkbd_keyboard_config_string_list_reset (&pl);
+
+ gkbd_keyboard_config_options_reset (kbd_config);
+
+ pl = gconf_client_get_list (kbd_config->conf_client,
+ param_names[2],
+ GCONF_VALUE_STRING, &gerror);
+ if (pl == NULL || gerror != NULL) {
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ }
+
+ while (pl != NULL) {
+ xkl_debug (150, "Loaded Kbd option: [%s]\n", pl->data);
+ gkbd_keyboard_config_options_add_full (kbd_config,
+ (const gchar *) pl->
+ data);
+ pl = pl->next;
+ }
+ gkbd_keyboard_config_string_list_reset (&pl);
+}
+
+static void
+gkbd_keyboard_config_save_params (GkbdKeyboardConfig * kbd_config,
+ GConfChangeSet * cs,
+ const gchar * param_names[])
+{
+ GSList *pl;
+
+ if (kbd_config->model)
+ gconf_change_set_set_string (cs, param_names[0],
+ kbd_config->model);
+ else
+ gconf_change_set_unset (cs, param_names[0]);
+ xkl_debug (150, "Saved Kbd model: [%s]\n",
+ kbd_config->model ? kbd_config->model : "(null)");
+
+ if (kbd_config->layouts) {
+ pl = kbd_config->layouts;
+ while (pl != NULL) {
+ xkl_debug (150, "Saved Kbd layout: [%s]\n",
+ pl->data);
+ pl = pl->next;
+ }
+ gconf_change_set_set_list (cs,
+ param_names[1],
+ GCONF_VALUE_STRING,
+ kbd_config->layouts);
+ } else {
+ xkl_debug (150, "Saved Kbd layouts: []\n");
+ gconf_change_set_unset (cs, param_names[1]);
+ }
+
+ if (kbd_config->options) {
+ pl = kbd_config->options;
+ while (pl != NULL) {
+ xkl_debug (150, "Saved Kbd option: [%s]\n",
+ pl->data);
+ pl = pl->next;
+ }
+ gconf_change_set_set_list (cs,
+ param_names[2],
+ GCONF_VALUE_STRING,
+ kbd_config->options);
+ } else {
+ xkl_debug (150, "Saved Kbd options: []\n");
+ gconf_change_set_unset (cs, param_names[2]);
+ }
+}
+
+/**
+ * extern GkbdKeyboardConfig config functions
+ */
+void
+gkbd_keyboard_config_init (GkbdKeyboardConfig * kbd_config,
+ GConfClient * conf_client, XklEngine * engine)
+{
+ GError *gerror = NULL;
+
+ memset (kbd_config, 0, sizeof (*kbd_config));
+ kbd_config->conf_client = conf_client;
+ kbd_config->engine = engine;
+ g_object_ref (kbd_config->conf_client);
+
+ gconf_client_add_dir (kbd_config->conf_client,
+ GKBD_KEYBOARD_CONFIG_DIR,
+ GCONF_CLIENT_PRELOAD_NONE, &gerror);
+ if (gerror != NULL) {
+ g_warning ("err: %s\n", gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+}
+
+void
+gkbd_keyboard_config_term (GkbdKeyboardConfig * kbd_config)
+{
+ gkbd_keyboard_config_model_set (kbd_config, NULL);
+
+ gkbd_keyboard_config_layouts_reset (kbd_config);
+
+ g_object_unref (kbd_config->conf_client);
+ kbd_config->conf_client = NULL;
+}
+
+void
+gkbd_keyboard_config_load_from_gconf (GkbdKeyboardConfig * kbd_config,
+ GkbdKeyboardConfig *
+ kbd_config_default)
+{
+ gkbd_keyboard_config_load_params (kbd_config,
+ GKBD_KEYBOARD_CONFIG_ACTIVE);
+
+ if (kbd_config_default != NULL) {
+ GSList *pl;
+
+ if (kbd_config->model == NULL)
+ kbd_config->model =
+ g_strdup (kbd_config_default->model);
+
+ if (kbd_config->layouts == NULL) {
+ pl = kbd_config_default->layouts;
+ while (pl != NULL) {
+ kbd_config->layouts =
+ g_slist_append (kbd_config->layouts,
+ g_strdup (pl->data));
+ pl = pl->next;
+ }
+ }
+
+ if (kbd_config->options == NULL) {
+ pl = kbd_config_default->options;
+ while (pl != NULL) {
+ kbd_config->options =
+ g_slist_append (kbd_config->options,
+ g_strdup (pl->data));
+ pl = pl->next;
+ }
+ }
+ }
+}
+
+void
+gkbd_keyboard_config_load_from_gconf_backup (GkbdKeyboardConfig *
+ kbd_config)
+{
+ gkbd_keyboard_config_load_params (kbd_config,
+ GKBD_KEYBOARD_CONFIG_SYSBACKUP);
+}
+
+void
+gkbd_keyboard_config_load_from_x_current (GkbdKeyboardConfig * kbd_config)
+{
+ XklConfigRec *data = xkl_config_rec_new ();
+ if (xkl_config_rec_get_from_server (data, kbd_config->engine))
+ gkbd_keyboard_config_copy_from_xkl_config (kbd_config,
+ data);
+ else
+ xkl_debug (150,
+ "Could not load keyboard config from server: [%s]\n",
+ xkl_get_last_error ());
+ g_object_unref (G_OBJECT (data));
+}
+
+void
+gkbd_keyboard_config_load_from_x_initial (GkbdKeyboardConfig * kbd_config)
+{
+ XklConfigRec *data = xkl_config_rec_new ();
+ if (xkl_config_rec_get_from_backup (data, kbd_config->engine))
+ gkbd_keyboard_config_copy_from_xkl_config (kbd_config,
+ data);
+ else
+ xkl_debug (150,
+ "Could not load keyboard config from backup: [%s]\n",
+ xkl_get_last_error ());
+ g_object_unref (G_OBJECT (data));
+}
+
+gboolean
+gkbd_keyboard_config_equals (GkbdKeyboardConfig * kbd_config1,
+ GkbdKeyboardConfig * kbd_config2)
+{
+ if (kbd_config1 == kbd_config2)
+ return True;
+ if ((kbd_config1->model != kbd_config2->model) &&
+ (kbd_config1->model != NULL) &&
+ (kbd_config2->model != NULL) &&
+ g_ascii_strcasecmp (kbd_config1->model, kbd_config2->model))
+ return False;
+ return gslist_str_equal (kbd_config1->layouts,
+ kbd_config2->layouts)
+ && gslist_str_equal (kbd_config1->options,
+ kbd_config2->options);
+}
+
+void
+gkbd_keyboard_config_save_to_gconf (GkbdKeyboardConfig * kbd_config)
+{
+ GConfChangeSet *cs;
+ GError *gerror = NULL;
+
+ cs = gconf_change_set_new ();
+
+ gkbd_keyboard_config_save_params (kbd_config, cs,
+ GKBD_KEYBOARD_CONFIG_ACTIVE);
+
+ gconf_client_commit_change_set (kbd_config->conf_client, cs, TRUE,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error saving active configuration: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ gconf_change_set_unref (cs);
+}
+
+void
+gkbd_keyboard_config_save_to_gconf_backup (GkbdKeyboardConfig * kbd_config)
+{
+ GConfChangeSet *cs;
+ GError *gerror = NULL;
+
+ cs = gconf_change_set_new ();
+
+ gkbd_keyboard_config_save_params (kbd_config, cs,
+ GKBD_KEYBOARD_CONFIG_SYSBACKUP);
+
+ gconf_client_commit_change_set (kbd_config->conf_client, cs, TRUE,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error saving backup configuration: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ gconf_change_set_unref (cs);
+}
+
+void
+gkbd_keyboard_config_model_set (GkbdKeyboardConfig * kbd_config,
+ const gchar * model_name)
+{
+ if (kbd_config->model != NULL)
+ g_free (kbd_config->model);
+ kbd_config->model =
+ (model_name == NULL
+ || model_name[0] == '\0') ? NULL : g_strdup (model_name);
+}
+
+void
+gkbd_keyboard_config_layouts_add (GkbdKeyboardConfig * kbd_config,
+ const gchar * layout_name,
+ const gchar * variant_name)
+{
+ const gchar *merged;
+ if (layout_name == NULL)
+ return;
+ merged =
+ gkbd_keyboard_config_merge_items (layout_name, variant_name);
+ if (merged == NULL)
+ return;
+ gkbd_keyboard_config_layouts_add_full (kbd_config, merged);
+}
+
+void
+gkbd_keyboard_config_layouts_reset (GkbdKeyboardConfig * kbd_config)
+{
+ gkbd_keyboard_config_string_list_reset (&kbd_config->layouts);
+}
+
+void
+gkbd_keyboard_config_options_reset (GkbdKeyboardConfig * kbd_config)
+{
+ gkbd_keyboard_config_string_list_reset (&kbd_config->options);
+}
+
+void
+gkbd_keyboard_config_options_add (GkbdKeyboardConfig * kbd_config,
+ const gchar * group_name,
+ const gchar * option_name)
+{
+ const gchar *merged;
+ if (group_name == NULL || option_name == NULL)
+ return;
+ merged =
+ gkbd_keyboard_config_merge_items (group_name, option_name);
+ if (merged == NULL)
+ return;
+ gkbd_keyboard_config_options_add_full (kbd_config, merged);
+}
+
+gboolean
+gkbd_keyboard_config_options_is_set (GkbdKeyboardConfig * kbd_config,
+ const gchar * group_name,
+ const gchar * option_name)
+{
+ const gchar *merged =
+ gkbd_keyboard_config_merge_items (group_name, option_name);
+ if (merged == NULL)
+ return FALSE;
+
+ return NULL != g_slist_find_custom (kbd_config->options, (gpointer)
+ merged, (GCompareFunc)
+ g_ascii_strcasecmp);
+}
+
+gboolean
+gkbd_keyboard_config_activate (GkbdKeyboardConfig * kbd_config)
+{
+ gboolean rv;
+ XklConfigRec *data = xkl_config_rec_new ();
+
+ gkbd_keyboard_config_copy_to_xkl_config (kbd_config, data);
+ rv = xkl_config_rec_activate (data, kbd_config->engine);
+ g_object_unref (G_OBJECT (data));
+
+ return rv;
+}
+
+void
+gkbd_keyboard_config_start_listen (GkbdKeyboardConfig * kbd_config,
+ GConfClientNotifyFunc func,
+ gpointer user_data)
+{
+ gkbd_desktop_config_add_listener (kbd_config->conf_client,
+ GKBD_KEYBOARD_CONFIG_DIR, func,
+ user_data,
+ &kbd_config->config_listener_id);
+}
+
+void
+gkbd_keyboard_config_stop_listen (GkbdKeyboardConfig * kbd_config)
+{
+ gkbd_desktop_config_remove_listener (kbd_config->conf_client,
+ &kbd_config->
+ config_listener_id);
+}
+
+gboolean
+gkbd_keyboard_config_get_descriptions (XklConfigRegistry * config_registry,
+ const gchar * name,
+ gchar ** layout_short_descr,
+ gchar ** layout_descr,
+ gchar ** variant_short_descr,
+ gchar ** variant_descr)
+{
+ char *layout_name = NULL, *variant_name = NULL;
+ if (!gkbd_keyboard_config_split_items
+ (name, &layout_name, &variant_name))
+ return FALSE;
+ return gkbd_keyboard_config_get_lv_descriptions (config_registry,
+ layout_name,
+ variant_name,
+ layout_short_descr,
+ layout_descr,
+ variant_short_descr,
+ variant_descr);
+}
+
+const gchar *
+gkbd_keyboard_config_format_full_layout (const gchar * layout_descr,
+ const gchar * variant_descr)
+{
+ static gchar full_descr[XKL_MAX_CI_DESC_LENGTH * 2];
+ if (variant_descr == NULL)
+ g_snprintf (full_descr, sizeof (full_descr), "%s",
+ layout_descr);
+ else
+ g_snprintf (full_descr, sizeof (full_descr), "%s %s",
+ layout_descr, variant_descr);
+ return full_descr;
+}
+
+gchar *
+gkbd_keyboard_config_to_string (const GkbdKeyboardConfig * config)
+{
+ gchar *layouts = NULL, *options = NULL;
+ GString *buffer = g_string_new (NULL);
+
+ GSList *iter;
+ gint count;
+ gchar *result;
+
+ if (config->layouts) {
+ /* g_slist_length is "expensive", so we determinate the length on the fly */
+ for (iter = config->layouts, count = 0; iter;
+ iter = iter->next, ++count) {
+ if (buffer->len)
+ g_string_append (buffer, " ");
+
+ g_string_append (buffer,
+ (const gchar *) iter->data);
+ }
+
+ /* TRANS: The count is related to the number of options. The %s format specifier should not be modified,
+ * left "as is". */
+ layouts =
+ g_strdup_printf (ngettext
+ ("layout \"%s\"", "layouts \"%s\"",
+ count), buffer->str);
+ g_string_truncate (buffer, 0);
+ }
+ if (config->options) {
+ /* g_slist_length is "expensive", so we determinate the length on the fly */
+ for (iter = config->options, count = 0; iter;
+ iter = iter->next, ++count) {
+ if (buffer->len)
+ g_string_append (buffer, " ");
+
+ g_string_append (buffer,
+ (const gchar *) iter->data);
+ }
+
+ /* TRANS: The count is related to the number of options. The %s format specifier should not be modified,
+ * left "as is". */
+ options =
+ g_strdup_printf (ngettext
+ ("option \"%s\"", "options \"%s\"",
+ count), buffer->str);
+ g_string_truncate (buffer, 0);
+ }
+
+ g_string_free (buffer, TRUE);
+
+ result =
+ g_strdup_printf (_("model \"%s\", %s and %s"), config->model,
+ layouts ? layouts : _("no layout"),
+ options ? options : _("no options"));
+
+ g_free (options);
+ g_free (layouts);
+
+ return result;
+}
diff --git a/libgnomekbd/gkbd-keyboard-config.h b/libgnomekbd/gkbd-keyboard-config.h
new file mode 100644
index 0000000..9e9083c
--- /dev/null
+++ b/libgnomekbd/gkbd-keyboard-config.h
@@ -0,0 +1,120 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GKBD_KEYBOARD_CONFIG_H__
+#define __GKBD_KEYBOARD_CONFIG_H__
+
+#include <X11/Xlib.h>
+
+#include <glib.h>
+#include <glib/gslist.h>
+
+#include <gconf/gconf-client.h>
+
+#include <libxklavier/xklavier.h>
+
+extern const gchar GKBD_KEYBOARD_CONFIG_DIR[];
+extern const gchar GKBD_KEYBOARD_CONFIG_KEY_MODEL[];
+extern const gchar GKBD_KEYBOARD_CONFIG_KEY_LAYOUTS[];
+extern const gchar GKBD_KEYBOARD_CONFIG_KEY_OPTIONS[];
+
+/*
+ * Keyboard Configuration
+ */
+typedef struct _GkbdKeyboardConfig {
+ gchar *model;
+ GSList *layouts;
+ GSList *options;
+
+ /* private, transient */
+ GConfClient *conf_client;
+ int config_listener_id;
+ XklEngine *engine;
+} GkbdKeyboardConfig;
+
+/**
+ * GkbdKeyboardConfig functions
+ */
+extern void gkbd_keyboard_config_init (GkbdKeyboardConfig * kbd_config,
+ GConfClient * conf_client,
+ XklEngine * engine);
+extern void gkbd_keyboard_config_term (GkbdKeyboardConfig * kbd_config);
+
+extern void gkbd_keyboard_config_load_from_gconf (GkbdKeyboardConfig *
+ kbd_config,
+ GkbdKeyboardConfig *
+ kbd_config_default);
+
+extern void gkbd_keyboard_config_save_to_gconf (GkbdKeyboardConfig *
+ kbd_config);
+
+extern void gkbd_keyboard_config_load_from_gconf_backup (GkbdKeyboardConfig
+ * kbd_config);
+
+extern void gkbd_keyboard_config_save_to_gconf_backup (GkbdKeyboardConfig *
+ kbd_config);
+
+extern void gkbd_keyboard_config_load_from_x_initial (GkbdKeyboardConfig *
+ kbd_config);
+
+extern void gkbd_keyboard_config_load_from_x_current (GkbdKeyboardConfig *
+ kbd_config);
+
+extern void gkbd_keyboard_config_start_listen (GkbdKeyboardConfig *
+ kbd_config,
+ GConfClientNotifyFunc func,
+ gpointer user_data);
+
+extern void gkbd_keyboard_config_stop_listen (GkbdKeyboardConfig *
+ kbd_config);
+
+extern gboolean gkbd_keyboard_config_equals (GkbdKeyboardConfig *
+ kbd_config1,
+ GkbdKeyboardConfig *
+ kbd_config2);
+
+extern gboolean gkbd_keyboard_config_activate (GkbdKeyboardConfig *
+ kbd_config);
+
+extern const gchar *gkbd_keyboard_config_merge_items (const gchar * parent,
+ const gchar * child);
+
+extern gboolean gkbd_keyboard_config_split_items (const gchar * merged,
+ gchar ** parent,
+ gchar ** child);
+
+extern gboolean gkbd_keyboard_config_get_descriptions (XklConfigRegistry *
+ config_registry,
+ const gchar * name,
+ gchar **
+ layout_short_descr,
+ gchar **
+ layout_descr,
+ gchar **
+ variant_short_descr,
+ gchar **
+ variant_descr);
+
+extern const gchar *gkbd_keyboard_config_format_full_layout (const gchar
+ *
+ layout_descr,
+ const gchar *
+ variant_descr);
+
+extern gchar *gkbd_keyboard_config_to_string (const GkbdKeyboardConfig *
+ config);
+
+#endif
diff --git a/libgnomekbd/gkbd-keyboard-drawing-marshal.list b/libgnomekbd/gkbd-keyboard-drawing-marshal.list
new file mode 100644
index 0000000..88a875f
--- /dev/null
+++ b/libgnomekbd/gkbd-keyboard-drawing-marshal.list
@@ -0,0 +1,2 @@
+# $Id$
+VOID:UINT
diff --git a/libgnomekbd/gkbd-keyboard-drawing.c b/libgnomekbd/gkbd-keyboard-drawing.c
new file mode 100644
index 0000000..8fa0453
--- /dev/null
+++ b/libgnomekbd/gkbd-keyboard-drawing.c
@@ -0,0 +1,1848 @@
+/* $Id$ */
+/*
+ * keyboard-drawing.c: implementation of a gtk+ widget that is a drawing of
+ * the keyboard of the default display
+ *
+ * Copyright (c) 2004 Noah Levitt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkkeysyms.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBgeom.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <math.h>
+
+#include <gkbd-keyboard-drawing.h>
+#include <gkbd-keyboard-drawing-marshal.h>
+
+#define noKBDRAW_DEBUG
+
+enum {
+ BAD_KEYCODE = 0,
+ NUM_SIGNALS
+};
+
+static guint gkbd_keyboard_drawing_signals[NUM_SIGNALS] = { 0 };
+
+static void gkbd_keyboard_drawing_set_mods (GkbdKeyboardDrawing * drawing,
+ guint mods);
+
+static gint
+xkb_to_pixmap_coord (GkbdKeyboardDrawing * drawing, gint n)
+{
+ return n * drawing->scale_numerator / drawing->scale_denominator;
+}
+
+/* angle is in tenths of a degree; coordinates can be anything as (xkb,
+ * pixels, pango) as long as they are all the same */
+static void
+rotate_coordinate (gint origin_x,
+ gint origin_y,
+ gint x,
+ gint y, gint angle, gint * rotated_x, gint * rotated_y)
+{
+ *rotated_x =
+ origin_x + (x - origin_x) * cos (M_PI * angle / 1800.0) - (y -
+ origin_y)
+ * sin (M_PI * angle / 1800.0);
+ *rotated_y =
+ origin_y + (x - origin_x) * sin (M_PI * angle / 1800.0) + (y -
+ origin_y)
+ * cos (M_PI * angle / 1800.0);
+}
+
+static void
+draw_polygon (GkbdKeyboardDrawing * drawing,
+ GdkColor * fill_color,
+ gint xkb_x,
+ gint xkb_y, XkbPointRec * xkb_points, guint num_points)
+{
+ GtkStateType state = GTK_WIDGET_STATE (GTK_WIDGET (drawing));
+ GdkGC *gc;
+ GdkPoint *points;
+ gboolean filled;
+ gint i;
+
+ if (drawing->pixmap == NULL)
+ return;
+
+ if (fill_color) {
+ gc = gdk_gc_new (GTK_WIDGET (drawing)->window);
+ gdk_gc_set_rgb_fg_color (gc, fill_color);
+ filled = TRUE;
+ } else {
+ gc = GTK_WIDGET (drawing)->style->dark_gc[state];
+ filled = FALSE;
+ }
+
+ points = g_new (GdkPoint, num_points);
+
+ for (i = 0; i < num_points; i++) {
+ points[i].x =
+ xkb_to_pixmap_coord (drawing, xkb_x + xkb_points[i].x);
+ points[i].y =
+ xkb_to_pixmap_coord (drawing, xkb_y + xkb_points[i].y);
+ }
+
+ gdk_draw_polygon (drawing->pixmap, gc, filled, points, num_points);
+
+ g_free (points);
+ if (fill_color)
+ g_object_unref (gc);
+}
+
+/* x, y, width, height are in the xkb coordinate system */
+static void
+draw_rectangle (GkbdKeyboardDrawing * drawing,
+ GdkColor * fill_color,
+ gint angle,
+ gint xkb_x, gint xkb_y, gint xkb_width, gint xkb_height)
+{
+ if (drawing->pixmap == NULL)
+ return;
+
+ if (angle == 0) {
+ GtkStateType state =
+ GTK_WIDGET_STATE (GTK_WIDGET (drawing));
+ gint x, y, width, height;
+ gboolean filled;
+ GdkGC *gc;
+
+ if (fill_color) {
+ gc = gdk_gc_new (GTK_WIDGET (drawing)->window);
+ gdk_gc_set_rgb_fg_color (gc, fill_color);
+ filled = TRUE;
+ } else {
+ gc = GTK_WIDGET (drawing)->style->dark_gc[state];
+ filled = FALSE;
+ }
+
+ x = xkb_to_pixmap_coord (drawing, xkb_x);
+ y = xkb_to_pixmap_coord (drawing, xkb_y);
+ width =
+ xkb_to_pixmap_coord (drawing, xkb_x + xkb_width) - x;
+ height =
+ xkb_to_pixmap_coord (drawing, xkb_y + xkb_height) - y;
+
+ gdk_draw_rectangle (drawing->pixmap, gc, filled, x, y,
+ width, height);
+
+ if (fill_color)
+ g_object_unref (gc);
+ } else {
+ XkbPointRec points[4];
+ gint x, y;
+
+ points[0].x = xkb_x;
+ points[0].y = xkb_y;
+ rotate_coordinate (xkb_x, xkb_y, xkb_x + xkb_width, xkb_y,
+ angle, &x, &y);
+ points[1].x = x;
+ points[1].y = y;
+ rotate_coordinate (xkb_x, xkb_y, xkb_x + xkb_width,
+ xkb_y + xkb_height, angle, &x, &y);
+ points[2].x = x;
+ points[2].y = y;
+ rotate_coordinate (xkb_x, xkb_y, xkb_x, xkb_y + xkb_height,
+ angle, &x, &y);
+ points[3].x = x;
+ points[3].y = y;
+
+ /* the points we've calculated are relative to 0,0 */
+ draw_polygon (drawing, fill_color, 0, 0, points, 4);
+ }
+}
+
+static void
+draw_outline (GkbdKeyboardDrawing * drawing,
+ XkbOutlineRec * outline,
+ GdkColor * color, gint angle, gint origin_x, gint origin_y)
+{
+#ifdef KBDRAW_DEBUG
+ printf ("num_points in %p: %d\n", outline, outline->num_points);
+#endif
+
+ if (outline->num_points == 1) {
+ if (color)
+ draw_rectangle (drawing, color, angle, origin_x,
+ origin_y, outline->points[0].x,
+ outline->points[0].y);
+
+#ifdef KBDRAW_DEBUG
+ printf ("points:%p\n", outline->points);
+ printf ("pointsxy:%d %d\n", outline->points[0].x,
+ outline->points[0].y);
+#endif
+
+ draw_rectangle (drawing, NULL, angle, origin_x, origin_y,
+ outline->points[0].x,
+ outline->points[0].y);
+ } else if (outline->num_points == 2) {
+ gint rotated_x0, rotated_y0;
+
+ rotate_coordinate (origin_x, origin_y,
+ origin_x + outline->points[0].x,
+ origin_y + outline->points[0].y,
+ angle, &rotated_x0, &rotated_y0);
+ if (color)
+ draw_rectangle (drawing, color, angle, rotated_x0,
+ rotated_y0, outline->points[1].x,
+ outline->points[1].y);
+
+ draw_rectangle (drawing, NULL, angle, rotated_x0,
+ rotated_y0, outline->points[1].x,
+ outline->points[1].y);
+ } else {
+ if (color)
+ draw_polygon (drawing, color, origin_x, origin_y,
+ outline->points,
+ outline->num_points);
+
+ draw_polygon (drawing, NULL, origin_x, origin_y,
+ outline->points, outline->num_points);
+ }
+}
+
+/* see PSColorDef in xkbprint */
+static gboolean
+parse_xkb_color_spec (gchar * colorspec, GdkColor * color)
+{
+ glong level;
+
+ if (g_ascii_strcasecmp (colorspec, "black") == 0) {
+ color->red = 0;
+ color->green = 0;
+ color->blue = 0;
+ } else if (g_ascii_strcasecmp (colorspec, "white") == 0) {
+ color->red = 65535;
+ color->green = 65535;
+ color->blue = 65535;
+ } else if (g_ascii_strncasecmp (colorspec, "grey", 4) == 0 ||
+ g_ascii_strncasecmp (colorspec, "gray", 4) == 0) {
+ level = strtol (colorspec + 4, NULL, 10);
+
+ color->red = 65535 - 65535 * level / 100;
+ color->green = 65535 - 65535 * level / 100;
+ color->blue = 65535 - 65535 * level / 100;
+ } else if (g_ascii_strcasecmp (colorspec, "red") == 0) {
+ color->red = 65535;
+ color->green = 0;
+ color->blue = 0;
+ } else if (g_ascii_strcasecmp (colorspec, "green") == 0) {
+ color->red = 0;
+ color->green = 65535;
+ color->blue = 0;
+ } else if (g_ascii_strcasecmp (colorspec, "blue") == 0) {
+ color->red = 0;
+ color->green = 0;
+ color->blue = 65535;
+ } else if (g_ascii_strncasecmp (colorspec, "red", 3) == 0) {
+ level = strtol (colorspec + 3, NULL, 10);
+
+ color->red = 65535 * level / 100;
+ color->green = 0;
+ color->blue = 0;
+ } else if (g_ascii_strncasecmp (colorspec, "green", 5) == 0) {
+ level = strtol (colorspec + 5, NULL, 10);
+
+ color->red = 0;
+ color->green = 65535 * level / 100;;
+ color->blue = 0;
+ } else if (g_ascii_strncasecmp (colorspec, "blue", 4) == 0) {
+ level = strtol (colorspec + 4, NULL, 10);
+
+ color->red = 0;
+ color->green = 0;
+ color->blue = 65535 * level / 100;
+ } else
+ return FALSE;
+
+ return TRUE;
+}
+
+
+static guint
+find_keycode (GkbdKeyboardDrawing * drawing, gchar * key_name)
+{
+ guint i;
+
+ if (!drawing->xkb)
+ return (gint) (-1);
+
+ for (i = drawing->xkb->min_key_code;
+ i <= drawing->xkb->max_key_code; i++) {
+ if (drawing->xkb->names->keys[i].name[0] == key_name[0]
+ && drawing->xkb->names->keys[i].name[1] == key_name[1]
+ && drawing->xkb->names->keys[i].name[2] == key_name[2]
+ && drawing->xkb->names->keys[i].name[3] == key_name[3])
+ return i;
+ }
+
+ return (guint) (-1);
+}
+
+
+static void
+fit_width (GkbdKeyboardDrawing * drawing, gint width)
+{
+ PangoRectangle logical_rect;
+ gint old_size;
+
+ pango_layout_get_extents (drawing->layout, NULL, &logical_rect);
+
+ if (logical_rect.width > 0 && logical_rect.width > width) {
+ old_size =
+ pango_font_description_get_size (drawing->font_desc);
+ pango_font_description_set_size (drawing->font_desc,
+ old_size * width /
+ logical_rect.width);
+ pango_layout_set_font_description (drawing->layout,
+ drawing->font_desc);
+ }
+}
+
+static void
+set_key_label_in_layout (GkbdKeyboardDrawing * drawing,
+ PangoLayout * layout, guint keyval)
+{
+ gchar buf[5];
+ gunichar uc;
+
+ switch (keyval) {
+ case GDK_Scroll_Lock:
+ pango_layout_set_text (layout, "Scroll\nLock", -1);
+ break;
+
+ case GDK_space:
+ pango_layout_set_text (layout, "", -1);
+ break;
+
+ case GDK_Sys_Req:
+ pango_layout_set_text (layout, "Sys Rq", -1);
+ break;
+
+ case GDK_Page_Up:
+ pango_layout_set_text (layout, "Page\nUp", -1);
+ break;
+
+ case GDK_Page_Down:
+ pango_layout_set_text (layout, "Page\nDown", -1);
+ break;
+
+ case GDK_Num_Lock:
+ pango_layout_set_text (layout, "Num\nLock", -1);
+ break;
+
+ case GDK_KP_Page_Up:
+ pango_layout_set_text (layout, "Pg Up", -1);
+ break;
+
+ case GDK_KP_Page_Down:
+ pango_layout_set_text (layout, "Pg Dn", -1);
+ break;
+
+ case GDK_KP_Home:
+ pango_layout_set_text (layout, "Home", -1);
+ break;
+
+ case GDK_KP_Left:
+ pango_layout_set_text (layout, "Left", -1);
+ break;
+
+ case GDK_KP_End:
+ pango_layout_set_text (layout, "End", -1);
+ break;
+
+ case GDK_KP_Up:
+ pango_layout_set_text (layout, "Up", -1);
+ break;
+
+ case GDK_KP_Begin:
+ pango_layout_set_text (layout, "Begin", -1);
+ break;
+
+ case GDK_KP_Right:
+ pango_layout_set_text (layout, "Right", -1);
+ break;
+
+ case GDK_KP_Enter:
+ pango_layout_set_text (layout, "Enter", -1);
+ break;
+
+ case GDK_KP_Down:
+ pango_layout_set_text (layout, "Down", -1);
+ break;
+
+ case GDK_KP_Insert:
+ pango_layout_set_text (layout, "Ins", -1);
+ break;
+
+ case GDK_KP_Delete:
+ pango_layout_set_text (layout, "Del", -1);
+ break;
+
+ case GDK_dead_grave:
+ pango_layout_set_text (layout, "ˋ", -1);
+ break;
+
+ case GDK_dead_acute:
+ pango_layout_set_text (layout, "ˊ", -1);
+ break;
+
+ case GDK_dead_circumflex:
+ pango_layout_set_text (layout, "ˆ", -1);
+ break;
+
+ case GDK_dead_tilde:
+ pango_layout_set_text (layout, "~", -1);
+ break;
+
+ case GDK_dead_macron:
+ pango_layout_set_text (layout, "ˉ", -1);
+ break;
+
+ case GDK_dead_breve:
+ pango_layout_set_text (layout, "˘", -1);
+ break;
+
+ case GDK_dead_abovedot:
+ pango_layout_set_text (layout, "˙", -1);
+ break;
+
+ case GDK_dead_diaeresis:
+ pango_layout_set_text (layout, "¨", -1);
+ break;
+
+ case GDK_dead_abovering:
+ pango_layout_set_text (layout, "˚", -1);
+ break;
+
+ case GDK_dead_doubleacute:
+ pango_layout_set_text (layout, "˝", -1);
+ break;
+
+ case GDK_dead_caron:
+ pango_layout_set_text (layout, "ˇ", -1);
+ break;
+
+ case GDK_dead_cedilla:
+ pango_layout_set_text (layout, "¸", -1);
+ break;
+
+ case GDK_dead_ogonek:
+ pango_layout_set_text (layout, "˛", -1);
+ break;
+
+ /* case GDK_dead_iota:
+ * case GDK_dead_voiced_sound:
+ * case GDK_dead_semivoiced_sound: */
+
+ case GDK_dead_belowdot:
+ pango_layout_set_text (layout, " ̣", -1);
+ break;
+
+ case GDK_horizconnector:
+ pango_layout_set_text (layout, "horiz\nconn", -1);
+ break;
+
+ case GDK_Mode_switch:
+ pango_layout_set_text (layout, "AltGr", -1);
+ break;
+
+ case GDK_Multi_key:
+ pango_layout_set_text (layout, "Compose", -1);
+ break;
+
+ default:
+ uc = gdk_keyval_to_unicode (keyval);
+ if (uc != 0 && g_unichar_isgraph (uc)) {
+ buf[g_unichar_to_utf8 (uc, buf)] = '\0';
+ pango_layout_set_text (layout, buf, -1);
+ } else {
+ gchar *name = gdk_keyval_name (keyval);
+ if (name)
+ pango_layout_set_text (layout, name, -1);
+ else
+ pango_layout_set_text (layout, "", -1);
+ }
+ }
+}
+
+
+static void
+draw_layout (GkbdKeyboardDrawing * drawing,
+ gint angle, gint x, gint y, PangoLayout * layout)
+{
+ GtkStateType state = GTK_WIDGET_STATE (GTK_WIDGET (drawing));
+ PangoLayoutLine *line;
+ gint x_off, y_off;
+ gint i;
+
+ if (drawing->pixmap == NULL)
+ return;
+
+ if (angle != drawing->angle) {
+ PangoMatrix matrix = PANGO_MATRIX_INIT;
+ pango_matrix_rotate (&matrix, -angle / 10.0);
+ pango_context_set_matrix (gtk_widget_get_pango_context
+ (GTK_WIDGET (drawing)), &matrix);
+ pango_layout_context_changed (drawing->layout);
+ drawing->angle = angle;
+ }
+
+ i = 0;
+ y_off = 0;
+ for (line = pango_layout_get_line (drawing->layout, i);
+ line != NULL;
+ line = pango_layout_get_line (drawing->layout, ++i)) {
+ GSList *runp;
+ PangoRectangle line_extents;
+
+ x_off = 0;
+
+ for (runp = line->runs; runp != NULL; runp = runp->next) {
+ PangoGlyphItem *run = runp->data;
+ gint j;
+
+ for (j = 0; j < run->glyphs->num_glyphs; j++) {
+ PangoGlyphGeometry *geometry;
+ gint xx, yy;
+
+ geometry =
+ &run->glyphs->glyphs[j].geometry;
+
+ rotate_coordinate (0, 0, x_off, y_off,
+ angle, &xx, &yy);
+ geometry->x_offset -= x_off - xx;
+ geometry->y_offset -= y_off - yy;
+
+ x_off += geometry->width;
+ }
+ }
+
+ pango_layout_line_get_extents (line, NULL, &line_extents);
+ y_off +=
+ line_extents.height +
+ pango_layout_get_spacing (drawing->layout);
+ }
+
+ gdk_draw_layout (drawing->pixmap,
+ GTK_WIDGET (drawing)->style->text_gc[state], x, y,
+ drawing->layout);
+}
+
+static void
+draw_key_label_helper (GkbdKeyboardDrawing * drawing,
+ KeySym keysym,
+ gint angle,
+ GkbdKeyboardDrawingGroupLevelPosition glp,
+ gint x,
+ gint y, gint width, gint height, gint padding)
+{
+ gint old_size;
+ gint label_x, label_y, label_max_width, ycell;
+
+ if (keysym == 0)
+ return;
+#ifdef KBDRAW_DEBUG
+ printf ("keysym: %04X(%c) at glp: %d\n",
+ (unsigned) keysym, (char) keysym, (int) glp);
+#endif
+
+ switch (glp) {
+ case GKBD_KEYBOARD_DRAWING_POS_TOPLEFT:
+ case GKBD_KEYBOARD_DRAWING_POS_BOTTOMLEFT:
+ {
+ ycell =
+ glp == GKBD_KEYBOARD_DRAWING_POS_BOTTOMLEFT;
+
+ rotate_coordinate (x, y, x + padding,
+ y + padding + (height -
+ 2 * padding) *
+ ycell * 4 / 7, angle, &label_x,
+ &label_y);
+ label_max_width =
+ PANGO_SCALE * (width - 2 * padding);
+ break;
+ }
+ case GKBD_KEYBOARD_DRAWING_POS_TOPRIGHT:
+ case GKBD_KEYBOARD_DRAWING_POS_BOTTOMRIGHT:
+ {
+ ycell =
+ glp == GKBD_KEYBOARD_DRAWING_POS_BOTTOMRIGHT;
+
+ rotate_coordinate (x, y,
+ x + padding + (width -
+ 2 * padding) *
+ 4 / 7,
+ y + padding + (height -
+ 2 * padding) *
+ ycell * 4 / 7, angle, &label_x,
+ &label_y);
+ label_max_width =
+ PANGO_SCALE * ((width - 2 * padding) -
+ (width - 2 * padding) * 4 / 7);
+ break;
+ }
+ default:
+ return;
+ }
+ set_key_label_in_layout (drawing, drawing->layout, keysym);
+
+ old_size = pango_font_description_get_size (drawing->font_desc);
+ fit_width (drawing, label_max_width);
+
+ draw_layout (drawing, angle, label_x, label_y, drawing->layout);
+
+ if (pango_font_description_get_size (drawing->font_desc) !=
+ old_size) {
+ pango_font_description_set_size (drawing->font_desc,
+ old_size);
+ pango_layout_set_font_description (drawing->layout,
+ drawing->font_desc);
+ }
+}
+
+static void
+draw_key_label (GkbdKeyboardDrawing * drawing,
+ guint keycode,
+ gint angle,
+ gint xkb_origin_x,
+ gint xkb_origin_y, gint xkb_width, gint xkb_height)
+{
+ gint x, y, width, height;
+ gint padding;
+ gint g, l, glp;
+
+ if (!drawing->xkb)
+ return;
+
+ padding = 23 * drawing->scale_numerator / drawing->scale_denominator; /* 2.3mm */
+
+ x = xkb_to_pixmap_coord (drawing, xkb_origin_x);
+ y = xkb_to_pixmap_coord (drawing, xkb_origin_y);
+ width =
+ xkb_to_pixmap_coord (drawing, xkb_origin_x + xkb_width) - x;
+ height =
+ xkb_to_pixmap_coord (drawing, xkb_origin_y + xkb_height) - y;
+
+ for (glp = GKBD_KEYBOARD_DRAWING_POS_TOPLEFT;
+ glp < GKBD_KEYBOARD_DRAWING_POS_TOTAL; glp++) {
+ if (drawing->groupLevels[glp] == NULL)
+ continue;
+ g = drawing->groupLevels[glp]->group;
+ l = drawing->groupLevels[glp]->level;
+
+ if (g < 0 || g >= XkbKeyNumGroups (drawing->xkb, keycode))
+ continue;
+ if (l < 0
+ || l >= XkbKeyGroupWidth (drawing->xkb, keycode, g))
+ continue;
+
+ if (drawing->track_modifiers) {
+ uint mods_rtrn;
+ KeySym keysym;
+
+ if (XkbTranslateKeyCode (drawing->xkb, keycode,
+ XkbBuildCoreState
+ (drawing->mods, g),
+ &mods_rtrn, &keysym)) {
+ draw_key_label_helper (drawing, keysym,
+ angle, glp, x, y,
+ width, height,
+ padding);
+ /* reverse y order */
+ }
+ } else {
+ KeySym keysym;
+
+ keysym =
+ XkbKeySymEntry (drawing->xkb, keycode, l, g);
+
+ draw_key_label_helper (drawing, keysym, angle, glp,
+ x, y, width, height,
+ padding);
+ /* reverse y order */
+ }
+ }
+}
+
+/* groups are from 0-3 */
+static void
+draw_key (GkbdKeyboardDrawing * drawing, GkbdKeyboardDrawingKey * key)
+{
+ XkbShapeRec *shape;
+ GdkColor *color;
+ gint i;
+
+ if (!drawing->xkb)
+ return;
+
+#ifdef KBDRAW_DEBUG
+ printf ("shape: %p (%p + %d)\n",
+ drawing->xkb->geom->shapes + key->xkbkey->shape_ndx,
+ drawing->xkb->geom->shapes, key->xkbkey->shape_ndx);
+#endif
+
+ shape = drawing->xkb->geom->shapes + key->xkbkey->shape_ndx;
+
+ if (key->pressed)
+ color =
+ &(GTK_WIDGET (drawing)->style->
+ base[GTK_STATE_SELECTED]);
+ else
+ color = drawing->colors + key->xkbkey->color_ndx;
+
+#ifdef KBDRAW_DEBUG
+ printf ("outlines: %p(%d)\n", shape->outlines,
+ shape->num_outlines);
+#endif
+
+ for (i = 0; i < 1 /* shape->num_outlines */ ; i++)
+ draw_outline (drawing, shape->outlines + i, color,
+ key->angle, key->origin_x, key->origin_y);
+
+ draw_key_label (drawing, key->keycode, key->angle, key->origin_x,
+ key->origin_y, shape->bounds.x2, shape->bounds.y2);
+}
+
+static void
+invalidate_region (GkbdKeyboardDrawing * drawing,
+ gdouble angle,
+ gint origin_x, gint origin_y, XkbShapeRec * shape)
+{
+ GdkPoint points[4];
+ gint x_min, x_max, y_min, y_max;
+ gint x, y, width, height;
+ gint xx, yy;
+
+ rotate_coordinate (0, 0, 0, 0, angle, &xx, &yy);
+ points[0].x = xx;
+ points[0].y = yy;
+ rotate_coordinate (0, 0, shape->bounds.x2, 0, angle, &xx, &yy);
+ points[1].x = xx;
+ points[1].y = yy;
+ rotate_coordinate (0, 0, shape->bounds.x2, shape->bounds.y2, angle,
+ &xx, &yy);
+ points[2].x = xx;
+ points[2].y = yy;
+ rotate_coordinate (0, 0, 0, shape->bounds.y2, angle, &xx, &yy);
+ points[3].x = xx;
+ points[3].y = yy;
+
+ x_min =
+ MIN (MIN (points[0].x, points[1].x),
+ MIN (points[2].x, points[3].x));
+ x_max =
+ MAX (MAX (points[0].x, points[1].x),
+ MAX (points[2].x, points[3].x));
+ y_min =
+ MIN (MIN (points[0].y, points[1].y),
+ MIN (points[2].y, points[3].y));
+ y_max =
+ MAX (MAX (points[0].y, points[1].y),
+ MAX (points[2].y, points[3].y));
+
+ x = xkb_to_pixmap_coord (drawing, origin_x + x_min) - 6;
+ y = xkb_to_pixmap_coord (drawing, origin_y + y_min) - 6;
+ width = xkb_to_pixmap_coord (drawing, x_max - x_min) + 12;
+ height = xkb_to_pixmap_coord (drawing, y_max - y_min) + 12;
+
+ gtk_widget_queue_draw_area (GTK_WIDGET (drawing), x, y, width,
+ height);
+}
+
+static void
+invalidate_indicator_doodad_region (GkbdKeyboardDrawing * drawing,
+ GkbdKeyboardDrawingDoodad * doodad)
+{
+ if (!drawing->xkb)
+ return;
+
+ invalidate_region (drawing,
+ doodad->angle,
+ doodad->origin_x +
+ doodad->doodad->indicator.left,
+ doodad->origin_y +
+ doodad->doodad->indicator.top,
+ &drawing->xkb->geom->shapes[doodad->doodad->
+ indicator.
+ shape_ndx]);
+}
+
+static void
+invalidate_key_region (GkbdKeyboardDrawing * drawing,
+ GkbdKeyboardDrawingKey * key)
+{
+ if (!drawing->xkb)
+ return;
+
+ invalidate_region (drawing,
+ key->angle,
+ key->origin_x,
+ key->origin_y,
+ &drawing->xkb->geom->shapes[key->xkbkey->
+ shape_ndx]);
+}
+
+static void
+draw_text_doodad (GkbdKeyboardDrawing * drawing,
+ GkbdKeyboardDrawingDoodad * doodad,
+ XkbTextDoodadRec * text_doodad)
+{
+ gint x, y;
+ if (!drawing->xkb)
+ return;
+
+ x = xkb_to_pixmap_coord (drawing,
+ doodad->origin_x + text_doodad->left);
+ y = xkb_to_pixmap_coord (drawing,
+ doodad->origin_y + text_doodad->top);
+
+ pango_layout_set_text (drawing->layout, text_doodad->text, -1);
+ draw_layout (drawing, doodad->angle, x, y, drawing->layout);
+}
+
+static void
+draw_indicator_doodad (GkbdKeyboardDrawing * drawing,
+ GkbdKeyboardDrawingDoodad * doodad,
+ XkbIndicatorDoodadRec * indicator_doodad)
+{
+ GdkColor *color;
+ XkbShapeRec *shape;
+ gint i;
+
+ if (!drawing->xkb)
+ return;
+
+ shape = drawing->xkb->geom->shapes + indicator_doodad->shape_ndx;
+
+ color = drawing->colors + (doodad->on ?
+ indicator_doodad->on_color_ndx :
+ indicator_doodad->off_color_ndx);
+
+ for (i = 0; i < 1; i++)
+ draw_outline (drawing, shape->outlines + i, color,
+ doodad->angle,
+ doodad->origin_x + indicator_doodad->left,
+ doodad->origin_y + indicator_doodad->top);
+}
+
+static void
+draw_shape_doodad (GkbdKeyboardDrawing * drawing,
+ GkbdKeyboardDrawingDoodad * doodad,
+ XkbShapeDoodadRec * shape_doodad)
+{
+ XkbShapeRec *shape;
+ GdkColor *color;
+ gint i;
+
+ if (!drawing->xkb)
+ return;
+
+ shape = drawing->xkb->geom->shapes + shape_doodad->shape_ndx;
+ color = drawing->colors + shape_doodad->color_ndx;
+
+ for (i = 0; i < shape->num_outlines; i++)
+ draw_outline (drawing, shape->outlines + i, color,
+ doodad->angle,
+ doodad->origin_x + shape_doodad->left,
+ doodad->origin_y + shape_doodad->top);
+}
+
+static void
+draw_doodad (GkbdKeyboardDrawing * drawing,
+ GkbdKeyboardDrawingDoodad * doodad)
+{
+ switch (doodad->doodad->any.type) {
+ case XkbOutlineDoodad:
+ case XkbSolidDoodad:
+ draw_shape_doodad (drawing, doodad,
+ &doodad->doodad->shape);
+ break;
+
+ case XkbTextDoodad:
+ draw_text_doodad (drawing, doodad, &doodad->doodad->text);
+ break;
+
+ case XkbIndicatorDoodad:
+ draw_indicator_doodad (drawing, doodad,
+ &doodad->doodad->indicator);
+ break;
+
+ case XkbLogoDoodad:
+ /* g_print ("draw_doodad: logo: %s\n", doodad->doodad->logo.logo_name); */
+ /* XkbLogoDoodadRec is essentially a subclass of XkbShapeDoodadRec */
+ draw_shape_doodad (drawing, doodad,
+ &doodad->doodad->shape);
+ break;
+ }
+}
+
+static void
+draw_keyboard_item (GkbdKeyboardDrawingItem * item,
+ GkbdKeyboardDrawing * drawing)
+{
+ if (!drawing->xkb)
+ return;
+
+ switch (item->type) {
+ case GKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY:
+ draw_key (drawing, (GkbdKeyboardDrawingKey *) item);
+ break;
+
+ case GKBD_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD:
+ draw_doodad (drawing, (GkbdKeyboardDrawingDoodad *) item);
+ break;
+ }
+}
+
+static void
+draw_keyboard (GkbdKeyboardDrawing * drawing)
+{
+ GtkStateType state = GTK_WIDGET_STATE (GTK_WIDGET (drawing));
+ gint pixw, pixh;
+
+ if (!drawing->xkb)
+ return;
+
+ pixw = GTK_WIDGET (drawing)->allocation.width;
+ pixh = GTK_WIDGET (drawing)->allocation.height;
+
+ drawing->pixmap =
+ gdk_pixmap_new (GTK_WIDGET (drawing)->window, pixw, pixh, -1);
+
+ /* blank background */
+ gdk_draw_rectangle (drawing->pixmap,
+ GTK_WIDGET (drawing)->style->base_gc[state],
+ TRUE, 0, 0, pixw, pixh);
+
+ if (drawing->xkb == NULL)
+ return;
+
+#ifdef KBDRAW_DEBUG
+ printf ("mods: %d\n", drawing->mods);
+#endif
+
+ g_list_foreach (drawing->keyboard_items,
+ (GFunc) draw_keyboard_item, drawing);
+}
+
+static void
+alloc_pango_layout (GkbdKeyboardDrawing * drawing)
+{
+ PangoContext *context =
+ gtk_widget_get_pango_context (GTK_WIDGET (drawing));
+ drawing->layout = pango_layout_new (context);
+}
+
+static void
+free_pango_layout (GkbdKeyboardDrawing * drawing)
+{
+ g_object_unref (G_OBJECT (drawing->layout));
+ drawing->layout = NULL;
+}
+
+static gboolean
+expose_event (GtkWidget * widget,
+ GdkEventExpose * event, GkbdKeyboardDrawing * drawing)
+{
+ GtkStateType state = GTK_WIDGET_STATE (GTK_WIDGET (drawing));
+
+ if (!drawing->xkb)
+ return FALSE;
+
+ if (drawing->pixmap == NULL)
+ draw_keyboard (drawing);
+
+ gdk_draw_drawable (widget->window,
+ widget->style->fg_gc[state],
+ drawing->pixmap,
+ event->area.x, event->area.y,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+ if (GTK_WIDGET_HAS_FOCUS (widget))
+ gtk_paint_focus (widget->style, widget->window,
+ GTK_WIDGET_STATE (widget), &event->area,
+ widget, "keyboard-drawing",
+ 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ return FALSE;
+}
+
+static void
+size_allocate (GtkWidget * widget,
+ GtkAllocation * allocation, GkbdKeyboardDrawing * drawing)
+{
+ if (!drawing->xkb)
+ return;
+
+ if (drawing->pixmap) {
+ g_object_unref (drawing->pixmap);
+ drawing->pixmap = NULL;
+ }
+
+ if (drawing->xkb->geom->width_mm <= 0
+ || drawing->xkb->geom->height_mm <= 0) {
+ g_critical
+ ("keyboard geometry reports width or height as zero!");
+ return;
+ }
+
+ if (allocation->width * drawing->xkb->geom->height_mm <
+ allocation->height * drawing->xkb->geom->width_mm) {
+ drawing->scale_numerator = allocation->width;
+ drawing->scale_denominator = drawing->xkb->geom->width_mm;
+ } else {
+ drawing->scale_numerator = allocation->height;
+ drawing->scale_denominator = drawing->xkb->geom->height_mm;
+ }
+
+ pango_font_description_set_size (drawing->font_desc,
+ 36000 * drawing->scale_numerator /
+ drawing->scale_denominator);
+ pango_layout_set_spacing (drawing->layout,
+ -8000 * drawing->scale_numerator /
+ drawing->scale_denominator);
+ pango_layout_set_font_description (drawing->layout,
+ drawing->font_desc);
+}
+
+static gint
+key_event (GtkWidget * widget,
+ GdkEventKey * event, GkbdKeyboardDrawing * drawing)
+{
+ GkbdKeyboardDrawingKey *key;
+ if (!drawing->xkb)
+ return FALSE;
+
+ key = drawing->keys + event->hardware_keycode;
+
+ if (event->hardware_keycode > drawing->xkb->max_key_code ||
+ event->hardware_keycode < drawing->xkb->min_key_code ||
+ key->xkbkey == NULL) {
+ g_signal_emit (drawing,
+ gkbd_keyboard_drawing_signals[BAD_KEYCODE],
+ 0, event->hardware_keycode);
+ return TRUE;
+ }
+
+ if ((event->type == GDK_KEY_PRESS && key->pressed) ||
+ (event->type == GDK_KEY_RELEASE && !key->pressed))
+ return TRUE;
+ /* otherwise this event changes the state we believed we had before */
+
+ key->pressed = (event->type == GDK_KEY_PRESS);
+
+ draw_key (drawing, key);
+
+ invalidate_key_region (drawing, key);
+
+ return TRUE;
+}
+
+static gint
+button_press_event (GtkWidget * widget,
+ GdkEventButton * event, GkbdKeyboardDrawing * drawing)
+{
+ if (!drawing->xkb)
+ return FALSE;
+
+ gtk_widget_grab_focus (widget);
+ return FALSE;
+}
+
+static gboolean
+unpress_keys (GkbdKeyboardDrawing * drawing)
+{
+ gint i;
+
+ if (!drawing->xkb)
+ return FALSE;
+
+ for (i = drawing->xkb->min_key_code;
+ i <= drawing->xkb->max_key_code; i++)
+ if (drawing->keys[i].pressed) {
+ drawing->keys[i].pressed = FALSE;
+ draw_key (drawing, drawing->keys + i);
+ invalidate_key_region (drawing, drawing->keys + i);
+ }
+
+ return FALSE;
+}
+
+static gint
+focus_event (GtkWidget * widget,
+ GdkEventFocus * event, GkbdKeyboardDrawing * drawing)
+{
+ if (event->in && drawing->timeout > 0) {
+ g_source_remove (drawing->timeout);
+ drawing->timeout = 0;
+ } else
+ drawing->timeout =
+ g_timeout_add (120, (GSourceFunc) unpress_keys,
+ drawing);
+
+ return FALSE;
+}
+
+static gint
+compare_keyboard_item_priorities (GkbdKeyboardDrawingItem * a,
+ GkbdKeyboardDrawingItem * b)
+{
+ if (a->priority > b->priority)
+ return 1;
+ else if (a->priority < b->priority)
+ return -1;
+ else
+ return 0;
+}
+
+static void
+init_indicator_doodad (GkbdKeyboardDrawing * drawing,
+ XkbDoodadRec * xkbdoodad,
+ GkbdKeyboardDrawingDoodad * doodad)
+{
+ if (!drawing->xkb)
+ return;
+
+ if (xkbdoodad->any.type == XkbIndicatorDoodad) {
+ gint index;
+ Atom iname = 0;
+ Atom sname = xkbdoodad->indicator.name;
+ unsigned long phys_indicators =
+ drawing->xkb->indicators->phys_indicators;
+ Atom *pind = drawing->xkb->names->indicators;
+
+#ifdef KBDRAW_DEBUG
+ printf ("Looking for %d[%s]\n",
+ (int) sname, XGetAtomName (drawing->display,
+ sname));
+#endif
+
+ for (index = 0; index < XkbNumIndicators; index++) {
+ iname = *pind++;
+ /* name matches and it is real */
+ if (iname == sname
+ && (phys_indicators & (1 << index)))
+ break;
+ if (iname == 0)
+ break;
+ }
+ if (iname == 0)
+ g_warning ("Could not find indicator %d [%s]\n",
+ (int) sname,
+ XGetAtomName (drawing->display, sname));
+ else {
+#ifdef KBDRAW_DEBUG
+ printf ("Found in xkbdesc as %d\n", index);
+#endif
+ drawing->physical_indicators[index] = doodad;
+ /* Trying to obtain the real state, but if fail - just assume OFF */
+ if (!XkbGetNamedIndicator
+ (drawing->display, sname, NULL, &doodad->on,
+ NULL, NULL))
+ doodad->on = 0;
+ }
+ }
+}
+
+static void
+init_keys_and_doodads (GkbdKeyboardDrawing * drawing)
+{
+ gint i, j, k;
+ gint x, y;
+
+ if (!drawing->xkb)
+ return;
+
+ for (i = 0; i < drawing->xkb->geom->num_doodads; i++) {
+ XkbDoodadRec *xkbdoodad = drawing->xkb->geom->doodads + i;
+ GkbdKeyboardDrawingDoodad *doodad =
+ g_new (GkbdKeyboardDrawingDoodad, 1);
+
+ doodad->type = GKBD_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD;
+ doodad->origin_x = 0;
+ doodad->origin_y = 0;
+ doodad->angle = 0;
+ doodad->priority = xkbdoodad->any.priority * 256 * 256;
+ doodad->doodad = xkbdoodad;
+
+ init_indicator_doodad (drawing, xkbdoodad, doodad);
+
+ drawing->keyboard_items =
+ g_list_append (drawing->keyboard_items, doodad);
+ }
+
+ for (i = 0; i < drawing->xkb->geom->num_sections; i++) {
+#ifdef KBDRAW_DEBUG
+ printf ("initing section %d\n", i);
+#endif
+ XkbSectionRec *section = drawing->xkb->geom->sections + i;
+ guint priority;
+
+ x = section->left;
+ y = section->top;
+ priority = section->priority * 256 * 256;
+
+ for (j = 0; j < section->num_rows; j++) {
+ XkbRowRec *row = section->rows + j;
+
+#ifdef KBDRAW_DEBUG
+ printf (" initing row %d\n", j);
+#endif
+ x = section->left + row->left;
+ y = section->top + row->top;
+
+ for (k = 0; k < row->num_keys; k++) {
+ XkbKeyRec *xkbkey = row->keys + k;
+ GkbdKeyboardDrawingKey *key;
+ XkbShapeRec *shape =
+ drawing->xkb->geom->shapes +
+ xkbkey->shape_ndx;
+ guint keycode = find_keycode (drawing,
+ xkbkey->name.
+ name);
+
+#ifdef KBDRAW_DEBUG
+ printf
+ (" initing key %d, shape: %p(%p + %d), code: %d\n",
+ k, shape, drawing->xkb->geom->shapes,
+ xkbkey->shape_ndx, keycode);
+#endif
+ if (row->vertical)
+ y += xkbkey->gap;
+ else
+ x += xkbkey->gap;
+
+ if (keycode >= drawing->xkb->min_key_code
+ && keycode <=
+ drawing->xkb->max_key_code)
+ key = drawing->keys + keycode;
+ else {
+ g_warning
+ ("key %4.4s: keycode = %u; not in range %d..%d\n",
+ xkbkey->name.name, keycode,
+ drawing->xkb->min_key_code,
+ drawing->xkb->max_key_code);
+
+ key =
+ g_new0 (GkbdKeyboardDrawingKey,
+ 1);
+ }
+
+ key->type =
+ GKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY;
+ key->xkbkey = xkbkey;
+ key->angle = section->angle;
+ rotate_coordinate (section->left,
+ section->top, x, y,
+ section->angle,
+ &key->origin_x,
+ &key->origin_y);
+ key->priority = priority;
+ key->keycode = keycode;
+
+ drawing->keyboard_items =
+ g_list_append (drawing->keyboard_items,
+ key);
+
+ if (row->vertical)
+ y += shape->bounds.y2;
+ else
+ x += shape->bounds.x2;
+
+ priority++;
+ }
+ }
+
+ for (j = 0; j < section->num_doodads; j++) {
+ XkbDoodadRec *xkbdoodad = section->doodads + j;
+ GkbdKeyboardDrawingDoodad *doodad =
+ g_new (GkbdKeyboardDrawingDoodad, 1);
+
+ doodad->type =
+ GKBD_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD;
+ doodad->origin_x = x;
+ doodad->origin_y = y;
+ doodad->angle = section->angle;
+ doodad->priority =
+ priority + xkbdoodad->any.priority;
+ doodad->doodad = xkbdoodad;
+
+ init_indicator_doodad (drawing, xkbdoodad, doodad);
+
+ drawing->keyboard_items =
+ g_list_append (drawing->keyboard_items,
+ doodad);
+ }
+ }
+
+ drawing->keyboard_items = g_list_sort (drawing->keyboard_items,
+ (GCompareFunc)
+ compare_keyboard_item_priorities);
+}
+
+static void
+init_colors (GkbdKeyboardDrawing * drawing)
+{
+ gboolean result;
+ gint i;
+
+ if (!drawing->xkb)
+ return;
+
+ drawing->colors = g_new (GdkColor, drawing->xkb->geom->num_colors);
+
+ for (i = 0; i < drawing->xkb->geom->num_colors; i++) {
+ result =
+ parse_xkb_color_spec (drawing->xkb->geom->colors[i].
+ spec, drawing->colors + i);
+
+ if (!result)
+ g_warning
+ ("init_colors: unable to parse color %s\n",
+ drawing->xkb->geom->colors[i].spec);
+ }
+}
+
+static void
+free_cdik ( /*colors doodads indicators keys */
+ GkbdKeyboardDrawing * drawing)
+{
+ GList *itemp;
+
+ if (!drawing->xkb)
+ return;
+
+ for (itemp = drawing->keyboard_items; itemp; itemp = itemp->next) {
+ GkbdKeyboardDrawingItem *item = itemp->data;
+ GkbdKeyboardDrawingKey *key;
+
+ switch (item->type) {
+ case GKBD_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD:
+ g_free (item);
+ break;
+
+ case GKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY:
+ key = (GkbdKeyboardDrawingKey *) item;
+ if (key->keycode < drawing->xkb->min_key_code ||
+ key->keycode > drawing->xkb->max_key_code)
+ g_free (key);
+ /* otherwise it's part of the array */
+ break;
+ }
+ }
+
+ g_list_free (drawing->keyboard_items);
+ drawing->keyboard_items = NULL;
+
+ g_free (drawing->keys);
+ g_free (drawing->colors);
+}
+
+static void
+alloc_cdik (GkbdKeyboardDrawing * drawing)
+{
+ drawing->physical_indicators_size =
+ drawing->xkb->indicators->phys_indicators + 1;
+ drawing->physical_indicators =
+ g_new0 (GkbdKeyboardDrawingDoodad *,
+ drawing->physical_indicators_size);
+ drawing->keys =
+ g_new0 (GkbdKeyboardDrawingKey,
+ drawing->xkb->max_key_code + 1);
+}
+
+static GdkFilterReturn
+xkb_state_notify_event_filter (GdkXEvent * gdkxev,
+ GdkEvent * event,
+ GkbdKeyboardDrawing * drawing)
+{
+#define group_change_mask (XkbGroupStateMask | XkbGroupBaseMask | XkbGroupLatchMask | XkbGroupLockMask)
+#define modifier_change_mask (XkbModifierStateMask | XkbModifierBaseMask | XkbModifierLatchMask | XkbModifierLockMask)
+
+ if (!drawing->xkb)
+ return GDK_FILTER_CONTINUE;
+
+ if (((XEvent *) gdkxev)->type == drawing->xkb_event_type) {
+ XkbEvent *kev = (XkbEvent *) gdkxev;
+ switch (kev->any.xkb_type) {
+ case XkbStateNotify:
+ if (((kev->state.changed & modifier_change_mask) &&
+ drawing->track_modifiers)) {
+ free_cdik (drawing);
+ if (drawing->track_modifiers)
+ gkbd_keyboard_drawing_set_mods
+ (drawing,
+ kev->state.compat_state);
+ drawing->keys =
+ g_new0 (GkbdKeyboardDrawingKey,
+ drawing->xkb->max_key_code +
+ 1);
+ size_allocate (GTK_WIDGET (drawing),
+ &(GTK_WIDGET (drawing)->
+ allocation), drawing);
+
+ init_keys_and_doodads (drawing);
+ init_colors (drawing);
+ }
+ break;
+
+ case XkbIndicatorStateNotify:
+ {
+ /* Good question: should we track indicators when the keyboard is
+ NOT really taken from the screen */
+ XkbIndicatorNotifyEvent *iev =
+ &((XkbEvent *) gdkxev)->indicators;
+ gint i;
+
+ for (i = 0;
+ i <=
+ drawing->xkb->indicators->
+ phys_indicators; i++)
+ if (drawing->
+ physical_indicators[i] != NULL
+ && (iev->changed & 1 << i)) {
+ gint state =
+ (iev->
+ state & 1 << i) !=
+ FALSE;
+
+ if ((state
+ && !drawing->
+ physical_indicators
+ [i]->on) || (!state
+ &&
+ drawing->
+ physical_indicators
+ [i]->
+ on)) {
+ drawing->
+ physical_indicators
+ [i]->on =
+ state;
+ draw_doodad
+ (drawing,
+ drawing->
+ physical_indicators
+ [i]);
+ invalidate_indicator_doodad_region
+ (drawing,
+ drawing->
+ physical_indicators
+ [i]);
+ }
+ }
+ }
+ break;
+
+ case XkbIndicatorMapNotify:
+ case XkbControlsNotify:
+ case XkbNamesNotify:
+ case XkbNewKeyboardNotify:
+ {
+ XkbStateRec state;
+ memset (&state, 0, sizeof (state));
+ XkbGetState (drawing->display,
+ XkbUseCoreKbd, &state);
+ if (drawing->track_modifiers)
+ gkbd_keyboard_drawing_set_mods
+ (drawing, state.compat_state);
+ if (drawing->track_config)
+ gkbd_keyboard_drawing_set_keyboard
+ (drawing, NULL);
+ }
+ break;
+ }
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+destroy (GkbdKeyboardDrawing * drawing)
+{
+ free_pango_layout (drawing);
+ gdk_window_remove_filter (NULL, (GdkFilterFunc)
+ xkb_state_notify_event_filter, drawing);
+ if (drawing->timeout > 0) {
+ g_source_remove (drawing->timeout);
+ drawing->timeout = 0;
+ }
+
+ g_object_unref (drawing->pixmap);
+}
+
+static void
+style_changed (GkbdKeyboardDrawing * drawing)
+{
+ pango_layout_context_changed (drawing->layout);
+}
+
+static void
+gkbd_keyboard_drawing_init (GkbdKeyboardDrawing * drawing)
+{
+ gint opcode = 0, error = 0, major = 1, minor = 0;
+ gint mask;
+
+ drawing->display =
+ GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ printf ("dpy: %p\n", drawing->display);
+
+ if (!XkbQueryExtension
+ (drawing->display, &opcode, &drawing->xkb_event_type, &error,
+ &major, &minor))
+ g_critical
+ ("XkbQueryExtension failed! Stuff probably won't work.");
+
+ printf ("evt/error/major/minor: %d/%d/%d/%d\n",
+ drawing->xkb_event_type, error, major, minor);
+
+ /* XXX: this stuff probably doesn't matter.. also, gdk_screen_get_default can fail */
+ if (gtk_widget_has_screen (GTK_WIDGET (drawing)))
+ drawing->screen_num =
+ gdk_screen_get_number (gtk_widget_get_screen
+ (GTK_WIDGET (drawing)));
+ else
+ drawing->screen_num =
+ gdk_screen_get_number (gdk_screen_get_default ());
+
+ drawing->pixmap = NULL;
+ alloc_pango_layout (drawing);
+
+ drawing->font_desc =
+ pango_font_description_copy (GTK_WIDGET (drawing)->style->
+ font_desc);
+ drawing->keyboard_items = NULL;
+ drawing->colors = NULL;
+ drawing->angle = 0;
+ drawing->scale_numerator = 1;
+ drawing->scale_denominator = 1;
+
+ drawing->track_modifiers = 0;
+ drawing->track_config = 0;
+
+ gtk_widget_set_double_buffered (GTK_WIDGET (drawing), FALSE);
+
+ /* XXX: XkbClientMapMask | XkbIndicatorMapMask | XkbNamesMask | XkbGeometryMask */
+ drawing->xkb = XkbGetKeyboard (drawing->display,
+ XkbGBN_GeometryMask |
+ XkbGBN_KeyNamesMask |
+ XkbGBN_OtherNamesMask |
+ XkbGBN_SymbolsMask |
+ XkbGBN_IndicatorMapMask,
+ XkbUseCoreKbd);
+ if (drawing->xkb == NULL) {
+ g_critical
+ ("XkbGetKeyboard failed to get keyboard from the server!");
+ return;
+ }
+
+ XkbGetNames (drawing->display, XkbAllNamesMask, drawing->xkb);
+
+ drawing->xkbOnDisplay = TRUE;
+
+ alloc_cdik (drawing);
+
+ XkbSelectEventDetails (drawing->display, XkbUseCoreKbd,
+ XkbIndicatorStateNotify,
+ drawing->xkb->indicators->phys_indicators,
+ drawing->xkb->indicators->phys_indicators);
+
+ mask =
+ (XkbStateNotifyMask | XkbNamesNotifyMask |
+ XkbControlsNotifyMask | XkbIndicatorMapNotifyMask |
+ XkbNewKeyboardNotifyMask);
+ XkbSelectEvents (drawing->display, XkbUseCoreKbd, mask, mask);
+
+ mask = XkbGroupStateMask | XkbModifierStateMask;
+ XkbSelectEventDetails (drawing->display, XkbUseCoreKbd,
+ XkbStateNotify, mask, mask);
+
+ mask = (XkbGroupNamesMask | XkbIndicatorNamesMask);
+ XkbSelectEventDetails (drawing->display, XkbUseCoreKbd,
+ XkbNamesNotify, mask, mask);
+ init_keys_and_doodads (drawing);
+ init_colors (drawing);
+
+ /* required to get key events */
+ GTK_WIDGET_SET_FLAGS (GTK_WIDGET (drawing), GTK_CAN_FOCUS);
+
+ gtk_widget_set_events (GTK_WIDGET (drawing),
+ GDK_EXPOSURE_MASK | GDK_KEY_PRESS_MASK |
+ GDK_KEY_RELEASE_MASK | GDK_BUTTON_PRESS_MASK
+ | GDK_FOCUS_CHANGE_MASK);
+ g_signal_connect (G_OBJECT (drawing), "expose-event",
+ G_CALLBACK (expose_event), drawing);
+ g_signal_connect (G_OBJECT (drawing), "key-press-event",
+ G_CALLBACK (key_event), drawing);
+ g_signal_connect (G_OBJECT (drawing), "key-release-event",
+ G_CALLBACK (key_event), drawing);
+ g_signal_connect (G_OBJECT (drawing), "button-press-event",
+ G_CALLBACK (button_press_event), drawing);
+ g_signal_connect (G_OBJECT (drawing), "focus-out-event",
+ G_CALLBACK (focus_event), drawing);
+ g_signal_connect (G_OBJECT (drawing), "focus-in-event",
+ G_CALLBACK (focus_event), drawing);
+ g_signal_connect (G_OBJECT (drawing), "size-allocate",
+ G_CALLBACK (size_allocate), drawing);
+ g_signal_connect (G_OBJECT (drawing), "destroy",
+ G_CALLBACK (destroy), drawing);
+ g_signal_connect (G_OBJECT (drawing), "style-set",
+ G_CALLBACK (style_changed), drawing);
+
+ gdk_window_add_filter (NULL, (GdkFilterFunc)
+ xkb_state_notify_event_filter, drawing);
+}
+
+GtkWidget *
+gkbd_keyboard_drawing_new (void)
+{
+ return
+ GTK_WIDGET (g_object_new
+ (gkbd_keyboard_drawing_get_type (), NULL));
+}
+
+static void
+gkbd_keyboard_drawing_class_init (GkbdKeyboardDrawingClass * klass)
+{
+ klass->bad_keycode = NULL;
+
+ gkbd_keyboard_drawing_signals[BAD_KEYCODE] =
+ g_signal_new ("bad-keycode", gkbd_keyboard_drawing_get_type (),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GkbdKeyboardDrawingClass,
+ bad_keycode), NULL, NULL,
+ gkbd_keyboard_drawing_VOID__UINT, G_TYPE_NONE, 1,
+ G_TYPE_UINT);
+}
+
+GType
+gkbd_keyboard_drawing_get_type (void)
+{
+ static GType gkbd_keyboard_drawing_type = 0;
+
+ if (!gkbd_keyboard_drawing_type) {
+ static const GTypeInfo gkbd_keyboard_drawing_info = {
+ sizeof (GkbdKeyboardDrawingClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) gkbd_keyboard_drawing_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GkbdKeyboardDrawing),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gkbd_keyboard_drawing_init,
+ };
+
+ gkbd_keyboard_drawing_type =
+ g_type_register_static (GTK_TYPE_DRAWING_AREA,
+ "GkbdKeyboardDrawing",
+ &gkbd_keyboard_drawing_info,
+ 0);
+ }
+
+ return gkbd_keyboard_drawing_type;
+}
+
+void
+gkbd_keyboard_drawing_set_mods (GkbdKeyboardDrawing * drawing, guint mods)
+{
+#ifdef KBDRAW_DEBUG
+ printf ("set_mods: %d\n", mods);
+#endif
+ if (mods != drawing->mods) {
+ drawing->mods = mods;
+ gtk_widget_queue_draw (GTK_WIDGET (drawing));
+ }
+}
+
+/* returns a pixbuf with the keyboard drawing at the current pixel size
+ * (which can then be saved to disk, etc) */
+GdkPixbuf *
+gkbd_keyboard_drawing_get_pixbuf (GkbdKeyboardDrawing * drawing)
+{
+ if (drawing->pixmap == NULL)
+ draw_keyboard (drawing);
+
+ return gdk_pixbuf_get_from_drawable (NULL, drawing->pixmap, NULL,
+ 0, 0, 0, 0,
+ xkb_to_pixmap_coord (drawing,
+ drawing->
+ xkb->
+ geom->
+ width_mm),
+ xkb_to_pixmap_coord (drawing,
+ drawing->
+ xkb->
+ geom->
+ height_mm));
+}
+
+gboolean
+gkbd_keyboard_drawing_set_keyboard (GkbdKeyboardDrawing * drawing,
+ XkbComponentNamesRec * names)
+{
+ free_cdik (drawing);
+ if (drawing->xkb)
+ XkbFreeKeyboard (drawing->xkb, 0, TRUE); /* free_all = TRUE */
+ drawing->xkb = NULL;
+
+ if (names) {
+ drawing->xkb =
+ XkbGetKeyboardByName (drawing->display, XkbUseCoreKbd,
+ names, 0,
+ XkbGBN_GeometryMask |
+ XkbGBN_KeyNamesMask |
+ XkbGBN_OtherNamesMask |
+ XkbGBN_ClientSymbolsMask |
+ XkbGBN_IndicatorMapMask, FALSE);
+ drawing->xkbOnDisplay = FALSE;
+ } else {
+ drawing->xkb = XkbGetKeyboard (drawing->display,
+ XkbGBN_GeometryMask |
+ XkbGBN_KeyNamesMask |
+ XkbGBN_OtherNamesMask |
+ XkbGBN_SymbolsMask |
+ XkbGBN_IndicatorMapMask,
+ XkbUseCoreKbd);
+ XkbGetNames (drawing->display, XkbAllNamesMask,
+ drawing->xkb);
+ drawing->xkbOnDisplay = TRUE;
+ }
+
+ if (drawing->xkb == NULL)
+ return FALSE;
+
+ alloc_cdik (drawing);
+
+ init_keys_and_doodads (drawing);
+ init_colors (drawing);
+
+ size_allocate (GTK_WIDGET (drawing),
+ &(GTK_WIDGET (drawing)->allocation), drawing);
+ gtk_widget_queue_draw (GTK_WIDGET (drawing));
+
+ return TRUE;
+}
+
+G_CONST_RETURN gchar *
+gkbd_keyboard_drawing_get_keycodes (GkbdKeyboardDrawing * drawing)
+{
+ if (!drawing->xkb || drawing->xkb->names->keycodes <= 0)
+ return NULL;
+ else
+ return XGetAtomName (drawing->display,
+ drawing->xkb->names->keycodes);
+}
+
+G_CONST_RETURN gchar *
+gkbd_keyboard_drawing_get_geometry (GkbdKeyboardDrawing * drawing)
+{
+ if (!drawing->xkb || drawing->xkb->names->geometry <= 0)
+ return NULL;
+ else
+ return XGetAtomName (drawing->display,
+ drawing->xkb->names->geometry);
+}
+
+G_CONST_RETURN gchar *
+gkbd_keyboard_drawing_get_symbols (GkbdKeyboardDrawing * drawing)
+{
+ if (!drawing->xkb || drawing->xkb->names->symbols <= 0)
+ return NULL;
+ else
+ return XGetAtomName (drawing->display,
+ drawing->xkb->names->symbols);
+}
+
+G_CONST_RETURN gchar *
+gkbd_keyboard_drawing_get_types (GkbdKeyboardDrawing * drawing)
+{
+ if (!drawing->xkb || drawing->xkb->names->types <= 0)
+ return NULL;
+ else
+ return XGetAtomName (drawing->display,
+ drawing->xkb->names->types);
+}
+
+G_CONST_RETURN gchar *
+gkbd_keyboard_drawing_get_compat (GkbdKeyboardDrawing * drawing)
+{
+ if (!drawing->xkb || drawing->xkb->names->compat <= 0)
+ return NULL;
+ else
+ return XGetAtomName (drawing->display,
+ drawing->xkb->names->compat);
+}
+
+void
+gkbd_keyboard_drawing_set_track_modifiers (GkbdKeyboardDrawing * drawing,
+ gboolean enable)
+{
+ if (enable) {
+ XkbStateRec state;
+ drawing->track_modifiers = 1;
+ memset (&state, 0, sizeof (state));
+ XkbGetState (drawing->display, XkbUseCoreKbd, &state);
+ gkbd_keyboard_drawing_set_mods (drawing,
+ state.compat_state);
+ } else
+ drawing->track_modifiers = 0;
+}
+
+void
+gkbd_keyboard_drawing_set_track_config (GkbdKeyboardDrawing * drawing,
+ gboolean enable)
+{
+ if (enable)
+ drawing->track_config = 1;
+ else
+ drawing->track_config = 0;
+}
+
+void
+gkbd_keyboard_drawing_set_groups_levels (GkbdKeyboardDrawing * drawing,
+ GkbdKeyboardDrawingGroupLevel *
+ groupLevels[])
+{
+#ifdef KBDRAW_DEBUG
+ printf ("set_group_levels [topLeft]: %d %d \n",
+ groupLevels[GKBD_KEYBOARD_DRAWING_POS_TOPLEFT]->group,
+ groupLevels[GKBD_KEYBOARD_DRAWING_POS_TOPLEFT]->level);
+ printf ("set_group_levels [topRight]: %d %d \n",
+ groupLevels[GKBD_KEYBOARD_DRAWING_POS_TOPRIGHT]->group,
+ groupLevels[GKBD_KEYBOARD_DRAWING_POS_TOPRIGHT]->level);
+ printf ("set_group_levels [bottomLeft]: %d %d \n",
+ groupLevels[GKBD_KEYBOARD_DRAWING_POS_BOTTOMLEFT]->group,
+ groupLevels[GKBD_KEYBOARD_DRAWING_POS_BOTTOMLEFT]->level);
+ printf ("set_group_levels [bottomRight]: %d %d \n",
+ groupLevels[GKBD_KEYBOARD_DRAWING_POS_BOTTOMRIGHT]->group,
+ groupLevels[GKBD_KEYBOARD_DRAWING_POS_BOTTOMRIGHT]->level);
+#endif
+ drawing->groupLevels = groupLevels;
+
+ gtk_widget_queue_draw (GTK_WIDGET (drawing));
+}
diff --git a/libgnomekbd/gkbd-keyboard-drawing.h b/libgnomekbd/gkbd-keyboard-drawing.h
new file mode 100644
index 0000000..c13c43d
--- /dev/null
+++ b/libgnomekbd/gkbd-keyboard-drawing.h
@@ -0,0 +1,189 @@
+/* $Id$ */
+/*
+ * keyboard-drawing.h: header file for a gtk+ widget that is a drawing of
+ * the keyboard of the default display
+ *
+ * Copyright (c) 2003 Noah Levitt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef GKBD_KEYBOARD_DRAWING_H
+#define GKBD_KEYBOARD_DRAWING_H 1
+
+#include <gtk/gtk.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBgeom.h>
+
+G_BEGIN_DECLS
+#define GKBD_KEYBOARD_DRAWING(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), gkbd_keyboard_drawing_get_type (), \
+ GkbdKeyboardDrawing))
+#define GKBD_KEYBOARD_DRAWING_CLASS(clazz) (G_TYPE_CHECK_CLASS_CAST ((clazz), gkbd_keyboard_drawing_get_type () \
+ GkbdKeyboardDrawingClass))
+#define GKBD_IS_KEYBOARD_DRAWING(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), gkbd_keyboard_drawing_get_type ())
+typedef struct _GkbdKeyboardDrawing GkbdKeyboardDrawing;
+typedef struct _GkbdKeyboardDrawingClass GkbdKeyboardDrawingClass;
+
+typedef struct _GkbdKeyboardDrawingItem GkbdKeyboardDrawingItem;
+typedef struct _GkbdKeyboardDrawingKey GkbdKeyboardDrawingKey;
+typedef struct _GkbdKeyboardDrawingDoodad GkbdKeyboardDrawingDoodad;
+typedef struct _GkbdKeyboardDrawingGroupLevel
+ GkbdKeyboardDrawingGroupLevel;
+
+typedef enum {
+ GKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY,
+ GKBD_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD
+} GkbdKeyboardDrawingItemType;
+
+typedef enum {
+ GKBD_KEYBOARD_DRAWING_POS_TOPLEFT,
+ GKBD_KEYBOARD_DRAWING_POS_TOPRIGHT,
+ GKBD_KEYBOARD_DRAWING_POS_BOTTOMLEFT,
+ GKBD_KEYBOARD_DRAWING_POS_BOTTOMRIGHT,
+ GKBD_KEYBOARD_DRAWING_POS_TOTAL,
+ GKBD_KEYBOARD_DRAWING_POS_FIRST =
+ GKBD_KEYBOARD_DRAWING_POS_TOPLEFT,
+ GKBD_KEYBOARD_DRAWING_POS_LAST =
+ GKBD_KEYBOARD_DRAWING_POS_BOTTOMRIGHT,
+} GkbdKeyboardDrawingGroupLevelPosition;
+
+/* units are in xkb form */
+struct _GkbdKeyboardDrawingItem {
+ /*< private > */
+
+ GkbdKeyboardDrawingItemType type;
+ gint origin_x;
+ gint origin_y;
+ gint angle;
+ guint priority;
+};
+
+/* units are in xkb form */
+struct _GkbdKeyboardDrawingKey {
+ /*< private > */
+
+ GkbdKeyboardDrawingItemType type;
+ gint origin_x;
+ gint origin_y;
+ gint angle;
+ guint priority;
+
+ XkbKeyRec *xkbkey;
+ gboolean pressed;
+ guint keycode;
+};
+
+/* units are in xkb form */
+struct _GkbdKeyboardDrawingDoodad {
+ /*< private > */
+
+ GkbdKeyboardDrawingItemType type;
+ gint origin_x;
+ gint origin_y;
+ gint angle;
+ guint priority;
+
+ XkbDoodadRec *doodad;
+ gboolean on; /* for indicator doodads */
+};
+
+struct _GkbdKeyboardDrawingGroupLevel {
+ gint group;
+ gint level;
+};
+
+struct _GkbdKeyboardDrawing {
+ /*< private > */
+
+ GtkDrawingArea parent;
+
+ GdkPixmap *pixmap;
+ XkbDescRec *xkb;
+ gboolean xkbOnDisplay;
+
+ gint angle; /* current angle pango is set to draw at, in tenths of a degree */
+ PangoLayout *layout;
+ PangoFontDescription *font_desc;
+
+ gint scale_numerator;
+ gint scale_denominator;
+
+ GkbdKeyboardDrawingKey *keys;
+
+ /* list of stuff to draw in priority order */
+ GList *keyboard_items;
+
+ GdkColor *colors;
+
+ guint timeout;
+
+ GkbdKeyboardDrawingGroupLevel **groupLevels;
+
+ guint mods;
+
+ Display *display;
+ gint screen_num;
+
+ gint xkb_event_type;
+
+ GkbdKeyboardDrawingDoodad **physical_indicators;
+ gint physical_indicators_size;
+
+ guint track_config:1;
+ guint track_modifiers:1;
+};
+
+struct _GkbdKeyboardDrawingClass {
+ GtkDrawingAreaClass parent_class;
+
+ /* we send this signal when the user presses a key that "doesn't exist"
+ * according to the keyboard geometry; it probably means their xkb
+ * configuration is incorrect */
+ void (*bad_keycode) (GkbdKeyboardDrawing * drawing, guint keycode);
+};
+
+GType gkbd_keyboard_drawing_get_type (void);
+GtkWidget *gkbd_keyboard_drawing_new (void);
+
+GdkPixbuf *gkbd_keyboard_drawing_get_pixbuf (GkbdKeyboardDrawing *
+ kbdrawing);
+gboolean gkbd_keyboard_drawing_set_keyboard (GkbdKeyboardDrawing *
+ kbdrawing,
+ XkbComponentNamesRec * names);
+
+G_CONST_RETURN gchar
+ * gkbd_keyboard_drawing_get_keycodes (GkbdKeyboardDrawing * kbdrawing);
+G_CONST_RETURN gchar
+ * gkbd_keyboard_drawing_get_geometry (GkbdKeyboardDrawing * kbdrawing);
+G_CONST_RETURN gchar
+ * gkbd_keyboard_drawing_get_symbols (GkbdKeyboardDrawing * kbdrawing);
+G_CONST_RETURN gchar *gkbd_keyboard_drawing_get_types (GkbdKeyboardDrawing
+ * kbdrawing);
+G_CONST_RETURN gchar *gkbd_keyboard_drawing_get_compat (GkbdKeyboardDrawing
+ * kbdrawing);
+
+void gkbd_keyboard_drawing_set_track_modifiers (GkbdKeyboardDrawing *
+ kbdrawing,
+ gboolean enable);
+void gkbd_keyboard_drawing_set_track_config (GkbdKeyboardDrawing *
+ kbdrawing, gboolean enable);
+
+void gkbd_keyboard_drawing_set_groups_levels (GkbdKeyboardDrawing *
+ kbdrawing,
+ GkbdKeyboardDrawingGroupLevel
+ * groupLevels[]);
+
+G_END_DECLS
+#endif /* #ifndef GKBD_KEYBOARD_DRAWING_H */
diff --git a/libgnomekbd/gkbd-util.c b/libgnomekbd/gkbd-util.c
new file mode 100644
index 0000000..dbc164b
--- /dev/null
+++ b/libgnomekbd/gkbd-util.c
@@ -0,0 +1,148 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <gkbd-util.h>
+
+#include <time.h>
+
+#include <glib/gi18n.h>
+
+#include <libxklavier/xklavier.h>
+
+#include <gconf/gconf-client.h>
+
+#include <gkbd-config-private.h>
+
+static void
+gkbd_log_appender (const char file[], const char function[],
+ int level, const char format[], va_list args)
+{
+ time_t now = time (NULL);
+ g_log (NULL, G_LOG_LEVEL_DEBUG, "[%08ld,%03d,%s:%s/] \t",
+ (long) now, level, file, function);
+ g_logv (NULL, G_LOG_LEVEL_DEBUG, format, args);
+}
+
+void
+gkbd_install_glib_log_appender (void)
+{
+ xkl_set_log_appender (gkbd_log_appender);
+}
+
+#define GKBD_PREVIEW_CONFIG_KEY_PREFIX GKBD_CONFIG_KEY_PREFIX "/preview"
+
+const gchar GKBD_PREVIEW_CONFIG_DIR[] = GKBD_PREVIEW_CONFIG_KEY_PREFIX;
+const gchar GKBD_PREVIEW_CONFIG_KEY_X[] =
+ GKBD_PREVIEW_CONFIG_KEY_PREFIX "/x";
+const gchar GKBD_PREVIEW_CONFIG_KEY_Y[] =
+ GKBD_PREVIEW_CONFIG_KEY_PREFIX "/y";
+const gchar GKBD_PREVIEW_CONFIG_KEY_WIDTH[] =
+ GKBD_PREVIEW_CONFIG_KEY_PREFIX "/width";
+const gchar GKBD_PREVIEW_CONFIG_KEY_HEIGHT[] =
+ GKBD_PREVIEW_CONFIG_KEY_PREFIX "/height";
+
+GdkRectangle *
+gkbd_preview_load_position (void)
+{
+ GError *gerror = NULL;
+ GdkRectangle *rv = NULL;
+ gint x, y, w, h;
+ GConfClient *conf_client = gconf_client_get_default ();
+
+ if (conf_client == NULL)
+ return NULL;
+
+ x = gconf_client_get_int (conf_client,
+ GKBD_PREVIEW_CONFIG_KEY_X, &gerror);
+ if (gerror != NULL) {
+ xkl_debug (0, "Error getting the preview x: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ g_object_unref (G_OBJECT (conf_client));
+ return NULL;
+ }
+
+ y = gconf_client_get_int (conf_client,
+ GKBD_PREVIEW_CONFIG_KEY_Y, &gerror);
+ if (gerror != NULL) {
+ xkl_debug (0, "Error getting the preview y: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ g_object_unref (G_OBJECT (conf_client));
+ return NULL;
+ }
+
+ w = gconf_client_get_int (conf_client,
+ GKBD_PREVIEW_CONFIG_KEY_WIDTH, &gerror);
+ if (gerror != NULL) {
+ xkl_debug (0, "Error getting the preview width: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ g_object_unref (G_OBJECT (conf_client));
+ return NULL;
+ }
+
+ h = gconf_client_get_int (conf_client,
+ GKBD_PREVIEW_CONFIG_KEY_HEIGHT, &gerror);
+ if (gerror != NULL) {
+ xkl_debug (0, "Error getting the preview height: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ g_object_unref (G_OBJECT (conf_client));
+ return NULL;
+ }
+
+ g_object_unref (G_OBJECT (conf_client));
+
+ // default values should be just ignored
+ if (x == -1 || y == -1 || w == -1 || h == -1)
+ return NULL;
+
+ rv = g_new (GdkRectangle, 1);
+ rv->x = x;
+ rv->y = y;
+ rv->width = w;
+ rv->height = h;
+ return rv;
+}
+
+void
+gkbd_preview_save_position (GdkRectangle * rect)
+{
+ GConfClient *conf_client = gconf_client_get_default ();
+ GConfChangeSet *cs;
+ GError *gerror = NULL;
+
+ cs = gconf_change_set_new ();
+
+ gconf_change_set_set_int (cs, GKBD_PREVIEW_CONFIG_KEY_X, rect->x);
+ gconf_change_set_set_int (cs, GKBD_PREVIEW_CONFIG_KEY_Y, rect->y);
+ gconf_change_set_set_int (cs, GKBD_PREVIEW_CONFIG_KEY_WIDTH,
+ rect->width);
+ gconf_change_set_set_int (cs, GKBD_PREVIEW_CONFIG_KEY_HEIGHT,
+ rect->height);
+
+ gconf_client_commit_change_set (conf_client, cs, TRUE, &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error saving preview configuration: %s\n",
+ gerror->message);
+ g_error_free (gerror);
+ }
+ gconf_change_set_unref (cs);
+ g_object_unref (G_OBJECT (conf_client));
+}
diff --git a/libgnomekbd/gkbd-util.h b/libgnomekbd/gkbd-util.h
new file mode 100644
index 0000000..3aca8c9
--- /dev/null
+++ b/libgnomekbd/gkbd-util.h
@@ -0,0 +1,30 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GKBD_UTIL_H__
+#define __GKBD_UTIL_H__
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+extern void gkbd_install_glib_log_appender (void);
+
+extern GdkRectangle *gkbd_preview_load_position (void);
+
+extern void gkbd_preview_save_position (GdkRectangle * rect);
+
+
+#endif
diff --git a/libgnomekbdui.pc.in b/libgnomekbdui.pc.in
new file mode 100644
index 0000000..53133c9
--- /dev/null
+++ b/libgnomekbdui.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libgnomekbd
+Description: GNOME keyboard shared library
+Version: @VERSION@
+Libs: -L${libdir} -lgnomekbd -lgnomekbdui
+Cflags: -I${includedir}
diff --git a/po/ChangeLog b/po/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/po/ChangeLog
diff --git a/po/Makefile.in.in b/po/Makefile.in.in
new file mode 100644
index 0000000..d2d4e4c
--- /dev/null
+++ b/po/Makefile.in.in
@@ -0,0 +1,221 @@
+# Makefile for program source directory in GNU NLS utilities package.
+# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper <drepper@gnu.ai.mit.edu>
+#
+# This file file be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+#
+# - Modified by Owen Taylor <otaylor@redhat.com> to use GETTEXT_PACKAGE
+# instead of PACKAGE and to look for po2tbl in ./ not in intl/
+#
+# - Modified by jacob berkman <jacob@ximian.com> to install
+# Makefile.in.in and po2tbl.sed.in for use with glib-gettextize
+#
+# - Modified by Rodney Dawes <dobey@novell.com> for use with intltool
+#
+# We have the following line for use by intltoolize:
+# INTLTOOL_MAKEFILE
+
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ..
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datadir = @datadir@
+datarootdir = @datarootdir@
+libdir = @libdir@
+DATADIRNAME = @DATADIRNAME@
+itlocaledir = $(prefix)/$(DATADIRNAME)/locale
+subdir = po
+install_sh = @install_sh@
+# Automake >= 1.8 provides @mkdir_p@.
+# Until it can be supposed, use the safe fallback:
+mkdir_p = $(install_sh) -d
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+
+GMSGFMT = @GMSGFMT@
+MSGFMT = @MSGFMT@
+XGETTEXT = @XGETTEXT@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+MSGMERGE = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --dist
+GENPOT = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --pot
+
+ALL_LINGUAS = @ALL_LINGUAS@
+
+PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; fi)
+
+POFILES=$(shell if test -n "$(PO_LINGUAS)"; then LINGUAS="$(PO_LINGUAS)"; else LINGUAS="$(ALL_LINGUAS)"; fi; for lang in $$LINGUAS; do printf "$$lang.po "; done)
+
+DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(POFILES)
+EXTRA_DISTFILES = POTFILES.skip Makevars LINGUAS
+
+POTFILES = \
+#This Gets Replace for some reason
+
+CATALOGS=$(shell if test -n "$(PO_LINGUAS)"; then LINGUAS="$(PO_LINGUAS)"; else LINGUAS="$(ALL_LINGUAS)"; fi; for lang in $$LINGUAS; do printf "$$lang.gmo "; done)
+
+.SUFFIXES:
+.SUFFIXES: .po .pox .gmo .mo .msg .cat
+
+.po.pox:
+ $(MAKE) $(GETTEXT_PACKAGE).pot
+ $(MSGMERGE) $< $(GETTEXT_PACKAGE).pot -o $*.pox
+
+.po.mo:
+ $(MSGFMT) -o $@ $<
+
+.po.gmo:
+ file=`echo $* | sed 's,.*/,,'`.gmo \
+ && rm -f $$file && $(GMSGFMT) -o $$file $<
+
+.po.cat:
+ sed -f ../intl/po2msg.sed < $< > $*.msg \
+ && rm -f $@ && gencat $@ $*.msg
+
+
+all: all-@USE_NLS@
+
+all-yes: $(CATALOGS)
+all-no:
+
+$(GETTEXT_PACKAGE).pot: $(POTFILES)
+ $(GENPOT)
+
+install: install-data
+install-data: install-data-@USE_NLS@
+install-data-no: all
+install-data-yes: all
+ $(mkdir_p) $(DESTDIR)$(itlocaledir)
+ if test -n "$(PO_LINGUAS)"; then \
+ linguas="$(PO_LINGUAS)"; \
+ else \
+ linguas="$(ALL_LINGUAS)"; \
+ fi; \
+ for lang in $$linguas; do \
+ dir=$(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES; \
+ $(mkdir_p) $$dir; \
+ if test -r $$lang.gmo; then \
+ $(INSTALL_DATA) $$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \
+ echo "installing $$lang.gmo as $$dir/$(GETTEXT_PACKAGE).mo"; \
+ else \
+ $(INSTALL_DATA) $(srcdir)/$$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \
+ echo "installing $(srcdir)/$$lang.gmo as" \
+ "$$dir/$(GETTEXT_PACKAGE).mo"; \
+ fi; \
+ if test -r $$lang.gmo.m; then \
+ $(INSTALL_DATA) $$lang.gmo.m $$dir/$(GETTEXT_PACKAGE).mo.m; \
+ echo "installing $$lang.gmo.m as $$dir/$(GETTEXT_PACKAGE).mo.m"; \
+ else \
+ if test -r $(srcdir)/$$lang.gmo.m ; then \
+ $(INSTALL_DATA) $(srcdir)/$$lang.gmo.m \
+ $$dir/$(GETTEXT_PACKAGE).mo.m; \
+ echo "installing $(srcdir)/$$lang.gmo.m as" \
+ "$$dir/$(GETTEXT_PACKAGE).mo.m"; \
+ else \
+ true; \
+ fi; \
+ fi; \
+ done
+
+# Empty stubs to satisfy archaic automake needs
+dvi info tags TAGS ID:
+
+# Define this as empty until I found a useful application.
+installcheck:
+
+uninstall:
+ if test -n "$(PO_LINGUAS)"; then \
+ linguas="$(PO_LINGUAS)"; \
+ else \
+ linguas="$(ALL_LINGUAS)"; \
+ fi; \
+ for lang in $$linguas; do \
+ rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \
+ rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo.m; \
+ done
+
+check: all $(GETTEXT_PACKAGE).pot
+
+mostlyclean:
+ rm -f *.pox $(GETTEXT_PACKAGE).pot *.old.po cat-id-tbl.tmp
+ rm -f .intltool-merge-cache
+
+clean: mostlyclean
+
+distclean: clean
+ rm -f Makefile Makefile.in POTFILES stamp-it
+ rm -f *.mo *.msg *.cat *.cat.m *.gmo
+
+maintainer-clean: distclean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+ rm -f Makefile.in.in
+
+distdir = ../$(PACKAGE)-$(VERSION)/$(subdir)
+dist distdir: $(DISTFILES)
+ dists="$(DISTFILES)"; \
+ extra_dists="$(EXTRA_DISTFILES)"; \
+ for file in $$extra_dists; do \
+ test -f $(srcdir)/$$file && dists="$$dists $(srcdir)/$$file"; \
+ done; \
+ for file in $$dists; do \
+ test -f $$file || file="$(srcdir)/$$file"; \
+ ln $$file $(distdir) 2> /dev/null \
+ || cp -p $$file $(distdir); \
+ done
+
+update-po: Makefile
+ $(MAKE) $(GETTEXT_PACKAGE).pot
+ tmpdir=`pwd`; \
+ if test -n "$(PO_LINGUAS)"; then \
+ linguas="$(PO_LINGUAS)"; \
+ else \
+ linguas="$(ALL_LINGUAS)"; \
+ fi; \
+ for lang in $$linguas; do \
+ echo "$$lang:"; \
+ result="`$(MSGMERGE) -o $$tmpdir/$$lang.new.po $$lang`"; \
+ if $$result; then \
+ if cmp $(srcdir)/$$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
+ rm -f $$tmpdir/$$lang.new.po; \
+ else \
+ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
+ :; \
+ else \
+ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
+ rm -f $$tmpdir/$$lang.new.po; \
+ exit 1; \
+ fi; \
+ fi; \
+ else \
+ echo "msgmerge for $$lang.gmo failed!"; \
+ rm -f $$tmpdir/$$lang.new.po; \
+ fi; \
+ done
+
+Makefile POTFILES: stamp-it
+ @if test ! -f $@; then \
+ rm -f stamp-it; \
+ $(MAKE) stamp-it; \
+ fi
+
+stamp-it: Makefile.in.in ../config.status POTFILES.in
+ cd .. \
+ && CONFIG_FILES=$(subdir)/Makefile.in CONFIG_HEADERS= CONFIG_LINKS= \
+ $(SHELL) ./config.status
+
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644
index 0000000..fae08c7
--- /dev/null
+++ b/po/POTFILES.in
@@ -0,0 +1,12 @@
+libgnomekbd/gkbd-keyboard-drawing.c
+libgnomekbd/gkbd-indicator.c
+libgnomekbd/gkbd-util.c
+libgnomekbd/gkbd-config-registry.c
+libgnomekbd/gkbd-indicator-plugin-manager.c
+libgnomekbd/gkbd-indicator-config.c
+libgnomekbd/gkbd-keyboard-config.c
+libgnomekbd/gkbd-desktop-config.c
+libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in
+capplet/gkbd-indicator-plugins-capplet.c
+capplet/gkbd-indicator-plugins-capplet.desktop.in.in
+capplet/gkbd-indicator-plugins-add.c
diff --git a/po/ru.po b/po/ru.po
new file mode 100644
index 0000000..f22a3ab
--- /dev/null
+++ b/po/ru.po
@@ -0,0 +1,169 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-09-24 17:15+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Sergey Udaltsov <svu@gnome.org>\n"
+"Language-Team: <gnome-cyr@gnome.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
+"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: ../libgnomekbd/gkbd-indicator.c:585
+msgid "XKB initialization error"
+msgstr "Ошибка инициализации XKB"
+
+#: ../libgnomekbd/gkbd-indicator-config.c:160
+#, c-format
+msgid "There was an error loading an image: %s"
+msgstr "Ошибка загрузки изображения: %s"
+
+#: ../libgnomekbd/gkbd-keyboard-config.c:790
+#, c-format
+msgid "layout \"%s\""
+msgid_plural "layouts \"%s\""
+msgstr[0] "раскладка \"%s\""
+msgstr[1] "раскладки \"%s\""
+
+#: ../libgnomekbd/gkbd-keyboard-config.c:809
+#, c-format
+msgid "option \"%s\""
+msgid_plural "options \"%s\""
+msgstr[0] "опция \"%s\""
+msgstr[1] "опции \"%s\""
+
+#: ../libgnomekbd/gkbd-keyboard-config.c:817
+#, c-format
+msgid "model \"%s\", %s and %s"
+msgstr "модель \"%s\", %s и %s"
+
+#: ../libgnomekbd/gkbd-keyboard-config.c:818
+msgid "no layout"
+msgstr "нет раскладки"
+
+#: ../libgnomekbd/gkbd-keyboard-config.c:819
+msgid "no options"
+msgstr "нет опций"
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:1
+msgid ""
+"A collection of scripts to run whenever the keyboard state is reloaded. "
+"Useful for re-applying xmodmap based adjustments"
+msgstr ""
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:2
+msgid "A list of modmap files available in the $HOME directory."
+msgstr ""
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:3
+msgid "Default group, assigned on window creation"
+msgstr "Группа по умолчанию, присваеваемая при создании окна"
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:4
+msgid "Keep and manage separate group per window"
+msgstr "Сохранять и подддерживать разные группы, пооконно"
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:5
+msgid "Keyboard Update Handlers"
+msgstr "Обработчики обновления клавиатуры"
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:6
+msgid "Keyboard layout"
+msgstr "Раскладка клавиатуры"
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:7
+msgid "Keyboard model"
+msgstr "Модель клавиатуры"
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:8
+msgid "Keyboard options"
+msgstr "Доп. параметры клавиатуры"
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:9
+msgid ""
+"Keyboard settings in gconf will be overridden from the system ASAP "
+"(deprecated)"
+msgstr "Клавиатурные установки в gconf будут немедленно заменены системными (устарело)"
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:10
+msgid "Save/restore indicators together with layout groups"
+msgstr "Сохранять/восстанавливать индикаторы вместе с группами"
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:11
+msgid "Show layout names instead of group names"
+msgstr "Показывать названия раскладок вместо названий групп"
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:12
+msgid ""
+"Show layout names instead of group names (only for versions of XFree "
+"supporting multiple layouts)"
+msgstr ""
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:13
+msgid "Suppress the \"X sysconfig changed\" warning message"
+msgstr ""
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:14
+msgid "The Keyboard Preview, X offset"
+msgstr ""
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:15
+msgid "The Keyboard Preview, Y offset"
+msgstr ""
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:16
+msgid "The Keyboard Preview, height"
+msgstr ""
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:17
+msgid "The Keyboard Preview, width"
+msgstr ""
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:18
+msgid ""
+"Very soon, keyboard settings in gconf will be overridden (from the system "
+"configuration) This key has been deprecated since GNOME 2.12, please unset "
+"the model, layouts and options keys to get the default system configuration."
+msgstr ""
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:19
+msgid "keyboard layout"
+msgstr "клавиатурная раскладка"
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:20
+msgid "keyboard model"
+msgstr "клавиатурная модель"
+
+#: ../libgnomekbd/desktop_gnome_peripherals_keyboard_xkb.schemas.in.h:21
+msgid "modmap file list"
+msgstr "список modmap файлов"
+
+#: ../capplet/gkbd-indicator-plugins-capplet.c:114
+#: ../capplet/gkbd-indicator-plugins-add.c:103
+msgid "No description."
+msgstr "Нет описания."
+
+#: ../capplet/gkbd-indicator-plugins-capplet.c:323
+#, c-format
+msgid "Failed to init GConf: %s\n"
+msgstr "Ошибка инициализации GConf: %s\n"
+
+#: ../capplet/gkbd-indicator-plugins-capplet.desktop.in.in.h:1
+msgid "Enable/disable installed plugins"
+msgstr "Включить/выключить установленные модули"
+
+#: ../capplet/gkbd-indicator-plugins-capplet.desktop.in.in.h:2
+msgid "Keyboard Indicator plugins"
+msgstr "Модули расширения клавиатурного индикатора"
+
+#~ msgid "There was an error displaying help: %s"
+#~ msgstr "Ошибка отображения справки: %s"
diff --git a/test/.indent.pro b/test/.indent.pro
new file mode 100644
index 0000000..bdff074
--- /dev/null
+++ b/test/.indent.pro
@@ -0,0 +1,2 @@
+-kr -i8 -pcs -lps -psl
+
diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644
index 0000000..1eabbe8
--- /dev/null
+++ b/test/Makefile.am
@@ -0,0 +1,45 @@
+noinst_PROGRAMS = gkbd-indicator-test \
+ gkbd-keyboard-drawing-test \
+ gkbd-config-registry-server
+
+gkbd_config_registry_server_CFLAGS= \
+ $(WARN_CFLAGS) -I$(top_srcdir) -Wall -Werror \
+ $(DBUS_CFLAGS) \
+ $(LIBXKLAVIER_CFLAGS)
+
+gkbd_config_registry_server_LDFLAGS= \
+ $(DBUS_LIBS) \
+ $(LIBXKLAVIER_LIBS) \
+ $(top_builddir)/libgnomekbd/libgnomekbd.la
+
+gkbd_indicator_test_CFLAGS= \
+ $(WARN_CFLAGS) -I$(top_srcdir) -Wall -Werror \
+ $(GTK_CFLAGS) \
+ $(LIBGLADE_CFLAGS) \
+ $(LIBGNOME_CFLAGS) \
+ $(LIBGNOMEUI_CFLAGS) \
+ $(LIBXKLAVIER_CFLAGS) \
+ -I$(top_srcdir)/intl \
+ -DSYS_PLUGIN_DIR=\"$(libdir)/gnomekbd/\" \
+ -DG_LOG_DOMAIN=\"GnomeKbdIndicatorTest\" \
+ -DDATADIR=\"$(datadir)\"
+
+gkbd_indicator_test_LDFLAGS= \
+ $(GTK_LIBS) \
+ $(LIBGLADE_LIBS) \
+ $(LIBGNOME_LIBS) \
+ $(LIBGNOMEUI_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)
+
+gkbd_keyboard_drawing_test_LDFLAGS= \
+ $(GTK_LIBS) \
+ $(LIBGNOME_LIBS) \
+ $(LIBXKLAVIER_LIBS) \
+ $(top_builddir)/libgnomekbd/libgnomekbd.la \
+ $(top_builddir)/libgnomekbd/libgnomekbdui.la
diff --git a/test/gkbd-config-registry-server.c b/test/gkbd-config-registry-server.c
new file mode 100644
index 0000000..8c43dbd
--- /dev/null
+++ b/test/gkbd-config-registry-server.c
@@ -0,0 +1,38 @@
+#include <config.h>
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <libxklavier/xklavier.h>
+#include <dbus/dbus-glib-bindings.h>
+
+#ifdef HAVE_SETLOCALE
+# include <locale.h>
+#endif
+
+#include "libgnomekbd/gkbd-config-registry.h"
+
+static GMainLoop *loop;
+
+int
+main ()
+{
+ g_type_init_with_debug_flags (G_TYPE_DEBUG_OBJECTS |
+ G_TYPE_DEBUG_SIGNALS);
+
+#ifdef HAVE_SETLOCALE
+ setlocale(LC_ALL, "");
+#endif
+
+ GkbdConfigRegistry *reg =
+ GKBD_CONFIG_REGISTRY (g_object_new
+ (gkbd_config_registry_get_type
+ (), NULL));
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ g_main_loop_run (loop);
+
+ g_object_unref (reg);
+
+ return 0;
+}
diff --git a/test/gkbd-indicator-test.c b/test/gkbd-indicator-test.c
new file mode 100644
index 0000000..a2ca21d
--- /dev/null
+++ b/test/gkbd-indicator-test.c
@@ -0,0 +1,79 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; 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-indicator.h"
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <gdk/gdkscreen.h>
+#include <gdk/gdkx.h>
+#include <gnome.h>
+#include <glade/glade.h>
+
+#include "X11/XKBlib.h"
+
+int
+main (int argc, char **argv)
+{
+ GtkWidget *gki;
+ GtkWidget *mainwin;
+ GtkWidget *vbox;
+
+ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ /* Different data dir defs in g-a and g-c-c */
+ gnome_program_init ("gkbd-indicator-test", VERSION,
+ LIBGNOMEUI_MODULE, argc, argv,
+ GNOME_PARAM_APP_DATADIR, DATADIR, NULL);
+
+ glade_gnome_init ();
+
+ mainwin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gki = gkbd_indicator_new ();
+ gkbd_indicator_set_tooltips_format (_
+ ("Keyboard Indicator Test (%s)"));
+ gkbd_indicator_set_parent_tooltips (GKBD_INDICATOR (gki), TRUE);
+
+ gtk_window_resize (GTK_WINDOW (mainwin), 250, 250);
+ vbox = gtk_vbox_new (TRUE, 6);
+
+ gtk_container_add (GTK_CONTAINER (mainwin), vbox);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
+ gtk_container_add (GTK_CONTAINER (vbox),
+ gtk_label_new (_("Indicator:")));
+ gtk_container_add (GTK_CONTAINER (vbox), gki);
+
+ gtk_widget_show_all (mainwin);
+
+ g_signal_connect (G_OBJECT (mainwin),
+ "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/test/gkbd-keyboard-drawing-test.c b/test/gkbd-keyboard-drawing-test.c
new file mode 100644
index 0000000..026cd79
--- /dev/null
+++ b/test/gkbd-keyboard-drawing-test.c
@@ -0,0 +1,286 @@
+/* $Id$ */
+/*
+ * kbdraw.c: main program file for kbdraw
+ *
+ * Copyright (c) 2003 Noah Levitt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <popt.h>
+#include <stdlib.h>
+#include <string.h>
+#include "libgnomekbd/gkbd-keyboard-drawing.h"
+
+
+static gchar *groups = NULL;
+static gchar *levels = NULL;
+static gchar *symbols = NULL;
+static gchar *keycodes = NULL;
+static gchar *geometry = NULL;
+static struct poptOption options[] = {
+ {"groups", '\0', POPT_ARG_STRING, &groups, 0,
+ "Keyboard groups to display, from 1-4. Up to four groups only may be displayed. Examples: --groups=3 or --groups=1,2,1,2",
+ "group1[,group2[,group3[,group4]]]"},
+ {"levels", '\0', POPT_ARG_STRING, &levels, 0,
+ "Keyboard shift levels to display, from 1-64. Up to four shift levels only may be displayed. Examples: --levels=3 or --levels=1,2,1,2",
+ "level1[,level2[,level3[,level4]]]"},
+ {"symbols", '\0', POPT_ARG_STRING, &symbols, 0,
+ "Symbols component of the keyboard. If you omit this option, it is obtained from the X server; that is, the keyboard that is currently configured is drawn. Examples: --symbols=us or --symbols=us(pc104)+iso9995-3+group(switch)+ctrl(nocaps)",
+ NULL},
+ {"keycodes", '\0', POPT_ARG_STRING, &keycodes, 0,
+ "Keycodes component of the keyboard. If you omit this option, it is obtained from the X server; that is, the keyboard that is currently configured is drawn. Examples: --keycodes=xfree86+aliases(qwerty)",
+ NULL},
+ {"geometry", '\0', POPT_ARG_STRING, &geometry, 0,
+ "Geometry xkb component. If you omit this option, it is obtained from the X server; that is, the keyboard that is currently configured is drawn. Example: --geometry=kinesis",
+ NULL},
+ {"track-modifiers", '\0', POPT_ARG_NONE, NULL, 3,
+ "Track the current modifiers", NULL},
+ {"track-config", '\0', POPT_ARG_NONE, NULL, 4,
+ "Track the server XKB configuration", NULL},
+ {"version", 'v', POPT_ARG_NONE, NULL, 1, "Show current version",
+ NULL},
+ POPT_AUTOHELP {NULL, '\0', 0, NULL, 0}
+};
+
+
+static gboolean
+set_groups (gchar * groups_option,
+ GkbdKeyboardDrawingGroupLevel * groupLevels)
+{
+ GkbdKeyboardDrawingGroupLevel *pgl = groupLevels;
+ gint cntr, g;
+
+ groupLevels[0].group =
+ groupLevels[1].group =
+ groupLevels[2].group = groupLevels[3].group = -1;
+
+ if (groups_option == NULL)
+ return TRUE;
+
+ for (cntr = 4; --cntr >= 0;) {
+ if (*groups_option == '\0')
+ return FALSE;
+
+ g = *groups_option - '1';
+ if (g < 0 || g >= 4)
+ return FALSE;
+
+ pgl->group = g;
+ /* printf ("group %d\n", pgl->group); */
+
+ groups_option++;
+ if (*groups_option == '\0')
+ return TRUE;
+ if (*groups_option != ',')
+ return FALSE;
+
+ groups_option++;
+ pgl++;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+set_levels (gchar * levels_option,
+ GkbdKeyboardDrawingGroupLevel * groupLevels)
+{
+ GkbdKeyboardDrawingGroupLevel *pgl = groupLevels;
+ gint cntr, l;
+ gchar *p;
+
+ groupLevels[0].level =
+ groupLevels[1].level =
+ groupLevels[2].level = groupLevels[3].level = -1;
+
+ if (levels_option == NULL)
+ return TRUE;
+
+ for (cntr = 4; --cntr >= 0;) {
+ if (*levels_option == '\0')
+ return FALSE;
+
+ l = (gint) strtol (levels_option, &p, 10) - 1;
+ if (l < 0 || l >= 64)
+ return FALSE;
+
+ pgl->level = l;
+ /* printf ("level %d\n", pgl->level); */
+
+ levels_option = p;
+ if (*levels_option == '\0')
+ return TRUE;
+ if (*levels_option != ',')
+ return FALSE;
+
+ levels_option++;
+ pgl++;
+ }
+
+ return TRUE;
+}
+
+static void
+bad_keycode (GkbdKeyboardDrawing * drawing, guint keycode)
+{
+ g_warning
+ ("got keycode %u, which is not on your keyboard according to your configuration",
+ keycode);
+}
+
+gint
+main (gint argc, gchar ** argv)
+{
+ GtkWidget *window;
+ GtkWidget *gkbd_keyboard_drawing;
+ GdkScreen *screen;
+ gint monitor;
+ GdkRectangle rect;
+ poptContext popt_context;
+ gint rc;
+ GkbdKeyboardDrawingGroupLevel groupLevels[4] =
+ { {0, 0}, {1, 0}, {0, 1}, {1, 1} };
+ GkbdKeyboardDrawingGroupLevel *pgroupLevels[4] =
+ { &groupLevels[0], &groupLevels[1], &groupLevels[2],
+ &groupLevels[3]
+ };
+ gboolean track_config = False, track_modifiers = False;
+
+ gtk_init (&argc, &argv);
+
+ popt_context =
+ poptGetContext ("kbdraw", argc, (const gchar **) argv, options,
+ 0);
+
+ for (rc = poptGetNextOpt (popt_context); rc > 0;
+ rc = poptGetNextOpt (popt_context))
+ switch (rc) {
+ case 1:
+ g_print ("kbdraw %s\n", VERSION);
+ exit (0);
+ case 3:
+ track_modifiers = True;
+ break;
+ case 4:
+ track_config = True;
+ break;
+ }
+
+ if (rc != -1) {
+ g_printerr ("%s: %s\n",
+ poptBadOption (popt_context,
+ POPT_BADOPTION_NOALIAS),
+ poptStrerror (rc));
+ exit (1);
+ }
+
+ if (!set_groups (groups, groupLevels)) {
+ g_printerr ("--groups: invalid argument\n");
+ exit (1);
+ }
+
+ if (!set_levels (levels, groupLevels)) {
+ g_printerr ("--levels: invalid argument\n");
+ exit (1);
+ }
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ g_signal_connect (G_OBJECT (window), "destroy",
+ G_CALLBACK (gtk_main_quit), NULL);
+
+ screen = gtk_window_get_screen (GTK_WINDOW (window));
+ monitor = gdk_screen_get_monitor_at_point (screen, 0, 0);
+ gdk_screen_get_monitor_geometry (screen, monitor, &rect);
+ gtk_window_set_default_size (GTK_WINDOW (window),
+ rect.width * 4 / 5,
+ rect.height * 1 / 2);
+
+ gtk_widget_show (window);
+
+ gkbd_keyboard_drawing = gkbd_keyboard_drawing_new ();
+ gtk_widget_show (gkbd_keyboard_drawing);
+ gtk_container_add (GTK_CONTAINER (window), gkbd_keyboard_drawing);
+
+ gkbd_keyboard_drawing_set_groups_levels (GKBD_KEYBOARD_DRAWING
+ (gkbd_keyboard_drawing),
+ pgroupLevels);
+
+ if (track_modifiers)
+ gkbd_keyboard_drawing_set_track_modifiers
+ (GKBD_KEYBOARD_DRAWING (gkbd_keyboard_drawing), TRUE);
+ if (track_config)
+ gkbd_keyboard_drawing_set_track_config
+ (GKBD_KEYBOARD_DRAWING (gkbd_keyboard_drawing), TRUE);
+ g_signal_connect (G_OBJECT (gkbd_keyboard_drawing), "bad-keycode",
+ G_CALLBACK (bad_keycode), NULL);
+
+ if (symbols || geometry || keycodes) {
+ XkbComponentNamesRec names;
+ gint success;
+
+ memset (&names, '\0', sizeof (names));
+
+ if (symbols)
+ names.symbols = symbols;
+ else
+ names.symbols = (gchar *)
+ gkbd_keyboard_drawing_get_symbols
+ (GKBD_KEYBOARD_DRAWING
+ (gkbd_keyboard_drawing));
+
+ if (keycodes)
+ names.keycodes = keycodes;
+ else
+ names.keycodes = (gchar *)
+ gkbd_keyboard_drawing_get_keycodes
+ (GKBD_KEYBOARD_DRAWING
+ (gkbd_keyboard_drawing));
+
+ if (geometry)
+ names.geometry = geometry;
+ else
+ names.geometry = (gchar *)
+ gkbd_keyboard_drawing_get_geometry
+ (GKBD_KEYBOARD_DRAWING
+ (gkbd_keyboard_drawing));
+
+ success =
+ gkbd_keyboard_drawing_set_keyboard
+ (GKBD_KEYBOARD_DRAWING (gkbd_keyboard_drawing),
+ &names);
+ if (!success) {
+ g_printerr
+ ("\nError loading new keyboard description with components:\n\n"
+ " keycodes: %s\n" " types: %s\n"
+ " compat: %s\n" " symbols: %s\n"
+ " geometry: %s\n\n", names.keycodes,
+ names.types, names.compat, names.symbols,
+ names.geometry);
+ exit (1);
+ }
+ }
+
+ gtk_widget_grab_focus (gkbd_keyboard_drawing);
+
+ gtk_main ();
+
+ return 0;
+}