From 916e2eafe251b44f9d0339282f5d00723899caec Mon Sep 17 00:00:00 2001 From: Perberos Date: Thu, 1 Dec 2011 20:53:10 -0300 Subject: moving from https://github.com/perberos/mate-desktop-environment --- libmatekbd/Makefile.am | 121 + libmatekbd/Makefile.in | 886 +++++++ ...esktop_mate_peripherals_keyboard_xkb.schemas.in | 277 ++ libmatekbd/matekbd-config-private.h | 102 + libmatekbd/matekbd-desktop-config.c | 403 +++ libmatekbd/matekbd-desktop-config.h | 92 + libmatekbd/matekbd-indicator-config.c | 445 ++++ libmatekbd/matekbd-indicator-config.h | 94 + libmatekbd/matekbd-indicator-marshal.list | 1 + libmatekbd/matekbd-indicator-plugin-manager.c | 406 +++ libmatekbd/matekbd-indicator-plugin-manager.h | 116 + libmatekbd/matekbd-indicator-plugin.h | 125 + libmatekbd/matekbd-indicator.c | 968 +++++++ libmatekbd/matekbd-indicator.h | 80 + libmatekbd/matekbd-keyboard-config.c | 827 ++++++ libmatekbd/matekbd-keyboard-config.h | 124 + libmatekbd/matekbd-keyboard-drawing-marshal.list | 2 + libmatekbd/matekbd-keyboard-drawing.c | 2635 ++++++++++++++++++++ libmatekbd/matekbd-keyboard-drawing.h | 214 ++ libmatekbd/matekbd-status.c | 867 +++++++ libmatekbd/matekbd-status.h | 72 + libmatekbd/matekbd-util.c | 159 ++ libmatekbd/matekbd-util.h | 33 + libmatekbd/show-layout.ui | 83 + 24 files changed, 9132 insertions(+) create mode 100644 libmatekbd/Makefile.am create mode 100644 libmatekbd/Makefile.in create mode 100644 libmatekbd/desktop_mate_peripherals_keyboard_xkb.schemas.in create mode 100644 libmatekbd/matekbd-config-private.h create mode 100644 libmatekbd/matekbd-desktop-config.c create mode 100644 libmatekbd/matekbd-desktop-config.h create mode 100644 libmatekbd/matekbd-indicator-config.c create mode 100644 libmatekbd/matekbd-indicator-config.h create mode 100644 libmatekbd/matekbd-indicator-marshal.list create mode 100644 libmatekbd/matekbd-indicator-plugin-manager.c create mode 100644 libmatekbd/matekbd-indicator-plugin-manager.h create mode 100644 libmatekbd/matekbd-indicator-plugin.h create mode 100644 libmatekbd/matekbd-indicator.c create mode 100644 libmatekbd/matekbd-indicator.h create mode 100644 libmatekbd/matekbd-keyboard-config.c create mode 100644 libmatekbd/matekbd-keyboard-config.h create mode 100644 libmatekbd/matekbd-keyboard-drawing-marshal.list create mode 100644 libmatekbd/matekbd-keyboard-drawing.c create mode 100644 libmatekbd/matekbd-keyboard-drawing.h create mode 100644 libmatekbd/matekbd-status.c create mode 100644 libmatekbd/matekbd-status.h create mode 100644 libmatekbd/matekbd-util.c create mode 100644 libmatekbd/matekbd-util.h create mode 100644 libmatekbd/show-layout.ui (limited to 'libmatekbd') 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 @@ + + + + + /schemas/desktop/mate/peripherals/keyboard/kbd/model + /desktop/mate/peripherals/keyboard/kbd/model + mate + string + + + Keyboard model + keyboard model + + + + + /schemas/desktop/mate/peripherals/keyboard/kbd/layouts + /desktop/mate/peripherals/keyboard/kbd/layouts + mate + list + string + [] + + Keyboard layout + keyboard layout + + + + + /schemas/desktop/mate/peripherals/keyboard/kbd/options + /desktop/mate/peripherals/keyboard/kbd/options + mate + list + string + [] + + Keyboard options + Keyboard options + + + + + /schemas/desktop/mate/peripherals/keyboard/general/update_handlers + /desktop/mate/peripherals/keyboard/general/update_handlers + mate + list + string + [] + + Keyboard Update Handlers + A collection of scripts to run whenever the keyboard state is + reloaded. Useful for re-applying xmodmap based adjustments + + + + + /schemas/desktop/mate/peripherals/keyboard/general/known_file_list + /desktop/mate/peripherals/keyboard/general/known_file_list + mate + list + string + [] + + modmap file list + A list of modmap files available in the $HOME directory. + + + + + + /schemas/desktop/mate/peripherals/keyboard/general/defaultGroup + /desktop/mate/peripherals/keyboard/general/defaultGroup + mate + int + -1 + + Default group, assigned on window creation + Default group, assigned on window creation + + + + + /schemas/desktop/mate/peripherals/keyboard/general/groupPerWindow + /desktop/mate/peripherals/keyboard/general/groupPerWindow + mate + bool + true + + Keep and manage separate group per window + Keep and manage separate group per window + + + + + /schemas/desktop/mate/peripherals/keyboard/general/handleIndicators + /desktop/mate/peripherals/keyboard/general/handleIndicators + mate + bool + false + + Save/restore indicators together with layout groups + Save/restore indicators together with layout groups + + + + + /schemas/desktop/mate/peripherals/keyboard/general/layoutNamesAsGroupNames + /desktop/mate/peripherals/keyboard/general/layoutNamesAsGroupNames + mate + bool + true + + Show layout names instead of group names + Show layout names instead of group names (only for versions of XFree supporting multiple layouts) + + + + + /schemas/desktop/mate/peripherals/keyboard/general/loadExtraItems + /desktop/mate/peripherals/keyboard/general/loadExtraItems + mate + bool + false + + Load extra configuration items + Load exotic, rarely used layouts and options + + + + + /schemas/desktop/mate/peripherals/keyboard/general/disable_sysconfig_changed_warning + /desktop/mate/peripherals/keyboard/general/disable_sysconfig_changed_warning + mate + bool + false + + Suppress the "X sysconfig changed" warning message + Suppress the "X sysconfig changed" warning message + + + + + /schemas/desktop/mate/peripherals/keyboard/preview/x + /desktop/mate/peripherals/keyboard/preview/x + mate + int + -1 + + The Keyboard Preview, X offset + The Keyboard Preview, X offset + + + + + /schemas/desktop/mate/peripherals/keyboard/preview/y + /desktop/mate/peripherals/keyboard/preview/y + mate + int + -1 + + The Keyboard Preview, Y offset + The Keyboard Preview, Y offset + + + + + /schemas/desktop/mate/peripherals/keyboard/preview/width + /desktop/mate/peripherals/keyboard/preview/width + mate + int + -1 + + The Keyboard Preview, width + The Keyboard Preview, width + + + + + /schemas/desktop/mate/peripherals/keyboard/preview/height + /desktop/mate/peripherals/keyboard/preview/height + mate + int + -1 + + The Keyboard Preview, height + The Keyboard Preview, height + + + + + /schemas/desktop/mate/peripherals/keyboard/indicator/secondary + /desktop/mate/peripherals/keyboard/indicator/secondary + mate + int + 0 + + Secondary groups + Secondary groups + + + + + /schemas/desktop/mate/peripherals/keyboard/indicator/showFlags + /desktop/mate/peripherals/keyboard/indicator/showFlags + mate + bool + false + + + Show flags in the applet + + Show flags in the applet to indicate the current layout + + + + + /schemas/desktop/mate/peripherals/keyboard/indicator/fontFamily + /desktop/mate/peripherals/keyboard/indicator/fontFamily + mate + string + + + The font family + The font family for the layout indicator + + + + + /schemas/desktop/mate/peripherals/keyboard/indicator/fontSize + /desktop/mate/peripherals/keyboard/indicator/fontSize + mate + int + 10 + + The font size + The font size for the layout indicator + + + + + /schemas/desktop/mate/peripherals/keyboard/indicator/foregroundColor + /desktop/mate/peripherals/keyboard/indicator/foregroundColor + mate + string + + + The foreground color + The foreground color for the layout indicator + + + + + /schemas/desktop/mate/peripherals/keyboard/indicator/backgroundColor + /desktop/mate/peripherals/keyboard/indicator/backgroundColor + mate + string + + + The background color + The background color for the layout indicator + + + + + /schemas/desktop/mate/peripherals/keyboard/indicator/enabledPlugins + /desktop/mate/peripherals/keyboard/indicator/enabledPlugins + mate + list + string + [] + + The list of enabled Keyboard Indicator plugins + The list of enabled Keyboard Indicator plugins + + + + 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 + * + * 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 + * + * 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 + +#include +#include +#include +#include + +#include + +#include +#include + +/** + * 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 + * + * 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 +#include +#include +#include + +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 + * + * 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 + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include + +#include + +/** + * 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 + * + * 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 + +#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 + * + * 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 + +#include + +#include + +#include + +#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 + * + * 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 +#include + +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 + * + * 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 +#include +#include + +#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 + * + * 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 + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +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 + * + * 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 + +#include + +#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 + * + * 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 + +#include +#include +#include +#include + +#include + +#include +#include + +/** + * 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 + * + * 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 +#include +#include +#include + +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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 = + >k_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 = + >k_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, + >k_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 © 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 + * + * 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 +#include +#include + +#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 + * + * 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 + +#include + +#include +#include +#include +#include + +#include + +#include +#include + +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 + * + * 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 + +#include + +#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 + * + * 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 + +#include + +#include + +#include + +#include + +#include + +#include + +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 + * + * 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 +#include + +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 @@ + + + + + 5 + Keyboard Layout + False + True + GDK_WINDOW_TYPE_HINT_DIALOG + False + + + True + 2 + + + True + 5 + 18 + + + + + + + + + 1 + + + + + True + GTK_BUTTONBOX_END + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-print + True + + + + + True + True + True + gtk-help + True + + + 1 + + + + + True + True + True + gtk-close + True + + + 2 + + + + + False + GTK_PACK_END + + + + + + btnPrint + btnHelp + btnClose + + + -- cgit v1.2.1