diff options
author | Sergey V. Udaltsov <svu@src.gnome.org> | 2006-09-27 20:27:09 +0000 |
---|---|---|
committer | Sergey V. Udaltsov <svu@src.gnome.org> | 2006-09-27 20:27:09 +0000 |
commit | 7699e660c678df45a7d0ce2edaec1611e210d583 (patch) | |
tree | a1e92bed7f668a851e276ec79a9bca846d70a2a1 | |
download | libgnomekbd-7699e660c678df45a7d0ce2edaec1611e210d583.tar.gz |
Initial revision
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 Binary files differnew file mode 100644 index 0000000..35c9d12 --- /dev/null +++ b/.tm_project2.cache @@ -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/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; +} |