summaryrefslogtreecommitdiff
path: root/libmatekbd
diff options
context:
space:
mode:
authorPerberos <[email protected]>2011-12-01 20:53:10 -0300
committerPerberos <[email protected]>2011-12-01 20:53:10 -0300
commit916e2eafe251b44f9d0339282f5d00723899caec (patch)
treed650ca8c97d834499ca107a2a59a41c86c1fc4a9 /libmatekbd
downloadlibmatekbd-916e2eafe251b44f9d0339282f5d00723899caec.tar.bz2
libmatekbd-916e2eafe251b44f9d0339282f5d00723899caec.tar.xz
moving from https://github.com/perberos/mate-desktop-environment
Diffstat (limited to 'libmatekbd')
-rw-r--r--libmatekbd/Makefile.am121
-rw-r--r--libmatekbd/Makefile.in886
-rw-r--r--libmatekbd/desktop_mate_peripherals_keyboard_xkb.schemas.in277
-rw-r--r--libmatekbd/matekbd-config-private.h102
-rw-r--r--libmatekbd/matekbd-desktop-config.c403
-rw-r--r--libmatekbd/matekbd-desktop-config.h92
-rw-r--r--libmatekbd/matekbd-indicator-config.c445
-rw-r--r--libmatekbd/matekbd-indicator-config.h94
-rw-r--r--libmatekbd/matekbd-indicator-marshal.list1
-rw-r--r--libmatekbd/matekbd-indicator-plugin-manager.c406
-rw-r--r--libmatekbd/matekbd-indicator-plugin-manager.h116
-rw-r--r--libmatekbd/matekbd-indicator-plugin.h125
-rw-r--r--libmatekbd/matekbd-indicator.c968
-rw-r--r--libmatekbd/matekbd-indicator.h80
-rw-r--r--libmatekbd/matekbd-keyboard-config.c827
-rw-r--r--libmatekbd/matekbd-keyboard-config.h124
-rw-r--r--libmatekbd/matekbd-keyboard-drawing-marshal.list2
-rw-r--r--libmatekbd/matekbd-keyboard-drawing.c2635
-rw-r--r--libmatekbd/matekbd-keyboard-drawing.h214
-rw-r--r--libmatekbd/matekbd-status.c867
-rw-r--r--libmatekbd/matekbd-status.h72
-rw-r--r--libmatekbd/matekbd-util.c159
-rw-r--r--libmatekbd/matekbd-util.h33
-rw-r--r--libmatekbd/show-layout.ui83
24 files changed, 9132 insertions, 0 deletions
diff --git a/libmatekbd/Makefile.am b/libmatekbd/Makefile.am
new file mode 100644
index 0000000..10b3f8b
--- /dev/null
+++ b/libmatekbd/Makefile.am
@@ -0,0 +1,121 @@
+lib_LTLIBRARIES = libmatekbd.la libmatekbdui.la
+
+uidir="$(pkgdatadir)/ui"
+ui_DATA = show-layout.ui
+
+common_CFLAGS = \
+ -I$(top_srcdir) -Wall \
+ $(GDK_CFLAGS) \
+ $(MATECONF_CFLAGS) \
+ $(LIBXKLAVIER_CFLAGS) \
+ $(XLIB_CFLAGS) \
+ -I$(top_srcdir)/intl \
+ -DSYS_PLUGIN_DIR=\"$(libdir)/matekbd/\" \
+ -DG_LOG_DOMAIN=\"MateKbdIndicator\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBDIR=\"$(libdir)\"
+
+libmatekbd_la_CFLAGS = $(common_CFLAGS)
+
+libmatekbdui_la_CFLAGS = $(common_CFLAGS) \
+ -DUIDIR=\"$(uidir)\" \
+ $(GTK_CFLAGS)
+
+common_LDFLAGS = -version-info @VERSION_INFO@ -no-undefined
+
+common_LIBADD = \
+ $(GDK_LIBS) \
+ $(MATECONF_LIBS) \
+ $(LIBXKLAVIER_LIBS) \
+ $(XLIB_LIBS)
+
+libmatekbd_la_LDFLAGS = $(common_LDFLAGS)
+libmatekbd_la_LIBADD = $(common_LIBADD)
+
+libmatekbdui_la_LDFLAGS = $(common_LDFLAGS)
+libmatekbdui_la_LIBADD = libmatekbd.la \
+ $(common_LIBADD) \
+ $(GTK_LIBS)
+
+libmatekbd_la_SOURCES = \
+ matekbd-desktop-config.c \
+ matekbd-keyboard-config.c \
+ matekbd-util.c
+
+libmatekbdui_la_SOURCES = \
+ matekbd-indicator-config.c \
+ matekbd-indicator.c \
+ matekbd-status.c \
+ matekbd-indicator-marshal.c \
+ matekbd-indicator-plugin-manager.c \
+ matekbd-keyboard-drawing-marshal.c \
+ matekbd-keyboard-drawing.c
+
+BUILT_SOURCES = matekbd-indicator-marshal.c \
+ matekbd-indicator-marshal.h \
+ matekbd-keyboard-drawing-marshal.c \
+ matekbd-keyboard-drawing-marshal.h
+
+CLEANFILES = $(BUILT_SOURCES) $(schema_DATA)
+
+matekbdincdir = $(includedir)/libmatekbd
+matekbdinc_HEADERS = \
+ matekbd-desktop-config.h \
+ matekbd-keyboard-config.h \
+ matekbd-indicator.h \
+ matekbd-status.h \
+ matekbd-indicator-config.h \
+ matekbd-indicator-plugin.h \
+ matekbd-keyboard-drawing.h \
+ matekbd-util.h
+
+@INTLTOOL_DESKTOP_RULE@
+
+@INTLTOOL_SCHEMAS_RULE@
+
+noinst_HEADERS = matekbd-indicator-plugin-manager.h \
+ $(extra_nih) \
+ matekbd-config-private.h
+
+EXTRA_DIST = matekbd-indicator-marshal.list \
+ matekbd-keyboard-drawing-marshal.list \
+ $(schema_in_files) $(ui_DATA)
+
+GLIB_GENMARSHAL = $(shell pkg-config --variable=glib_genmarshal glib-2.0)
+
+matekbd-indicator-marshal.h: matekbd-indicator-marshal.list
+ $(AM_V_GEN)$(GLIB_GENMARSHAL) --prefix=matekbd_indicator $(srcdir)/matekbd-indicator-marshal.list --header > $@
+
+matekbd-indicator-marshal.c: matekbd-indicator-marshal.h
+ $(AM_V_GEN)$(GLIB_GENMARSHAL) --prefix=matekbd_indicator $(srcdir)/matekbd-indicator-marshal.list --body > $@
+
+matekbd-keyboard-drawing-marshal.h: matekbd-keyboard-drawing-marshal.list
+ $(AM_V_GEN)( $(GLIB_GENMARSHAL) --prefix=matekbd_keyboard_drawing $(srcdir)/matekbd-keyboard-drawing-marshal.list \
+ --header > matekbd-keyboard-drawing-marshal.tmp \
+ && mv matekbd-keyboard-drawing-marshal.tmp matekbd-keyboard-drawing-marshal.h ) \
+ || ( rm -f matekbd-keyboard-drawing-marshal.tmp && exit 1 )
+
+matekbd-keyboard-drawing-marshal.c: matekbd-keyboard-drawing-marshal.h
+ $(AM_V_GEN)( $(GLIB_GENMARSHAL) --prefix=matekbd_keyboard_drawing $(srcdir)/matekbd-keyboard-drawing-marshal.list \
+ --body > matekbd-keyboard-drawing-marshal.tmp \
+ && mv matekbd-keyboard-drawing-marshal.tmp matekbd-keyboard-drawing-marshal.c ) \
+ || ( rm -f matekbd-keyboard-drawing-marshal.tmp && exit 1 )
+
+schemadir = $(MATECONF_SCHEMA_FILE_DIR)
+schema_in_files= desktop_mate_peripherals_keyboard_xkb.schemas.in
+
+schema_DATA = $(schema_in_files:.schemas.in=.schemas)
+
+if MATECONF_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 \
+ MATECONF_CONFIG_SOURCE=$(MATECONF_SCHEMA_CONFIG_SOURCE) $(MATECONFTOOL) --makefile-install-rule $$p; \
+ done \
+ fi
+else
+install-data-local:
+endif
+
diff --git a/libmatekbd/Makefile.in b/libmatekbd/Makefile.in
new file mode 100644
index 0000000..993f916
--- /dev/null
+++ b/libmatekbd/Makefile.in
@@ -0,0 +1,886 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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.
+
+@SET_MAKE@
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+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 = @build@
+host_triplet = @host@
+subdir = libmatekbd
+DIST_COMMON = $(matekbdinc_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)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.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 =
+CONFIG_CLEAN_VPATH_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 = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(schemadir)" \
+ "$(DESTDIR)$(uidir)" "$(DESTDIR)$(matekbdincdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+libmatekbd_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_libmatekbd_la_OBJECTS = libmatekbd_la-matekbd-desktop-config.lo \
+ libmatekbd_la-matekbd-keyboard-config.lo \
+ libmatekbd_la-matekbd-util.lo
+libmatekbd_la_OBJECTS = $(am_libmatekbd_la_OBJECTS)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+libmatekbd_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libmatekbd_la_CFLAGS) \
+ $(CFLAGS) $(libmatekbd_la_LDFLAGS) $(LDFLAGS) -o $@
+libmatekbdui_la_DEPENDENCIES = libmatekbd.la $(am__DEPENDENCIES_2) \
+ $(am__DEPENDENCIES_1)
+am_libmatekbdui_la_OBJECTS = \
+ libmatekbdui_la-matekbd-indicator-config.lo \
+ libmatekbdui_la-matekbd-indicator.lo \
+ libmatekbdui_la-matekbd-status.lo \
+ libmatekbdui_la-matekbd-indicator-marshal.lo \
+ libmatekbdui_la-matekbd-indicator-plugin-manager.lo \
+ libmatekbdui_la-matekbd-keyboard-drawing-marshal.lo \
+ libmatekbdui_la-matekbd-keyboard-drawing.lo
+libmatekbdui_la_OBJECTS = $(am_libmatekbdui_la_OBJECTS)
+libmatekbdui_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(libmatekbdui_la_CFLAGS) $(CFLAGS) $(libmatekbdui_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libmatekbd_la_SOURCES) $(libmatekbdui_la_SOURCES)
+DIST_SOURCES = $(libmatekbd_la_SOURCES) $(libmatekbdui_la_SOURCES)
+DATA = $(schema_DATA) $(ui_DATA)
+HEADERS = $(matekbdinc_HEADERS) $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GDK_CFLAGS = @GDK_CFLAGS@
+GDK_LIBS = @GDK_LIBS@
+GDK_REQUIRED = @GDK_REQUIRED@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+GTK_REQUIRED = @GTK_REQUIRED@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBXKLAVIER_CFLAGS = @LIBXKLAVIER_CFLAGS@
+LIBXKLAVIER_LIBS = @LIBXKLAVIER_LIBS@
+LIBXKLAVIER_REQUIRED = @LIBXKLAVIER_REQUIRED@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATECONFTOOL = @MATECONFTOOL@
+MATECONF_CFLAGS = @MATECONF_CFLAGS@
+MATECONF_LIBS = @MATECONF_LIBS@
+MATECONF_REQUIRED = @MATECONF_REQUIRED@
+MATECONF_SCHEMA_CONFIG_SOURCE = @MATECONF_SCHEMA_CONFIG_SOURCE@
+MATECONF_SCHEMA_FILE_DIR = @MATECONF_SCHEMA_FILE_DIR@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+VERSION_INFO = @VERSION_INFO@
+WARN_CFLAGS = @WARN_CFLAGS@
+XGETTEXT = @XGETTEXT@
+XLIB_CFLAGS = @XLIB_CFLAGS@
+XLIB_LIBS = @XLIB_LIBS@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+lib_LTLIBRARIES = libmatekbd.la libmatekbdui.la
+uidir = "$(pkgdatadir)/ui"
+ui_DATA = show-layout.ui
+common_CFLAGS = \
+ -I$(top_srcdir) -Wall \
+ $(GDK_CFLAGS) \
+ $(MATECONF_CFLAGS) \
+ $(LIBXKLAVIER_CFLAGS) \
+ $(XLIB_CFLAGS) \
+ -I$(top_srcdir)/intl \
+ -DSYS_PLUGIN_DIR=\"$(libdir)/matekbd/\" \
+ -DG_LOG_DOMAIN=\"MateKbdIndicator\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBDIR=\"$(libdir)\"
+
+libmatekbd_la_CFLAGS = $(common_CFLAGS)
+libmatekbdui_la_CFLAGS = $(common_CFLAGS) \
+ -DUIDIR=\"$(uidir)\" \
+ $(GTK_CFLAGS)
+
+common_LDFLAGS = -version-info @VERSION_INFO@ -no-undefined
+common_LIBADD = \
+ $(GDK_LIBS) \
+ $(MATECONF_LIBS) \
+ $(LIBXKLAVIER_LIBS) \
+ $(XLIB_LIBS)
+
+libmatekbd_la_LDFLAGS = $(common_LDFLAGS)
+libmatekbd_la_LIBADD = $(common_LIBADD)
+libmatekbdui_la_LDFLAGS = $(common_LDFLAGS)
+libmatekbdui_la_LIBADD = libmatekbd.la \
+ $(common_LIBADD) \
+ $(GTK_LIBS)
+
+libmatekbd_la_SOURCES = \
+ matekbd-desktop-config.c \
+ matekbd-keyboard-config.c \
+ matekbd-util.c
+
+libmatekbdui_la_SOURCES = \
+ matekbd-indicator-config.c \
+ matekbd-indicator.c \
+ matekbd-status.c \
+ matekbd-indicator-marshal.c \
+ matekbd-indicator-plugin-manager.c \
+ matekbd-keyboard-drawing-marshal.c \
+ matekbd-keyboard-drawing.c
+
+BUILT_SOURCES = matekbd-indicator-marshal.c \
+ matekbd-indicator-marshal.h \
+ matekbd-keyboard-drawing-marshal.c \
+ matekbd-keyboard-drawing-marshal.h
+
+CLEANFILES = $(BUILT_SOURCES) $(schema_DATA)
+matekbdincdir = $(includedir)/libmatekbd
+matekbdinc_HEADERS = \
+ matekbd-desktop-config.h \
+ matekbd-keyboard-config.h \
+ matekbd-indicator.h \
+ matekbd-status.h \
+ matekbd-indicator-config.h \
+ matekbd-indicator-plugin.h \
+ matekbd-keyboard-drawing.h \
+ matekbd-util.h
+
+noinst_HEADERS = matekbd-indicator-plugin-manager.h \
+ $(extra_nih) \
+ matekbd-config-private.h
+
+EXTRA_DIST = matekbd-indicator-marshal.list \
+ matekbd-keyboard-drawing-marshal.list \
+ $(schema_in_files) $(ui_DATA)
+
+GLIB_GENMARSHAL = $(shell pkg-config --variable=glib_genmarshal glib-2.0)
+schemadir = $(MATECONF_SCHEMA_FILE_DIR)
+schema_in_files = desktop_mate_peripherals_keyboard_xkb.schemas.in
+schema_DATA = $(schema_in_files:.schemas.in=.schemas)
+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 ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libmatekbd/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu libmatekbd/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
+$(am__aclocal_m4_deps):
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ 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
+libmatekbd.la: $(libmatekbd_la_OBJECTS) $(libmatekbd_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libmatekbd_la_LINK) -rpath $(libdir) $(libmatekbd_la_OBJECTS) $(libmatekbd_la_LIBADD) $(LIBS)
+libmatekbdui.la: $(libmatekbdui_la_OBJECTS) $(libmatekbdui_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libmatekbdui_la_LINK) -rpath $(libdir) $(libmatekbdui_la_OBJECTS) $(libmatekbdui_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmatekbd_la-matekbd-desktop-config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmatekbd_la-matekbd-keyboard-config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmatekbd_la-matekbd-util.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmatekbdui_la-matekbd-indicator-config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmatekbdui_la-matekbd-indicator-marshal.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmatekbdui_la-matekbd-indicator-plugin-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmatekbdui_la-matekbd-indicator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmatekbdui_la-matekbd-keyboard-drawing-marshal.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmatekbdui_la-matekbd-keyboard-drawing.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmatekbdui_la-matekbd-status.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libmatekbd_la-matekbd-desktop-config.lo: matekbd-desktop-config.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbd_la_CFLAGS) $(CFLAGS) -MT libmatekbd_la-matekbd-desktop-config.lo -MD -MP -MF $(DEPDIR)/libmatekbd_la-matekbd-desktop-config.Tpo -c -o libmatekbd_la-matekbd-desktop-config.lo `test -f 'matekbd-desktop-config.c' || echo '$(srcdir)/'`matekbd-desktop-config.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmatekbd_la-matekbd-desktop-config.Tpo $(DEPDIR)/libmatekbd_la-matekbd-desktop-config.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='matekbd-desktop-config.c' object='libmatekbd_la-matekbd-desktop-config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbd_la_CFLAGS) $(CFLAGS) -c -o libmatekbd_la-matekbd-desktop-config.lo `test -f 'matekbd-desktop-config.c' || echo '$(srcdir)/'`matekbd-desktop-config.c
+
+libmatekbd_la-matekbd-keyboard-config.lo: matekbd-keyboard-config.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbd_la_CFLAGS) $(CFLAGS) -MT libmatekbd_la-matekbd-keyboard-config.lo -MD -MP -MF $(DEPDIR)/libmatekbd_la-matekbd-keyboard-config.Tpo -c -o libmatekbd_la-matekbd-keyboard-config.lo `test -f 'matekbd-keyboard-config.c' || echo '$(srcdir)/'`matekbd-keyboard-config.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmatekbd_la-matekbd-keyboard-config.Tpo $(DEPDIR)/libmatekbd_la-matekbd-keyboard-config.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='matekbd-keyboard-config.c' object='libmatekbd_la-matekbd-keyboard-config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbd_la_CFLAGS) $(CFLAGS) -c -o libmatekbd_la-matekbd-keyboard-config.lo `test -f 'matekbd-keyboard-config.c' || echo '$(srcdir)/'`matekbd-keyboard-config.c
+
+libmatekbd_la-matekbd-util.lo: matekbd-util.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbd_la_CFLAGS) $(CFLAGS) -MT libmatekbd_la-matekbd-util.lo -MD -MP -MF $(DEPDIR)/libmatekbd_la-matekbd-util.Tpo -c -o libmatekbd_la-matekbd-util.lo `test -f 'matekbd-util.c' || echo '$(srcdir)/'`matekbd-util.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmatekbd_la-matekbd-util.Tpo $(DEPDIR)/libmatekbd_la-matekbd-util.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='matekbd-util.c' object='libmatekbd_la-matekbd-util.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbd_la_CFLAGS) $(CFLAGS) -c -o libmatekbd_la-matekbd-util.lo `test -f 'matekbd-util.c' || echo '$(srcdir)/'`matekbd-util.c
+
+libmatekbdui_la-matekbd-indicator-config.lo: matekbd-indicator-config.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbdui_la_CFLAGS) $(CFLAGS) -MT libmatekbdui_la-matekbd-indicator-config.lo -MD -MP -MF $(DEPDIR)/libmatekbdui_la-matekbd-indicator-config.Tpo -c -o libmatekbdui_la-matekbd-indicator-config.lo `test -f 'matekbd-indicator-config.c' || echo '$(srcdir)/'`matekbd-indicator-config.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmatekbdui_la-matekbd-indicator-config.Tpo $(DEPDIR)/libmatekbdui_la-matekbd-indicator-config.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='matekbd-indicator-config.c' object='libmatekbdui_la-matekbd-indicator-config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbdui_la_CFLAGS) $(CFLAGS) -c -o libmatekbdui_la-matekbd-indicator-config.lo `test -f 'matekbd-indicator-config.c' || echo '$(srcdir)/'`matekbd-indicator-config.c
+
+libmatekbdui_la-matekbd-indicator.lo: matekbd-indicator.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbdui_la_CFLAGS) $(CFLAGS) -MT libmatekbdui_la-matekbd-indicator.lo -MD -MP -MF $(DEPDIR)/libmatekbdui_la-matekbd-indicator.Tpo -c -o libmatekbdui_la-matekbd-indicator.lo `test -f 'matekbd-indicator.c' || echo '$(srcdir)/'`matekbd-indicator.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmatekbdui_la-matekbd-indicator.Tpo $(DEPDIR)/libmatekbdui_la-matekbd-indicator.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='matekbd-indicator.c' object='libmatekbdui_la-matekbd-indicator.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbdui_la_CFLAGS) $(CFLAGS) -c -o libmatekbdui_la-matekbd-indicator.lo `test -f 'matekbd-indicator.c' || echo '$(srcdir)/'`matekbd-indicator.c
+
+libmatekbdui_la-matekbd-status.lo: matekbd-status.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbdui_la_CFLAGS) $(CFLAGS) -MT libmatekbdui_la-matekbd-status.lo -MD -MP -MF $(DEPDIR)/libmatekbdui_la-matekbd-status.Tpo -c -o libmatekbdui_la-matekbd-status.lo `test -f 'matekbd-status.c' || echo '$(srcdir)/'`matekbd-status.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmatekbdui_la-matekbd-status.Tpo $(DEPDIR)/libmatekbdui_la-matekbd-status.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='matekbd-status.c' object='libmatekbdui_la-matekbd-status.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbdui_la_CFLAGS) $(CFLAGS) -c -o libmatekbdui_la-matekbd-status.lo `test -f 'matekbd-status.c' || echo '$(srcdir)/'`matekbd-status.c
+
+libmatekbdui_la-matekbd-indicator-marshal.lo: matekbd-indicator-marshal.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbdui_la_CFLAGS) $(CFLAGS) -MT libmatekbdui_la-matekbd-indicator-marshal.lo -MD -MP -MF $(DEPDIR)/libmatekbdui_la-matekbd-indicator-marshal.Tpo -c -o libmatekbdui_la-matekbd-indicator-marshal.lo `test -f 'matekbd-indicator-marshal.c' || echo '$(srcdir)/'`matekbd-indicator-marshal.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmatekbdui_la-matekbd-indicator-marshal.Tpo $(DEPDIR)/libmatekbdui_la-matekbd-indicator-marshal.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='matekbd-indicator-marshal.c' object='libmatekbdui_la-matekbd-indicator-marshal.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbdui_la_CFLAGS) $(CFLAGS) -c -o libmatekbdui_la-matekbd-indicator-marshal.lo `test -f 'matekbd-indicator-marshal.c' || echo '$(srcdir)/'`matekbd-indicator-marshal.c
+
+libmatekbdui_la-matekbd-indicator-plugin-manager.lo: matekbd-indicator-plugin-manager.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbdui_la_CFLAGS) $(CFLAGS) -MT libmatekbdui_la-matekbd-indicator-plugin-manager.lo -MD -MP -MF $(DEPDIR)/libmatekbdui_la-matekbd-indicator-plugin-manager.Tpo -c -o libmatekbdui_la-matekbd-indicator-plugin-manager.lo `test -f 'matekbd-indicator-plugin-manager.c' || echo '$(srcdir)/'`matekbd-indicator-plugin-manager.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmatekbdui_la-matekbd-indicator-plugin-manager.Tpo $(DEPDIR)/libmatekbdui_la-matekbd-indicator-plugin-manager.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='matekbd-indicator-plugin-manager.c' object='libmatekbdui_la-matekbd-indicator-plugin-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbdui_la_CFLAGS) $(CFLAGS) -c -o libmatekbdui_la-matekbd-indicator-plugin-manager.lo `test -f 'matekbd-indicator-plugin-manager.c' || echo '$(srcdir)/'`matekbd-indicator-plugin-manager.c
+
+libmatekbdui_la-matekbd-keyboard-drawing-marshal.lo: matekbd-keyboard-drawing-marshal.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbdui_la_CFLAGS) $(CFLAGS) -MT libmatekbdui_la-matekbd-keyboard-drawing-marshal.lo -MD -MP -MF $(DEPDIR)/libmatekbdui_la-matekbd-keyboard-drawing-marshal.Tpo -c -o libmatekbdui_la-matekbd-keyboard-drawing-marshal.lo `test -f 'matekbd-keyboard-drawing-marshal.c' || echo '$(srcdir)/'`matekbd-keyboard-drawing-marshal.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmatekbdui_la-matekbd-keyboard-drawing-marshal.Tpo $(DEPDIR)/libmatekbdui_la-matekbd-keyboard-drawing-marshal.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='matekbd-keyboard-drawing-marshal.c' object='libmatekbdui_la-matekbd-keyboard-drawing-marshal.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbdui_la_CFLAGS) $(CFLAGS) -c -o libmatekbdui_la-matekbd-keyboard-drawing-marshal.lo `test -f 'matekbd-keyboard-drawing-marshal.c' || echo '$(srcdir)/'`matekbd-keyboard-drawing-marshal.c
+
+libmatekbdui_la-matekbd-keyboard-drawing.lo: matekbd-keyboard-drawing.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbdui_la_CFLAGS) $(CFLAGS) -MT libmatekbdui_la-matekbd-keyboard-drawing.lo -MD -MP -MF $(DEPDIR)/libmatekbdui_la-matekbd-keyboard-drawing.Tpo -c -o libmatekbdui_la-matekbd-keyboard-drawing.lo `test -f 'matekbd-keyboard-drawing.c' || echo '$(srcdir)/'`matekbd-keyboard-drawing.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmatekbdui_la-matekbd-keyboard-drawing.Tpo $(DEPDIR)/libmatekbdui_la-matekbd-keyboard-drawing.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='matekbd-keyboard-drawing.c' object='libmatekbdui_la-matekbd-keyboard-drawing.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmatekbdui_la_CFLAGS) $(CFLAGS) -c -o libmatekbdui_la-matekbd-keyboard-drawing.lo `test -f 'matekbd-keyboard-drawing.c' || echo '$(srcdir)/'`matekbd-keyboard-drawing.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-schemaDATA: $(schema_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(schemadir)" || $(MKDIR_P) "$(DESTDIR)$(schemadir)"
+ @list='$(schema_DATA)'; test -n "$(schemadir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(schemadir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(schemadir)" || exit $$?; \
+ done
+
+uninstall-schemaDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(schema_DATA)'; test -n "$(schemadir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(schemadir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(schemadir)" && rm -f $$files
+install-uiDATA: $(ui_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(uidir)" || $(MKDIR_P) "$(DESTDIR)$(uidir)"
+ @list='$(ui_DATA)'; test -n "$(uidir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(uidir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(uidir)" || exit $$?; \
+ done
+
+uninstall-uiDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(ui_DATA)'; test -n "$(uidir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(uidir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(uidir)" && rm -f $$files
+install-matekbdincHEADERS: $(matekbdinc_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(matekbdincdir)" || $(MKDIR_P) "$(DESTDIR)$(matekbdincdir)"
+ @list='$(matekbdinc_HEADERS)'; test -n "$(matekbdincdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(matekbdincdir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(matekbdincdir)" || exit $$?; \
+ done
+
+uninstall-matekbdincHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(matekbdinc_HEADERS)'; test -n "$(matekbdincdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(matekbdincdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(matekbdincdir)" && rm -f $$files
+
+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; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ 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; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ 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; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__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)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$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) $(DATA) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(schemadir)" "$(DESTDIR)$(uidir)" "$(DESTDIR)$(matekbdincdir)"; 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)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local install-matekbdincHEADERS \
+ install-schemaDATA install-uiDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+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-libLTLIBRARIES uninstall-matekbdincHEADERS \
+ uninstall-schemaDATA uninstall-uiDATA
+
+.MAKE: all check install install-am install-strip
+
+.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-data-local install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-libLTLIBRARIES install-man \
+ install-matekbdincHEADERS install-pdf install-pdf-am \
+ install-ps install-ps-am install-schemaDATA install-strip \
+ install-uiDATA 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-libLTLIBRARIES uninstall-matekbdincHEADERS \
+ uninstall-schemaDATA uninstall-uiDATA
+
+
+@INTLTOOL_DESKTOP_RULE@
+
+@INTLTOOL_SCHEMAS_RULE@
+
+matekbd-indicator-marshal.h: matekbd-indicator-marshal.list
+ $(AM_V_GEN)$(GLIB_GENMARSHAL) --prefix=matekbd_indicator $(srcdir)/matekbd-indicator-marshal.list --header > $@
+
+matekbd-indicator-marshal.c: matekbd-indicator-marshal.h
+ $(AM_V_GEN)$(GLIB_GENMARSHAL) --prefix=matekbd_indicator $(srcdir)/matekbd-indicator-marshal.list --body > $@
+
+matekbd-keyboard-drawing-marshal.h: matekbd-keyboard-drawing-marshal.list
+ $(AM_V_GEN)( $(GLIB_GENMARSHAL) --prefix=matekbd_keyboard_drawing $(srcdir)/matekbd-keyboard-drawing-marshal.list \
+ --header > matekbd-keyboard-drawing-marshal.tmp \
+ && mv matekbd-keyboard-drawing-marshal.tmp matekbd-keyboard-drawing-marshal.h ) \
+ || ( rm -f matekbd-keyboard-drawing-marshal.tmp && exit 1 )
+
+matekbd-keyboard-drawing-marshal.c: matekbd-keyboard-drawing-marshal.h
+ $(AM_V_GEN)( $(GLIB_GENMARSHAL) --prefix=matekbd_keyboard_drawing $(srcdir)/matekbd-keyboard-drawing-marshal.list \
+ --body > matekbd-keyboard-drawing-marshal.tmp \
+ && mv matekbd-keyboard-drawing-marshal.tmp matekbd-keyboard-drawing-marshal.c ) \
+ || ( rm -f matekbd-keyboard-drawing-marshal.tmp && exit 1 )
+
+# don't do this if we are building in eg. rpm
+@MATECONF_SCHEMAS_INSTALL_TRUE@install-data-local:
+@MATECONF_SCHEMAS_INSTALL_TRUE@ if test -z "$(DESTDIR)" ; then \
+@MATECONF_SCHEMAS_INSTALL_TRUE@ for p in $(schema_DATA) ; do \
+@MATECONF_SCHEMAS_INSTALL_TRUE@ MATECONF_CONFIG_SOURCE=$(MATECONF_SCHEMA_CONFIG_SOURCE) $(MATECONFTOOL) --makefile-install-rule $$p; \
+@MATECONF_SCHEMAS_INSTALL_TRUE@ done \
+@MATECONF_SCHEMAS_INSTALL_TRUE@ fi
+@MATECONF_SCHEMAS_INSTALL_FALSE@install-data-local:
+
+# 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/libmatekbd/desktop_mate_peripherals_keyboard_xkb.schemas.in b/libmatekbd/desktop_mate_peripherals_keyboard_xkb.schemas.in
new file mode 100644
index 0000000..6ac1108
--- /dev/null
+++ b/libmatekbd/desktop_mate_peripherals_keyboard_xkb.schemas.in
@@ -0,0 +1,277 @@
+<?xml version="1.0"?>
+<mateconfschemafile>
+ <schemalist>
+ <schema>
+ <key>/schemas/desktop/mate/peripherals/keyboard/kbd/model</key>
+ <applyto>/desktop/mate/peripherals/keyboard/kbd/model</applyto>
+ <owner>mate</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>Keyboard model</short>
+ <long>keyboard model</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/mate/peripherals/keyboard/kbd/layouts</key>
+ <applyto>/desktop/mate/peripherals/keyboard/kbd/layouts</applyto>
+ <owner>mate</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/mate/peripherals/keyboard/kbd/options</key>
+ <applyto>/desktop/mate/peripherals/keyboard/kbd/options</applyto>
+ <owner>mate</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/mate/peripherals/keyboard/general/update_handlers</key>
+ <applyto>/desktop/mate/peripherals/keyboard/general/update_handlers</applyto>
+ <owner>mate</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/mate/peripherals/keyboard/general/known_file_list</key>
+ <applyto>/desktop/mate/peripherals/keyboard/general/known_file_list</applyto>
+ <owner>mate</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/mate/peripherals/keyboard/general/defaultGroup</key>
+ <applyto>/desktop/mate/peripherals/keyboard/general/defaultGroup</applyto>
+ <owner>mate</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/mate/peripherals/keyboard/general/groupPerWindow</key>
+ <applyto>/desktop/mate/peripherals/keyboard/general/groupPerWindow</applyto>
+ <owner>mate</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/mate/peripherals/keyboard/general/handleIndicators</key>
+ <applyto>/desktop/mate/peripherals/keyboard/general/handleIndicators</applyto>
+ <owner>mate</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/mate/peripherals/keyboard/general/layoutNamesAsGroupNames</key>
+ <applyto>/desktop/mate/peripherals/keyboard/general/layoutNamesAsGroupNames</applyto>
+ <owner>mate</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/mate/peripherals/keyboard/general/loadExtraItems</key>
+ <applyto>/desktop/mate/peripherals/keyboard/general/loadExtraItems</applyto>
+ <owner>mate</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Load extra configuration items</short>
+ <long>Load exotic, rarely used layouts and options</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/mate/peripherals/keyboard/general/disable_sysconfig_changed_warning</key>
+ <applyto>/desktop/mate/peripherals/keyboard/general/disable_sysconfig_changed_warning</applyto>
+ <owner>mate</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/desktop/mate/peripherals/keyboard/preview/x</key>
+ <applyto>/desktop/mate/peripherals/keyboard/preview/x</applyto>
+ <owner>mate</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/desktop/mate/peripherals/keyboard/preview/y</key>
+ <applyto>/desktop/mate/peripherals/keyboard/preview/y</applyto>
+ <owner>mate</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/desktop/mate/peripherals/keyboard/preview/width</key>
+ <applyto>/desktop/mate/peripherals/keyboard/preview/width</applyto>
+ <owner>mate</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/desktop/mate/peripherals/keyboard/preview/height</key>
+ <applyto>/desktop/mate/peripherals/keyboard/preview/height</applyto>
+ <owner>mate</owner>
+ <type>int</type>
+ <default>-1</default>
+ <locale name="C">
+ <short>The Keyboard Preview, height</short>
+ <long>The Keyboard Preview, height</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/mate/peripherals/keyboard/indicator/secondary</key>
+ <applyto>/desktop/mate/peripherals/keyboard/indicator/secondary</applyto>
+ <owner>mate</owner>
+ <type>int</type>
+ <default>0</default>
+ <locale name="C">
+ <short>Secondary groups</short>
+ <long>Secondary groups</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/mate/peripherals/keyboard/indicator/showFlags</key>
+ <applyto>/desktop/mate/peripherals/keyboard/indicator/showFlags</applyto>
+ <owner>mate</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short><!-- TRANSLATORS: real national flags -->
+ Show flags in the applet</short>
+ <long><!-- TRANSLATORS: real national flags -->
+ Show flags in the applet to indicate the current layout</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/mate/peripherals/keyboard/indicator/fontFamily</key>
+ <applyto>/desktop/mate/peripherals/keyboard/indicator/fontFamily</applyto>
+ <owner>mate</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>The font family</short>
+ <long>The font family for the layout indicator</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/mate/peripherals/keyboard/indicator/fontSize</key>
+ <applyto>/desktop/mate/peripherals/keyboard/indicator/fontSize</applyto>
+ <owner>mate</owner>
+ <type>int</type>
+ <default>10</default>
+ <locale name="C">
+ <short>The font size</short>
+ <long>The font size for the layout indicator</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/mate/peripherals/keyboard/indicator/foregroundColor</key>
+ <applyto>/desktop/mate/peripherals/keyboard/indicator/foregroundColor</applyto>
+ <owner>mate</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>The foreground color</short>
+ <long>The foreground color for the layout indicator</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/mate/peripherals/keyboard/indicator/backgroundColor</key>
+ <applyto>/desktop/mate/peripherals/keyboard/indicator/backgroundColor</applyto>
+ <owner>mate</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>The background color</short>
+ <long>The background color for the layout indicator</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/desktop/mate/peripherals/keyboard/indicator/enabledPlugins</key>
+ <applyto>/desktop/mate/peripherals/keyboard/indicator/enabledPlugins</applyto>
+ <owner>mate</owner>
+ <type>list</type>
+ <list_type>string</list_type>
+ <default>[]</default>
+ <locale name="C">
+ <short>The list of enabled Keyboard Indicator plugins</short>
+ <long>The list of enabled Keyboard Indicator plugins</long>
+ </locale>
+ </schema>
+ </schemalist>
+</mateconfschemafile>
diff --git a/libmatekbd/matekbd-config-private.h b/libmatekbd/matekbd-config-private.h
new file mode 100644
index 0000000..a49c373
--- /dev/null
+++ b/libmatekbd/matekbd-config-private.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MATEKBD_CONFIG_PRIVATE_H__
+#define __MATEKBD_CONFIG_PRIVATE_H__
+
+#include "libmatekbd/matekbd-desktop-config.h"
+#include "libmatekbd/matekbd-keyboard-config.h"
+
+#define MATEKBD_CONFIG_KEY_PREFIX "/desktop/mate/peripherals/keyboard"
+
+extern const gchar MATEKBD_PREVIEW_CONFIG_DIR[];
+extern const gchar MATEKBD_PREVIEW_CONFIG_KEY_X[];
+extern const gchar MATEKBD_PREVIEW_CONFIG_KEY_Y[];
+extern const gchar MATEKBD_PREVIEW_CONFIG_KEY_WIDTH[];
+extern const gchar MATEKBD_PREVIEW_CONFIG_KEY_HEIGHT[];
+
+/**
+ * General config functions (private)
+ */
+extern void
+ matekbd_desktop_config_add_listener (MateConfClient * conf_client,
+ const gchar * key,
+ MateConfClientNotifyFunc func,
+ gpointer user_data, int *pid);
+
+
+extern void
+ matekbd_desktop_config_remove_listener (MateConfClient * conf_client, int *pid);
+
+extern void matekbd_keyboard_config_model_set (MatekbdKeyboardConfig *
+ kbd_config,
+ const gchar * model_name);
+
+extern void matekbd_keyboard_config_layouts_reset (MatekbdKeyboardConfig *
+ kbd_config);
+extern void matekbd_keyboard_config_layouts_add (MatekbdKeyboardConfig *
+ kbd_config,
+ const gchar * layout_name,
+ const gchar * variant_name);
+
+extern void matekbd_keyboard_config_layouts_reset (MatekbdKeyboardConfig *
+ kbd_config);
+extern void matekbd_keyboard_config_options_reset (MatekbdKeyboardConfig *
+ kbd_config);
+
+extern void matekbd_keyboard_config_options_add (MatekbdKeyboardConfig *
+ kbd_config,
+ const gchar * group_name,
+ const gchar * option_name);
+extern gboolean matekbd_keyboard_config_options_is_set (MatekbdKeyboardConfig *
+ kbd_config,
+ const gchar *
+ group_name,
+ const gchar *
+ option_name);
+
+extern gboolean matekbd_keyboard_config_dump_settings (MatekbdKeyboardConfig *
+ kbd_config,
+ const char *file_name);
+
+extern void matekbd_keyboard_config_start_listen (MatekbdKeyboardConfig *
+ kbd_config,
+ MateConfClientNotifyFunc func,
+ gpointer user_data);
+
+extern void matekbd_keyboard_config_stop_listen (MatekbdKeyboardConfig *
+ kbd_config);
+
+extern gboolean matekbd_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/libmatekbd/matekbd-desktop-config.c b/libmatekbd/matekbd-desktop-config.c
new file mode 100644
index 0000000..bcc2259
--- /dev/null
+++ b/libmatekbd/matekbd-desktop-config.c
@@ -0,0 +1,403 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <X11/keysym.h>
+
+#include <glib/gi18n.h>
+
+#include <matekbd-desktop-config.h>
+#include <matekbd-config-private.h>
+
+/**
+ * MatekbdDesktopConfig
+ */
+#define MATEKBD_DESKTOP_CONFIG_KEY_PREFIX MATEKBD_CONFIG_KEY_PREFIX "/general"
+
+const gchar MATEKBD_DESKTOP_CONFIG_DIR[] = MATEKBD_DESKTOP_CONFIG_KEY_PREFIX;
+const gchar MATEKBD_DESKTOP_CONFIG_KEY_DEFAULT_GROUP[] =
+ MATEKBD_DESKTOP_CONFIG_KEY_PREFIX "/defaultGroup";
+const gchar MATEKBD_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW[] =
+ MATEKBD_DESKTOP_CONFIG_KEY_PREFIX "/groupPerWindow";
+const gchar MATEKBD_DESKTOP_CONFIG_KEY_HANDLE_INDICATORS[] =
+ MATEKBD_DESKTOP_CONFIG_KEY_PREFIX "/handleIndicators";
+const gchar MATEKBD_DESKTOP_CONFIG_KEY_LAYOUT_NAMES_AS_GROUP_NAMES[]
+ = MATEKBD_DESKTOP_CONFIG_KEY_PREFIX "/layoutNamesAsGroupNames";
+const gchar MATEKBD_DESKTOP_CONFIG_KEY_LOAD_EXTRA_ITEMS[]
+ = MATEKBD_DESKTOP_CONFIG_KEY_PREFIX "/loadExtraItems";
+
+/**
+ * static common functions
+ */
+
+static gboolean
+ matekbd_desktop_config_get_lv_descriptions
+ (MatekbdDesktopConfig * config,
+ XklConfigRegistry * registry,
+ const gchar ** layout_ids,
+ const gchar ** variant_ids,
+ gchar *** short_layout_descriptions,
+ gchar *** long_layout_descriptions,
+ gchar *** short_variant_descriptions,
+ gchar *** long_variant_descriptions) {
+ const gchar **pl, **pv;
+ guint total_layouts;
+ gchar **sld, **lld, **svd, **lvd;
+ XklConfigItem *item = xkl_config_item_new ();
+
+ if (!
+ (xkl_engine_get_features (config->engine) &
+ XKLF_MULTIPLE_LAYOUTS_SUPPORTED))
+ return FALSE;
+
+ pl = layout_ids;
+ pv = variant_ids;
+ total_layouts = g_strv_length ((char **) layout_ids);
+ 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) {
+
+ xkl_debug (100, "ids: [%s][%s]\n", *pl,
+ pv == NULL ? NULL : *pv);
+
+ g_snprintf (item->name, sizeof item->name, "%s", *pl);
+ if (xkl_config_registry_find_layout (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, *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 ("");
+ }
+
+ xkl_debug (100, "description: [%s][%s][%s][%s]\n",
+ *sld, *lld, *svd, *lvd);
+ sld++;
+ lld++;
+ svd++;
+ lvd++;
+
+ pl++;
+
+ if (*pv != NULL)
+ pv++;
+ }
+
+ g_object_unref (item);
+ return TRUE;
+}
+
+void
+matekbd_desktop_config_add_listener (MateConfClient * conf_client,
+ const gchar * key,
+ MateConfClientNotifyFunc func,
+ gpointer user_data, int *pid)
+{
+ GError *gerror = NULL;
+ xkl_debug (150, "Listening to [%s]\n", key);
+ *pid = mateconf_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
+matekbd_desktop_config_remove_listener (MateConfClient * conf_client, int *pid)
+{
+ if (*pid != 0) {
+ mateconf_client_notify_remove (conf_client, *pid);
+ *pid = 0;
+ }
+}
+
+/**
+ * extern MatekbdDesktopConfig config functions
+ */
+void
+matekbd_desktop_config_init (MatekbdDesktopConfig * config,
+ MateConfClient * 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);
+
+ mateconf_client_add_dir (config->conf_client,
+ MATEKBD_DESKTOP_CONFIG_DIR,
+ MATECONF_CLIENT_PRELOAD_NONE, &gerror);
+ if (gerror != NULL) {
+ g_warning ("err: %s\n", gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+}
+
+void
+matekbd_desktop_config_term (MatekbdDesktopConfig * config)
+{
+ g_object_unref (config->conf_client);
+ config->conf_client = NULL;
+}
+
+void
+matekbd_desktop_config_load_from_mateconf (MatekbdDesktopConfig * config)
+{
+ GError *gerror = NULL;
+
+ config->group_per_app =
+ mateconf_client_get_bool (config->conf_client,
+ MATEKBD_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 =
+ mateconf_client_get_bool (config->conf_client,
+ MATEKBD_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 =
+ mateconf_client_get_bool (config->conf_client,
+ MATEKBD_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->load_extra_items =
+ mateconf_client_get_bool (config->conf_client,
+ MATEKBD_DESKTOP_CONFIG_KEY_LOAD_EXTRA_ITEMS,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ config->load_extra_items = FALSE;
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+ xkl_debug (150, "load_extra_items: %d\n",
+ config->load_extra_items);
+
+ config->default_group =
+ mateconf_client_get_int (config->conf_client,
+ MATEKBD_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
+matekbd_desktop_config_save_to_mateconf (MatekbdDesktopConfig * config)
+{
+ MateConfChangeSet *cs;
+ GError *gerror = NULL;
+
+ cs = mateconf_change_set_new ();
+
+ mateconf_change_set_set_bool (cs,
+ MATEKBD_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW,
+ config->group_per_app);
+ mateconf_change_set_set_bool (cs,
+ MATEKBD_DESKTOP_CONFIG_KEY_HANDLE_INDICATORS,
+ config->handle_indicators);
+ mateconf_change_set_set_bool (cs,
+ MATEKBD_DESKTOP_CONFIG_KEY_LAYOUT_NAMES_AS_GROUP_NAMES,
+ config->layout_names_as_group_names);
+ mateconf_change_set_set_bool (cs,
+ MATEKBD_DESKTOP_CONFIG_KEY_LOAD_EXTRA_ITEMS,
+ config->load_extra_items);
+ mateconf_change_set_set_int (cs,
+ MATEKBD_DESKTOP_CONFIG_KEY_DEFAULT_GROUP,
+ config->default_group);
+
+ mateconf_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;
+ }
+ mateconf_change_set_unref (cs);
+}
+
+gboolean
+matekbd_desktop_config_activate (MatekbdDesktopConfig * 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
+matekbd_desktop_config_lock_next_group (MatekbdDesktopConfig * config)
+{
+ int group = xkl_engine_get_next_group (config->engine);
+ xkl_engine_lock_group (config->engine, group);
+}
+
+void
+matekbd_desktop_config_lock_prev_group (MatekbdDesktopConfig * config)
+{
+ int group = xkl_engine_get_prev_group (config->engine);
+ xkl_engine_lock_group (config->engine, group);
+}
+
+void
+matekbd_desktop_config_restore_group (MatekbdDesktopConfig * config)
+{
+ int group = xkl_engine_get_current_window_group (config->engine);
+ xkl_engine_lock_group (config->engine, group);
+}
+
+void
+matekbd_desktop_config_start_listen (MatekbdDesktopConfig * config,
+ MateConfClientNotifyFunc func,
+ gpointer user_data)
+{
+ matekbd_desktop_config_add_listener (config->conf_client,
+ MATEKBD_DESKTOP_CONFIG_DIR, func,
+ user_data,
+ &config->config_listener_id);
+}
+
+void
+matekbd_desktop_config_stop_listen (MatekbdDesktopConfig * config)
+{
+ matekbd_desktop_config_remove_listener (config->conf_client,
+ &config->config_listener_id);
+}
+
+gboolean
+matekbd_desktop_config_load_group_descriptions (MatekbdDesktopConfig
+ * config,
+ XklConfigRegistry *
+ registry,
+ const gchar **
+ layout_ids,
+ const gchar **
+ variant_ids,
+ gchar ***
+ short_group_names,
+ gchar *** full_group_names)
+{
+ gchar **sld, **lld, **svd, **lvd;
+ gchar **psld, **plld, **plvd;
+ gchar **psgn, **pfgn;
+ gint total_descriptions;
+
+ if (!matekbd_desktop_config_get_lv_descriptions
+ (config, registry, layout_ids, variant_ids, &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 (matekbd_keyboard_config_format_full_layout
+ (*plld++, *plvd++));
+ }
+ g_strfreev (sld);
+ g_strfreev (lld);
+ g_strfreev (svd);
+ g_strfreev (lvd);
+
+ return True;
+}
diff --git a/libmatekbd/matekbd-desktop-config.h b/libmatekbd/matekbd-desktop-config.h
new file mode 100644
index 0000000..e6a1639
--- /dev/null
+++ b/libmatekbd/matekbd-desktop-config.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MATEKBD_DESKTOP_CONFIG_H__
+#define __MATEKBD_DESKTOP_CONFIG_H__
+
+#include <X11/Xlib.h>
+#include <glib.h>
+#include <mateconf/mateconf-client.h>
+#include <libxklavier/xklavier.h>
+
+extern const gchar MATEKBD_DESKTOP_CONFIG_DIR[];
+extern const gchar MATEKBD_DESKTOP_CONFIG_KEY_DEFAULT_GROUP[];
+extern const gchar MATEKBD_DESKTOP_CONFIG_KEY_GROUP_PER_WINDOW[];
+extern const gchar MATEKBD_DESKTOP_CONFIG_KEY_HANDLE_INDICATORS[];
+extern const gchar MATEKBD_DESKTOP_CONFIG_KEY_LAYOUT_NAMES_AS_GROUP_NAMES[];
+
+/*
+ * General configuration
+ */
+typedef struct _MatekbdDesktopConfig {
+ gint default_group;
+ gboolean group_per_app;
+ gboolean handle_indicators;
+ gboolean layout_names_as_group_names;
+ gboolean load_extra_items;
+
+ /* private, transient */
+ MateConfClient *conf_client;
+ int config_listener_id;
+ XklEngine *engine;
+} MatekbdDesktopConfig;
+
+/**
+ * MatekbdDesktopConfig functions
+ */
+extern void matekbd_desktop_config_init (MatekbdDesktopConfig * config,
+ MateConfClient * conf_client,
+ XklEngine * engine);
+extern void matekbd_desktop_config_term (MatekbdDesktopConfig * config);
+
+extern void matekbd_desktop_config_load_from_mateconf (MatekbdDesktopConfig *
+ config);
+
+extern void matekbd_desktop_config_save_to_mateconf (MatekbdDesktopConfig * config);
+
+extern gboolean matekbd_desktop_config_activate (MatekbdDesktopConfig * config);
+
+extern gboolean
+matekbd_desktop_config_load_group_descriptions (MatekbdDesktopConfig
+ * config,
+ XklConfigRegistry *
+ registry,
+ const gchar **
+ layout_ids,
+ const gchar **
+ variant_ids,
+ gchar ***
+ short_group_names,
+ gchar *** full_group_names);
+
+extern void matekbd_desktop_config_lock_next_group (MatekbdDesktopConfig *
+ config);
+
+extern void matekbd_desktop_config_lock_prev_group (MatekbdDesktopConfig *
+ config);
+
+extern void matekbd_desktop_config_restore_group (MatekbdDesktopConfig * config);
+
+extern void matekbd_desktop_config_start_listen (MatekbdDesktopConfig * config,
+ MateConfClientNotifyFunc func,
+ gpointer user_data);
+
+extern void matekbd_desktop_config_stop_listen (MatekbdDesktopConfig * config);
+
+#endif
diff --git a/libmatekbd/matekbd-indicator-config.c b/libmatekbd/matekbd-indicator-config.c
new file mode 100644
index 0000000..328e0cb
--- /dev/null
+++ b/libmatekbd/matekbd-indicator-config.c
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <X11/keysym.h>
+
+#include <pango/pango.h>
+
+#include <glib/gi18n.h>
+#include <gdk/gdkx.h>
+
+#include <matekbd-keyboard-config.h>
+#include <matekbd-indicator-config.h>
+
+#include <matekbd-config-private.h>
+
+/**
+ * MatekbdIndicatorConfig
+ */
+#define MATEKBD_INDICATOR_CONFIG_KEY_PREFIX MATEKBD_CONFIG_KEY_PREFIX "/indicator"
+#define GTK_STYLE_PATH "*PanelWidget*"
+
+const gchar MATEKBD_INDICATOR_CONFIG_DIR[] = MATEKBD_INDICATOR_CONFIG_KEY_PREFIX;
+const gchar MATEKBD_INDICATOR_CONFIG_KEY_SHOW_FLAGS[] =
+ MATEKBD_INDICATOR_CONFIG_KEY_PREFIX "/showFlags";
+const gchar MATEKBD_INDICATOR_CONFIG_KEY_ENABLED_PLUGINS[] =
+ MATEKBD_INDICATOR_CONFIG_KEY_PREFIX "/enabledPlugins";
+const gchar MATEKBD_INDICATOR_CONFIG_KEY_SECONDARIES[] =
+ MATEKBD_INDICATOR_CONFIG_KEY_PREFIX "/secondary";
+const gchar MATEKBD_INDICATOR_CONFIG_KEY_FONT_FAMILY[] =
+ MATEKBD_INDICATOR_CONFIG_KEY_PREFIX "/fontFamily";
+const gchar MATEKBD_INDICATOR_CONFIG_KEY_FONT_SIZE[] =
+ MATEKBD_INDICATOR_CONFIG_KEY_PREFIX "/fontSize";
+const gchar MATEKBD_INDICATOR_CONFIG_KEY_FOREGROUND_COLOR[] =
+ MATEKBD_INDICATOR_CONFIG_KEY_PREFIX "/foregroundColor";
+const gchar MATEKBD_INDICATOR_CONFIG_KEY_BACKGROUND_COLOR[] =
+ MATEKBD_INDICATOR_CONFIG_KEY_PREFIX "/backgroundColor";
+
+#define SYSTEM_FONT_MATECONF_ENTRY "/desktop/mate/interface/font_name"
+
+/**
+ * static applet config functions
+ */
+static void
+matekbd_indicator_config_free_enabled_plugins (MatekbdIndicatorConfig *
+ 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;
+ }
+}
+
+static void
+matekbd_indicator_config_load_font (MatekbdIndicatorConfig * ind_config)
+{
+ GError *gerror = NULL;
+
+ ind_config->font_family =
+ mateconf_client_get_string (ind_config->conf_client,
+ MATEKBD_INDICATOR_CONFIG_KEY_FONT_FAMILY,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ ind_config->font_family = g_strdup ("Helvetica");
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+
+ ind_config->font_size =
+ mateconf_client_get_int (ind_config->conf_client,
+ MATEKBD_INDICATOR_CONFIG_KEY_FONT_SIZE,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ ind_config->font_size = 10;
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+
+ if (ind_config->font_family == NULL ||
+ ind_config->font_family[0] == '\0') {
+ PangoFontDescription *fd = NULL;
+ GtkStyle *style =
+ gtk_rc_get_style_by_paths (gtk_settings_get_default (),
+ GTK_STYLE_PATH,
+ GTK_STYLE_PATH,
+ GTK_TYPE_LABEL);
+ if (style != NULL)
+ fd = style->font_desc;
+ if (fd != NULL) {
+ ind_config->font_family =
+ g_strdup (pango_font_description_get_family
+ (fd));
+ ind_config->font_size =
+ pango_font_description_get_size (fd) /
+ PANGO_SCALE;
+ }
+ }
+ xkl_debug (150, "font: [%s], size %d\n", ind_config->font_family,
+ ind_config->font_size);
+
+}
+
+static void
+matekbd_indicator_config_load_colors (MatekbdIndicatorConfig * ind_config)
+{
+ GError *gerror = NULL;
+
+ ind_config->foreground_color =
+ mateconf_client_get_string (ind_config->conf_client,
+ MATEKBD_INDICATOR_CONFIG_KEY_FOREGROUND_COLOR,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+
+ if (ind_config->foreground_color == NULL ||
+ ind_config->foreground_color[0] == '\0') {
+ GtkStyle *style =
+ gtk_rc_get_style_by_paths (gtk_settings_get_default (),
+ GTK_STYLE_PATH,
+ GTK_STYLE_PATH,
+ GTK_TYPE_LABEL);
+ if (style != NULL) {
+ ind_config->foreground_color =
+ g_strdup_printf ("%g %g %g", ((double)
+ style->
+ fg
+ [GTK_STATE_NORMAL].red)
+ / 0x10000, ((double)
+ style->
+ fg
+ [GTK_STATE_NORMAL].green)
+ / 0x10000, ((double)
+ style->
+ fg
+ [GTK_STATE_NORMAL].blue)
+ / 0x10000);
+ }
+
+ }
+
+ ind_config->background_color =
+ mateconf_client_get_string (ind_config->conf_client,
+ MATEKBD_INDICATOR_CONFIG_KEY_BACKGROUND_COLOR,
+ &gerror);
+ if (gerror != NULL) {
+ g_warning ("Error reading configuration:%s\n",
+ gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+}
+
+void
+matekbd_indicator_config_refresh_style (MatekbdIndicatorConfig * ind_config)
+{
+ g_free (ind_config->font_family);
+ g_free (ind_config->foreground_color);
+ g_free (ind_config->background_color);
+ matekbd_indicator_config_load_font (ind_config);
+ matekbd_indicator_config_load_colors (ind_config);
+}
+
+char *
+matekbd_indicator_config_get_images_file (MatekbdIndicatorConfig *
+ ind_config,
+ MatekbdKeyboardConfig *
+ kbd_config, int group)
+{
+ char *image_file = NULL;
+ GtkIconInfo *icon_info = NULL;
+
+ if (!ind_config->show_flags)
+ return NULL;
+
+ if ((kbd_config->layouts_variants != NULL) &&
+ (g_slist_length (kbd_config->layouts_variants) > group)) {
+ char *full_layout_name = (char *)
+ g_slist_nth_data (kbd_config->layouts_variants, group);
+
+ if (full_layout_name != NULL) {
+ char *l, *v;
+ matekbd_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
+matekbd_indicator_config_load_image_filenames (MatekbdIndicatorConfig *
+ ind_config,
+ MatekbdKeyboardConfig *
+ kbd_config)
+{
+ int i;
+ ind_config->image_filenames = NULL;
+
+ if (!ind_config->show_flags)
+ return;
+
+ for (i = xkl_engine_get_max_num_groups (ind_config->engine);
+ --i >= 0;) {
+ char *image_file =
+ matekbd_indicator_config_get_images_file (ind_config,
+ kbd_config,
+ i);
+ ind_config->image_filenames =
+ g_slist_prepend (ind_config->image_filenames,
+ image_file);
+ }
+}
+
+void
+matekbd_indicator_config_free_image_filenames (MatekbdIndicatorConfig *
+ ind_config)
+{
+ while (ind_config->image_filenames) {
+ if (ind_config->image_filenames->data)
+ g_free (ind_config->image_filenames->data);
+ ind_config->image_filenames =
+ g_slist_delete_link (ind_config->image_filenames,
+ ind_config->image_filenames);
+ }
+}
+
+void
+matekbd_indicator_config_init (MatekbdIndicatorConfig * ind_config,
+ MateConfClient * conf_client, XklEngine * engine)
+{
+ GError *gerror = NULL;
+ gchar *sp;
+
+ memset (ind_config, 0, sizeof (*ind_config));
+ ind_config->conf_client = conf_client;
+ ind_config->engine = engine;
+ g_object_ref (ind_config->conf_client);
+
+ mateconf_client_add_dir (ind_config->conf_client,
+ MATEKBD_INDICATOR_CONFIG_DIR,
+ MATECONF_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 ();
+
+ 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);
+}
+
+void
+matekbd_indicator_config_term (MatekbdIndicatorConfig * ind_config)
+{
+ g_free (ind_config->font_family);
+ ind_config->font_family = NULL;
+
+ g_free (ind_config->foreground_color);
+ ind_config->foreground_color = NULL;
+
+ g_free (ind_config->background_color);
+ ind_config->background_color = NULL;
+
+ ind_config->icon_theme = NULL;
+
+ matekbd_indicator_config_free_image_filenames (ind_config);
+
+ matekbd_indicator_config_free_enabled_plugins (ind_config);
+ g_object_unref (ind_config->conf_client);
+ ind_config->conf_client = NULL;
+}
+
+void
+matekbd_indicator_config_load_from_mateconf (MatekbdIndicatorConfig * ind_config)
+{
+ GError *gerror = NULL;
+
+ ind_config->secondary_groups_mask =
+ mateconf_client_get_int (ind_config->conf_client,
+ MATEKBD_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 =
+ mateconf_client_get_bool (ind_config->conf_client,
+ MATEKBD_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;
+ }
+
+ matekbd_indicator_config_load_font (ind_config);
+ matekbd_indicator_config_load_colors (ind_config);
+
+ matekbd_indicator_config_free_enabled_plugins (ind_config);
+ ind_config->enabled_plugins =
+ mateconf_client_get_list (ind_config->conf_client,
+ MATEKBD_INDICATOR_CONFIG_KEY_ENABLED_PLUGINS,
+ MATECONF_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
+matekbd_indicator_config_save_to_mateconf (MatekbdIndicatorConfig * ind_config)
+{
+ MateConfChangeSet *cs;
+ GError *gerror = NULL;
+
+ cs = mateconf_change_set_new ();
+
+ mateconf_change_set_set_int (cs,
+ MATEKBD_INDICATOR_CONFIG_KEY_SECONDARIES,
+ ind_config->secondary_groups_mask);
+ mateconf_change_set_set_bool (cs,
+ MATEKBD_INDICATOR_CONFIG_KEY_SHOW_FLAGS,
+ ind_config->show_flags);
+ mateconf_change_set_set_list (cs,
+ MATEKBD_INDICATOR_CONFIG_KEY_ENABLED_PLUGINS,
+ MATECONF_VALUE_STRING,
+ ind_config->enabled_plugins);
+
+ mateconf_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;
+ }
+ mateconf_change_set_unref (cs);
+}
+
+void
+matekbd_indicator_config_activate (MatekbdIndicatorConfig * ind_config)
+{
+ xkl_engine_set_secondary_groups_mask (ind_config->engine,
+ ind_config->secondary_groups_mask);
+}
+
+void
+matekbd_indicator_config_start_listen (MatekbdIndicatorConfig *
+ ind_config,
+ MateConfClientNotifyFunc func,
+ gpointer user_data)
+{
+ matekbd_desktop_config_add_listener (ind_config->conf_client,
+ MATEKBD_INDICATOR_CONFIG_DIR, func,
+ user_data,
+ &ind_config->config_listener_id);
+}
+
+void
+matekbd_indicator_config_stop_listen (MatekbdIndicatorConfig * ind_config)
+{
+ matekbd_desktop_config_remove_listener (ind_config->conf_client,
+ &ind_config->config_listener_id);
+}
diff --git a/libmatekbd/matekbd-indicator-config.h b/libmatekbd/matekbd-indicator-config.h
new file mode 100644
index 0000000..d01cadc
--- /dev/null
+++ b/libmatekbd/matekbd-indicator-config.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MATEKBD_INDICATOR_CONFIG_H__
+#define __MATEKBD_INDICATOR_CONFIG_H__
+
+#include <gtk/gtk.h>
+
+#include "libmatekbd/matekbd-keyboard-config.h"
+
+/*
+ * Indicator configuration
+ */
+typedef struct _MatekbdIndicatorConfig {
+ int secondary_groups_mask;
+ gboolean show_flags;
+
+ gchar *font_family;
+ int font_size;
+ gchar *foreground_color;
+ gchar *background_color;
+
+ GSList *enabled_plugins;
+
+ /* private, transient */
+ MateConfClient *conf_client;
+ GSList *image_filenames;
+ GtkIconTheme *icon_theme;
+ int config_listener_id;
+ XklEngine *engine;
+} MatekbdIndicatorConfig;
+
+/**
+ * MatekbdIndicatorConfig functions -
+ * some of them require MatekbdKeyboardConfig as well -
+ * for loading approptiate images
+ */
+extern void matekbd_indicator_config_init (MatekbdIndicatorConfig *
+ applet_config,
+ MateConfClient * conf_client,
+ XklEngine * engine);
+extern void matekbd_indicator_config_term (MatekbdIndicatorConfig *
+ applet_config);
+
+extern void matekbd_indicator_config_load_from_mateconf (MatekbdIndicatorConfig
+ * applet_config);
+extern void matekbd_indicator_config_save_to_mateconf (MatekbdIndicatorConfig *
+ applet_config);
+
+extern void matekbd_indicator_config_refresh_style (MatekbdIndicatorConfig *
+ applet_config);
+
+extern gchar
+ * matekbd_indicator_config_get_images_file (MatekbdIndicatorConfig *
+ applet_config,
+ MatekbdKeyboardConfig *
+ kbd_config, int group);
+
+extern void matekbd_indicator_config_load_image_filenames (MatekbdIndicatorConfig
+ * applet_config,
+ MatekbdKeyboardConfig
+ * kbd_config);
+extern void matekbd_indicator_config_free_image_filenames (MatekbdIndicatorConfig
+ * applet_config);
+
+/* Should be updated on Indicator/MateConf configuration change */
+extern void matekbd_indicator_config_activate (MatekbdIndicatorConfig *
+ applet_config);
+
+extern void matekbd_indicator_config_start_listen (MatekbdIndicatorConfig *
+ applet_config,
+ MateConfClientNotifyFunc
+ func, gpointer user_data);
+
+extern void matekbd_indicator_config_stop_listen (MatekbdIndicatorConfig *
+ applet_config);
+
+#endif
diff --git a/libmatekbd/matekbd-indicator-marshal.list b/libmatekbd/matekbd-indicator-marshal.list
new file mode 100644
index 0000000..5b76282
--- /dev/null
+++ b/libmatekbd/matekbd-indicator-marshal.list
@@ -0,0 +1 @@
+VOID:VOID
diff --git a/libmatekbd/matekbd-indicator-plugin-manager.c b/libmatekbd/matekbd-indicator-plugin-manager.c
new file mode 100644
index 0000000..8236038
--- /dev/null
+++ b/libmatekbd/matekbd-indicator-plugin-manager.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <libxklavier/xklavier.h>
+
+#include <matekbd-indicator-plugin-manager.h>
+
+#define FOREACH_INITED_PLUGIN() \
+{ \
+ GSList *prec; \
+ for( prec = manager->inited_plugin_recs; prec != NULL; prec = prec->next ) \
+ { \
+ const MatekbdIndicatorPlugin *plugin = \
+ ( ( MatekbdIndicatorPluginManagerRecord * ) ( prec->data ) )->plugin; \
+ if( plugin != NULL ) \
+ {
+
+#define NEXT_INITED_PLUGIN() \
+ } \
+ } \
+}
+
+static void
+matekbd_indicator_plugin_manager_add_plugins_dir (MatekbdIndicatorPluginManager *
+ manager,
+ const char *dirname)
+{
+ GDir *dir = g_dir_open (dirname, 0, NULL);
+ const gchar *filename;
+ const MatekbdIndicatorPlugin *plugin;
+
+ 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)) {
+ plugin =
+ ((MatekbdIndicatorPluginGetPluginFunc)
+ get_plugin_func) ();
+ if (plugin != NULL) {
+ MatekbdIndicatorPluginManagerRecord
+ * rec =
+ g_new0
+ (MatekbdIndicatorPluginManagerRecord,
+ 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
+matekbd_indicator_plugin_manager_load_all (MatekbdIndicatorPluginManager *
+ manager)
+{
+ if (!g_module_supported ()) {
+ xkl_debug (0, "Modules are not supported - no plugins!\n");
+ return;
+ }
+ matekbd_indicator_plugin_manager_add_plugins_dir (manager,
+ SYS_PLUGIN_DIR);
+}
+
+static void
+matekbd_indicator_plugin_manager_rec_term (MatekbdIndicatorPluginManagerRecord *
+ rec, void *user_data)
+{
+ const MatekbdIndicatorPlugin *plugin = rec->plugin;
+ if (plugin != NULL) {
+ xkl_debug (100, "Terminating plugin: [%s]...\n",
+ plugin->name);
+ if (plugin->term_callback)
+ (*plugin->term_callback) ();
+ }
+}
+
+static void
+matekbd_indicator_plugin_manager_rec_destroy (MatekbdIndicatorPluginManagerRecord
+ * rec)
+{
+ xkl_debug (100, "Unloading plugin: [%s]...\n", rec->plugin->name);
+
+ g_module_close (rec->module);
+ g_free (rec);
+}
+
+void
+matekbd_indicator_plugin_manager_init (MatekbdIndicatorPluginManager * manager)
+{
+ manager->all_plugin_recs =
+ g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify)
+ matekbd_indicator_plugin_manager_rec_destroy);
+ matekbd_indicator_plugin_manager_load_all (manager);
+}
+
+void
+matekbd_indicator_plugin_manager_term (MatekbdIndicatorPluginManager * manager)
+{
+ matekbd_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
+ matekbd_indicator_plugin_manager_init_enabled_plugins
+ (MatekbdIndicatorPluginManager * manager,
+ MatekbdIndicatorPluginContainer * 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) {
+ MatekbdIndicatorPluginManagerRecord *rec =
+ (MatekbdIndicatorPluginManagerRecord *)
+ g_hash_table_lookup (manager->all_plugin_recs,
+ full_path);
+
+ if (rec != NULL) {
+ const MatekbdIndicatorPlugin *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
+ matekbd_indicator_plugin_manager_term_initialized_plugins
+ (MatekbdIndicatorPluginManager * manager) {
+
+ if (manager->inited_plugin_recs == NULL)
+ return;
+ g_slist_foreach (manager->inited_plugin_recs,
+ (GFunc) matekbd_indicator_plugin_manager_rec_term,
+ NULL);
+ g_slist_free (manager->inited_plugin_recs);
+ manager->inited_plugin_recs = NULL;
+}
+
+void
+matekbd_indicator_plugin_manager_toggle_plugins (MatekbdIndicatorPluginManager *
+ manager,
+ MatekbdIndicatorPluginContainer
+ * pc,
+ GSList * enabled_plugins)
+{
+ matekbd_indicator_plugin_manager_term_initialized_plugins (manager);
+ matekbd_indicator_plugin_manager_init_enabled_plugins (manager, pc,
+ enabled_plugins);
+}
+
+void
+matekbd_indicator_plugin_manager_group_changed (MatekbdIndicatorPluginManager *
+ 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
+matekbd_indicator_plugin_manager_config_changed (MatekbdIndicatorPluginManager *
+ manager,
+ MatekbdKeyboardConfig * from,
+ MatekbdKeyboardConfig * to)
+{
+ FOREACH_INITED_PLUGIN ();
+ if (plugin->config_changed_callback)
+ (*plugin->config_changed_callback) (from, to);
+ NEXT_INITED_PLUGIN ();
+}
+
+const MatekbdIndicatorPlugin *
+matekbd_indicator_plugin_manager_get_plugin (MatekbdIndicatorPluginManager *
+ manager, const char *full_path)
+{
+ MatekbdIndicatorPluginManagerRecord *rec =
+ (MatekbdIndicatorPluginManagerRecord *)
+ g_hash_table_lookup (manager->all_plugin_recs,
+ full_path);
+ if (rec == NULL)
+ return NULL;
+ return rec->plugin;
+}
+
+void
+matekbd_indicator_plugin_manager_promote_plugin (MatekbdIndicatorPluginManager *
+ 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
+matekbd_indicator_plugin_manager_demote_plugin (MatekbdIndicatorPluginManager *
+ 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
+matekbd_indicator_plugin_manager_enable_plugin (MatekbdIndicatorPluginManager *
+ manager,
+ GSList ** enabled_plugins,
+ const char *full_path)
+{
+ if (NULL !=
+ matekbd_indicator_plugin_manager_get_plugin (manager,
+ full_path)) {
+ *enabled_plugins =
+ g_slist_append (*enabled_plugins,
+ (gpointer) g_strdup (full_path));
+ }
+}
+
+void
+matekbd_indicator_plugin_manager_disable_plugin (MatekbdIndicatorPluginManager *
+ 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
+matekbd_indicator_plugin_manager_window_created (MatekbdIndicatorPluginManager *
+ 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 *
+matekbd_indicator_plugin_manager_decorate_widget (MatekbdIndicatorPluginManager *
+ manager, GtkWidget * widget,
+ const gint group,
+ const char
+ *group_description,
+ MatekbdKeyboardConfig *
+ 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
+matekbd_indicator_plugin_manager_configure_plugin (MatekbdIndicatorPluginManager
+ * manager,
+ MatekbdIndicatorPluginContainer
+ * pc,
+ const char *full_path,
+ GtkWindow * parent)
+{
+ const MatekbdIndicatorPlugin *plugin =
+ matekbd_indicator_plugin_manager_get_plugin (manager, full_path);
+ if (plugin->configure_properties_callback != NULL)
+ plugin->configure_properties_callback (pc, parent);
+}
+
+void
+matekbd_indicator_plugin_container_init (MatekbdIndicatorPluginContainer * pc,
+ MateConfClient * conf_client)
+{
+ pc->conf_client = conf_client;
+ g_object_ref (pc->conf_client);
+}
+
+void
+matekbd_indicator_plugin_container_term (MatekbdIndicatorPluginContainer * pc)
+{
+ g_object_unref (pc->conf_client);
+}
diff --git a/libmatekbd/matekbd-indicator-plugin-manager.h b/libmatekbd/matekbd-indicator-plugin-manager.h
new file mode 100644
index 0000000..416bdab
--- /dev/null
+++ b/libmatekbd/matekbd-indicator-plugin-manager.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GSWITCHIT_PLUGIN_MANAGER_H__
+#define __GSWITCHIT_PLUGIN_MANAGER_H__
+
+#include <gmodule.h>
+#include <libmatekbd/matekbd-indicator-plugin.h>
+
+typedef struct _MatekbdIndicatorPluginManager {
+ GHashTable *all_plugin_recs;
+ GSList *inited_plugin_recs;
+} MatekbdIndicatorPluginManager;
+
+typedef struct _MatekbdIndicatorPluginManagerRecord {
+ const char *full_path;
+ GModule *module;
+ const MatekbdIndicatorPlugin *plugin;
+} MatekbdIndicatorPluginManagerRecord;
+
+extern void
+ matekbd_indicator_plugin_manager_init (MatekbdIndicatorPluginManager * manager);
+
+extern void
+ matekbd_indicator_plugin_manager_term (MatekbdIndicatorPluginManager * manager);
+
+extern void
+ matekbd_indicator_plugin_manager_init_enabled_plugins (MatekbdIndicatorPluginManager * manager,
+ MatekbdIndicatorPluginContainer
+ * pc,
+ GSList *
+ enabled_plugins);
+
+extern void
+ matekbd_indicator_plugin_manager_term_initialized_plugins (MatekbdIndicatorPluginManager * manager);
+
+extern void
+ matekbd_indicator_plugin_manager_toggle_plugins (MatekbdIndicatorPluginManager * manager,
+ MatekbdIndicatorPluginContainer
+ * pc,
+ GSList * enabled_plugins);
+
+extern const MatekbdIndicatorPlugin
+ *
+matekbd_indicator_plugin_manager_get_plugin (MatekbdIndicatorPluginManager *
+ manager, const char *full_path);
+
+extern void
+ matekbd_indicator_plugin_manager_promote_plugin (MatekbdIndicatorPluginManager * manager,
+ GSList * enabled_plugins,
+ const char *full_path);
+
+extern void
+ matekbd_indicator_plugin_manager_demote_plugin (MatekbdIndicatorPluginManager * manager,
+ GSList * enabled_plugins,
+ const char *full_path);
+
+extern void
+ matekbd_indicator_plugin_manager_enable_plugin (MatekbdIndicatorPluginManager * manager,
+ GSList ** enabled_plugins,
+ const char *full_path);
+
+extern void
+ matekbd_indicator_plugin_manager_disable_plugin (MatekbdIndicatorPluginManager * manager,
+ GSList ** enabled_plugins,
+ const char *full_path);
+
+extern void
+ matekbd_indicator_plugin_manager_configure_plugin (MatekbdIndicatorPluginManager * manager,
+ MatekbdIndicatorPluginContainer
+ * pc,
+ const char *full_path,
+ GtkWindow * parent);
+
+/* actual calling plugin notification methods */
+
+extern void
+ matekbd_indicator_plugin_manager_group_changed (MatekbdIndicatorPluginManager * manager,
+ GtkWidget * notebook,
+ int new_group);
+
+extern void
+ matekbd_indicator_plugin_manager_config_changed (MatekbdIndicatorPluginManager * manager,
+ MatekbdKeyboardConfig * from,
+ MatekbdKeyboardConfig * to);
+
+extern int
+ matekbd_indicator_plugin_manager_window_created (MatekbdIndicatorPluginManager * manager,
+ Window win, Window parent);
+
+extern GtkWidget
+ *
+matekbd_indicator_plugin_manager_decorate_widget (MatekbdIndicatorPluginManager *
+ manager, GtkWidget * widget,
+ const gint group, const char
+ *group_description,
+ MatekbdKeyboardConfig *
+ config);
+
+#endif
diff --git a/libmatekbd/matekbd-indicator-plugin.h b/libmatekbd/matekbd-indicator-plugin.h
new file mode 100644
index 0000000..c1398c0
--- /dev/null
+++ b/libmatekbd/matekbd-indicator-plugin.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MATEKBD_INDICATOR_PLUGIN_H__
+#define __MATEKBD_INDICATOR_PLUGIN_H__
+
+#include <gtk/gtk.h>
+#include <mateconf/mateconf-client.h>
+#include <libmatekbd/matekbd-keyboard-config.h>
+
+#define MAX_LOCAL_NAME_BUF_LENGTH 512
+
+struct _MatekbdIndicatorPlugin;
+
+typedef struct _MatekbdIndicatorPluginContainer {
+ MateConfClient *conf_client;
+} MatekbdIndicatorPluginContainer;
+
+typedef const struct _MatekbdIndicatorPlugin
+*(*MatekbdIndicatorPluginGetPluginFunc) (void);
+
+typedef
+ gboolean (*MatekbdIndicatorPluginInitFunc) (MatekbdIndicatorPluginContainer *
+ pc);
+
+typedef void (*MatekbdIndicatorPluginGroupChangedFunc) (GtkWidget * notebook,
+ int new_group);
+
+typedef void (*MatekbdIndicatorPluginConfigChangedFunc) (const
+ MatekbdKeyboardConfig *
+ from,
+ const
+ MatekbdKeyboardConfig *
+ to);
+
+typedef int (*MatekbdIndicatorPluginWindowCreatedFunc) (const Window win,
+ const Window parent);
+
+typedef void (*MatekbdIndicatorPluginTermFunc) (void);
+
+typedef GtkWidget *(*MatekbdIndicatorPluginCreateWidget) (void);
+
+typedef GtkWidget *(*MatekbdIndicatorPluginDecorateWidget) (GtkWidget *
+ widget,
+ const gint group,
+ const char
+ *group_description,
+ MatekbdKeyboardConfig
+ * config);
+
+typedef
+void (*MatekbdIndicatorPluginConfigureProperties)
+ (MatekbdIndicatorPluginContainer * pc, GtkWindow * parent);
+
+typedef struct _MatekbdIndicatorPlugin {
+ const char *name;
+
+ const char *description;
+
+/* implemented */
+ MatekbdIndicatorPluginInitFunc init_callback;
+
+/* implemented */
+ MatekbdIndicatorPluginTermFunc term_callback;
+
+/* implemented */
+ MatekbdIndicatorPluginConfigureProperties
+ configure_properties_callback;
+
+/* implemented */
+ MatekbdIndicatorPluginGroupChangedFunc group_changed_callback;
+
+/* implemented */
+ MatekbdIndicatorPluginWindowCreatedFunc window_created_callback;
+
+/* implemented */
+ MatekbdIndicatorPluginDecorateWidget decorate_widget_callback;
+
+/* not implemented */
+ MatekbdIndicatorPluginConfigChangedFunc config_changed_callback;
+
+/* not implemented */
+ MatekbdIndicatorPluginCreateWidget create_widget_callback;
+
+} MatekbdIndicatorPlugin;
+
+/**
+ * Functions accessible for plugins
+ */
+
+extern void
+ matekbd_indicator_plugin_container_init (MatekbdIndicatorPluginContainer * pc,
+ MateConfClient * conf_client);
+
+extern void
+ matekbd_indicator_plugin_container_term (MatekbdIndicatorPluginContainer * pc);
+
+extern void
+ matekbd_indicator_plugin_container_reinit_ui (MatekbdIndicatorPluginContainer * pc);
+
+extern guint
+matekbd_indicator_plugin_get_num_groups (MatekbdIndicatorPluginContainer * pc);
+
+extern gchar
+ **
+ matekbd_indicator_plugin_load_localized_group_names
+ (MatekbdIndicatorPluginContainer * pc);
+
+#endif
diff --git a/libmatekbd/matekbd-indicator.c b/libmatekbd/matekbd-indicator.c
new file mode 100644
index 0000000..c4928aa
--- /dev/null
+++ b/libmatekbd/matekbd-indicator.c
@@ -0,0 +1,968 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <memory.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gdk/gdkx.h>
+#include <glib/gi18n.h>
+
+#include <matekbd-indicator.h>
+#include <matekbd-indicator-marshal.h>
+
+#include <matekbd-desktop-config.h>
+#include <matekbd-indicator-config.h>
+
+#include <matekbd-indicator-plugin-manager.h>
+
+typedef struct _gki_globals {
+ XklEngine *engine;
+ XklConfigRegistry *registry;
+
+ MatekbdDesktopConfig cfg;
+ MatekbdIndicatorConfig ind_cfg;
+ MatekbdKeyboardConfig kbd_cfg;
+
+ MatekbdIndicatorPluginContainer plugin_container;
+ MatekbdIndicatorPluginManager plugin_manager;
+
+ const gchar *tooltips_format;
+ gchar **full_group_names;
+ gchar **short_group_names;
+ GSList *widget_instances;
+ GSList *images;
+} gki_globals;
+
+struct _MatekbdIndicatorPrivate {
+ 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) { \
+ MatekbdIndicator * gki = (MatekbdIndicator*)cur->data;
+#define NextIndicator() \
+ } \
+ }
+
+G_DEFINE_TYPE (MatekbdIndicator, matekbd_indicator, GTK_TYPE_NOTEBOOK)
+
+static void
+matekbd_indicator_global_init (void);
+static void
+matekbd_indicator_global_term (void);
+static GtkWidget *
+matekbd_indicator_prepare_drawing (MatekbdIndicator * gki, int group);
+static void
+matekbd_indicator_set_current_page_for_group (MatekbdIndicator * gki, int group);
+static void
+matekbd_indicator_set_current_page (MatekbdIndicator * gki);
+static void
+matekbd_indicator_cleanup (MatekbdIndicator * gki);
+static void
+matekbd_indicator_fill (MatekbdIndicator * gki);
+static void
+matekbd_indicator_set_tooltips (MatekbdIndicator * gki, const char *str);
+
+void
+matekbd_indicator_load_images ()
+{
+ int i;
+ GSList *image_filename;
+
+ globals.images = NULL;
+ matekbd_indicator_config_load_image_filenames (&globals.ind_cfg,
+ &globals.kbd_cfg);
+
+ if (!globals.ind_cfg.show_flags)
+ return;
+
+ image_filename = globals.ind_cfg.image_filenames;
+
+ for (i = xkl_engine_get_max_num_groups (globals.engine);
+ --i >= 0; image_filename = image_filename->next) {
+ GdkPixbuf *image = NULL;
+ char *image_file = (char *) image_filename->data;
+
+ if (image_file != NULL) {
+ GError *gerror = NULL;
+ image =
+ gdk_pixbuf_new_from_file (image_file, &gerror);
+ if (image == NULL) {
+ GtkWidget *dialog =
+ gtk_message_dialog_new (NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _
+ ("There was an error loading an image: %s"),
+ gerror->
+ message);
+ g_signal_connect (G_OBJECT (dialog),
+ "response",
+ G_CALLBACK
+ (gtk_widget_destroy),
+ NULL);
+
+ gtk_window_set_resizable (GTK_WINDOW
+ (dialog), FALSE);
+
+ gtk_widget_show (dialog);
+ g_error_free (gerror);
+ }
+ xkl_debug (150,
+ "Image %d[%s] loaded -> %p[%dx%d]\n",
+ i, image_file, image,
+ gdk_pixbuf_get_width (image),
+ gdk_pixbuf_get_height (image));
+ }
+ /* We append the image anyway - even if it is NULL! */
+ globals.images = g_slist_append (globals.images, image);
+ }
+}
+
+static void
+matekbd_indicator_free_images ()
+{
+ GdkPixbuf *pi;
+ GSList *img_node;
+
+ matekbd_indicator_config_free_image_filenames (&globals.ind_cfg);
+
+ while ((img_node = globals.images) != NULL) {
+ pi = GDK_PIXBUF (img_node->data);
+ /* It can be NULL - some images may be missing */
+ if (pi != NULL) {
+ g_object_unref (pi);
+ }
+ globals.images =
+ g_slist_remove_link (globals.images, img_node);
+ g_slist_free_1 (img_node);
+ }
+}
+
+static void
+matekbd_indicator_update_images (void)
+{
+ matekbd_indicator_free_images ();
+ matekbd_indicator_load_images ();
+}
+
+void
+matekbd_indicator_set_tooltips (MatekbdIndicator * gki, const char *str)
+{
+ g_assert (str == NULL || g_utf8_validate (str, -1, NULL));
+
+ gtk_widget_set_tooltip_text (GTK_WIDGET (gki), str);
+
+ if (gki->priv->set_parent_tooltips) {
+ GtkWidget *parent =
+ gtk_widget_get_parent (GTK_WIDGET (gki));
+ if (parent) {
+ gtk_widget_set_tooltip_text (parent, str);
+ }
+ }
+}
+
+void
+matekbd_indicator_cleanup (MatekbdIndicator * 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
+matekbd_indicator_fill (MatekbdIndicator * 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 = NULL;
+ gchar *full_group_name =
+ (grp <
+ g_strv_length (globals.full_group_names)) ?
+ globals.full_group_names[grp] : "?";
+ page = matekbd_indicator_prepare_drawing (gki, grp);
+
+ if (page == NULL)
+ page = gtk_label_new ("");
+
+ decorated_page =
+ matekbd_indicator_plugin_manager_decorate_widget
+ (&globals.plugin_manager, page, grp,
+ full_group_name, &globals.kbd_cfg);
+
+ page = decorated_page == NULL ? page : decorated_page;
+
+ gtk_notebook_append_page (notebook, page, NULL);
+ gtk_widget_show_all (page);
+ }
+}
+
+static gboolean
+matekbd_indicator_key_pressed (GtkWidget *
+ widget, GdkEventKey * event,
+ MatekbdIndicator * 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:
+ matekbd_desktop_config_lock_next_group (&globals.cfg);
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+static gboolean
+matekbd_indicator_button_pressed (GtkWidget *
+ widget,
+ GdkEventButton * event, MatekbdIndicator * gki)
+{
+ GtkWidget *img = gtk_bin_get_child (GTK_BIN (widget));
+ GtkAllocation allocation;
+ gtk_widget_get_allocation (img, &allocation);
+ xkl_debug (150, "Flag img size %d x %d\n",
+ allocation.width, allocation.height);
+ if (event->button == 1 && event->type == GDK_BUTTON_PRESS) {
+ xkl_debug (150, "Mouse button pressed on applet\n");
+ matekbd_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);
+ GtkAllocation allocation;
+ double xwiratio, ywiratio, wiratio;
+ cairo_t *cr;
+
+ gtk_widget_get_allocation (flag, &allocation);
+
+ cr = gdk_cairo_create (event->window);
+ gdk_cairo_region (cr, event->region);
+ cairo_clip (cr);
+
+ /* widget-to-image scales, X and Y */
+ xwiratio = 1.0 * allocation.width / iw;
+ ywiratio = 1.0 * allocation.height / ih;
+ wiratio = xwiratio < ywiratio ? xwiratio : ywiratio;
+
+ /* transform cairo context */
+ cairo_translate (cr, allocation.width / 2.0, allocation.height / 2.0);
+ cairo_scale (cr, wiratio, wiratio);
+ cairo_translate (cr, - iw / 2.0, - ih / 2.0);
+
+ gdk_cairo_set_source_pixbuf (cr, image, 0, 0);
+ cairo_paint (cr);
+
+ cairo_destroy (cr);
+}
+
+gchar *
+matekbd_indicator_extract_layout_name (int group, XklEngine * engine,
+ MatekbdKeyboardConfig * kbd_cfg,
+ gchar ** short_group_names,
+ gchar ** full_group_names)
+{
+ char *layout_name = NULL;
+ if (group < g_strv_length (short_group_names)) {
+ if (xkl_engine_get_features (engine) &
+ XKLF_MULTIPLE_LAYOUTS_SUPPORTED) {
+ char *full_layout_name = (char *)
+ g_slist_nth_data (kbd_cfg->layouts_variants,
+ group);
+ char *variant_name;
+ if (!matekbd_keyboard_config_split_items
+ (full_layout_name, &layout_name,
+ &variant_name))
+ /* just in case */
+ layout_name = full_layout_name;
+
+ /* make it freeable */
+ layout_name = g_strdup (layout_name);
+
+ if (short_group_names != NULL) {
+ char *short_group_name =
+ short_group_names[group];
+ if (short_group_name != NULL
+ && *short_group_name != '\0') {
+ /* drop the long name */
+ g_free (layout_name);
+ layout_name =
+ g_strdup (short_group_name);
+ }
+ }
+ } else {
+ layout_name = g_strdup (full_group_names[group]);
+ }
+ }
+
+ if (layout_name == NULL)
+ layout_name = g_strdup ("");
+
+ return layout_name;
+}
+
+gchar *
+matekbd_indicator_create_label_title (int group, GHashTable ** ln2cnt_map,
+ gchar * layout_name)
+{
+ gpointer pcounter = NULL;
+ char *prev_layout_name = NULL;
+ char *lbl_title = NULL;
+ int counter = 0;
+
+ if (group == 0) {
+ *ln2cnt_map =
+ g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+ }
+
+ /* Process layouts with repeating description */
+ if (g_hash_table_lookup_extended
+ (*ln2cnt_map, layout_name, (gpointer *) & prev_layout_name,
+ &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 (*ln2cnt_map, layout_name,
+ GINT_TO_POINTER (counter + 1));
+ return lbl_title;
+}
+
+static GtkWidget *
+matekbd_indicator_prepare_drawing (MatekbdIndicator * gki, int group)
+{
+ gpointer pimage;
+ GdkPixbuf *image;
+ GtkWidget *ebox;
+
+ pimage = g_slist_nth_data (globals.images, group);
+ ebox = gtk_event_box_new ();
+ gtk_event_box_set_visible_window (GTK_EVENT_BOX (ebox), FALSE);
+ if (globals.ind_cfg.show_flags) {
+ GtkWidget *flag;
+ if (pimage == NULL)
+ return NULL;
+ image = GDK_PIXBUF (pimage);
+ flag = gtk_drawing_area_new ();
+ gtk_widget_add_events (GTK_WIDGET (flag),
+ GDK_BUTTON_PRESS_MASK);
+ g_signal_connect (G_OBJECT (flag), "expose_event",
+ G_CALLBACK (flag_exposed), image);
+ gtk_container_add (GTK_CONTAINER (ebox), flag);
+ } else {
+ char *lbl_title = NULL;
+ char *layout_name = NULL;
+ GtkWidget *align, *label;
+ static GHashTable *ln2cnt_map = NULL;
+
+ layout_name =
+ matekbd_indicator_extract_layout_name (group,
+ globals.engine,
+ &globals.kbd_cfg,
+ globals.short_group_names,
+ globals.full_group_names);
+
+ lbl_title =
+ matekbd_indicator_create_label_title (group,
+ &ln2cnt_map,
+ layout_name);
+
+ 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 + 1 ==
+ xkl_engine_get_num_groups (globals.engine)) {
+ g_hash_table_destroy (ln2cnt_map);
+ ln2cnt_map = 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 (matekbd_indicator_button_pressed), gki);
+
+ g_signal_connect (G_OBJECT (gki),
+ "key_press_event",
+ G_CALLBACK (matekbd_indicator_key_pressed), gki);
+
+ /* We have everything prepared for that size */
+
+ return ebox;
+}
+
+static void
+matekbd_indicator_update_tooltips (MatekbdIndicator * gki)
+{
+ XklState *state = xkl_engine_get_current_state (globals.engine);
+ gchar *buf;
+ if (state == NULL || state->group < 0
+ || state->group >= g_strv_length (globals.full_group_names))
+ return;
+
+ buf = g_strdup_printf (globals.tooltips_format,
+ globals.full_group_names[state->group]);
+
+ matekbd_indicator_set_tooltips (gki, buf);
+ g_free (buf);
+}
+
+static void
+matekbd_indicator_parent_set (GtkWidget * gki, GtkWidget * previous_parent)
+{
+ matekbd_indicator_update_tooltips (MATEKBD_INDICATOR (gki));
+}
+
+
+void
+matekbd_indicator_reinit_ui (MatekbdIndicator * gki)
+{
+ matekbd_indicator_cleanup (gki);
+ matekbd_indicator_fill (gki);
+
+ matekbd_indicator_set_current_page (gki);
+
+ g_signal_emit_by_name (gki, "reinit-ui");
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_indicator_cfg_changed (MateConfClient * client,
+ guint cnxn_id, MateConfEntry * entry)
+{
+ xkl_debug (100,
+ "General configuration changed in MateConf - reiniting...\n");
+ matekbd_desktop_config_load_from_mateconf (&globals.cfg);
+ matekbd_desktop_config_activate (&globals.cfg);
+ ForAllIndicators () {
+ matekbd_indicator_reinit_ui (gki);
+ } NextIndicator ();
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_indicator_ind_cfg_changed (MateConfClient * client,
+ guint cnxn_id, MateConfEntry * entry)
+{
+ xkl_debug (100,
+ "Applet configuration changed in MateConf - reiniting...\n");
+ matekbd_indicator_config_load_from_mateconf (&globals.ind_cfg);
+ matekbd_indicator_update_images ();
+ matekbd_indicator_config_activate (&globals.ind_cfg);
+
+ matekbd_indicator_plugin_manager_toggle_plugins
+ (&globals.plugin_manager, &globals.plugin_container,
+ globals.ind_cfg.enabled_plugins);
+
+ ForAllIndicators () {
+ matekbd_indicator_reinit_ui (gki);
+ } NextIndicator ();
+}
+
+static void
+matekbd_indicator_load_group_names (const gchar ** layout_ids,
+ const gchar ** variant_ids)
+{
+ if (!matekbd_desktop_config_load_group_descriptions
+ (&globals.cfg, globals.registry, layout_ids, variant_ids,
+ &globals.short_group_names, &globals.full_group_names)) {
+ /* We just populate no short names (remain NULL) -
+ * full names are going to be used anyway */
+ gint i, total_groups =
+ xkl_engine_get_num_groups (globals.engine);
+ globals.full_group_names =
+ g_new0 (char *, total_groups + 1);
+
+ if (xkl_engine_get_features (globals.engine) &
+ XKLF_MULTIPLE_LAYOUTS_SUPPORTED) {
+ GSList *lst = globals.kbd_cfg.layouts_variants;
+ for (i = 0; lst; lst = lst->next, i++) {
+ globals.full_group_names[i] =
+ g_strdup ((char *) lst->data);
+ }
+ } else {
+ for (i = total_groups; --i >= 0;) {
+ globals.full_group_names[i] =
+ g_strdup_printf ("Group %d", i);
+ }
+ }
+ }
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_indicator_kbd_cfg_callback (MatekbdIndicator * gki)
+{
+ XklConfigRec *xklrec = xkl_config_rec_new ();
+ xkl_debug (100,
+ "XKB configuration changed on X Server - reiniting...\n");
+
+ matekbd_keyboard_config_load_from_x_current (&globals.kbd_cfg,
+ xklrec);
+ matekbd_indicator_update_images ();
+
+ g_strfreev (globals.full_group_names);
+ globals.full_group_names = NULL;
+
+ if (globals.short_group_names != NULL) {
+ g_strfreev (globals.short_group_names);
+ globals.short_group_names = NULL;
+ }
+
+ matekbd_indicator_load_group_names ((const gchar **) xklrec->layouts,
+ (const gchar **)
+ xklrec->variants);
+
+ ForAllIndicators () {
+ matekbd_indicator_reinit_ui (gki);
+ } NextIndicator ();
+ g_object_unref (G_OBJECT (xklrec));
+}
+
+/* Should be called once for all applets */
+static void
+matekbd_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 () {
+ matekbd_indicator_plugin_manager_group_changed
+ (&globals.plugin_manager, GTK_WIDGET (gki),
+ group);
+ xkl_debug (200, "do repaint\n");
+ matekbd_indicator_set_current_page_for_group
+ (gki, group);
+ }
+ NextIndicator ();
+ }
+}
+
+
+void
+matekbd_indicator_set_current_page (MatekbdIndicator * gki)
+{
+ XklState *cur_state;
+ cur_state = xkl_engine_get_current_state (globals.engine);
+ if (cur_state->group >= 0)
+ matekbd_indicator_set_current_page_for_group (gki,
+ cur_state->
+ group);
+}
+
+void
+matekbd_indicator_set_current_page_for_group (MatekbdIndicator * gki, int group)
+{
+ xkl_debug (200, "Revalidating for group %d\n", group);
+
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (gki), group + 1);
+
+ matekbd_indicator_update_tooltips (gki);
+}
+
+/* Should be called once for all widgets */
+static GdkFilterReturn
+matekbd_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
+matekbd_indicator_start_listen (void)
+{
+ gdk_window_add_filter (NULL, (GdkFilterFunc)
+ matekbd_indicator_filter_x_evt, NULL);
+ gdk_window_add_filter (gdk_get_default_root_window (),
+ (GdkFilterFunc)
+ matekbd_indicator_filter_x_evt, NULL);
+
+ xkl_engine_start_listen (globals.engine,
+ XKLL_TRACK_KEYBOARD_STATE);
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_indicator_stop_listen (void)
+{
+ xkl_engine_stop_listen (globals.engine, XKLL_TRACK_KEYBOARD_STATE);
+
+ gdk_window_remove_filter (NULL, (GdkFilterFunc)
+ matekbd_indicator_filter_x_evt, NULL);
+ gdk_window_remove_filter
+ (gdk_get_default_root_window (),
+ (GdkFilterFunc) matekbd_indicator_filter_x_evt, NULL);
+}
+
+static gboolean
+matekbd_indicator_scroll (GtkWidget * gki, GdkEventScroll * event)
+{
+ /* mouse wheel events should be ignored, otherwise funny effects appear */
+ return TRUE;
+}
+
+static void
+matekbd_indicator_init (MatekbdIndicator * gki)
+{
+ GtkWidget *def_drawing;
+ GtkNotebook *notebook;
+
+ if (!g_slist_length (globals.widget_instances))
+ matekbd_indicator_global_init ();
+
+ gki->priv = g_new0 (MatekbdIndicatorPrivate, 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) {
+ matekbd_indicator_set_tooltips (gki,
+ _
+ ("XKB initialization error"));
+ return;
+ }
+
+ matekbd_indicator_set_tooltips (gki, NULL);
+
+ matekbd_indicator_fill (gki);
+ matekbd_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
+matekbd_indicator_finalize (GObject * obj)
+{
+ MatekbdIndicator *gki = MATEKBD_INDICATOR (obj);
+ xkl_debug (100,
+ "Starting the mate-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);
+
+ matekbd_indicator_cleanup (gki);
+
+ xkl_debug (100,
+ "The instance of mate-kbd-indicator successfully finalized\n");
+
+ g_free (gki->priv);
+
+ G_OBJECT_CLASS (matekbd_indicator_parent_class)->finalize (obj);
+
+ if (!g_slist_length (globals.widget_instances))
+ matekbd_indicator_global_term ();
+}
+
+static void
+matekbd_indicator_global_term (void)
+{
+ xkl_debug (100, "*** Last MatekbdIndicator instance *** \n");
+ matekbd_indicator_stop_listen ();
+
+ matekbd_desktop_config_stop_listen (&globals.cfg);
+ matekbd_indicator_config_stop_listen (&globals.ind_cfg);
+
+ matekbd_indicator_plugin_manager_term_initialized_plugins
+ (&globals.plugin_manager);
+ matekbd_indicator_plugin_manager_term (&globals.plugin_manager);
+
+ matekbd_indicator_config_term (&globals.ind_cfg);
+ matekbd_keyboard_config_term (&globals.kbd_cfg);
+ matekbd_desktop_config_term (&globals.cfg);
+
+ matekbd_indicator_plugin_container_term (&globals.plugin_container);
+
+ g_object_unref (G_OBJECT (globals.registry));
+ globals.registry = NULL;
+ g_object_unref (G_OBJECT (globals.engine));
+ globals.engine = NULL;
+ xkl_debug (100, "*** Terminated globals *** \n");
+}
+
+static void
+matekbd_indicator_class_init (MatekbdIndicatorClass * klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ xkl_debug (100, "*** First MatekbdIndicator instance *** \n");
+
+ memset (&globals, 0, sizeof (globals));
+
+ /* Initing some global vars */
+ globals.tooltips_format = "%s";
+
+ /* Initing vtable */
+ object_class->finalize = matekbd_indicator_finalize;
+
+ widget_class->scroll_event = matekbd_indicator_scroll;
+ widget_class->parent_set = matekbd_indicator_parent_set;
+
+ /* Signals */
+ g_signal_new ("reinit-ui", MATEKBD_TYPE_INDICATOR,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (MatekbdIndicatorClass, reinit_ui),
+ NULL, NULL, matekbd_indicator_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+matekbd_indicator_global_init (void)
+{
+ MateConfClient *mateconf_client;
+ XklConfigRec *xklrec = xkl_config_rec_new ();
+
+ globals.engine = xkl_engine_get_instance (GDK_DISPLAY ());
+ if (globals.engine == NULL) {
+ xkl_debug (0, "Libxklavier initialization error");
+ return;
+ }
+
+ mateconf_client = mateconf_client_get_default ();
+
+ g_signal_connect (globals.engine, "X-state-changed",
+ G_CALLBACK (matekbd_indicator_state_callback),
+ NULL);
+ g_signal_connect (globals.engine, "X-config-changed",
+ G_CALLBACK (matekbd_indicator_kbd_cfg_callback),
+ NULL);
+
+ matekbd_indicator_plugin_container_init (&globals.plugin_container,
+ mateconf_client);
+
+ matekbd_desktop_config_init (&globals.cfg, mateconf_client,
+ globals.engine);
+ matekbd_keyboard_config_init (&globals.kbd_cfg, mateconf_client,
+ globals.engine);
+ matekbd_indicator_config_init (&globals.ind_cfg, mateconf_client,
+ globals.engine);
+
+ g_object_unref (mateconf_client);
+
+ matekbd_desktop_config_load_from_mateconf (&globals.cfg);
+ matekbd_desktop_config_activate (&globals.cfg);
+
+ globals.registry =
+ xkl_config_registry_get_instance (globals.engine);
+ xkl_config_registry_load (globals.registry,
+ globals.cfg.load_extra_items);
+
+ matekbd_keyboard_config_load_from_x_current (&globals.kbd_cfg,
+ xklrec);
+
+ matekbd_indicator_config_load_from_mateconf (&globals.ind_cfg);
+ matekbd_indicator_update_images ();
+ matekbd_indicator_config_activate (&globals.ind_cfg);
+
+ matekbd_indicator_load_group_names ((const gchar **) xklrec->layouts,
+ (const gchar **)
+ xklrec->variants);
+ g_object_unref (G_OBJECT (xklrec));
+
+ matekbd_indicator_plugin_manager_init (&globals.plugin_manager);
+ matekbd_indicator_plugin_manager_init_enabled_plugins
+ (&globals.plugin_manager, &globals.plugin_container,
+ globals.ind_cfg.enabled_plugins);
+ matekbd_desktop_config_start_listen (&globals.cfg,
+ (MateConfClientNotifyFunc)
+ matekbd_indicator_cfg_changed,
+ NULL);
+ matekbd_indicator_config_start_listen (&globals.ind_cfg,
+ (MateConfClientNotifyFunc)
+ matekbd_indicator_ind_cfg_changed,
+ NULL);
+ matekbd_indicator_start_listen ();
+
+ xkl_debug (100, "*** Inited globals *** \n");
+}
+
+GtkWidget *
+matekbd_indicator_new (void)
+{
+ return
+ GTK_WIDGET (g_object_new (matekbd_indicator_get_type (), NULL));
+}
+
+void
+matekbd_indicator_set_parent_tooltips (MatekbdIndicator * gki, gboolean spt)
+{
+ gki->priv->set_parent_tooltips = spt;
+ matekbd_indicator_update_tooltips (gki);
+}
+
+void
+matekbd_indicator_set_tooltips_format (const gchar format[])
+{
+ globals.tooltips_format = format;
+ ForAllIndicators ()
+ matekbd_indicator_update_tooltips (gki);
+ NextIndicator ()
+}
+
+XklEngine *
+matekbd_indicator_get_xkl_engine ()
+{
+ return globals.engine;
+}
+
+gchar **
+matekbd_indicator_get_group_names ()
+{
+ return globals.full_group_names;
+}
+
+gchar *
+matekbd_indicator_get_image_filename (guint group)
+{
+ if (!globals.ind_cfg.show_flags)
+ return NULL;
+ return matekbd_indicator_config_get_images_file (&globals.ind_cfg,
+ &globals.kbd_cfg,
+ group);
+}
+
+gdouble
+matekbd_indicator_get_max_width_height_ratio (void)
+{
+ gdouble rv = 0.0;
+ GSList *ip = globals.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
+matekbd_indicator_set_angle (MatekbdIndicator * gki, gdouble angle)
+{
+ gki->priv->angle = angle;
+}
+
+/* Plugin support */
+/* Preserve the plugin container functions during the linking */
+void
+matekbd_indicator_plugin_container_reinit_ui (MatekbdIndicatorPluginContainer *
+ pc)
+{
+ ForAllIndicators () {
+ matekbd_indicator_reinit_ui (gki);
+ } NextIndicator ();
+}
+
+gchar **matekbd_indicator_plugin_load_localized_group_names
+ (MatekbdIndicatorPluginContainer * pc) {
+ return globals.full_group_names;
+}
diff --git a/libmatekbd/matekbd-indicator.h b/libmatekbd/matekbd-indicator.h
new file mode 100644
index 0000000..80a4f1f
--- /dev/null
+++ b/libmatekbd/matekbd-indicator.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MATEKBD_INDICATOR_H__
+#define __MATEKBD_INDICATOR_H__
+
+#include <gtk/gtk.h>
+
+#include <libxklavier/xklavier.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef struct _MatekbdIndicator MatekbdIndicator;
+ typedef struct _MatekbdIndicatorPrivate MatekbdIndicatorPrivate;
+ typedef struct _MatekbdIndicatorClass MatekbdIndicatorClass;
+
+#define MATEKBD_TYPE_INDICATOR (matekbd_indicator_get_type ())
+#define MATEKBD_INDICATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MATEKBD_TYPE_INDICATOR, MatekbdIndicator))
+#define MATEKBD_INDCATOR_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), MATEKBD_TYPE_INDICATOR, MatekbdIndicatorClass))
+#define MATEKBD_IS_INDICATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MATEKBD_TYPE_INDICATOR))
+#define MATEKBD_IS_INDICATOR_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), MATEKBD_TYPE_INDICATOR))
+#define MATEKBD_INDICATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MATEKBD_TYPE_INDICATOR, MatekbdIndicatorClass))
+
+ struct _MatekbdIndicator {
+ GtkNotebook parent;
+ MatekbdIndicatorPrivate *priv;
+ };
+
+ struct _MatekbdIndicatorClass {
+ GtkNotebookClass parent_class;
+
+ void (*reinit_ui) (MatekbdIndicator * gki);
+ };
+
+ extern GType matekbd_indicator_get_type (void);
+
+ extern GtkWidget *matekbd_indicator_new (void);
+
+ extern void matekbd_indicator_reinit_ui (MatekbdIndicator * gki);
+
+ extern void matekbd_indicator_set_angle (MatekbdIndicator * gki,
+ gdouble angle);
+
+ extern XklEngine *matekbd_indicator_get_xkl_engine (void);
+
+ extern gchar **matekbd_indicator_get_group_names (void);
+
+ extern gchar *matekbd_indicator_get_image_filename (guint group);
+
+ extern gdouble matekbd_indicator_get_max_width_height_ratio (void);
+
+ extern void
+ matekbd_indicator_set_parent_tooltips (MatekbdIndicator *
+ gki, gboolean ifset);
+
+ extern void
+ matekbd_indicator_set_tooltips_format (const gchar str[]);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/libmatekbd/matekbd-keyboard-config.c b/libmatekbd/matekbd-keyboard-config.c
new file mode 100644
index 0000000..8be2a37
--- /dev/null
+++ b/libmatekbd/matekbd-keyboard-config.c
@@ -0,0 +1,827 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <X11/keysym.h>
+
+#include <glib/gi18n.h>
+
+#include <matekbd-keyboard-config.h>
+#include <matekbd-config-private.h>
+
+/**
+ * MatekbdKeyboardConfig
+ */
+#define MATEKBD_KEYBOARD_CONFIG_KEY_PREFIX MATEKBD_CONFIG_KEY_PREFIX "/kbd"
+
+#define GROUP_SWITCHERS_GROUP "grp"
+#define DEFAULT_GROUP_SWITCH "grp:shift_caps_toggle"
+
+const gchar MATEKBD_KEYBOARD_CONFIG_DIR[] = MATEKBD_KEYBOARD_CONFIG_KEY_PREFIX;
+const gchar MATEKBD_KEYBOARD_CONFIG_KEY_MODEL[] =
+ MATEKBD_KEYBOARD_CONFIG_KEY_PREFIX "/model";
+const gchar MATEKBD_KEYBOARD_CONFIG_KEY_LAYOUTS[] =
+ MATEKBD_KEYBOARD_CONFIG_KEY_PREFIX "/layouts";
+const gchar MATEKBD_KEYBOARD_CONFIG_KEY_OPTIONS[] =
+ MATEKBD_KEYBOARD_CONFIG_KEY_PREFIX "/options";
+
+const gchar *MATEKBD_KEYBOARD_CONFIG_ACTIVE[] = {
+ MATEKBD_KEYBOARD_CONFIG_KEY_MODEL,
+ MATEKBD_KEYBOARD_CONFIG_KEY_LAYOUTS,
+ MATEKBD_KEYBOARD_CONFIG_KEY_OPTIONS
+};
+
+/**
+ * static common functions
+ */
+static void
+matekbd_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
+matekbd_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)
+{
+ /* TODO make it not static */
+ static XklConfigItem *litem = NULL;
+ static XklConfigItem *vitem = NULL;
+
+ if (litem == NULL)
+ litem = xkl_config_item_new ();
+ if (vitem == NULL)
+ vitem = xkl_config_item_new ();
+
+ 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 *
+matekbd_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 && *child != 0) {
+ if (strlen (child) >= XKL_MAX_CI_NAME_LENGTH)
+ return NULL;
+ strcat (buffer, "\t");
+ strcat (buffer, child);
+ }
+ return buffer;
+}
+
+gboolean
+matekbd_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 MatekbdKeyboardConfig functions
+ */
+static void
+matekbd_keyboard_config_options_add_full (MatekbdKeyboardConfig * kbd_config,
+ const gchar * full_option_name)
+{
+ kbd_config->options =
+ g_slist_append (kbd_config->options,
+ g_strdup (full_option_name));
+}
+
+static void
+matekbd_keyboard_config_layouts_add_full (MatekbdKeyboardConfig * kbd_config,
+ const gchar * full_layout_name)
+{
+ kbd_config->layouts_variants =
+ g_slist_append (kbd_config->layouts_variants,
+ g_strdup (full_layout_name));
+}
+
+static void
+matekbd_keyboard_config_copy_from_xkl_config (MatekbdKeyboardConfig * kbd_config,
+ XklConfigRec * pdata)
+{
+ char **p, **p1;
+ matekbd_keyboard_config_model_set (kbd_config, pdata->model);
+ xkl_debug (150, "Loaded Kbd model: [%s]\n", pdata->model);
+
+ matekbd_keyboard_config_layouts_reset (kbd_config);
+ p = pdata->layouts;
+ p1 = pdata->variants;
+ while (p != NULL && *p != NULL) {
+ const gchar *full_layout =
+ matekbd_keyboard_config_merge_items (*p, *p1);
+ xkl_debug (150,
+ "Loaded Kbd layout (with variant): [%s]\n",
+ full_layout);
+ matekbd_keyboard_config_layouts_add_full (kbd_config,
+ full_layout);
+ p++;
+ p1++;
+ }
+
+ matekbd_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);
+ matekbd_keyboard_config_options_add (kbd_config,
+ group, option);
+ }
+ p++;
+ }
+}
+
+static void
+matekbd_keyboard_config_copy_to_xkl_config (MatekbdKeyboardConfig * 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_variants ==
+ NULL) ? 0 : g_slist_length (kbd_config->layouts_variants);
+ 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_variant = kbd_config->layouts_variants;
+ 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 (matekbd_keyboard_config_split_items
+ (the_layout_variant->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_variant->data ==
+ NULL) ? g_strdup ("") :
+ g_strdup (the_layout_variant->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_variant = the_layout_variant->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 (matekbd_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
+matekbd_keyboard_config_load_params (MatekbdKeyboardConfig * kbd_config,
+ const gchar * param_names[])
+{
+ GError *gerror = NULL;
+ gchar *pc;
+ GSList *pl, *l;
+
+ pc = mateconf_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;
+ }
+ matekbd_keyboard_config_model_set (kbd_config, NULL);
+ } else {
+ matekbd_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)");
+
+ matekbd_keyboard_config_layouts_reset (kbd_config);
+
+ l = pl = mateconf_client_get_list (kbd_config->conf_client,
+ param_names[1],
+ MATECONF_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 (l != NULL) {
+ xkl_debug (150, "Loaded Kbd layout: [%s]\n", l->data);
+ matekbd_keyboard_config_layouts_add_full (kbd_config,
+ l->data);
+ l = l->next;
+ }
+ matekbd_keyboard_config_string_list_reset (&pl);
+
+ matekbd_keyboard_config_options_reset (kbd_config);
+
+ l = pl = mateconf_client_get_list (kbd_config->conf_client,
+ param_names[2],
+ MATECONF_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 (l != NULL) {
+ xkl_debug (150, "Loaded Kbd option: [%s]\n", l->data);
+ matekbd_keyboard_config_options_add_full (kbd_config,
+ (const gchar *)
+ l->data);
+ l = l->next;
+ }
+ matekbd_keyboard_config_string_list_reset (&pl);
+}
+
+static void
+matekbd_keyboard_config_save_params (MatekbdKeyboardConfig * kbd_config,
+ MateConfChangeSet * cs,
+ const gchar * param_names[])
+{
+ GSList *pl;
+
+ if (kbd_config->model)
+ mateconf_change_set_set_string (cs, param_names[0],
+ kbd_config->model);
+ else
+ mateconf_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_variants) {
+ pl = kbd_config->layouts_variants;
+ while (pl != NULL) {
+ xkl_debug (150, "Saved Kbd layout: [%s]\n",
+ pl->data);
+ pl = pl->next;
+ }
+ mateconf_change_set_set_list (cs,
+ param_names[1],
+ MATECONF_VALUE_STRING,
+ kbd_config->layouts_variants);
+ } else {
+ xkl_debug (150, "Saved Kbd layouts: []\n");
+ mateconf_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;
+ }
+ mateconf_change_set_set_list (cs,
+ param_names[2],
+ MATECONF_VALUE_STRING,
+ kbd_config->options);
+ } else {
+ xkl_debug (150, "Saved Kbd options: []\n");
+ mateconf_change_set_unset (cs, param_names[2]);
+ }
+}
+
+/**
+ * extern MatekbdKeyboardConfig config functions
+ */
+void
+matekbd_keyboard_config_init (MatekbdKeyboardConfig * kbd_config,
+ MateConfClient * 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);
+
+ mateconf_client_add_dir (kbd_config->conf_client,
+ MATEKBD_KEYBOARD_CONFIG_DIR,
+ MATECONF_CLIENT_PRELOAD_NONE, &gerror);
+ if (gerror != NULL) {
+ g_warning ("err: %s\n", gerror->message);
+ g_error_free (gerror);
+ gerror = NULL;
+ }
+}
+
+void
+matekbd_keyboard_config_term (MatekbdKeyboardConfig * kbd_config)
+{
+ matekbd_keyboard_config_model_set (kbd_config, NULL);
+
+ matekbd_keyboard_config_layouts_reset (kbd_config);
+ matekbd_keyboard_config_options_reset (kbd_config);
+
+ g_object_unref (kbd_config->conf_client);
+ kbd_config->conf_client = NULL;
+}
+
+void
+matekbd_keyboard_config_load_from_mateconf (MatekbdKeyboardConfig * kbd_config,
+ MatekbdKeyboardConfig *
+ kbd_config_default)
+{
+ matekbd_keyboard_config_load_params (kbd_config,
+ MATEKBD_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_variants == NULL) {
+ pl = kbd_config_default->layouts_variants;
+ while (pl != NULL) {
+ kbd_config->layouts_variants =
+ g_slist_append
+ (kbd_config->layouts_variants,
+ 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
+matekbd_keyboard_config_load_from_x_current (MatekbdKeyboardConfig * kbd_config,
+ XklConfigRec * data)
+{
+ gboolean own_data = data == NULL;
+ xkl_debug (150, "Copying config from X(current)\n");
+ if (own_data)
+ data = xkl_config_rec_new ();
+ if (xkl_config_rec_get_from_server (data, kbd_config->engine))
+ matekbd_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 ());
+ if (own_data)
+ g_object_unref (G_OBJECT (data));
+}
+
+void
+matekbd_keyboard_config_load_from_x_initial (MatekbdKeyboardConfig * kbd_config,
+ XklConfigRec * data)
+{
+ gboolean own_data = data == NULL;
+ xkl_debug (150, "Copying config from X(initial)\n");
+ if (own_data)
+ data = xkl_config_rec_new ();
+ if (xkl_config_rec_get_from_backup (data, kbd_config->engine))
+ matekbd_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 ());
+ if (own_data)
+ g_object_unref (G_OBJECT (data));
+}
+
+gboolean
+matekbd_keyboard_config_equals (MatekbdKeyboardConfig * kbd_config1,
+ MatekbdKeyboardConfig * 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_variants,
+ kbd_config2->layouts_variants)
+ && gslist_str_equal (kbd_config1->options,
+ kbd_config2->options);
+}
+
+void
+matekbd_keyboard_config_save_to_mateconf (MatekbdKeyboardConfig * kbd_config)
+{
+ MateConfChangeSet *cs;
+ GError *gerror = NULL;
+
+ cs = mateconf_change_set_new ();
+
+ matekbd_keyboard_config_save_params (kbd_config, cs,
+ MATEKBD_KEYBOARD_CONFIG_ACTIVE);
+
+ mateconf_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;
+ }
+ mateconf_change_set_unref (cs);
+}
+
+void
+matekbd_keyboard_config_model_set (MatekbdKeyboardConfig * 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
+matekbd_keyboard_config_layouts_add (MatekbdKeyboardConfig * kbd_config,
+ const gchar * layout_name,
+ const gchar * variant_name)
+{
+ const gchar *merged;
+ if (layout_name == NULL)
+ return;
+ merged =
+ matekbd_keyboard_config_merge_items (layout_name, variant_name);
+ if (merged == NULL)
+ return;
+ matekbd_keyboard_config_layouts_add_full (kbd_config, merged);
+}
+
+void
+matekbd_keyboard_config_layouts_reset (MatekbdKeyboardConfig * kbd_config)
+{
+ matekbd_keyboard_config_string_list_reset
+ (&kbd_config->layouts_variants);
+}
+
+void
+matekbd_keyboard_config_options_reset (MatekbdKeyboardConfig * kbd_config)
+{
+ matekbd_keyboard_config_string_list_reset (&kbd_config->options);
+}
+
+void
+matekbd_keyboard_config_options_add (MatekbdKeyboardConfig * kbd_config,
+ const gchar * group_name,
+ const gchar * option_name)
+{
+ const gchar *merged;
+ if (group_name == NULL || option_name == NULL)
+ return;
+ merged =
+ matekbd_keyboard_config_merge_items (group_name, option_name);
+ if (merged == NULL)
+ return;
+ matekbd_keyboard_config_options_add_full (kbd_config, merged);
+}
+
+gboolean
+matekbd_keyboard_config_options_is_set (MatekbdKeyboardConfig * kbd_config,
+ const gchar * group_name,
+ const gchar * option_name)
+{
+ const gchar *merged =
+ matekbd_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
+matekbd_keyboard_config_activate (MatekbdKeyboardConfig * kbd_config)
+{
+ gboolean rv;
+ XklConfigRec *data = xkl_config_rec_new ();
+
+ matekbd_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
+matekbd_keyboard_config_start_listen (MatekbdKeyboardConfig * kbd_config,
+ MateConfClientNotifyFunc func,
+ gpointer user_data)
+{
+ matekbd_desktop_config_add_listener (kbd_config->conf_client,
+ MATEKBD_KEYBOARD_CONFIG_DIR, func,
+ user_data,
+ &kbd_config->config_listener_id);
+}
+
+void
+matekbd_keyboard_config_stop_listen (MatekbdKeyboardConfig * kbd_config)
+{
+ matekbd_desktop_config_remove_listener (kbd_config->conf_client,
+ &kbd_config->
+ config_listener_id);
+}
+
+gboolean
+matekbd_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 (!matekbd_keyboard_config_split_items
+ (name, &layout_name, &variant_name))
+ return FALSE;
+ return matekbd_keyboard_config_get_lv_descriptions (config_registry,
+ layout_name,
+ variant_name,
+ layout_short_descr,
+ layout_descr,
+ variant_short_descr,
+ variant_descr);
+}
+
+const gchar *
+matekbd_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 || variant_descr[0] == 0)
+ 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 *
+matekbd_keyboard_config_to_string (const MatekbdKeyboardConfig * config)
+{
+ gchar *layouts = NULL, *options = NULL;
+ GString *buffer = g_string_new (NULL);
+
+ GSList *iter;
+ gint count;
+ gchar *result;
+
+ if (config->layouts_variants) {
+ /* g_slist_length is "expensive", so we determinate the length on the fly */
+ for (iter = config->layouts_variants, count = 0; iter;
+ iter = iter->next, ++count) {
+ if (buffer->len)
+ g_string_append (buffer, " ");
+
+ g_string_append (buffer,
+ (const gchar *) iter->data);
+ }
+
+ /* Translators: 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);
+ }
+
+ /* Translators: 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;
+}
+
+GSList *
+matekbd_keyboard_config_add_default_switch_option_if_necessary (GSList *
+ layouts_list,
+ GSList *
+ options_list, gboolean *was_appended)
+{
+ *was_appended = FALSE;
+ if (g_slist_length (layouts_list) >= 2) {
+ gboolean any_switcher = False;
+ GSList *option = options_list;
+ while (option != NULL) {
+ char *g, *o;
+ if (matekbd_keyboard_config_split_items
+ (option->data, &g, &o)) {
+ if (!g_ascii_strcasecmp
+ (g, GROUP_SWITCHERS_GROUP)) {
+ any_switcher = True;
+ break;
+ }
+ }
+ option = option->next;
+ }
+ if (!any_switcher) {
+ const gchar *id =
+ matekbd_keyboard_config_merge_items
+ (GROUP_SWITCHERS_GROUP,
+ DEFAULT_GROUP_SWITCH);
+ options_list =
+ g_slist_append (options_list, g_strdup (id));
+ *was_appended = TRUE;
+ }
+ }
+ return options_list;
+}
diff --git a/libmatekbd/matekbd-keyboard-config.h b/libmatekbd/matekbd-keyboard-config.h
new file mode 100644
index 0000000..db5bf76
--- /dev/null
+++ b/libmatekbd/matekbd-keyboard-config.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MATEKBD_KEYBOARD_CONFIG_H__
+#define __MATEKBD_KEYBOARD_CONFIG_H__
+
+#include <X11/Xlib.h>
+#include <glib.h>
+#include <mateconf/mateconf-client.h>
+#include <libxklavier/xklavier.h>
+
+extern const gchar MATEKBD_KEYBOARD_CONFIG_DIR[];
+extern const gchar MATEKBD_KEYBOARD_CONFIG_KEY_MODEL[];
+extern const gchar MATEKBD_KEYBOARD_CONFIG_KEY_LAYOUTS[];
+extern const gchar MATEKBD_KEYBOARD_CONFIG_KEY_OPTIONS[];
+
+/*
+ * Keyboard Configuration
+ */
+typedef struct _MatekbdKeyboardConfig {
+ gchar *model;
+ GSList *layouts_variants;
+ GSList *options;
+
+ /* private, transient */
+ MateConfClient *conf_client;
+ int config_listener_id;
+ XklEngine *engine;
+} MatekbdKeyboardConfig;
+
+/**
+ * MatekbdKeyboardConfig functions
+ */
+extern void matekbd_keyboard_config_init (MatekbdKeyboardConfig * kbd_config,
+ MateConfClient * conf_client,
+ XklEngine * engine);
+extern void matekbd_keyboard_config_term (MatekbdKeyboardConfig * kbd_config);
+
+extern void matekbd_keyboard_config_load_from_mateconf (MatekbdKeyboardConfig *
+ kbd_config,
+ MatekbdKeyboardConfig *
+ kbd_config_default);
+
+extern void matekbd_keyboard_config_save_to_mateconf (MatekbdKeyboardConfig *
+ kbd_config);
+
+extern void matekbd_keyboard_config_load_from_x_initial (MatekbdKeyboardConfig *
+ kbd_config,
+ XklConfigRec * buf);
+
+extern void matekbd_keyboard_config_load_from_x_current (MatekbdKeyboardConfig *
+ kbd_config,
+ XklConfigRec * buf);
+
+extern void matekbd_keyboard_config_start_listen (MatekbdKeyboardConfig *
+ kbd_config,
+ MateConfClientNotifyFunc func,
+ gpointer user_data);
+
+extern void matekbd_keyboard_config_stop_listen (MatekbdKeyboardConfig *
+ kbd_config);
+
+extern gboolean matekbd_keyboard_config_equals (MatekbdKeyboardConfig *
+ kbd_config1,
+ MatekbdKeyboardConfig *
+ kbd_config2);
+
+extern gboolean matekbd_keyboard_config_activate (MatekbdKeyboardConfig *
+ kbd_config);
+
+extern const gchar *matekbd_keyboard_config_merge_items (const gchar * parent,
+ const gchar * child);
+
+extern gboolean matekbd_keyboard_config_split_items (const gchar * merged,
+ gchar ** parent,
+ gchar ** child);
+
+extern gboolean matekbd_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 *matekbd_keyboard_config_format_full_layout (const gchar
+ *
+ layout_descr,
+ const gchar *
+ variant_descr);
+
+extern gchar *matekbd_keyboard_config_to_string (const MatekbdKeyboardConfig *
+ config);
+
+extern GSList
+ *matekbd_keyboard_config_add_default_switch_option_if_necessary (GSList *
+ layouts_list,
+ GSList *
+ options_list,
+ gboolean
+ *
+ was_appended);
+
+#endif
diff --git a/libmatekbd/matekbd-keyboard-drawing-marshal.list b/libmatekbd/matekbd-keyboard-drawing-marshal.list
new file mode 100644
index 0000000..88a875f
--- /dev/null
+++ b/libmatekbd/matekbd-keyboard-drawing-marshal.list
@@ -0,0 +1,2 @@
+# $Id$
+VOID:UINT
diff --git a/libmatekbd/matekbd-keyboard-drawing.c b/libmatekbd/matekbd-keyboard-drawing.c
new file mode 100644
index 0000000..77e481f
--- /dev/null
+++ b/libmatekbd/matekbd-keyboard-drawing.c
@@ -0,0 +1,2635 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <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 <glib/gi18n.h>
+#include <libxklavier/xklavier.h>
+
+#include <matekbd-keyboard-drawing.h>
+#include <matekbd-keyboard-drawing-marshal.h>
+#include <matekbd-util.h>
+
+#define noKBDRAW_DEBUG
+
+#define INVALID_KEYCODE ((guint)(-1))
+
+#define GTK_RESPONSE_PRINT 2
+
+enum {
+ BAD_KEYCODE = 0,
+ NUM_SIGNALS
+};
+
+static guint matekbd_keyboard_drawing_signals[NUM_SIGNALS] = { 0 };
+
+static void matekbd_keyboard_drawing_set_mods (MatekbdKeyboardDrawing * drawing,
+ guint mods);
+
+static gint
+xkb_to_pixmap_coord (MatekbdKeyboardDrawingRenderContext * context, gint n)
+{
+ return n * context->scale_numerator / context->scale_denominator;
+}
+
+static gdouble
+xkb_to_pixmap_double (MatekbdKeyboardDrawingRenderContext * context,
+ gdouble d)
+{
+ return d * context->scale_numerator / context->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 gdouble
+length (gdouble x, gdouble y)
+{
+ return sqrt (x * x + y * y);
+}
+
+static gdouble
+point_line_distance (gdouble ax, gdouble ay, gdouble nx, gdouble ny)
+{
+ return ax * nx + ay * ny;
+}
+
+static void
+normal_form (gdouble ax, gdouble ay,
+ gdouble bx, gdouble by,
+ gdouble * nx, gdouble * ny, gdouble * d)
+{
+ gdouble l;
+
+ *nx = by - ay;
+ *ny = ax - bx;
+
+ l = length (*nx, *ny);
+
+ *nx /= l;
+ *ny /= l;
+
+ *d = point_line_distance (ax, ay, *nx, *ny);
+}
+
+static void
+inverse (gdouble a, gdouble b, gdouble c, gdouble d,
+ gdouble * e, gdouble * f, gdouble * g, gdouble * h)
+{
+ gdouble det;
+
+ det = a * d - b * c;
+
+ *e = d / det;
+ *f = -b / det;
+ *g = -c / det;
+ *h = a / det;
+}
+
+static void
+multiply (gdouble a, gdouble b, gdouble c, gdouble d,
+ gdouble e, gdouble f, gdouble * x, gdouble * y)
+{
+ *x = a * e + b * f;
+ *y = c * e + d * f;
+}
+
+static void
+intersect (gdouble n1x, gdouble n1y, gdouble d1,
+ gdouble n2x, gdouble n2y, gdouble d2, gdouble * x, gdouble * y)
+{
+ gdouble e, f, g, h;
+
+ inverse (n1x, n1y, n2x, n2y, &e, &f, &g, &h);
+ multiply (e, f, g, h, d1, d2, x, y);
+}
+
+
+/* draw an angle from the current point to b and then to c,
+ * with a rounded corner of the given radius.
+ */
+static void
+rounded_corner (cairo_t * cr,
+ gdouble bx, gdouble by,
+ gdouble cx, gdouble cy, gdouble radius)
+{
+ gdouble ax, ay;
+ gdouble n1x, n1y, d1;
+ gdouble n2x, n2y, d2;
+ gdouble pd1, pd2;
+ gdouble ix, iy;
+ gdouble dist1, dist2;
+ gdouble nx, ny, d;
+ gdouble a1x, a1y, c1x, c1y;
+ gdouble phi1, phi2;
+
+ cairo_get_current_point (cr, &ax, &ay);
+#ifdef KBDRAW_DEBUG
+ printf (" current point: (%f, %f), radius %f:\n", ax, ay,
+ radius);
+#endif
+
+ /* make sure radius is not too large */
+ dist1 = length (bx - ax, by - ay);
+ dist2 = length (cx - bx, cy - by);
+
+ radius = MIN (radius, MIN (dist1, dist2));
+
+ /* construct normal forms of the lines */
+ normal_form (ax, ay, bx, by, &n1x, &n1y, &d1);
+ normal_form (bx, by, cx, cy, &n2x, &n2y, &d2);
+
+ /* find which side of the line a,b the point c is on */
+ if (point_line_distance (cx, cy, n1x, n1y) < d1)
+ pd1 = d1 - radius;
+ else
+ pd1 = d1 + radius;
+
+ /* find which side of the line b,c the point a is on */
+ if (point_line_distance (ax, ay, n2x, n2y) < d2)
+ pd2 = d2 - radius;
+ else
+ pd2 = d2 + radius;
+
+ /* intersect the parallels to find the center of the arc */
+ intersect (n1x, n1y, pd1, n2x, n2y, pd2, &ix, &iy);
+
+ nx = (bx - ax) / dist1;
+ ny = (by - ay) / dist1;
+ d = point_line_distance (ix, iy, nx, ny);
+
+ /* a1 is the point on the line a-b where the arc starts */
+ intersect (n1x, n1y, d1, nx, ny, d, &a1x, &a1y);
+
+ nx = (cx - bx) / dist2;
+ ny = (cy - by) / dist2;
+ d = point_line_distance (ix, iy, nx, ny);
+
+ /* c1 is the point on the line b-c where the arc ends */
+ intersect (n2x, n2y, d2, nx, ny, d, &c1x, &c1y);
+
+ /* determine the first angle */
+ if (a1x - ix == 0)
+ phi1 = (a1y - iy > 0) ? M_PI_2 : 3 * M_PI_2;
+ else if (a1x - ix > 0)
+ phi1 = atan ((a1y - iy) / (a1x - ix));
+ else
+ phi1 = M_PI + atan ((a1y - iy) / (a1x - ix));
+
+ /* determine the second angle */
+ if (c1x - ix == 0)
+ phi2 = (c1y - iy > 0) ? M_PI_2 : 3 * M_PI_2;
+ else if (c1x - ix > 0)
+ phi2 = atan ((c1y - iy) / (c1x - ix));
+ else
+ phi2 = M_PI + atan ((c1y - iy) / (c1x - ix));
+
+ /* compute the difference between phi2 and phi1 mod 2pi */
+ d = phi2 - phi1;
+ while (d < 0)
+ d += 2 * M_PI;
+ while (d > 2 * M_PI)
+ d -= 2 * M_PI;
+
+#ifdef KBDRAW_DEBUG
+ printf (" line 1 to: (%f, %f):\n", a1x, a1y);
+#endif
+ if (!(isnan (a1x) || isnan (a1y)))
+ cairo_line_to (cr, a1x, a1y);
+
+ /* pick the short arc from phi1 to phi2 */
+ if (d < M_PI)
+ cairo_arc (cr, ix, iy, radius, phi1, phi2);
+ else
+ cairo_arc_negative (cr, ix, iy, radius, phi1, phi2);
+
+#ifdef KBDRAW_DEBUG
+ printf (" line 2 to: (%f, %f):\n", cx, cy);
+#endif
+ cairo_line_to (cr, cx, cy);
+}
+
+static void
+rounded_polygon (cairo_t * cr,
+ gboolean filled,
+ gdouble radius, GdkPoint * points, gint num_points)
+{
+ gint i, j;
+
+ cairo_move_to (cr,
+ (gdouble) (points[num_points - 1].x +
+ points[0].x) / 2,
+ (gdouble) (points[num_points - 1].y +
+ points[0].y) / 2);
+
+
+#ifdef KBDRAW_DEBUG
+ printf (" rounded polygon of radius %f:\n", radius);
+#endif
+ for (i = 0; i < num_points; i++) {
+ j = (i + 1) % num_points;
+ rounded_corner (cr, (gdouble) points[i].x,
+ (gdouble) points[i].y,
+ (gdouble) (points[i].x + points[j].x) / 2,
+ (gdouble) (points[i].y + points[j].y) / 2,
+ radius);
+#ifdef KBDRAW_DEBUG
+ printf (" corner (%d, %d) -> (%d, %d):\n",
+ points[i].x, points[i].y, points[j].x,
+ points[j].y);
+#endif
+ };
+ cairo_close_path (cr);
+
+ if (filled)
+ cairo_fill (cr);
+ else
+ cairo_stroke (cr);
+}
+
+static void
+draw_polygon (MatekbdKeyboardDrawingRenderContext * context,
+ GdkColor * fill_color,
+ gint xkb_x,
+ gint xkb_y, XkbPointRec * xkb_points, guint num_points,
+ gdouble radius)
+{
+ GdkPoint *points;
+ gboolean filled;
+ gint i;
+
+ if (fill_color) {
+ filled = TRUE;
+ } else {
+ fill_color = context->dark_color;
+ filled = FALSE;
+ }
+
+ gdk_cairo_set_source_color (context->cr, fill_color);
+
+ points = g_new (GdkPoint, num_points);
+
+#ifdef KBDRAW_DEBUG
+ printf (" Polygon points:\n");
+#endif
+ for (i = 0; i < num_points; i++) {
+ points[i].x =
+ xkb_to_pixmap_coord (context, xkb_x + xkb_points[i].x);
+ points[i].y =
+ xkb_to_pixmap_coord (context, xkb_y + xkb_points[i].y);
+#ifdef KBDRAW_DEBUG
+ printf (" %d, %d\n", points[i].x, points[i].y);
+#endif
+ }
+
+ rounded_polygon (context->cr, filled,
+ xkb_to_pixmap_double (context, radius),
+ points, num_points);
+
+ g_free (points);
+}
+
+static void
+curve_rectangle (cairo_t * cr,
+ gdouble x0,
+ gdouble y0, gdouble width, gdouble height, gdouble radius)
+{
+ gdouble x1, y1;
+
+ if (!width || !height)
+ return;
+
+ x1 = x0 + width;
+ y1 = y0 + height;
+
+ radius = MIN (radius, MIN (width / 2, height / 2));
+
+ cairo_move_to (cr, x0, y0 + radius);
+ cairo_arc (cr, x0 + radius, y0 + radius, radius, M_PI,
+ 3 * M_PI / 2);
+ cairo_line_to (cr, x1 - radius, y0);
+ cairo_arc (cr, x1 - radius, y0 + radius, radius, 3 * M_PI / 2,
+ 2 * M_PI);
+ cairo_line_to (cr, x1, y1 - radius);
+ cairo_arc (cr, x1 - radius, y1 - radius, radius, 0, M_PI / 2);
+ cairo_line_to (cr, x0 + radius, y1);
+ cairo_arc (cr, x0 + radius, y1 - radius, radius, M_PI / 2, M_PI);
+
+ cairo_close_path (cr);
+}
+
+static void
+draw_curve_rectangle (cairo_t * cr,
+ gboolean filled,
+ GdkColor * fill_color,
+ gint x, gint y, gint width, gint height, gint radius)
+{
+ curve_rectangle (cr, x, y, width, height, radius);
+
+ gdk_cairo_set_source_color (cr, fill_color);
+
+ if (filled)
+ cairo_fill (cr);
+ else
+ cairo_stroke (cr);
+}
+
+/* x, y, width, height are in the xkb coordinate system */
+static void
+draw_rectangle (MatekbdKeyboardDrawingRenderContext * context,
+ GdkColor * fill_color,
+ gint angle,
+ gint xkb_x, gint xkb_y, gint xkb_width, gint xkb_height,
+ gint radius)
+{
+ if (angle == 0) {
+ gint x, y, width, height;
+ gboolean filled;
+
+ if (fill_color) {
+ filled = TRUE;
+ } else {
+ fill_color = context->dark_color;
+ filled = FALSE;
+ }
+
+ x = xkb_to_pixmap_coord (context, xkb_x);
+ y = xkb_to_pixmap_coord (context, xkb_y);
+ width =
+ xkb_to_pixmap_coord (context, xkb_x + xkb_width) - x;
+ height =
+ xkb_to_pixmap_coord (context, xkb_y + xkb_height) - y;
+
+ draw_curve_rectangle (context->cr, filled, fill_color,
+ x, y, width, height,
+ xkb_to_pixmap_double (context,
+ radius));
+ } 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 (context, fill_color, 0, 0, points, 4,
+ radius);
+ }
+}
+
+static void
+draw_outline (MatekbdKeyboardDrawingRenderContext * context,
+ 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 (context, color, angle, origin_x,
+ origin_y, outline->points[0].x,
+ outline->points[0].y,
+ outline->corner_radius);
+
+#ifdef KBDRAW_DEBUG
+ printf ("pointsxy:%d %d %d\n", outline->points[0].x,
+ outline->points[0].y, outline->corner_radius);
+#endif
+
+ draw_rectangle (context, NULL, angle, origin_x, origin_y,
+ outline->points[0].x,
+ outline->points[0].y,
+ outline->corner_radius);
+ } 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 (context, color, angle, rotated_x0,
+ rotated_y0, outline->points[1].x,
+ outline->points[1].y,
+ outline->corner_radius);
+
+ draw_rectangle (context, NULL, angle, rotated_x0,
+ rotated_y0, outline->points[1].x,
+ outline->points[1].y,
+ outline->corner_radius);
+ } else {
+ if (color)
+ draw_polygon (context, color, origin_x, origin_y,
+ outline->points,
+ outline->num_points,
+ outline->corner_radius);
+
+ draw_polygon (context, NULL, origin_x, origin_y,
+ outline->points, outline->num_points,
+ outline->corner_radius);
+ }
+}
+
+/* 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 (MatekbdKeyboardDrawing * drawing, gchar * key_name)
+{
+#define KEYSYM_NAME_MAX_LENGTH 4
+ guint keycode;
+ gint i, j;
+ XkbKeyNamePtr pkey;
+ XkbKeyAliasPtr palias;
+ guint is_name_matched;
+ gchar *src, *dst;
+
+ if (!drawing->xkb)
+ return INVALID_KEYCODE;
+
+#ifdef KBDRAW_DEBUG
+ printf (" looking for keycode for (%c%c%c%c)\n",
+ key_name[0], key_name[1], key_name[2], key_name[3]);
+#endif
+
+ pkey = drawing->xkb->names->keys + drawing->xkb->min_key_code;
+ for (keycode = drawing->xkb->min_key_code;
+ keycode <= drawing->xkb->max_key_code; keycode++) {
+ is_name_matched = 1;
+ src = key_name;
+ dst = pkey->name;
+ for (i = KEYSYM_NAME_MAX_LENGTH; --i >= 0;) {
+ if ('\0' == *src)
+ break;
+ if (*src++ != *dst++) {
+ is_name_matched = 0;
+ break;
+ }
+ }
+ if (is_name_matched) {
+#ifdef KBDRAW_DEBUG
+ printf (" found keycode %u\n", keycode);
+#endif
+ return keycode;
+ }
+ pkey++;
+ }
+
+ palias = drawing->xkb->names->key_aliases;
+ for (j = drawing->xkb->names->num_key_aliases; --j >= 0;) {
+ is_name_matched = 1;
+ src = key_name;
+ dst = palias->alias;
+ for (i = KEYSYM_NAME_MAX_LENGTH; --i >= 0;) {
+ if ('\0' == *src)
+ break;
+ if (*src++ != *dst++) {
+ is_name_matched = 0;
+ break;
+ }
+ }
+
+ if (is_name_matched) {
+ keycode = find_keycode (drawing, palias->real);
+#ifdef KBDRAW_DEBUG
+ printf ("found alias keycode %u\n", keycode);
+#endif
+ return keycode;
+ }
+ palias++;
+ }
+
+ return INVALID_KEYCODE;
+}
+
+
+static void
+set_key_label_in_layout (MatekbdKeyboardDrawingRenderContext * context,
+ guint keyval)
+{
+ gchar buf[5];
+ gunichar uc;
+ PangoLayout *layout = context->layout;
+
+ 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_pango_layout (MatekbdKeyboardDrawingRenderContext * context,
+ MatekbdKeyboardDrawing * drawing,
+ gint angle, gint x, gint y)
+{
+ PangoLayout *layout = context->layout;
+ GdkColor *color;
+ PangoLayoutLine *line;
+ gint x_off, y_off;
+ gint i;
+
+ color =
+ drawing->colors + (drawing->xkb->geom->label_color -
+ drawing->xkb->geom->colors);
+
+ if (angle != context->angle) {
+ PangoMatrix matrix = PANGO_MATRIX_INIT;
+ pango_matrix_rotate (&matrix, -angle / 10.0);
+ pango_context_set_matrix (pango_layout_get_context
+ (layout), &matrix);
+ pango_layout_context_changed (layout);
+ context->angle = angle;
+ }
+
+ i = 0;
+ y_off = 0;
+ for (line = pango_layout_get_line (layout, i);
+ line != NULL; line = pango_layout_get_line (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;
+
+ geometry =
+ &run->glyphs->glyphs[j].geometry;
+
+ x_off += geometry->width;
+ }
+ }
+
+ pango_layout_line_get_extents (line, NULL, &line_extents);
+ y_off +=
+ line_extents.height +
+ pango_layout_get_spacing (layout);
+ }
+
+ cairo_move_to (context->cr, x, y);
+ gdk_cairo_set_source_color (context->cr, color);
+ pango_cairo_show_layout (context->cr, layout);
+}
+
+static void
+draw_key_label_helper (MatekbdKeyboardDrawingRenderContext * context,
+ MatekbdKeyboardDrawing * drawing,
+ KeySym keysym,
+ gint angle,
+ MatekbdKeyboardDrawingGroupLevelPosition glp,
+ gint x,
+ gint y, gint width, gint height, gint padding)
+{
+ 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 MATEKBD_KEYBOARD_DRAWING_POS_TOPLEFT:
+ case MATEKBD_KEYBOARD_DRAWING_POS_BOTTOMLEFT:
+ {
+ ycell =
+ glp == MATEKBD_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 MATEKBD_KEYBOARD_DRAWING_POS_TOPRIGHT:
+ case MATEKBD_KEYBOARD_DRAWING_POS_BOTTOMRIGHT:
+ {
+ ycell =
+ glp == MATEKBD_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 (context, keysym);
+ pango_layout_set_width (context->layout, label_max_width);
+ label_y -= (pango_layout_get_line_count (context->layout) - 1) *
+ (pango_font_description_get_size (context->font_desc) /
+ PANGO_SCALE);
+ cairo_save (context->cr);
+ cairo_rectangle (context->cr, x + padding / 2, y + padding / 2,
+ width - padding, height - padding);
+ cairo_clip (context->cr);
+ draw_pango_layout (context, drawing, angle, label_x, label_y);
+ cairo_restore (context->cr);
+}
+
+static void
+draw_key_label (MatekbdKeyboardDrawingRenderContext * context,
+ MatekbdKeyboardDrawing * 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 * context->scale_numerator / context->scale_denominator; /* 2.3mm */
+
+ x = xkb_to_pixmap_coord (context, xkb_origin_x);
+ y = xkb_to_pixmap_coord (context, xkb_origin_y);
+ width =
+ xkb_to_pixmap_coord (context, xkb_origin_x + xkb_width) - x;
+ height =
+ xkb_to_pixmap_coord (context, xkb_origin_y + xkb_height) - y;
+
+ for (glp = MATEKBD_KEYBOARD_DRAWING_POS_TOPLEFT;
+ glp < MATEKBD_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;
+
+ /* Skip "exotic" levels like the "Ctrl" level in PC_SYSREQ */
+ if (l > 0) {
+ guint mods = XkbKeyKeyType (drawing->xkb, keycode,
+ g)->mods.mask;
+ if ((mods & (ShiftMask | drawing->l3mod)) == 0)
+ continue;
+ }
+
+ if (drawing->track_modifiers) {
+ guint mods_rtrn;
+ KeySym keysym;
+
+ if (XkbTranslateKeyCode (drawing->xkb, keycode,
+ XkbBuildCoreState
+ (drawing->mods, g),
+ &mods_rtrn, &keysym)) {
+ draw_key_label_helper (context, 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 (context, drawing, keysym,
+ angle, glp, x, y, width,
+ height, padding);
+ /* reverse y order */
+ }
+ }
+}
+
+/* groups are from 0-3 */
+static void
+draw_key (MatekbdKeyboardDrawingRenderContext * context,
+ MatekbdKeyboardDrawing * drawing, MatekbdKeyboardDrawingKey * key)
+{
+ XkbShapeRec *shape;
+ GdkColor *color;
+ /* gint i; */
+
+ if (!drawing->xkb)
+ return;
+
+#ifdef KBDRAW_DEBUG
+ printf ("shape: %p (base %p, index %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_get_style (GTK_WIDGET (drawing))->base
+ [GTK_STATE_SELECTED];
+ else
+ color = drawing->colors + key->xkbkey->color_ndx;
+
+#ifdef KBDRAW_DEBUG
+ printf
+ (" outlines base in the shape: %p (total: %d), origin: (%d, %d), angle %d, colored: %s\n",
+ shape->outlines, shape->num_outlines, key->origin_x,
+ key->origin_y, key->angle, color ? "yes" : "no");
+#endif
+
+ /* draw the primary outline */
+ draw_outline (context,
+ shape->primary ? shape->primary : shape->outlines,
+ color, key->angle, key->origin_x, key->origin_y);
+#if 0
+ /* don't draw other outlines for now, since
+ * the text placement does not take them into account
+ */
+ for (i = 0; i < shape->num_outlines; i++) {
+ if (shape->outlines + i == shape->approx ||
+ shape->outlines + i == shape->primary)
+ continue;
+ draw_outline (context, shape->outlines + i, NULL,
+ key->angle, key->origin_x, key->origin_y);
+ }
+#endif
+
+ draw_key_label (context, drawing, key->keycode, key->angle,
+ key->origin_x, key->origin_y,
+ shape->bounds.x2, shape->bounds.y2);
+}
+
+static void
+invalidate_region (MatekbdKeyboardDrawing * 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->renderContext,
+ origin_x + x_min) - 6;
+ y = xkb_to_pixmap_coord (drawing->renderContext,
+ origin_y + y_min) - 6;
+ width =
+ xkb_to_pixmap_coord (drawing->renderContext,
+ x_max - x_min) + 12;
+ height =
+ xkb_to_pixmap_coord (drawing->renderContext,
+ y_max - y_min) + 12;
+
+ gtk_widget_queue_draw_area (GTK_WIDGET (drawing), x, y, width,
+ height);
+}
+
+static void
+invalidate_indicator_doodad_region (MatekbdKeyboardDrawing * drawing,
+ MatekbdKeyboardDrawingDoodad * 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 (MatekbdKeyboardDrawing * drawing,
+ MatekbdKeyboardDrawingKey * 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 (MatekbdKeyboardDrawingRenderContext * context,
+ MatekbdKeyboardDrawing * drawing,
+ MatekbdKeyboardDrawingDoodad * doodad,
+ XkbTextDoodadRec * text_doodad)
+{
+ gint x, y;
+ if (!drawing->xkb)
+ return;
+
+ x = xkb_to_pixmap_coord (context,
+ doodad->origin_x + text_doodad->left);
+ y = xkb_to_pixmap_coord (context,
+ doodad->origin_y + text_doodad->top);
+
+ pango_layout_set_text (context->layout, text_doodad->text, -1);
+ draw_pango_layout (context, drawing, doodad->angle, x, y);
+}
+
+static void
+draw_indicator_doodad (MatekbdKeyboardDrawingRenderContext * context,
+ MatekbdKeyboardDrawing * drawing,
+ MatekbdKeyboardDrawingDoodad * 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 (context, shape->outlines + i, color,
+ doodad->angle,
+ doodad->origin_x + indicator_doodad->left,
+ doodad->origin_y + indicator_doodad->top);
+}
+
+static void
+draw_shape_doodad (MatekbdKeyboardDrawingRenderContext * context,
+ MatekbdKeyboardDrawing * drawing,
+ MatekbdKeyboardDrawingDoodad * 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;
+
+ /* draw the primary outline filled */
+ draw_outline (context,
+ shape->primary ? shape->primary : shape->outlines,
+ color, doodad->angle,
+ doodad->origin_x + shape_doodad->left,
+ doodad->origin_y + shape_doodad->top);
+
+ /* stroke the other outlines */
+ for (i = 0; i < shape->num_outlines; i++) {
+ if (shape->outlines + i == shape->approx ||
+ shape->outlines + i == shape->primary)
+ continue;
+ draw_outline (context, shape->outlines + i, NULL,
+ doodad->angle,
+ doodad->origin_x + shape_doodad->left,
+ doodad->origin_y + shape_doodad->top);
+ }
+}
+
+static void
+draw_doodad (MatekbdKeyboardDrawingRenderContext * context,
+ MatekbdKeyboardDrawing * drawing,
+ MatekbdKeyboardDrawingDoodad * doodad)
+{
+ switch (doodad->doodad->any.type) {
+ case XkbOutlineDoodad:
+ case XkbSolidDoodad:
+ draw_shape_doodad (context, drawing, doodad,
+ &doodad->doodad->shape);
+ break;
+
+ case XkbTextDoodad:
+ draw_text_doodad (context, drawing, doodad,
+ &doodad->doodad->text);
+ break;
+
+ case XkbIndicatorDoodad:
+ draw_indicator_doodad (context, 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 (context, drawing, doodad,
+ &doodad->doodad->shape);
+ break;
+ }
+}
+
+typedef struct {
+ MatekbdKeyboardDrawing *drawing;
+ MatekbdKeyboardDrawingRenderContext *context;
+} DrawKeyboardItemData;
+
+static void
+redraw_overlapping_doodads (MatekbdKeyboardDrawingRenderContext * context,
+ MatekbdKeyboardDrawing * drawing,
+ MatekbdKeyboardDrawingKey * key)
+{
+ GList *list;
+ gboolean do_draw = FALSE;
+
+ for (list = drawing->keyboard_items; list; list = list->next) {
+ MatekbdKeyboardDrawingItem *item = list->data;
+
+ if (do_draw
+ && item->type ==
+ MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD)
+ draw_doodad (context, drawing,
+ (MatekbdKeyboardDrawingDoodad *) item);
+
+ if (list->data == key)
+ do_draw = TRUE;
+ }
+}
+
+static void
+draw_keyboard_item (MatekbdKeyboardDrawingItem * item,
+ DrawKeyboardItemData * data)
+{
+ MatekbdKeyboardDrawing *drawing = data->drawing;
+ MatekbdKeyboardDrawingRenderContext *context = data->context;
+
+ if (!drawing->xkb)
+ return;
+
+ switch (item->type) {
+ case MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_INVALID:
+ break;
+
+ case MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY:
+ case MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY_EXTRA:
+ draw_key (context, drawing,
+ (MatekbdKeyboardDrawingKey *) item);
+ break;
+
+ case MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD:
+ draw_doodad (context, drawing,
+ (MatekbdKeyboardDrawingDoodad *) item);
+ break;
+ }
+}
+
+static void
+draw_keyboard_to_context (MatekbdKeyboardDrawingRenderContext * context,
+ MatekbdKeyboardDrawing * drawing)
+{
+ DrawKeyboardItemData data = { drawing, context };
+#ifdef KBDRAW_DEBUG
+ printf ("mods: %d\n", drawing->mods);
+#endif
+ g_list_foreach (drawing->keyboard_items,
+ (GFunc) draw_keyboard_item, &data);
+}
+
+static gboolean
+create_cairo (MatekbdKeyboardDrawing * drawing)
+{
+ GtkStateType state;
+ if (drawing == NULL || drawing->pixmap == NULL)
+ return FALSE;
+ drawing->renderContext->cr =
+ gdk_cairo_create (GDK_DRAWABLE (drawing->pixmap));
+
+ state = gtk_widget_get_state (GTK_WIDGET (drawing));
+ drawing->renderContext->dark_color =
+ &gtk_widget_get_style (GTK_WIDGET (drawing))->dark[state];
+ return TRUE;
+}
+
+static void
+destroy_cairo (MatekbdKeyboardDrawing * drawing)
+{
+ cairo_destroy (drawing->renderContext->cr);
+ drawing->renderContext->cr = NULL;
+ drawing->renderContext->dark_color = NULL;
+}
+
+static void
+draw_keyboard (MatekbdKeyboardDrawing * drawing)
+{
+ GtkStateType state = gtk_widget_get_state (GTK_WIDGET (drawing));
+ GtkStyle *style = gtk_widget_get_style (GTK_WIDGET (drawing));
+ GtkAllocation allocation;
+
+ if (!drawing->xkb)
+ return;
+
+ gtk_widget_get_allocation (GTK_WIDGET (drawing), &allocation);
+
+ drawing->pixmap =
+ gdk_pixmap_new (gtk_widget_get_window (GTK_WIDGET (drawing)),
+ allocation.width, allocation.height, -1);
+
+ if (create_cairo (drawing)) {
+ /* blank background */
+ gdk_cairo_set_source_color (drawing->renderContext->cr,
+ &style->base[state]);
+ cairo_paint (drawing->renderContext->cr);
+
+ draw_keyboard_to_context (drawing->renderContext, drawing);
+ destroy_cairo (drawing);
+ }
+}
+
+static void
+alloc_render_context (MatekbdKeyboardDrawing * drawing)
+{
+ MatekbdKeyboardDrawingRenderContext *context =
+ drawing->renderContext =
+ g_new0 (MatekbdKeyboardDrawingRenderContext, 1);
+
+ PangoContext *pangoContext =
+ gtk_widget_get_pango_context (GTK_WIDGET (drawing));
+ context->layout = pango_layout_new (pangoContext);
+ pango_layout_set_ellipsize (context->layout, PANGO_ELLIPSIZE_END);
+
+ context->font_desc =
+ pango_font_description_copy (gtk_widget_get_style
+ (GTK_WIDGET
+ (drawing))->font_desc);
+ context->angle = 0;
+ context->scale_numerator = 1;
+ context->scale_denominator = 1;
+}
+
+static void
+free_render_context (MatekbdKeyboardDrawing * drawing)
+{
+ MatekbdKeyboardDrawingRenderContext *context = drawing->renderContext;
+ g_object_unref (G_OBJECT (context->layout));
+ pango_font_description_free (context->font_desc);
+
+ g_free (drawing->renderContext);
+ drawing->renderContext = NULL;
+}
+
+static gboolean
+expose_event (GtkWidget * widget,
+ GdkEventExpose * event, MatekbdKeyboardDrawing * drawing)
+{
+ GtkAllocation allocation;
+ cairo_t *cr;
+
+ if (!drawing->xkb)
+ return FALSE;
+
+ if (drawing->pixmap == NULL)
+ return FALSE;
+
+ cr = gdk_cairo_create (event->window);
+ gdk_cairo_region (cr, event->region);
+ cairo_clip (cr);
+
+ gdk_cairo_set_source_pixmap (cr, drawing->pixmap, 0, 0);
+ cairo_paint (cr);
+
+ cairo_destroy (cr);
+
+ if (gtk_widget_has_focus (widget)) {
+ gtk_widget_get_allocation (widget, &allocation);
+ gtk_paint_focus (gtk_widget_get_style (widget),
+ gtk_widget_get_window (widget),
+ gtk_widget_get_state (widget),
+ &event->area, widget, "keyboard-drawing",
+ 0, 0, allocation.width,
+ allocation.height);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+idle_redraw (gpointer user_data)
+{
+ MatekbdKeyboardDrawing *drawing = user_data;
+
+ drawing->idle_redraw = 0;
+ draw_keyboard (drawing);
+ gtk_widget_queue_draw (GTK_WIDGET (drawing));
+ return FALSE;
+}
+
+static gboolean
+context_setup_scaling (MatekbdKeyboardDrawingRenderContext * context,
+ MatekbdKeyboardDrawing * drawing,
+ gdouble width, gdouble height,
+ gdouble dpi_x, gdouble dpi_y)
+{
+ if (!drawing->xkb)
+ return FALSE;
+
+ if (drawing->xkb->geom->width_mm <= 0
+ || drawing->xkb->geom->height_mm <= 0) {
+ g_critical
+ ("keyboard geometry reports width or height as zero!");
+ return FALSE;
+ }
+
+ if (width * drawing->xkb->geom->height_mm <
+ height * drawing->xkb->geom->width_mm) {
+ context->scale_numerator = width;
+ context->scale_denominator = drawing->xkb->geom->width_mm;
+ } else {
+ context->scale_numerator = height;
+ context->scale_denominator = drawing->xkb->geom->height_mm;
+ }
+
+ pango_font_description_set_size (context->font_desc,
+ 720 * dpi_x *
+ context->scale_numerator /
+ context->scale_denominator);
+ pango_layout_set_spacing (context->layout,
+ -160 * dpi_y * context->scale_numerator /
+ context->scale_denominator);
+ pango_layout_set_font_description (context->layout,
+ context->font_desc);
+
+ return TRUE;
+}
+
+static void
+size_allocate (GtkWidget * widget,
+ GtkAllocation * allocation, MatekbdKeyboardDrawing * drawing)
+{
+ MatekbdKeyboardDrawingRenderContext *context = drawing->renderContext;
+
+ if (drawing->pixmap) {
+ g_object_unref (drawing->pixmap);
+ drawing->pixmap = NULL;
+ }
+
+ if (!context_setup_scaling (context, drawing,
+ allocation->width, allocation->height,
+ 50, 50))
+ return;
+
+ if (!drawing->idle_redraw)
+ drawing->idle_redraw = g_idle_add (idle_redraw, drawing);
+}
+
+static gint
+key_event (GtkWidget * widget,
+ GdkEventKey * event, MatekbdKeyboardDrawing * drawing)
+{
+ MatekbdKeyboardDrawingKey *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,
+ matekbd_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);
+
+ if (create_cairo (drawing)) {
+ draw_key (drawing->renderContext, drawing, key);
+ redraw_overlapping_doodads (drawing->renderContext,
+ drawing, key);
+ destroy_cairo (drawing);
+ }
+
+ invalidate_key_region (drawing, key);
+ return FALSE;
+}
+
+static gint
+button_press_event (GtkWidget * widget,
+ GdkEventButton * event, MatekbdKeyboardDrawing * drawing)
+{
+ if (!drawing->xkb)
+ return FALSE;
+
+ gtk_widget_grab_focus (widget);
+ return FALSE;
+}
+
+static gboolean
+unpress_keys (MatekbdKeyboardDrawing * drawing)
+{
+ gint i;
+
+ if (!drawing->xkb)
+ return FALSE;
+
+ if (create_cairo (drawing)) {
+ 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->renderContext, drawing,
+ drawing->keys + i);
+ invalidate_key_region (drawing,
+ drawing->keys + i);
+ }
+ destroy_cairo (drawing);
+ }
+
+ return FALSE;
+}
+
+static gint
+focus_event (GtkWidget * widget,
+ GdkEventFocus * event, MatekbdKeyboardDrawing * 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 (MatekbdKeyboardDrawingItem * a,
+ MatekbdKeyboardDrawingItem * b)
+{
+ if (a->priority > b->priority)
+ return 1;
+ else if (a->priority < b->priority)
+ return -1;
+ else
+ return 0;
+}
+
+static void
+init_indicator_doodad (MatekbdKeyboardDrawing * drawing,
+ XkbDoodadRec * xkbdoodad,
+ MatekbdKeyboardDrawingDoodad * 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 (MatekbdKeyboardDrawing * 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;
+ MatekbdKeyboardDrawingDoodad *doodad =
+ g_new (MatekbdKeyboardDrawingDoodad, 1);
+
+ doodad->type = MATEKBD_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++) {
+ XkbSectionRec *section = drawing->xkb->geom->sections + i;
+ guint priority;
+
+#ifdef KBDRAW_DEBUG
+ printf ("initing section %d containing %d rows\n", i,
+ section->num_rows);
+#endif
+ 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;
+ MatekbdKeyboardDrawingKey *key;
+ XkbShapeRec *shape =
+ drawing->xkb->geom->shapes +
+ xkbkey->shape_ndx;
+ guint keycode = find_keycode (drawing,
+ xkbkey->
+ name.name);
+
+ if (keycode == INVALID_KEYCODE)
+ continue;
+#ifdef KBDRAW_DEBUG
+ printf
+ (" initing key %d, shape: %p(%p + %d), code: %u\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;
+ if (key->type ==
+ MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_INVALID)
+ {
+ key->type =
+ MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY;
+ } else {
+ /* duplicate key for the same keycode,
+ already defined as MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY */
+ key =
+ g_new0
+ (MatekbdKeyboardDrawingKey,
+ 1);
+ key->type =
+ MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY_EXTRA;
+ }
+ } 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 (MatekbdKeyboardDrawingKey,
+ 1);
+ key->type =
+ MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY_EXTRA;
+ }
+
+ 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;
+ MatekbdKeyboardDrawingDoodad *doodad =
+ g_new (MatekbdKeyboardDrawingDoodad, 1);
+
+ doodad->type =
+ MATEKBD_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 (MatekbdKeyboardDrawing * 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 */
+ MatekbdKeyboardDrawing * drawing)
+{
+ GList *itemp;
+
+ if (!drawing->xkb)
+ return;
+
+ for (itemp = drawing->keyboard_items; itemp; itemp = itemp->next) {
+ MatekbdKeyboardDrawingItem *item = itemp->data;
+
+ switch (item->type) {
+ case MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_INVALID:
+ case MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY:
+ break;
+
+ case MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY_EXTRA:
+ case MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD:
+ g_free (item);
+ break;
+ }
+ }
+
+ g_list_free (drawing->keyboard_items);
+ drawing->keyboard_items = NULL;
+
+ g_free (drawing->keys);
+ g_free (drawing->colors);
+}
+
+static void
+alloc_cdik (MatekbdKeyboardDrawing * drawing)
+{
+ drawing->physical_indicators_size =
+ drawing->xkb->indicators->phys_indicators + 1;
+ drawing->physical_indicators =
+ g_new0 (MatekbdKeyboardDrawingDoodad *,
+ drawing->physical_indicators_size);
+ drawing->keys =
+ g_new0 (MatekbdKeyboardDrawingKey,
+ drawing->xkb->max_key_code + 1);
+}
+
+static void
+process_indicators_state_notify (XkbIndicatorNotifyEvent * iev,
+ MatekbdKeyboardDrawing * drawing)
+{
+ /* Good question: should we track indicators when the keyboard is
+ NOT really taken from the screen */
+ 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;
+ if (create_cairo (drawing)) {
+ draw_doodad
+ (drawing->renderContext,
+ drawing,
+ drawing->physical_indicators
+ [i]);
+ destroy_cairo (drawing);
+ }
+ invalidate_indicator_doodad_region
+ (drawing,
+ drawing->physical_indicators[i]);
+ }
+ }
+}
+
+static GdkFilterReturn
+xkb_state_notify_event_filter (GdkXEvent * gdkxev,
+ GdkEvent * event,
+ MatekbdKeyboardDrawing * 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;
+ GtkAllocation allocation;
+ switch (kev->any.xkb_type) {
+ case XkbStateNotify:
+ if (((kev->state.changed & modifier_change_mask) &&
+ drawing->track_modifiers)) {
+ free_cdik (drawing);
+ if (drawing->track_modifiers)
+ matekbd_keyboard_drawing_set_mods
+ (drawing,
+ kev->state.compat_state);
+ drawing->keys =
+ g_new0 (MatekbdKeyboardDrawingKey,
+ drawing->xkb->max_key_code +
+ 1);
+
+ gtk_widget_get_allocation (GTK_WIDGET
+ (drawing),
+ &allocation);
+ size_allocate (GTK_WIDGET (drawing),
+ &allocation, drawing);
+
+ init_keys_and_doodads (drawing);
+ init_colors (drawing);
+ }
+ break;
+
+ case XkbIndicatorStateNotify:
+ {
+ process_indicators_state_notify (&
+ ((XkbEvent
+ *)
+ gdkxev)->indicators,
+drawing);
+ }
+ 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)
+ matekbd_keyboard_drawing_set_mods
+ (drawing, state.compat_state);
+ if (drawing->track_config)
+ matekbd_keyboard_drawing_set_keyboard
+ (drawing, NULL);
+ }
+ break;
+ }
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+destroy (MatekbdKeyboardDrawing * drawing)
+{
+ free_render_context (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;
+ }
+ if (drawing->idle_redraw > 0) {
+ g_source_remove (drawing->idle_redraw);
+ drawing->idle_redraw = 0;
+ }
+
+ g_object_unref (drawing->pixmap);
+}
+
+static void
+style_changed (MatekbdKeyboardDrawing * drawing)
+{
+ pango_layout_context_changed (drawing->renderContext->layout);
+}
+
+static void
+matekbd_keyboard_drawing_init (MatekbdKeyboardDrawing * 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", (void *) 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_render_context (drawing);
+
+ drawing->keyboard_items = NULL;
+ drawing->colors = NULL;
+
+ 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->l3mod = XkbKeysymToModifiers (drawing->display,
+ GDK_ISO_Level3_Shift);
+
+ 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_can_focus (GTK_WIDGET (drawing), TRUE);
+
+ 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_after (G_OBJECT (drawing), "key-press-event",
+ G_CALLBACK (key_event), drawing);
+ g_signal_connect_after (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 *
+matekbd_keyboard_drawing_new (void)
+{
+ return
+ GTK_WIDGET (g_object_new
+ (matekbd_keyboard_drawing_get_type (), NULL));
+}
+
+static void
+matekbd_keyboard_drawing_class_init (MatekbdKeyboardDrawingClass * klass)
+{
+ klass->bad_keycode = NULL;
+
+ matekbd_keyboard_drawing_signals[BAD_KEYCODE] =
+ g_signal_new ("bad-keycode", matekbd_keyboard_drawing_get_type (),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (MatekbdKeyboardDrawingClass,
+ bad_keycode), NULL, NULL,
+ matekbd_keyboard_drawing_VOID__UINT, G_TYPE_NONE, 1,
+ G_TYPE_UINT);
+}
+
+GType
+matekbd_keyboard_drawing_get_type (void)
+{
+ static GType matekbd_keyboard_drawing_type = 0;
+
+ if (!matekbd_keyboard_drawing_type) {
+ static const GTypeInfo matekbd_keyboard_drawing_info = {
+ sizeof (MatekbdKeyboardDrawingClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) matekbd_keyboard_drawing_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (MatekbdKeyboardDrawing),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) matekbd_keyboard_drawing_init,
+ };
+
+ matekbd_keyboard_drawing_type =
+ g_type_register_static (GTK_TYPE_DRAWING_AREA,
+ "MatekbdKeyboardDrawing",
+ &matekbd_keyboard_drawing_info,
+ 0);
+ }
+
+ return matekbd_keyboard_drawing_type;
+}
+
+void
+matekbd_keyboard_drawing_set_mods (MatekbdKeyboardDrawing * 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 *
+matekbd_keyboard_drawing_get_pixbuf (MatekbdKeyboardDrawing * drawing)
+{
+ MatekbdKeyboardDrawingRenderContext *context = drawing->renderContext;
+
+ 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 (context,
+ drawing->xkb->geom->width_mm),
+ xkb_to_pixmap_coord (context,
+ drawing->xkb->geom->height_mm));
+}
+
+/**
+ * matekbd_keyboard_drawing_render:
+ * @drawing: keyboard layout to render
+ * @cr: Cairo context to render to
+ * @layout: Pango layout to use to render text
+ * @x: left coordinate (pixels) of region to render in
+ * @y: top coordinate (pixels) of region to render in
+ * @width: width (pixels) of region to render in
+ * @height: height (pixels) of region to render in
+ *
+ * Renders a keyboard layout to a cairo_t context. @cr and @layout can be got
+ * from e.g. a GtkWidget or a GtkPrintContext. @cr and @layout may be modified
+ * by the function but will not be unreffed.
+ *
+ * @returns: %TRUE on success, %FALSE on failure
+ */
+gboolean
+matekbd_keyboard_drawing_render (MatekbdKeyboardDrawing * drawing,
+ cairo_t * cr,
+ PangoLayout * layout,
+ double x, double y,
+ double width, double height,
+ double dpi_x, double dpi_y)
+{
+ MatekbdKeyboardDrawingRenderContext context = {
+ cr,
+ drawing->renderContext->angle,
+ layout,
+ pango_font_description_copy (gtk_widget_get_style
+ (GTK_WIDGET
+ (drawing))->font_desc),
+ 1, 1,
+ &gtk_widget_get_style (GTK_WIDGET (drawing))->dark
+ [gtk_widget_get_state (GTK_WIDGET (drawing))]
+ };
+
+ if (!context_setup_scaling (&context, drawing, width, height,
+ dpi_x, dpi_y))
+ return FALSE;
+ cairo_translate (cr, x, y);
+
+ draw_keyboard_to_context (&context, drawing);
+
+ pango_font_description_free (context.font_desc);
+
+ return TRUE;
+}
+
+gboolean
+matekbd_keyboard_drawing_set_keyboard (MatekbdKeyboardDrawing * drawing,
+ XkbComponentNamesRec * names)
+{
+ GtkAllocation allocation;
+
+ 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);
+
+ gtk_widget_get_allocation (GTK_WIDGET (drawing), &allocation);
+ size_allocate (GTK_WIDGET (drawing), &allocation, drawing);
+ gtk_widget_queue_draw (GTK_WIDGET (drawing));
+
+ return TRUE;
+}
+
+const gchar* matekbd_keyboard_drawing_get_keycodes(MatekbdKeyboardDrawing* drawing)
+{
+ if (!drawing->xkb || drawing->xkb->names->keycodes <= 0)
+ {
+ return NULL;
+ }
+ else
+ {
+ return XGetAtomName(drawing->display, drawing->xkb->names->keycodes);
+ }
+}
+
+const gchar* matekbd_keyboard_drawing_get_geometry(MatekbdKeyboardDrawing* drawing)
+{
+ if (!drawing->xkb || drawing->xkb->names->geometry <= 0)
+ {
+ return NULL;
+ }
+ else
+ {
+ return XGetAtomName(drawing->display, drawing->xkb->names->geometry);
+ }
+}
+
+const gchar* matekbd_keyboard_drawing_get_symbols(MatekbdKeyboardDrawing* drawing)
+{
+ if (!drawing->xkb || drawing->xkb->names->symbols <= 0)
+ {
+ return NULL;
+ }
+ else
+ {
+ return XGetAtomName(drawing->display, drawing->xkb->names->symbols);
+ }
+}
+
+const gchar* matekbd_keyboard_drawing_get_types(MatekbdKeyboardDrawing* drawing)
+{
+ if (!drawing->xkb || drawing->xkb->names->types <= 0)
+ {
+ return NULL;
+ }
+ else
+ {
+ return XGetAtomName(drawing->display, drawing->xkb->names->types);
+ }
+}
+
+const gchar* matekbd_keyboard_drawing_get_compat(MatekbdKeyboardDrawing* drawing)
+{
+ if (!drawing->xkb || drawing->xkb->names->compat <= 0)
+ {
+ return NULL;
+ }
+ else
+ {
+ return XGetAtomName(drawing->display, drawing->xkb->names->compat);
+ }
+}
+
+void
+matekbd_keyboard_drawing_set_track_modifiers (MatekbdKeyboardDrawing * drawing,
+ gboolean enable)
+{
+ if (enable) {
+ XkbStateRec state;
+ drawing->track_modifiers = 1;
+ memset (&state, 0, sizeof (state));
+ XkbGetState (drawing->display, XkbUseCoreKbd, &state);
+ matekbd_keyboard_drawing_set_mods (drawing,
+ state.compat_state);
+ } else
+ drawing->track_modifiers = 0;
+}
+
+void
+matekbd_keyboard_drawing_set_track_config (MatekbdKeyboardDrawing * drawing,
+ gboolean enable)
+{
+ if (enable)
+ drawing->track_config = 1;
+ else
+ drawing->track_config = 0;
+}
+
+void
+matekbd_keyboard_drawing_set_groups_levels (MatekbdKeyboardDrawing * drawing,
+ MatekbdKeyboardDrawingGroupLevel *
+ groupLevels[])
+{
+#ifdef KBDRAW_DEBUG
+ printf ("set_group_levels [topLeft]: %d %d \n",
+ groupLevels[MATEKBD_KEYBOARD_DRAWING_POS_TOPLEFT]->group,
+ groupLevels[MATEKBD_KEYBOARD_DRAWING_POS_TOPLEFT]->level);
+ printf ("set_group_levels [topRight]: %d %d \n",
+ groupLevels[MATEKBD_KEYBOARD_DRAWING_POS_TOPRIGHT]->group,
+ groupLevels[MATEKBD_KEYBOARD_DRAWING_POS_TOPRIGHT]->level);
+ printf ("set_group_levels [bottomLeft]: %d %d \n",
+ groupLevels[MATEKBD_KEYBOARD_DRAWING_POS_BOTTOMLEFT]->group,
+ groupLevels[MATEKBD_KEYBOARD_DRAWING_POS_BOTTOMLEFT]->level);
+ printf ("set_group_levels [bottomRight]: %d %d \n",
+ groupLevels[MATEKBD_KEYBOARD_DRAWING_POS_BOTTOMRIGHT]->group,
+ groupLevels[MATEKBD_KEYBOARD_DRAWING_POS_BOTTOMRIGHT]->level);
+#endif
+ drawing->groupLevels = groupLevels;
+
+ gtk_widget_queue_draw (GTK_WIDGET (drawing));
+}
+
+typedef struct {
+ MatekbdKeyboardDrawing *drawing;
+ const gchar *description;
+} XkbLayoutPreviewPrintData;
+
+static void
+matekbd_keyboard_drawing_begin_print (GtkPrintOperation * operation,
+ GtkPrintContext * context,
+ XkbLayoutPreviewPrintData * data)
+{
+ /* We always print single-page documents */
+ GtkPrintSettings *settings =
+ gtk_print_operation_get_print_settings (operation);
+ gtk_print_operation_set_n_pages (operation, 1);
+ if (!gtk_print_settings_has_key
+ (settings, GTK_PRINT_SETTINGS_ORIENTATION))
+ gtk_print_settings_set_orientation (settings,
+ GTK_PAGE_ORIENTATION_LANDSCAPE);
+}
+
+static void
+matekbd_keyboard_drawing_draw_page (GtkPrintOperation * operation,
+ GtkPrintContext * context,
+ gint page_nr,
+ XkbLayoutPreviewPrintData * data)
+{
+ cairo_t *cr = gtk_print_context_get_cairo_context (context);
+ PangoLayout *layout =
+ gtk_print_context_create_pango_layout (context);
+ PangoFontDescription *desc =
+ pango_font_description_from_string ("sans 8");
+ gdouble width = gtk_print_context_get_width (context);
+ gdouble height = gtk_print_context_get_height (context);
+ gdouble dpi_x = gtk_print_context_get_dpi_x (context);
+ gdouble dpi_y = gtk_print_context_get_dpi_y (context);
+ gchar *header;
+
+ gtk_print_operation_set_unit (operation, GTK_PIXELS);
+
+ header = g_strdup_printf
+ (_("Keyboard layout \"%s\"\n"
+ "Copyright &#169; X.Org Foundation and "
+ "XKeyboardConfig contributors\n"
+ "For licensing see package metadata"), data->description);
+ pango_layout_set_markup (layout, header, -1);
+ pango_layout_set_font_description (layout, desc);
+ pango_font_description_free (desc);
+ pango_layout_set_width (layout, pango_units_from_double (width));
+ pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_move_to (cr, 0, 0);
+ pango_cairo_show_layout (cr, layout);
+
+ matekbd_keyboard_drawing_render (MATEKBD_KEYBOARD_DRAWING
+ (data->drawing), cr, layout, 0.0,
+ 0.0, width, height, dpi_x, dpi_y);
+
+ g_object_unref (layout);
+}
+
+void
+matekbd_keyboard_drawing_print (MatekbdKeyboardDrawing * drawing,
+ GtkWindow * parent_window,
+ const gchar * description)
+{
+ GtkPrintOperation *print;
+ GtkPrintOperationResult res;
+ static GtkPrintSettings *settings = NULL;
+ XkbLayoutPreviewPrintData data = { drawing, description };
+
+ print = gtk_print_operation_new ();
+
+ if (settings != NULL)
+ gtk_print_operation_set_print_settings (print, settings);
+
+ g_signal_connect (print, "begin_print",
+ G_CALLBACK (matekbd_keyboard_drawing_begin_print),
+ &data);
+ g_signal_connect (print, "draw_page",
+ G_CALLBACK (matekbd_keyboard_drawing_draw_page),
+ &data);
+
+ res = gtk_print_operation_run (print,
+ GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+ parent_window, NULL);
+
+ if (res == GTK_PRINT_OPERATION_RESULT_APPLY) {
+ if (settings != NULL)
+ g_object_unref (settings);
+ settings = gtk_print_operation_get_print_settings (print);
+ g_object_ref (settings);
+ }
+
+ g_object_unref (print);
+}
+
+static void
+show_layout_response (GtkWidget * dialog, gint resp)
+{
+ GdkRectangle rect;
+ GtkWidget *kbdraw;
+ const gchar *groupName;
+
+ switch (resp) {
+ case GTK_RESPONSE_HELP:
+ gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (dialog)),
+ "ghelp:gswitchit?layout-view",
+ gtk_get_current_event_time (), NULL);
+ return;
+ case GTK_RESPONSE_CLOSE:
+ gtk_window_get_position (GTK_WINDOW (dialog), &rect.x,
+ &rect.y);
+ gtk_window_get_size (GTK_WINDOW (dialog), &rect.width,
+ &rect.height);
+ matekbd_preview_save_position (&rect);
+ gtk_widget_destroy (dialog);
+ break;
+ case GTK_RESPONSE_PRINT:
+ kbdraw =
+ GTK_WIDGET (g_object_get_data
+ (G_OBJECT (dialog), "kbdraw"));
+ groupName =
+ (const gchar *) g_object_get_data (G_OBJECT (dialog),
+ "groupName");
+ matekbd_keyboard_drawing_print (MATEKBD_KEYBOARD_DRAWING
+ (kbdraw), GTK_WINDOW (dialog),
+ groupName ? groupName :
+ _("Unknown"));
+ }
+}
+
+GtkWidget *
+matekbd_keyboard_drawing_new_dialog (gint group, gchar * group_name)
+{
+ static MatekbdKeyboardDrawingGroupLevel groupsLevels[] = { {
+ 0, 1}, {
+ 0,
+ 3},
+ {
+ 0, 0}, {
+ 0, 2}
+ };
+ static MatekbdKeyboardDrawingGroupLevel *pGroupsLevels[] = {
+ groupsLevels, groupsLevels + 1, groupsLevels + 2,
+ groupsLevels + 3
+ };
+
+ GtkBuilder *builder;
+ GtkWidget *dialog, *kbdraw;
+ XkbComponentNamesRec component_names;
+ XklConfigRec *xkl_data;
+ GdkRectangle *rect;
+ GError *error = NULL;
+ char title[128] = "";
+ XklEngine *engine = xkl_engine_get_instance (GDK_DISPLAY ());
+
+ builder = gtk_builder_new ();
+ gtk_builder_add_from_file (builder, UIDIR "/show-layout.ui",
+ &error);
+
+ if (error) {
+ g_error ("building ui from %s failed: %s",
+ UIDIR "/show-layout.ui", error->message);
+ g_clear_error (&error);
+ }
+
+
+ dialog =
+ GTK_WIDGET (gtk_builder_get_object
+ (builder, "gswitchit_layout_view"));
+ kbdraw = matekbd_keyboard_drawing_new ();
+
+ snprintf (title, sizeof (title), _("Keyboard Layout \"%s\""),
+ group_name);
+ gtk_window_set_title (GTK_WINDOW (dialog), title);
+ g_object_set_data_full (G_OBJECT (dialog), "group_name",
+ g_strdup (group_name), g_free);
+
+ matekbd_keyboard_drawing_set_groups_levels (MATEKBD_KEYBOARD_DRAWING
+ (kbdraw), pGroupsLevels);
+
+ xkl_data = xkl_config_rec_new ();
+ if (xkl_config_rec_get_from_server (xkl_data, engine)) {
+ int num_layouts = g_strv_length (xkl_data->layouts);
+ int num_variants = g_strv_length (xkl_data->variants);
+ if (group >= 0 && group < num_layouts
+ && group < num_variants) {
+ char *l = g_strdup (xkl_data->layouts[group]);
+ char *v = g_strdup (xkl_data->variants[group]);
+ char **p;
+ int i;
+
+ if ((p = xkl_data->layouts) != NULL)
+ for (i = num_layouts; --i >= 0;)
+ g_free (*p++);
+
+ if ((p = xkl_data->variants) != NULL)
+ for (i = num_variants; --i >= 0;)
+ g_free (*p++);
+
+ xkl_data->layouts =
+ g_realloc (xkl_data->layouts,
+ sizeof (char *) * 2);
+ xkl_data->variants =
+ g_realloc (xkl_data->variants,
+ sizeof (char *) * 2);
+ xkl_data->layouts[0] = l;
+ xkl_data->variants[0] = v;
+ xkl_data->layouts[1] = xkl_data->variants[1] =
+ NULL;
+ }
+
+ if (xkl_xkb_config_native_prepare
+ (engine, xkl_data, &component_names)) {
+ matekbd_keyboard_drawing_set_keyboard
+ (MATEKBD_KEYBOARD_DRAWING (kbdraw),
+ &component_names);
+ xkl_xkb_config_native_cleanup (engine,
+ &component_names);
+ }
+ }
+ g_object_unref (G_OBJECT (xkl_data));
+
+ g_object_set_data (G_OBJECT (dialog), "builderData", builder);
+ g_signal_connect (G_OBJECT (dialog), "response",
+ G_CALLBACK (show_layout_response), NULL);
+
+ rect = matekbd_preview_load_position ();
+ if (rect != NULL) {
+ gtk_window_move (GTK_WINDOW (dialog), rect->x, rect->y);
+ gtk_window_resize (GTK_WINDOW (dialog), rect->width,
+ rect->height);
+ g_free (rect);
+ } else
+ gtk_window_resize (GTK_WINDOW (dialog), 700, 400);
+
+ gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
+
+ gtk_container_add (GTK_CONTAINER
+ (gtk_builder_get_object
+ (builder, "preview_vbox")), kbdraw);
+
+ g_object_set_data (G_OBJECT (dialog), "kbdraw", kbdraw);
+
+ g_signal_connect_swapped (GTK_OBJECT (dialog), "destroy",
+ G_CALLBACK (g_object_unref),
+ g_object_get_data (G_OBJECT (dialog),
+ "builderData"));
+
+ gtk_widget_show_all (dialog);
+
+ return dialog;
+}
diff --git a/libmatekbd/matekbd-keyboard-drawing.h b/libmatekbd/matekbd-keyboard-drawing.h
new file mode 100644
index 0000000..35fe2cd
--- /dev/null
+++ b/libmatekbd/matekbd-keyboard-drawing.h
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef MATEKBD_KEYBOARD_DRAWING_H
+#define MATEKBD_KEYBOARD_DRAWING_H 1
+
+#include <gtk/gtk.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBgeom.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define MATEKBD_KEYBOARD_DRAWING(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), matekbd_keyboard_drawing_get_type (), \
+ MatekbdKeyboardDrawing))
+#define MATEKBD_KEYBOARD_DRAWING_CLASS(clazz) (G_TYPE_CHECK_CLASS_CAST ((clazz), matekbd_keyboard_drawing_get_type () \
+ MatekbdKeyboardDrawingClass))
+#define MATEKBD_IS_KEYBOARD_DRAWING(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), matekbd_keyboard_drawing_get_type ())
+typedef struct _MatekbdKeyboardDrawing MatekbdKeyboardDrawing;
+typedef struct _MatekbdKeyboardDrawingClass MatekbdKeyboardDrawingClass;
+
+typedef struct _MatekbdKeyboardDrawingItem MatekbdKeyboardDrawingItem;
+typedef struct _MatekbdKeyboardDrawingKey MatekbdKeyboardDrawingKey;
+typedef struct _MatekbdKeyboardDrawingDoodad MatekbdKeyboardDrawingDoodad;
+typedef struct _MatekbdKeyboardDrawingGroupLevel
+ MatekbdKeyboardDrawingGroupLevel;
+typedef struct _MatekbdKeyboardDrawingRenderContext
+ MatekbdKeyboardDrawingRenderContext;
+
+typedef enum {
+ MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_INVALID = 0,
+ MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY,
+ MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY_EXTRA,
+ MATEKBD_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD
+} MatekbdKeyboardDrawingItemType;
+
+typedef enum {
+ MATEKBD_KEYBOARD_DRAWING_POS_TOPLEFT,
+ MATEKBD_KEYBOARD_DRAWING_POS_TOPRIGHT,
+ MATEKBD_KEYBOARD_DRAWING_POS_BOTTOMLEFT,
+ MATEKBD_KEYBOARD_DRAWING_POS_BOTTOMRIGHT,
+ MATEKBD_KEYBOARD_DRAWING_POS_TOTAL,
+ MATEKBD_KEYBOARD_DRAWING_POS_FIRST =
+ MATEKBD_KEYBOARD_DRAWING_POS_TOPLEFT,
+ MATEKBD_KEYBOARD_DRAWING_POS_LAST =
+ MATEKBD_KEYBOARD_DRAWING_POS_BOTTOMRIGHT
+} MatekbdKeyboardDrawingGroupLevelPosition;
+
+/* units are in xkb form */
+struct _MatekbdKeyboardDrawingItem {
+ /*< private > */
+
+ MatekbdKeyboardDrawingItemType type;
+ gint origin_x;
+ gint origin_y;
+ gint angle;
+ guint priority;
+};
+
+/* units are in xkb form */
+struct _MatekbdKeyboardDrawingKey {
+ /*< private > */
+
+ MatekbdKeyboardDrawingItemType type;
+ gint origin_x;
+ gint origin_y;
+ gint angle;
+ guint priority;
+
+ XkbKeyRec *xkbkey;
+ gboolean pressed;
+ guint keycode;
+};
+
+/* units are in xkb form */
+struct _MatekbdKeyboardDrawingDoodad {
+ /*< private > */
+
+ MatekbdKeyboardDrawingItemType type;
+ gint origin_x;
+ gint origin_y;
+ gint angle;
+ guint priority;
+
+ XkbDoodadRec *doodad;
+ gboolean on; /* for indicator doodads */
+};
+
+struct _MatekbdKeyboardDrawingGroupLevel {
+ gint group;
+ gint level;
+};
+
+struct _MatekbdKeyboardDrawingRenderContext {
+ cairo_t *cr;
+
+ 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;
+
+ GdkColor *dark_color;
+};
+
+struct _MatekbdKeyboardDrawing {
+ /*< private > */
+
+ GtkDrawingArea parent;
+
+ GdkPixmap *pixmap;
+ XkbDescRec *xkb;
+ gboolean xkbOnDisplay;
+ guint l3mod;
+
+ MatekbdKeyboardDrawingRenderContext *renderContext;
+
+ /* Indexed by keycode */
+ MatekbdKeyboardDrawingKey *keys;
+
+ /* list of stuff to draw in priority order */
+ GList *keyboard_items;
+
+ GdkColor *colors;
+
+ guint timeout;
+ guint idle_redraw;
+
+ MatekbdKeyboardDrawingGroupLevel **groupLevels;
+
+ guint mods;
+
+ Display *display;
+ gint screen_num;
+
+ gint xkb_event_type;
+
+ MatekbdKeyboardDrawingDoodad **physical_indicators;
+ gint physical_indicators_size;
+
+ guint track_config:1;
+ guint track_modifiers:1;
+};
+
+struct _MatekbdKeyboardDrawingClass {
+ 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) (MatekbdKeyboardDrawing * drawing, guint keycode);
+};
+
+GType matekbd_keyboard_drawing_get_type (void);
+GtkWidget *matekbd_keyboard_drawing_new (void);
+
+GdkPixbuf *matekbd_keyboard_drawing_get_pixbuf (MatekbdKeyboardDrawing *
+ kbdrawing);
+gboolean matekbd_keyboard_drawing_render (MatekbdKeyboardDrawing * kbdrawing,
+ cairo_t * cr,
+ PangoLayout * layout,
+ double x, double y,
+ double width, double height,
+ gdouble dpi_x, gdouble dpi_y);
+gboolean matekbd_keyboard_drawing_set_keyboard (MatekbdKeyboardDrawing *
+ kbdrawing,
+ XkbComponentNamesRec * names);
+
+const gchar* matekbd_keyboard_drawing_get_keycodes(MatekbdKeyboardDrawing* kbdrawing);
+const gchar* matekbd_keyboard_drawing_get_geometry(MatekbdKeyboardDrawing* kbdrawing);
+const gchar* matekbd_keyboard_drawing_get_symbols(MatekbdKeyboardDrawing* kbdrawing);
+const gchar* matekbd_keyboard_drawing_get_types(MatekbdKeyboardDrawing* kbdrawing);
+const gchar* matekbd_keyboard_drawing_get_compat(MatekbdKeyboardDrawing* kbdrawing);
+
+void matekbd_keyboard_drawing_set_track_modifiers (MatekbdKeyboardDrawing *
+ kbdrawing,
+ gboolean enable);
+void matekbd_keyboard_drawing_set_track_config (MatekbdKeyboardDrawing *
+ kbdrawing, gboolean enable);
+
+void matekbd_keyboard_drawing_set_groups_levels (MatekbdKeyboardDrawing *
+ kbdrawing,
+ MatekbdKeyboardDrawingGroupLevel
+ * groupLevels[]);
+
+
+void matekbd_keyboard_drawing_print (MatekbdKeyboardDrawing * drawing,
+ GtkWindow * parent_window,
+ const gchar * description);
+
+
+GtkWidget* matekbd_keyboard_drawing_new_dialog (gint group, gchar* group_name);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* #ifndef MATEKBD_KEYBOARD_DRAWING_H */
diff --git a/libmatekbd/matekbd-status.c b/libmatekbd/matekbd-status.c
new file mode 100644
index 0000000..72a9add
--- /dev/null
+++ b/libmatekbd/matekbd-status.c
@@ -0,0 +1,867 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <memory.h>
+
+#include <cairo.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gdk/gdkx.h>
+#include <glib/gi18n.h>
+#include <glib/gprintf.h>
+
+#include <matekbd-status.h>
+
+#include <matekbd-desktop-config.h>
+#include <matekbd-indicator-config.h>
+
+typedef struct _gki_globals {
+ XklEngine *engine;
+ XklConfigRegistry *registry;
+
+ MatekbdDesktopConfig cfg;
+ MatekbdIndicatorConfig ind_cfg;
+ MatekbdKeyboardConfig kbd_cfg;
+
+ const gchar *tooltips_format;
+ gchar **full_group_names;
+ gchar **short_group_names;
+
+ gint current_width;
+ gint current_height;
+ int real_width;
+
+ GSList *icons; /* list of GdkPixbuf */
+ GSList *widget_instances; /* list of MatekbdStatus */
+ gulong state_changed_handler;
+ gulong config_changed_handler;
+} gki_globals;
+
+static gchar *settings_signal_names[] = {
+ "notify::gtk-theme-name",
+ "notify::gtk-key-theme-name",
+ "notify::gtk-font-name",
+ "notify::font-options",
+};
+
+struct _MatekbdStatusPrivate {
+ gdouble angle;
+ gulong settings_signal_handlers[sizeof (settings_signal_names) /
+ sizeof (settings_signal_names[0])];
+};
+
+/* one instance for ALL widgets */
+static gki_globals globals;
+
+#define ForAllIndicators() \
+ { \
+ GSList* cur; \
+ for (cur = globals.widget_instances; cur != NULL; cur = cur->next) { \
+ MatekbdStatus * gki = (MatekbdStatus*)cur->data;
+#define NextIndicator() \
+ } \
+ }
+
+G_DEFINE_TYPE (MatekbdStatus, matekbd_status, GTK_TYPE_STATUS_ICON)
+static void
+matekbd_status_global_init (void);
+static void
+matekbd_status_global_term (void);
+static GdkPixbuf *
+matekbd_status_prepare_drawing (MatekbdStatus * gki, int group);
+static void
+matekbd_status_set_current_page_for_group (MatekbdStatus * gki, int group);
+static void
+matekbd_status_set_current_page (MatekbdStatus * gki);
+static void
+matekbd_status_global_cleanup (MatekbdStatus * gki);
+static void
+matekbd_status_global_fill (MatekbdStatus * gki);
+static void
+matekbd_status_set_tooltips (MatekbdStatus * gki, const char *str);
+
+void
+matekbd_status_set_tooltips (MatekbdStatus * gki, const char *str)
+{
+ g_assert (str == NULL || g_utf8_validate (str, -1, NULL));
+
+ gtk_status_icon_set_tooltip_text (GTK_STATUS_ICON (gki), str);
+}
+
+void
+matekbd_status_global_cleanup (MatekbdStatus * gki)
+{
+ while (globals.icons) {
+ if (globals.icons->data)
+ g_object_unref (G_OBJECT (globals.icons->data));
+ globals.icons =
+ g_slist_delete_link (globals.icons, globals.icons);
+ }
+}
+
+void
+matekbd_status_global_fill (MatekbdStatus * gki)
+{
+ int grp;
+ int total_groups = xkl_engine_get_num_groups (globals.engine);
+
+ for (grp = 0; grp < total_groups; grp++) {
+ GdkPixbuf *page = matekbd_status_prepare_drawing (gki, grp);
+ globals.icons = g_slist_append (globals.icons, page);
+ }
+}
+
+static void
+matekbd_status_activate (MatekbdStatus * gki)
+{
+ xkl_debug (150, "Mouse button pressed on applet\n");
+ matekbd_desktop_config_lock_next_group (&globals.cfg);
+}
+
+/* hackish xref */
+extern gchar *matekbd_indicator_extract_layout_name (int group,
+ XklEngine * engine,
+ MatekbdKeyboardConfig *
+ kbd_cfg,
+ gchar **
+ short_group_names,
+ gchar **
+ full_group_names);
+
+extern gchar *matekbd_indicator_create_label_title (int group,
+ GHashTable **
+ ln2cnt_map,
+ gchar * layout_name);
+
+static void
+matekbd_status_render_cairo (cairo_t * cr, int group)
+{
+ double r, g, b;
+ PangoFontDescription *pfd;
+ PangoContext *pcc;
+ PangoLayout *pl;
+ int lwidth, lheight;
+ gchar *layout_name, *lbl_title;
+ cairo_font_options_t *fo;
+ static GHashTable *ln2cnt_map = NULL;
+
+ xkl_debug (160, "Rendering cairo for group %d\n", group);
+ if (globals.ind_cfg.background_color != NULL &&
+ globals.ind_cfg.background_color[0] != 0) {
+ if (sscanf
+ (globals.ind_cfg.background_color, "%lg %lg %lg", &r,
+ &g, &b) == 3) {
+ cairo_set_source_rgb (cr, r, g, b);
+ cairo_rectangle (cr, 0, 0, globals.current_width,
+ globals.current_height);
+ cairo_fill (cr);
+ }
+ }
+
+ if (globals.ind_cfg.foreground_color != NULL &&
+ globals.ind_cfg.foreground_color[0] != 0) {
+ if (sscanf
+ (globals.ind_cfg.foreground_color, "%lg %lg %lg", &r,
+ &g, &b) == 3) {
+ cairo_set_source_rgb (cr, r, g, b);
+ }
+ }
+
+ if (globals.ind_cfg.font_family != NULL &&
+ globals.ind_cfg.font_family[0] != 0) {
+ cairo_select_font_face (cr, globals.ind_cfg.font_family,
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ }
+
+ pfd = pango_font_description_new ();
+ pango_font_description_set_family (pfd,
+ globals.ind_cfg.font_family);
+ pango_font_description_set_style (pfd, PANGO_STYLE_NORMAL);
+ pango_font_description_set_weight (pfd, PANGO_WEIGHT_NORMAL);
+ pango_font_description_set_size (pfd,
+ globals.ind_cfg.font_size *
+ PANGO_SCALE);
+
+ pcc = pango_cairo_create_context (cr);
+
+ fo = cairo_font_options_copy (gdk_screen_get_font_options
+ (gdk_screen_get_default ()));
+ /* SUBPIXEL antialiasing gives bad results on in-memory images */
+ if (cairo_font_options_get_antialias (fo) ==
+ CAIRO_ANTIALIAS_SUBPIXEL)
+ cairo_font_options_set_antialias (fo,
+ CAIRO_ANTIALIAS_GRAY);
+ pango_cairo_context_set_font_options (pcc, fo);
+
+ pl = pango_layout_new (pcc);
+
+ layout_name = matekbd_indicator_extract_layout_name (group,
+ globals.engine,
+ &globals.kbd_cfg,
+ globals.short_group_names,
+ globals.full_group_names);
+ lbl_title =
+ matekbd_indicator_create_label_title (group, &ln2cnt_map,
+ layout_name);
+
+ if (group + 1 == xkl_engine_get_num_groups (globals.engine)) {
+ g_hash_table_destroy (ln2cnt_map);
+ ln2cnt_map = NULL;
+ }
+
+ pango_layout_set_text (pl, lbl_title, -1);
+
+ g_free (lbl_title);
+
+ pango_layout_set_font_description (pl, pfd);
+ pango_layout_get_size (pl, &lwidth, &lheight);
+
+ cairo_move_to (cr,
+ (globals.current_width - lwidth / PANGO_SCALE) / 2,
+ (globals.current_height -
+ lheight / PANGO_SCALE) / 2);
+
+ pango_cairo_show_layout (cr, pl);
+
+ pango_font_description_free (pfd);
+ g_object_unref (pl);
+ g_object_unref (pcc);
+ cairo_font_options_destroy (fo);
+ cairo_destroy (cr);
+
+ globals.real_width = (lwidth / PANGO_SCALE) + 4;
+ if (globals.real_width > globals.current_width)
+ globals.real_width = globals.current_width;
+ if (globals.real_width < globals.current_height)
+ globals.real_width = globals.current_height;
+}
+
+static inline guint8
+convert_color_channel (guint8 src, guint8 alpha)
+{
+ return alpha ? ((((guint) src) << 8) - src) / alpha : 0;
+}
+
+static void
+convert_bgra_to_rgba (guint8 const *src, guint8 * dst, int width,
+ int height, int new_width)
+{
+ int xoffset = width - new_width;
+
+ /* *4 */
+ int ptr_step = xoffset << 2;
+
+ int x, y;
+
+ /* / 2 * 4 */
+ src = src + ((xoffset >> 1) << 2);
+
+ for (y = height; --y >= 0; src += ptr_step) {
+ for (x = new_width; --x >= 0;) {
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ dst[0] = convert_color_channel (src[2], src[3]);
+ dst[1] = convert_color_channel (src[1], src[3]);
+ dst[2] = convert_color_channel (src[0], src[3]);
+ dst[3] = src[3];
+#else
+ dst[0] = convert_color_channel (src[1], src[0]);
+ dst[1] = convert_color_channel (src[2], src[0]);
+ dst[2] = convert_color_channel (src[3], src[0]);
+ dst[3] = src[0];
+#endif
+ dst += 4;
+ src += 4;
+ }
+ }
+}
+
+static GdkPixbuf *
+matekbd_status_prepare_drawing (MatekbdStatus * gki, int group)
+{
+ GError *gerror = NULL;
+ char *image_filename;
+ GdkPixbuf *image;
+
+ if (globals.current_width == 0)
+ return NULL;
+
+ if (globals.ind_cfg.show_flags) {
+
+ image_filename =
+ (char *) g_slist_nth_data (globals.
+ ind_cfg.image_filenames,
+ group);
+
+ image = gdk_pixbuf_new_from_file_at_size (image_filename,
+ globals.current_width,
+ globals.current_height,
+ &gerror);
+
+ if (image == NULL) {
+ GtkWidget *dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _
+ ("There was an error loading an image: %s"),
+ gerror
+ ==
+ NULL ?
+ "Unknown"
+ :
+ gerror->message);
+ g_signal_connect (G_OBJECT (dialog), "response",
+ G_CALLBACK (gtk_widget_destroy),
+ NULL);
+
+ gtk_window_set_resizable (GTK_WINDOW (dialog),
+ FALSE);
+
+ gtk_widget_show (dialog);
+ g_error_free (gerror);
+
+ return NULL;
+ }
+ xkl_debug (150,
+ "Image %d[%s] loaded -> %p[%dx%d], alpha: %d\n",
+ group, image_filename, image,
+ gdk_pixbuf_get_width (image),
+ gdk_pixbuf_get_height (image),
+ gdk_pixbuf_get_has_alpha (image));
+
+ return image;
+ } else {
+ cairo_surface_t *cs =
+ cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ globals.current_width,
+ globals.current_height);
+ unsigned char *cairo_data;
+ guchar *pixbuf_data;
+ matekbd_status_render_cairo (cairo_create (cs), group);
+ cairo_data = cairo_image_surface_get_data (cs);
+#if 0
+ char pngfilename[20];
+ g_sprintf (pngfilename, "label%d.png", group);
+ cairo_surface_write_to_png (cs, pngfilename);
+#endif
+ pixbuf_data =
+ g_new0 (guchar,
+ 4 * globals.real_width *
+ globals.current_height);
+ convert_bgra_to_rgba (cairo_data, pixbuf_data,
+ globals.current_width,
+ globals.current_height,
+ globals.real_width);
+
+ cairo_surface_destroy (cs);
+
+ image = gdk_pixbuf_new_from_data (pixbuf_data,
+ GDK_COLORSPACE_RGB,
+ TRUE,
+ 8,
+ globals.real_width,
+ globals.current_height,
+ globals.real_width *
+ 4,
+ (GdkPixbufDestroyNotify)
+ g_free, NULL);
+ xkl_debug (150,
+ "Image %d created -> %p[%dx%d], alpha: %d\n",
+ group, image, gdk_pixbuf_get_width (image),
+ gdk_pixbuf_get_height (image),
+ gdk_pixbuf_get_has_alpha (image));
+
+ return image;
+ }
+ return NULL;
+}
+
+static void
+matekbd_status_update_tooltips (MatekbdStatus * gki)
+{
+ XklState *state = xkl_engine_get_current_state (globals.engine);
+ gchar *buf;
+ if (state == NULL || state->group < 0
+ || state->group >= g_strv_length (globals.full_group_names))
+ return;
+
+ buf = g_strdup_printf (globals.tooltips_format,
+ globals.full_group_names[state->group]);
+
+ matekbd_status_set_tooltips (gki, buf);
+ g_free (buf);
+}
+
+void
+matekbd_status_reinit_ui (MatekbdStatus * gki)
+{
+ matekbd_status_global_cleanup (gki);
+ matekbd_status_global_fill (gki);
+
+ matekbd_status_set_current_page (gki);
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_status_cfg_changed (MateConfClient * client,
+ guint cnxn_id, MateConfEntry * entry)
+{
+ xkl_debug (100,
+ "General configuration changed in MateConf - reiniting...\n");
+ matekbd_desktop_config_load_from_mateconf (&globals.cfg);
+ matekbd_desktop_config_activate (&globals.cfg);
+ ForAllIndicators () {
+ matekbd_status_reinit_ui (gki);
+ } NextIndicator ();
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_status_ind_cfg_changed (MateConfClient * client,
+ guint cnxn_id, MateConfEntry * entry)
+{
+ xkl_debug (100,
+ "Applet configuration changed in MateConf - reiniting...\n");
+ matekbd_indicator_config_load_from_mateconf (&globals.ind_cfg);
+
+ matekbd_indicator_config_free_image_filenames (&globals.ind_cfg);
+ matekbd_indicator_config_load_image_filenames (&globals.ind_cfg,
+ &globals.kbd_cfg);
+
+ matekbd_indicator_config_activate (&globals.ind_cfg);
+
+ ForAllIndicators () {
+ matekbd_status_reinit_ui (gki);
+ } NextIndicator ();
+}
+
+static void
+matekbd_status_load_group_names (const gchar ** layout_ids,
+ const gchar ** variant_ids)
+{
+ if (!matekbd_desktop_config_load_group_descriptions
+ (&globals.cfg, globals.registry, layout_ids, variant_ids,
+ &globals.short_group_names, &globals.full_group_names)) {
+ /* We just populate no short names (remain NULL) -
+ * full names are going to be used anyway */
+ gint i, total_groups =
+ xkl_engine_get_num_groups (globals.engine);
+ xkl_debug (150, "group descriptions loaded: %d!\n",
+ total_groups);
+ globals.full_group_names =
+ g_new0 (char *, total_groups + 1);
+
+ if (xkl_engine_get_features (globals.engine) &
+ XKLF_MULTIPLE_LAYOUTS_SUPPORTED) {
+ GSList *lst = globals.kbd_cfg.layouts_variants;
+ for (i = 0; lst; lst = lst->next, i++) {
+ globals.full_group_names[i] =
+ g_strdup ((char *) lst->data);
+ }
+ } else {
+ for (i = total_groups; --i >= 0;) {
+ globals.full_group_names[i] =
+ g_strdup_printf ("Group %d", i);
+ }
+ }
+ }
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_status_kbd_cfg_callback (MatekbdStatus * gki)
+{
+ XklConfigRec *xklrec = xkl_config_rec_new ();
+ xkl_debug (100,
+ "XKB configuration changed on X Server - reiniting...\n");
+
+ matekbd_keyboard_config_load_from_x_current (&globals.kbd_cfg,
+ xklrec);
+
+ matekbd_indicator_config_free_image_filenames (&globals.ind_cfg);
+ matekbd_indicator_config_load_image_filenames (&globals.ind_cfg,
+ &globals.kbd_cfg);
+
+ g_strfreev (globals.full_group_names);
+ globals.full_group_names = NULL;
+
+ if (globals.short_group_names != NULL) {
+ g_strfreev (globals.short_group_names);
+ globals.short_group_names = NULL;
+ }
+
+ matekbd_status_load_group_names ((const gchar **) xklrec->layouts,
+ (const gchar **) xklrec->variants);
+
+ ForAllIndicators () {
+ matekbd_status_reinit_ui (gki);
+ } NextIndicator ();
+ g_object_unref (G_OBJECT (xklrec));
+}
+
+/* Should be called once for all applets */
+static void
+matekbd_status_state_callback (XklEngine * engine,
+ XklEngineStateChange changeType,
+ gint group, gboolean restore)
+{
+ xkl_debug (150, "group is now %d, restore: %d\n", group, restore);
+
+ if (changeType == GROUP_CHANGED) {
+ ForAllIndicators () {
+ xkl_debug (200, "do repaint\n");
+ matekbd_status_set_current_page_for_group (gki,
+ group);
+ }
+ NextIndicator ();
+ }
+}
+
+
+void
+matekbd_status_set_current_page (MatekbdStatus * gki)
+{
+ XklState *cur_state;
+ cur_state = xkl_engine_get_current_state (globals.engine);
+ if (cur_state->group >= 0)
+ matekbd_status_set_current_page_for_group (gki,
+ cur_state->group);
+}
+
+void
+matekbd_status_set_current_page_for_group (MatekbdStatus * gki, int group)
+{
+ xkl_debug (200, "Revalidating for group %d\n", group);
+
+ gtk_status_icon_set_from_pixbuf (GTK_STATUS_ICON (gki),
+ GDK_PIXBUF (g_slist_nth_data
+ (globals.icons,
+ group)));
+
+ matekbd_status_update_tooltips (gki);
+}
+
+/* Should be called once for all widgets */
+static GdkFilterReturn
+matekbd_status_filter_x_evt (GdkXEvent * xev, GdkEvent * event)
+{
+ XEvent *xevent = (XEvent *) xev;
+
+ xkl_engine_filter_events (globals.engine, xevent);
+ switch (xevent->type) {
+ case ReparentNotify:
+ {
+ XReparentEvent *rne = (XReparentEvent *) xev;
+
+ ForAllIndicators () {
+ guint32 xid =
+ gtk_status_icon_get_x11_window_id
+ (GTK_STATUS_ICON (gki));
+
+ /* compare the indicator's parent window with the even window */
+ if (xid == rne->window) {
+ /* if so - make it transparent... */
+ xkl_engine_set_window_transparent
+ (globals.engine, rne->window,
+ TRUE);
+ }
+ }
+ NextIndicator ()}
+ break;
+ }
+ return GDK_FILTER_CONTINUE;
+}
+
+
+/* Should be called once for all widgets */
+static void
+matekbd_status_start_listen (void)
+{
+ gdk_window_add_filter (NULL, (GdkFilterFunc)
+ matekbd_status_filter_x_evt, NULL);
+ gdk_window_add_filter (gdk_get_default_root_window (),
+ (GdkFilterFunc) matekbd_status_filter_x_evt,
+ NULL);
+
+ xkl_engine_start_listen (globals.engine,
+ XKLL_TRACK_KEYBOARD_STATE);
+}
+
+/* Should be called once for all widgets */
+static void
+matekbd_status_stop_listen (void)
+{
+ xkl_engine_stop_listen (globals.engine, XKLL_TRACK_KEYBOARD_STATE);
+
+ gdk_window_remove_filter (NULL, (GdkFilterFunc)
+ matekbd_status_filter_x_evt, NULL);
+ gdk_window_remove_filter
+ (gdk_get_default_root_window (),
+ (GdkFilterFunc) matekbd_status_filter_x_evt, NULL);
+}
+
+static void
+matekbd_status_size_changed (MatekbdStatus * gki, gint size)
+{
+ if (globals.current_height != size) {
+ globals.current_height = size;
+ globals.current_width = size * 3 / 2;
+ matekbd_status_reinit_ui (gki);
+ }
+}
+
+static void
+matekbd_status_theme_changed (GtkSettings * settings, GParamSpec * pspec,
+ MatekbdStatus * gki)
+{
+ matekbd_indicator_config_refresh_style (&globals.ind_cfg);
+ matekbd_status_reinit_ui (gki);
+}
+
+static void
+matekbd_status_init (MatekbdStatus * gki)
+{
+ int i;
+
+ if (!g_slist_length (globals.widget_instances))
+ matekbd_status_global_init ();
+
+ gki->priv = g_new0 (MatekbdStatusPrivate, 1);
+
+ /* This should give NA a hint about the order */
+ gtk_status_icon_set_name (GTK_STATUS_ICON (gki), "keyboard");
+
+ xkl_debug (100, "Initiating the widget startup process for %p\n",
+ gki);
+
+ if (globals.engine == NULL) {
+ matekbd_status_set_tooltips (gki,
+ _("XKB initialization error"));
+ return;
+ }
+
+ matekbd_status_set_tooltips (gki, NULL);
+
+ matekbd_status_global_fill (gki);
+ matekbd_status_set_current_page (gki);
+
+ /* append AFTER all initialization work is finished */
+ globals.widget_instances =
+ g_slist_append (globals.widget_instances, gki);
+
+ g_signal_connect (gki, "size-changed",
+ G_CALLBACK (matekbd_status_size_changed), NULL);
+ g_signal_connect (gki, "activate",
+ G_CALLBACK (matekbd_status_activate), NULL);
+
+ for (i = sizeof (settings_signal_names) /
+ sizeof (settings_signal_names[0]); --i >= 0;)
+ gki->priv->settings_signal_handlers[i] =
+ g_signal_connect_after (gtk_settings_get_default (),
+ settings_signal_names[i],
+ G_CALLBACK
+ (matekbd_status_theme_changed),
+ gki);
+}
+
+static void
+matekbd_status_finalize (GObject * obj)
+{
+ int i;
+ MatekbdStatus *gki = MATEKBD_STATUS (obj);
+ xkl_debug (100,
+ "Starting the mate-kbd-status widget shutdown process for %p\n",
+ gki);
+
+ for (i = sizeof (settings_signal_names) /
+ sizeof (settings_signal_names[0]); --i >= 0;)
+ g_signal_handler_disconnect (gtk_settings_get_default (),
+ gki->
+ priv->settings_signal_handlers
+ [i]);
+
+ /* remove BEFORE all termination work is finished */
+ globals.widget_instances =
+ g_slist_remove (globals.widget_instances, gki);
+
+ matekbd_status_global_cleanup (gki);
+
+ xkl_debug (100,
+ "The instance of mate-kbd-status successfully finalized\n");
+
+ g_free (gki->priv);
+
+ G_OBJECT_CLASS (matekbd_status_parent_class)->finalize (obj);
+
+ if (!g_slist_length (globals.widget_instances))
+ matekbd_status_global_term ();
+}
+
+static void
+matekbd_status_global_term (void)
+{
+ xkl_debug (100, "*** Last MatekbdStatus instance *** \n");
+ matekbd_status_stop_listen ();
+
+ matekbd_desktop_config_stop_listen (&globals.cfg);
+ matekbd_indicator_config_stop_listen (&globals.ind_cfg);
+
+ matekbd_indicator_config_term (&globals.ind_cfg);
+ matekbd_keyboard_config_term (&globals.kbd_cfg);
+ matekbd_desktop_config_term (&globals.cfg);
+
+ if (g_signal_handler_is_connected
+ (globals.engine, globals.state_changed_handler)) {
+ g_signal_handler_disconnect (globals.engine,
+ globals.state_changed_handler);
+ globals.state_changed_handler = 0;
+ }
+ if (g_signal_handler_is_connected
+ (globals.engine, globals.config_changed_handler)) {
+ g_signal_handler_disconnect (globals.engine,
+ globals.config_changed_handler);
+ globals.config_changed_handler = 0;
+ }
+
+ g_object_unref (G_OBJECT (globals.registry));
+ globals.registry = NULL;
+ g_object_unref (G_OBJECT (globals.engine));
+ globals.engine = NULL;
+ xkl_debug (100, "*** Terminated globals *** \n");
+}
+
+static void
+matekbd_status_class_init (MatekbdStatusClass * klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ xkl_debug (100, "*** First MatekbdStatus instance *** \n");
+
+ memset (&globals, 0, sizeof (globals));
+
+ /* Initing some global vars */
+ globals.tooltips_format = "%s";
+
+ /* Initing vtable */
+ object_class->finalize = matekbd_status_finalize;
+
+ /* Signals */
+}
+
+static void
+matekbd_status_global_init (void)
+{
+ MateConfClient *mateconf_client;
+ XklConfigRec *xklrec = xkl_config_rec_new ();
+
+ globals.engine = xkl_engine_get_instance (GDK_DISPLAY ());
+ if (globals.engine == NULL) {
+ xkl_debug (0, "Libxklavier initialization error");
+ return;
+ }
+
+ mateconf_client = mateconf_client_get_default ();
+
+ globals.state_changed_handler =
+ g_signal_connect (globals.engine, "X-state-changed",
+ G_CALLBACK (matekbd_status_state_callback),
+ NULL);
+ globals.config_changed_handler =
+ g_signal_connect (globals.engine, "X-config-changed",
+ G_CALLBACK (matekbd_status_kbd_cfg_callback),
+ NULL);
+
+ matekbd_desktop_config_init (&globals.cfg, mateconf_client,
+ globals.engine);
+ matekbd_keyboard_config_init (&globals.kbd_cfg, mateconf_client,
+ globals.engine);
+ matekbd_indicator_config_init (&globals.ind_cfg, mateconf_client,
+ globals.engine);
+
+ g_object_unref (mateconf_client);
+
+ matekbd_desktop_config_load_from_mateconf (&globals.cfg);
+ matekbd_desktop_config_activate (&globals.cfg);
+
+ globals.registry =
+ xkl_config_registry_get_instance (globals.engine);
+ xkl_config_registry_load (globals.registry,
+ globals.cfg.load_extra_items);
+
+ matekbd_keyboard_config_load_from_x_current (&globals.kbd_cfg,
+ xklrec);
+
+ matekbd_indicator_config_load_from_mateconf (&globals.ind_cfg);
+
+ matekbd_indicator_config_load_image_filenames (&globals.ind_cfg,
+ &globals.kbd_cfg);
+
+ matekbd_indicator_config_activate (&globals.ind_cfg);
+
+ matekbd_status_load_group_names ((const gchar **) xklrec->layouts,
+ (const gchar **) xklrec->variants);
+ g_object_unref (G_OBJECT (xklrec));
+
+ matekbd_desktop_config_start_listen (&globals.cfg,
+ (MateConfClientNotifyFunc)
+ matekbd_status_cfg_changed, NULL);
+ matekbd_indicator_config_start_listen (&globals.ind_cfg,
+ (MateConfClientNotifyFunc)
+ matekbd_status_ind_cfg_changed,
+ NULL);
+ matekbd_status_start_listen ();
+
+ xkl_debug (100, "*** Inited globals *** \n");
+}
+
+GtkStatusIcon *
+matekbd_status_new (void)
+{
+ return
+ GTK_STATUS_ICON (g_object_new (matekbd_status_get_type (), NULL));
+}
+
+XklEngine *
+matekbd_status_get_xkl_engine ()
+{
+ return globals.engine;
+}
+
+gchar **
+matekbd_status_get_group_names ()
+{
+ return globals.full_group_names;
+}
+
+gchar *
+matekbd_status_get_image_filename (guint group)
+{
+ if (!globals.ind_cfg.show_flags)
+ return NULL;
+ return matekbd_indicator_config_get_images_file (&globals.ind_cfg,
+ &globals.kbd_cfg,
+ group);
+}
+
+void
+matekbd_status_set_angle (MatekbdStatus * gki, gdouble angle)
+{
+ gki->priv->angle = angle;
+}
diff --git a/libmatekbd/matekbd-status.h b/libmatekbd/matekbd-status.h
new file mode 100644
index 0000000..3126167
--- /dev/null
+++ b/libmatekbd/matekbd-status.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2009 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MATEKBD_STATUS_H__
+#define __MATEKBD_STATUS_H__
+
+#include <gtk/gtk.h>
+
+#include <libxklavier/xklavier.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef struct _MatekbdStatus MatekbdStatus;
+ typedef struct _MatekbdStatusPrivate MatekbdStatusPrivate;
+ typedef struct _MatekbdStatusClass MatekbdStatusClass;
+
+ #define MATEKBD_TYPE_STATUS (matekbd_status_get_type ())
+ #define MATEKBD_STATUS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MATEKBD_TYPE_STATUS, MatekbdStatus))
+ #define MATEKBD_INDCATOR_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), MATEKBD_TYPE_STATUS, MatekbdStatusClass))
+ #define MATEKBD_IS_STATUS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MATEKBD_TYPE_STATUS))
+ #define MATEKBD_IS_STATUS_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), MATEKBD_TYPE_STATUS))
+ #define MATEKBD_STATUS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MATEKBD_TYPE_STATUS, MatekbdStatusClass))
+
+ struct _MatekbdStatus {
+ GtkStatusIcon parent;
+ MatekbdStatusPrivate *priv;
+ };
+
+ struct _MatekbdStatusClass {
+ GtkNotebookClass parent_class;
+ };
+
+ extern GType matekbd_status_get_type (void);
+
+ extern GtkStatusIcon *matekbd_status_new (void);
+
+ extern void matekbd_status_reinit_ui (MatekbdStatus * gki);
+
+ extern void matekbd_status_set_angle (MatekbdStatus * gki,
+ gdouble angle);
+
+ extern XklEngine *matekbd_status_get_xkl_engine (void);
+
+ extern gchar **matekbd_status_get_group_names (void);
+
+ extern gchar *matekbd_status_get_image_filename (guint group);
+
+ extern void
+ matekbd_status_set_tooltips_format (const gchar str[]);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/libmatekbd/matekbd-util.c b/libmatekbd/matekbd-util.c
new file mode 100644
index 0000000..e52ee5c
--- /dev/null
+++ b/libmatekbd/matekbd-util.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <matekbd-util.h>
+
+#include <time.h>
+
+#include <glib/gi18n.h>
+
+#include <libxklavier/xklavier.h>
+
+#include <mateconf/mateconf-client.h>
+
+#include <matekbd-config-private.h>
+
+static void
+matekbd_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
+matekbd_install_glib_log_appender (void)
+{
+ xkl_set_log_appender (matekbd_log_appender);
+}
+
+#define MATEKBD_PREVIEW_CONFIG_KEY_PREFIX MATEKBD_CONFIG_KEY_PREFIX "/preview"
+
+const gchar MATEKBD_PREVIEW_CONFIG_DIR[] = MATEKBD_PREVIEW_CONFIG_KEY_PREFIX;
+const gchar MATEKBD_PREVIEW_CONFIG_KEY_X[] =
+ MATEKBD_PREVIEW_CONFIG_KEY_PREFIX "/x";
+const gchar MATEKBD_PREVIEW_CONFIG_KEY_Y[] =
+ MATEKBD_PREVIEW_CONFIG_KEY_PREFIX "/y";
+const gchar MATEKBD_PREVIEW_CONFIG_KEY_WIDTH[] =
+ MATEKBD_PREVIEW_CONFIG_KEY_PREFIX "/width";
+const gchar MATEKBD_PREVIEW_CONFIG_KEY_HEIGHT[] =
+ MATEKBD_PREVIEW_CONFIG_KEY_PREFIX "/height";
+
+GdkRectangle *
+matekbd_preview_load_position (void)
+{
+ GError *gerror = NULL;
+ GdkRectangle *rv = NULL;
+ gint x, y, w, h;
+ MateConfClient *conf_client = mateconf_client_get_default ();
+
+ if (conf_client == NULL)
+ return NULL;
+
+ x = mateconf_client_get_int (conf_client,
+ MATEKBD_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 = mateconf_client_get_int (conf_client,
+ MATEKBD_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 = mateconf_client_get_int (conf_client,
+ MATEKBD_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 = mateconf_client_get_int (conf_client,
+ MATEKBD_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));
+
+ rv = g_new (GdkRectangle, 1);
+ if (x == -1 || y == -1 || w == -1 || h == -1) {
+ /* default values should be treated as
+ * "0.75 of the screen size" */
+ GdkScreen *scr = gdk_screen_get_default ();
+ gint w = gdk_screen_get_width (scr);
+ gint h = gdk_screen_get_height (scr);
+ rv->x = w >> 3;
+ rv->y = h >> 3;
+ rv->width = w - (w >> 2);
+ rv->height = h - (h >> 2);
+ } else {
+ rv->x = x;
+ rv->y = y;
+ rv->width = w;
+ rv->height = h;
+ }
+ return rv;
+}
+
+void
+matekbd_preview_save_position (GdkRectangle * rect)
+{
+ MateConfClient *conf_client = mateconf_client_get_default ();
+ MateConfChangeSet *cs;
+ GError *gerror = NULL;
+
+ cs = mateconf_change_set_new ();
+
+ mateconf_change_set_set_int (cs, MATEKBD_PREVIEW_CONFIG_KEY_X, rect->x);
+ mateconf_change_set_set_int (cs, MATEKBD_PREVIEW_CONFIG_KEY_Y, rect->y);
+ mateconf_change_set_set_int (cs, MATEKBD_PREVIEW_CONFIG_KEY_WIDTH,
+ rect->width);
+ mateconf_change_set_set_int (cs, MATEKBD_PREVIEW_CONFIG_KEY_HEIGHT,
+ rect->height);
+
+ mateconf_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);
+ }
+ mateconf_change_set_unref (cs);
+ g_object_unref (G_OBJECT (conf_client));
+}
diff --git a/libmatekbd/matekbd-util.h b/libmatekbd/matekbd-util.h
new file mode 100644
index 0000000..68d534d
--- /dev/null
+++ b/libmatekbd/matekbd-util.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2006 Sergey V. Udaltsov <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __MATEKBD_UTIL_H__
+#define __MATEKBD_UTIL_H__
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+extern void matekbd_install_glib_log_appender (void);
+
+extern GdkRectangle *matekbd_preview_load_position (void);
+
+extern void matekbd_preview_save_position (GdkRectangle * rect);
+
+
+#endif
diff --git a/libmatekbd/show-layout.ui b/libmatekbd/show-layout.ui
new file mode 100644
index 0000000..026ba63
--- /dev/null
+++ b/libmatekbd/show-layout.ui
@@ -0,0 +1,83 @@
+<?xml version="1.0"?>
+<!--*- mode: xml -*-->
+<interface>
+ <object class="GtkDialog" id="gswitchit_layout_view">
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Keyboard Layout</property>
+ <property name="resizable">False</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="has_separator">False</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkVBox" id="preview_vbox">
+ <property name="visible">True</property>
+ <property name="border_width">5</property>
+ <property name="spacing">18</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+ <child>
+ <object class="GtkButton" id="btnPrint">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label">gtk-print</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="btnHelp">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="label">gtk-help</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="btnClose">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="label">gtk-close</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="2">btnPrint</action-widget>
+ <action-widget response="-11">btnHelp</action-widget>
+ <action-widget response="-7">btnClose</action-widget>
+ </action-widgets>
+ </object>
+</interface>