summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Udaltsov <svu@gnome.org>2004-11-25 23:17:30 +0000
committerSergey Udaltsov <svu@gnome.org>2004-11-25 23:17:30 +0000
commitd431ef4a3ca6228954ddb21e2e4a88f0cf9e8624 (patch)
treebf8eb5bf48f308bfe325e1d7dcffa89bdfb9245e
parentd5c0ab08dad47f5a9d1c17eb18f80aceca5843b9 (diff)
downloadlibxklavier-d431ef4a3ca6228954ddb21e2e4a88f0cf9e8624.tar.gz
first commit with xmodmap support
-rw-r--r--ChangeLog7
-rw-r--r--Doxyfile.in692
-rw-r--r--configure.in32
-rw-r--r--libxklavier/Makefile.am20
-rw-r--r--libxklavier/xklavier.c85
-rw-r--r--libxklavier/xklavier.h75
-rw-r--r--libxklavier/xklavier_config.c76
-rw-r--r--libxklavier/xklavier_config.h5
-rw-r--r--libxklavier/xklavier_config_i18n.c10
-rw-r--r--libxklavier/xklavier_config_xkb.c37
-rw-r--r--libxklavier/xklavier_config_xmm.c36
-rw-r--r--libxklavier/xklavier_evt.c97
-rw-r--r--libxklavier/xklavier_evt_xkb.c18
-rw-r--r--libxklavier/xklavier_evt_xmm.c130
-rw-r--r--libxklavier/xklavier_private.h115
-rw-r--r--libxklavier/xklavier_private_xkb.h6
-rw-r--r--libxklavier/xklavier_private_xmm.h52
-rw-r--r--libxklavier/xklavier_props.c66
-rw-r--r--libxklavier/xklavier_util.c21
-rw-r--r--libxklavier/xklavier_xkb.c55
-rwxr-xr-xlibxklavier/xklavier_xmm.c219
-rw-r--r--libxklavier/xklavier_xmm_opts.c104
-rw-r--r--tests/test_config.c49
-rw-r--r--tests/test_monitor.c54
24 files changed, 1556 insertions, 505 deletions
diff --git a/ChangeLog b/ChangeLog
index 9215dd0..ed61206 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,13 @@
+2004-11-25 23:00 svu
+
+ * libxklavier, tests: MASSIVE commit. First version
+ with somewhat working xmodmap support. Broken API
+
2004-11-04 19:00 svu
* libxklavier/Makefile.am,
+
+ * libxklavier/Makefile.am,
libxklavier/xklavier.c,
libxklavier/xklavier_config_xkb.c,
libxklavier/xklavier_config_xmm.c,
diff --git a/Doxyfile.in b/Doxyfile.in
index ad44261..371a6a0 100644
--- a/Doxyfile.in
+++ b/Doxyfile.in
@@ -1,4 +1,4 @@
-# Doxyfile 1.2.8.1
+# Doxyfile 1.3.9.1
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
@@ -11,7 +11,7 @@
# Values that contain spaces should be placed between quotes (" ")
#---------------------------------------------------------------------------
-# General configuration options
+# Project related configuration options
#---------------------------------------------------------------------------
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
@@ -32,47 +32,36 @@ PROJECT_NUMBER = @VERSION@
OUTPUT_DIRECTORY = doc
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of source
+# files, where putting all generated files in the same directory would otherwise
+# cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# The default language is English, other supported languages are:
-# Brazilian, Chinese, Croatian, Czech, Danish, Dutch, Finnish, French,
-# German, Hungarian, Italian, Japanese, Korean, Norwegian, Polish,
-# Portuguese, Romanian, Russian, Slovak, Slovene, Spanish and Swedish.
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
+# Swedish, and Ukrainian.
OUTPUT_LANGUAGE = English
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
-# documentation are documented, even if no documentation was available.
-# Private class members and static file members will be hidden unless
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
-
-EXTRACT_ALL = NO
-
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
-# will be included in the documentation.
-
-EXTRACT_PRIVATE = NO
-
-# If the EXTRACT_STATIC tag is set to YES all static members of a file
-# will be included in the documentation.
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
-EXTRACT_STATIC = NO
-
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
-# undocumented members of documented classes, files or namespaces.
-# If set to NO (the default) these members will be included in the
-# various overviews, but no documentation section is generated.
-# This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_MEMBERS = NO
-
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy.
-# If set to NO (the default) these class will be included in the various
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_CLASSES = NO
+USE_WINDOWS_ENCODING = NO
# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
# include brief member descriptions after the members that are listed in
@@ -88,12 +77,30 @@ BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is used
+# as the annotated text. Otherwise, the brief description is used as-is. If left
+# blank, the following values are used ("$name" is automatically replaced with the
+# name of the entity): "The $name class" "The $name widget" "The $name file"
+# "is" "provides" "specifies" "contains" "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# Doxygen will generate a detailed section even if there is only a brief
# description.
ALWAYS_DETAILED_SEC = NO
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
+# members of a class in the documentation of that class as if those members were
+# ordinary class members. Constructors, destructors and assignment operators of
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
@@ -101,87 +108,191 @@ ALWAYS_DETAILED_SEC = NO
FULL_PATH_NAMES = NO
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user defined part of the path. Stripping is
+# can be used to strip a user-defined part of the path. Stripping is
# only done if one of the specified strings matches the left-hand part of
-# the path. It is allowed to use relative paths in the argument list.
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
STRIP_FROM_PATH =
-# The INTERNAL_DOCS tag determines if documentation
-# that is typed after a \internal command is included. If the tag is set
-# to NO (the default) then the documentation will be excluded.
-# Set it to YES to include the internal documentation.
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
-INTERNAL_DOCS = NO
+STRIP_FROM_INC_PATH =
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a class diagram (in Html and LaTeX) for classes with base or
-# super classes. Setting the tag to NO turns the diagrams off.
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
-CLASS_DIAGRAMS = YES
+SHORT_NAMES = NO
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
-SOURCE_BROWSER = NO
+JAVADOC_AUTOBRIEF = NO
-# Setting the INLINE_SOURCES tag to YES will include the body
-# of functions and classes directly in the documentation.
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
-INLINE_SOURCES = NO
+MULTILINE_CPP_IS_BRIEF = NO
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C and C++ comments will always remain visible.
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
-STRIP_CODE_COMMENTS = YES
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
-# file names in lower case letters. If set to YES upper case letters are also
+# file names in lower-case letters. If set to YES upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
-# users are adviced to set this option to NO.
+# and Mac users are advised to set this option to NO.
CASE_SENSE_NAMES = YES
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful is your file systems
-# doesn't support long names like on DOS, Mac, or CD-ROM.
-
-SHORT_NAMES = NO
-
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
HIDE_SCOPE_NAMES = NO
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
-# will generate a verbatim copy of the header file for each class for
-# which an include is specified. Set to NO to disable this.
-
-VERBATIM_HEADERS = YES
-
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put list of the files that are included by a file in the documentation
+# will put a list of the files that are included by a file in the documentation
# of that file.
SHOW_INCLUDE_FILES = YES
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like the Qt-style comments (thus requiring an
-# explict @brief command for a brief description.
-
-JAVADOC_AUTOBRIEF = NO
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
-# reimplements.
-
-INHERIT_DOCS = YES
-
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
@@ -194,22 +305,22 @@ INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
-# all members of a group must be documented explicitly.
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
-DISTRIBUTE_GROUP_DOC = NO
+SORT_BRIEF_DOCS = NO
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
-# Doxygen uses this value to replace tabs by spaces in code fragments.
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
-TAB_SIZE = 8
-
-# The ENABLED_SECTIONS tag can be used to enable conditional
-# documentation sections, marked by \if sectionname ... \endif.
-
-ENABLED_SECTIONS =
+SORT_BY_SCOPE_NAME = NO
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
@@ -229,17 +340,19 @@ GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user defined paragraph with heading "Side Effects:".
-# You can put \n's in the value part of an alias to insert newlines.
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
-ALIASES =
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or define consist of for it to appear in
+# the initial value of a variable or define consists of for it to appear in
# the documentation. If the initializer consists of more lines than specified
# here it will be hidden. Use a value of 0 to hide initializers completely.
# The appearance of the initializer of individual variables and defines in the
@@ -248,19 +361,18 @@ ALIASES =
MAX_INITIALIZER_LINES = 30
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
-# only. Doxygen will then generate output that is more tailored for C.
-# For instance some of the names that are used will be different. The list
-# of all members will be omitted, etc.
-
-OPTIMIZE_OUTPUT_FOR_C = NO
-
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
SHOW_USED_FILES = YES
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation.
+
+SHOW_DIRECTORIES = YES
+
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
@@ -282,6 +394,13 @@ WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
# The WARN_FORMAT tag determines the format of the warning messages that
# doxygen can produce. The string should contain the $file, $line, and $text
# tags, which will be replaced by the file and line number from which the
@@ -309,9 +428,12 @@ INPUT = libxklavier
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
-# blank all files are included.
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
+# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
-FILE_PATTERNS = xklavier.h xklavier_config.h
+FILE_PATTERNS = xklavier.h \
+ xklavier_config.h
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
@@ -325,6 +447,11 @@ RECURSIVE = NO
EXCLUDE =
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS = NO
+
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories.
@@ -344,6 +471,13 @@ EXAMPLE_PATH =
EXAMPLE_PATTERNS =
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
# The IMAGE_PATH tag can be used to specify one or more files or
# directories that contain image that are included in the documentation (see
# the \image command).
@@ -355,17 +489,67 @@ IMAGE_PATH =
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
-# to standard output.
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
INPUT_FILTER =
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will be used to filter the input files when producing source
-# files to browse.
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
@@ -403,6 +587,12 @@ GENERATE_HTML = YES
HTML_OUTPUT =
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
# The HTML_HEADER tag can be used to specify a personal HTML header for
# each generated HTML page. If it is left blank doxygen will generate a
# standard header.
@@ -415,10 +605,12 @@ HTML_HEADER =
HTML_FOOTER =
-# The HTML_STYLESHEET tag can be used to specify a user defined cascading
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
# style sheet that is used by each HTML page. It can be used to
# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
HTML_STYLESHEET =
@@ -435,6 +627,20 @@ HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = NO
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
# controls if a separate .chi index file is generated (YES) or that
# it should be included in the master .chm file (NO).
@@ -448,7 +654,7 @@ GENERATE_CHI = NO
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members
-# to the contents of the Html help documentation and to the tree view.
+# to the contents of the HTML help documentation and to the tree view.
TOC_EXPAND = NO
@@ -466,8 +672,9 @@ ENUM_VALUES_PER_LINE = 4
# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
# generated containing a tree-like index structure (just like the one that
# is generated for HTML Help). For this to work a browser that supports
-# JavaScript and frames is required (for instance Netscape 4.0+
-# or Internet explorer 4.0+).
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
GENERATE_TREEVIEW = NO
@@ -492,6 +699,17 @@ GENERATE_LATEX = NO
LATEX_OUTPUT =
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
@@ -536,12 +754,18 @@ USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimised for Word 97 and may not look very pretty with
+# The RTF output is optimized for Word 97 and may not look very pretty with
# other RTF readers or editors.
GENERATE_RTF = NO
@@ -568,7 +792,7 @@ COMPACT_RTF = NO
RTF_HYPERLINKS = NO
# Load stylesheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assigments. You only have to provide
+# config file, i.e. a series of assignments. You only have to provide
# replacements, missing definitions are set to their default value.
RTF_STYLESHEET_FILE =
@@ -598,15 +822,95 @@ MAN_OUTPUT =
MAN_EXTENSION =
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
-# then it will generate one additional man file for each entity
-# documented in the real man page(s). These additional files
-# only source the real man page, but without them the man command
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
# would be unable to find the correct page. The default is NO.
MAN_LINKS = NO
#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
@@ -651,22 +955,45 @@ INCLUDE_FILE_PATTERNS =
# are defined before the preprocessor is started (similar to the -D option of
# gcc). The argument of the tag is a list of macros of the form: name
# or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed.
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
PREDEFINED =
-# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
# The macro definition that is found in the sources will be used.
# Use the PREDEFINED tag if you want to use a different macro definition.
EXPAND_AS_DEFINED =
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse the
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
#---------------------------------------------------------------------------
-# Configuration::addtions related to external references
+# Configuration::additions related to external references
#---------------------------------------------------------------------------
-# The TAGFILES tag can be used to specify one or more tagfiles.
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
TAGFILES =
@@ -681,6 +1008,12 @@ GENERATE_TAGFILE =
ALLEXTERNALS = NO
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of `which perl').
@@ -690,6 +1023,20 @@ PERL_PATH =
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off. Note that this
+# option is superseded by the HAVE_DOT option below. This is only a fallback. It is
+# recommended to install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz, a graph visualization
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
@@ -711,6 +1058,17 @@ CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
# tags are set to YES then doxygen will generate a graph for each documented
# file showing the direct and indirect include dependencies of the file with
@@ -725,16 +1083,36 @@ INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will graphical hierarchy of all classes instead of a textual one.
GRAPHICAL_HIERARCHY = YES
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
# The tag DOT_PATH can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found on the path.
DOT_PATH =
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
# this value, doxygen will try to truncate the graph, so that it fits within
@@ -751,6 +1129,17 @@ MAX_DOT_GRAPH_WIDTH = 1024
MAX_DOT_GRAPH_HEIGHT = 1024
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes that
+# lay further from the root node will be omitted. Note that setting this option to
+# 1 or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that a graph may be further truncated if the graph's image dimensions are
+# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT).
+# If 0 is used for the depth value (the default), the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
# generate a legend page explaining the meaning of the various boxes and
# arrows in the dot generated graphs.
@@ -758,51 +1147,16 @@ MAX_DOT_GRAPH_HEIGHT = 1024
GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
-# remove the intermedate dot files that are used to generate
+# remove the intermediate dot files that are used to generate
# the various graphs.
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
-# Configuration::addtions related to the search engine
+# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
# The SEARCHENGINE tag specifies whether or not a search engine should be
# used. If set to NO the values of all tags below this one will be ignored.
SEARCHENGINE = NO
-
-# The CGI_NAME tag should be the name of the CGI script that
-# starts the search engine (doxysearch) with the correct parameters.
-# A script with this name will be generated by doxygen.
-
-CGI_NAME =
-
-# The CGI_URL tag should be the absolute URL to the directory where the
-# cgi binaries are located. See the documentation of your http daemon for
-# details.
-
-CGI_URL =
-
-# The DOC_URL tag should be the absolute URL to the directory where the
-# documentation is located. If left blank the absolute path to the
-# documentation, with file:// prepended to it, will be used.
-
-DOC_URL =
-
-# The DOC_ABSPATH tag should be the absolute path to the directory where the
-# documentation is located. If left blank the directory on the local machine
-# will be used.
-
-DOC_ABSPATH =
-
-# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
-# is installed.
-
-BIN_ABSPATH =
-
-# The EXT_DOC_PATHS tag can be used to specify one or more paths to
-# documentation generated for other projects. This allows doxysearch to search
-# the documentation for these projects as well.
-
-EXT_DOC_PATHS =
diff --git a/configure.in b/configure.in
index b8a4c74..f695e6e 100644
--- a/configure.in
+++ b/configure.in
@@ -2,9 +2,9 @@ AC_INIT(libxklavier/xklavier.c)
PACKAGE=libxklavier
MAJOR_VERSION=1
-MINOR_VERSION=11
+MINOR_VERSION=12
VERSION=$MAJOR_VERSION.$MINOR_VERSION
-VERSION_INFO=9:0:0
+VERSION_INFO=10:0:0
AC_SUBST(MAJOR_VERSION)
AC_SUBST(MINOR_VERSION)
@@ -58,10 +58,6 @@ AC_ARG_WITH( xkb_base,
xkb_base="$withval",
xkb_base="$x_libraries/X11/xkb" )
-if ! test -d $xkb_base; then
- AC_MSG_ERROR([The path $xkb_base does not denote the directory])
-fi
-
AC_DEFINE_UNQUOTED(XKB_BASE,"${xkb_base}",Base for XKB configuration)
AC_ARG_WITH( xkb_default_ruleset,
@@ -71,6 +67,16 @@ AC_ARG_WITH( xkb_default_ruleset,
AC_DEFINE_UNQUOTED(XKB_DEFAULT_RULESET,"${xkb_default_ruleset}",Default XKB set of rules)
+AC_ARG_WITH( xmodmap_base,
+ [ --with-xmodmap-base=DIR xmodmap base path (by default it is /usr/share/xmodmap)],
+ xmodmap_base="$withval",
+ xmodmap_base="/usr/share/xmodmap" )
+
+AC_DEFINE_UNQUOTED(XMODMAP_BASE,"${xmodmap_base}",Base for xmodmap configuration)
+
+save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -I$x_includes"
+
ac_xkblib_include="\
#include <stdio.h>
#include <X11/Xlib.h>
@@ -83,12 +89,26 @@ AM_CONDITIONAL(XKB_HEADERS_PRESENT, test "$xkb_headers_present" = "yes")
AC_SUBST(xkbheaders_present)
+CFLAGS="$save_CFLAGS"
+
AC_ARG_ENABLE(doxygen,
[ --enable-doxygen Build doxygen documentation],
, enable_doxygen=no)
AC_SUBST(DO_DOXYGEN,"${enable_doxygen}")
+AC_ARG_ENABLE(xkb-support,
+[ --enable-xkb-support Enable XKB support],
+, enable_xkb_support=yes)
+
+AM_CONDITIONAL(ENABLE_XKB_SUPPORT, test "$enable_xkb_support" = "yes")
+
+AC_ARG_ENABLE(xmm-support,
+[ --enable-xmm-support Enable xmodmap support],
+, enable_xmm_support=no)
+
+AM_CONDITIONAL(ENABLE_XMM_SUPPORT, test "$enable_xmm_support" = "yes")
+
dnl Checks for libraries.
PKG_CHECK_MODULES(XML, \
libxml-2.0 >= 2.0.0)
diff --git a/libxklavier/Makefile.am b/libxklavier/Makefile.am
index 2525209..1643522 100644
--- a/libxklavier/Makefile.am
+++ b/libxklavier/Makefile.am
@@ -2,7 +2,23 @@ if XKB_HEADERS_PRESENT
XKB_HEADERS_PRESENT_CFLAG = -DXKB_HEADERS_PRESENT=1
endif
-AM_CFLAGS = -Wall -Werror -DDATA_DIR=\"$(datadir)/$(PACKAGE)\" -I. -I$(includedir) $(XML_CFLAGS) -I$(x_includes) -I$(top_srcdir) $(XKB_HEADERS_PRESENT_CFLAG)
+if ENABLE_XKB_SUPPORT
+ ENABLE_XKB_SUPPORT_CFLAG = -DENABLE_XKB_SUPPORT=1
+else
+ ENABLE_XKB_SUPPORT_CFLAG = -DDISABLE_XKB_SUPPORT=1
+endif
+
+if ENABLE_XMM_SUPPORT
+ ENABLE_XMM_SUPPORT_CFLAG = -DENABLE_XMM_SUPPORT=1
+else
+ ENABLE_XMM_SUPPORT_CFLAG = -DDISABLE_XMM_SUPPORT=1
+endif
+
+AM_CFLAGS=-Wall -Werror -DDATA_DIR=\"$(datadir)/$(PACKAGE)\" \
+ -I. -I$(includedir) $(XML_CFLAGS) -I$(x_includes) -I$(top_srcdir) \
+ $(XKB_HEADERS_PRESENT_CFLAG) \
+ $(ENABLE_XKB_SUPPORT_CFLAG) \
+ $(ENABLE_XMM_SUPPORT_CFLAG)
lib_LTLIBRARIES = libxklavier.la
noinst_HEADERS = xklavier_private.h xklavier_private_xkb.h xklavier_private_xmm.h
@@ -12,7 +28,7 @@ xklavierinc_HEADERS = xklavier.h xklavier_config.h
libxklavier_la_SOURCES = xklavier.c xklavier_evt.c xklavier_config.c \
xklavier_xkb.c xklavier_evt_xkb.c xklavier_config_xkb.c \
- xklavier_xmm.c xklavier_evt_xmm.c xklavier_config_xmm.c \
+ xklavier_xmm.c xklavier_xmm_opts.c xklavier_evt_xmm.c xklavier_config_xmm.c \
xklavier_util.c xklavier_config_i18n.c xklavier_props.c xklavier_dump.c \
$(noinst_HEADERS) $(xklavierinc_HEADERS)
libxklavier_la_LDFLAGS = -version-info @VERSION_INFO@ $(XML_LIBS) -lxkbfile -L$(x_libraries) $(LIBICONV)
diff --git a/libxklavier/xklavier.c b/libxklavier/xklavier.c
index 1a70046..5cfd752 100644
--- a/libxklavier/xklavier.c
+++ b/libxklavier/xklavier.c
@@ -37,6 +37,8 @@ int _xklDebugLevel = 0;
Window _xklPrevAppWindow;
+int _xklListenerType = 0;
+
XklVTable *xklVTable = NULL;
XklConfigCallback _xklConfigCallback = NULL;
@@ -132,8 +134,15 @@ void XklSetLogAppender( XklLogAppender fun )
logAppender = fun;
}
-int XklStartListen( )
+int XklStartListen( int what )
{
+ _xklListenerType = what;
+
+ if( !( xklVTable->features & XKLF_REQUIRES_MANUAL_LAYOUT_MANAGEMENT ) &&
+ ( what & XKLL_MANAGE_LAYOUTS ) )
+ XklDebug( 0, "The backend does not require manual layout management - "
+ "but it is provided by the application" );
+
XklResumeListen( );
_XklLoadWindowTree( );
XFlush( _xklDpy );
@@ -183,10 +192,19 @@ int XklInit( Display * a_dpy )
_xklAtoms[XKLAVIER_TRANSPARENT] =
XInternAtom( _xklDpy, "XKLAVIER_TRANSPARENT", False );
+ rv = -1;
+ XklDebug( 150, "Trying all backends:\n" );
+#ifdef ENABLE_XKB_SUPPORT
+ XklDebug( 150, "Trying XKB backend\n" );
rv = _XklXkbInit();
- if ( rv != 0 )
+#endif
+#ifdef ENABLE_XMM_SUPPORT
+ XklDebug( 150, "Trying XMM backend\n" );
+ if( rv != 0 )
rv = _XklXmmInit();
- return rv;
+#endif
+ return ( rv == 0 ) ?
+ ( _XklLoadAllInfo() ? 0 : _xklLastErrorCode ) : -1;
}
int XklTerm( )
@@ -202,28 +220,28 @@ int XklTerm( )
return 0;
}
-Bool XklGrabKey( int key, unsigned modifiers )
+Bool XklGrabKey( int keycode, unsigned modifiers )
{
- int keyCode;
Bool retCode;
char *keyName;
- keyCode = XKeysymToKeycode( _xklDpy, key );
- keyName = XKeysymToString( key );
-
- XklDebug( 100, "listen to the key %X(%d/%s)/%d\n", key, keyCode, keyName,
- modifiers );
+ if( _xklDebugLevel >= 100 )
+ {
+ keyName = XKeysymToString( XKeycodeToKeysym( _xklDpy, keycode, 0 ) );
+ XklDebug( 100, "Listen to the key %d/(%s)/%d\n",
+ keycode, keyName, modifiers );
+ }
- if( ( KeyCode ) NULL == keyCode )
+ if( ( KeyCode ) NULL == keycode )
return False;
_xklLastErrorCode = Success;
- retCode = XGrabKey( _xklDpy, keyCode, modifiers, _xklRootWindow,
+ retCode = XGrabKey( _xklDpy, keycode, modifiers, _xklRootWindow,
True, GrabModeAsync, GrabModeAsync );
XSync( _xklDpy, False );
- XklDebug( 100, "trying to listen: %d/%d\n", retCode, _xklLastErrorCode );
+ XklDebug( 100, "XGrabKey recode %d/error %d\n", retCode, _xklLastErrorCode );
retCode = ( _xklLastErrorCode == Success );
@@ -233,16 +251,12 @@ Bool XklGrabKey( int key, unsigned modifiers )
return retCode;
}
-Bool XklUngrabKey( int key, unsigned modifiers )
+Bool XklUngrabKey( int keycode, unsigned modifiers )
{
- int keyCode;
-
- keyCode = XKeysymToKeycode( _xklDpy, key );
-
- if( ( KeyCode ) NULL == keyCode )
+ if( ( KeyCode ) NULL == keycode )
return False;
- return Success == XUngrabKey( _xklDpy, keyCode, 0, _xklRootWindow );
+ return Success == XUngrabKey( _xklDpy, keycode, 0, _xklRootWindow );
}
int XklGetNextGroup( )
@@ -284,7 +298,7 @@ void XklSetTransparent( Window win, Bool transparent )
{
XklDebug( 150, "No app window!\n" );
appWin = win;
-// return;
+/* return; */
}
wasTransparent = XklIsTransparent( appWin );
@@ -488,9 +502,10 @@ Bool _XklLoadWindowTree( )
{
Window focused;
int revert;
- Bool retval, haveAppWindow;
+ Bool retval = True, haveAppWindow;
- retval = _XklLoadSubtree( _xklRootWindow, 0, &_xklCurState );
+ if( _xklListenerType & XKLL_MANAGE_WINDOW_STATES )
+ retval = _XklLoadSubtree( _xklRootWindow, 0, &_xklCurState );
XGetInputFocus( _xklDpy, &focused, &revert );
@@ -624,7 +639,7 @@ void _XklSelectInput( Window win, long mask )
{
if( _xklRootWindow == win )
XklDebug( 160,
- "Someone is looking for " WINID_FORMAT " on root window ***\n",
+ "Someone is looking for %lx on root window ***\n",
mask );
XSelectInput( _xklDpy, win, mask );
@@ -664,7 +679,7 @@ void _XklTryCallStateCallback( XklStateChange changeType,
XklDebug( 150, "secondary -> go next\n" );
group = XklGetNextGroup( );
XklLockGroup( group );
- return; // we do not need to revalidate
+ return; /* we do not need to revalidate */
}
}
_xklAllowSecondaryGroupOnce = False;
@@ -706,6 +721,16 @@ void _XklEnsureVTableInited( void )
}
}
+const char *XklGetBackendName( void )
+{
+ return xklVTable->id;
+}
+
+int XklGetBackendFeatures( void )
+{
+ return xklVTable->features;
+}
+
/**
* Calling through vtable
*/
@@ -736,7 +761,15 @@ int XklPauseListen( void )
int XklResumeListen( void )
{
_XklEnsureVTableInited();
- return (*xklVTable->xklResumeListenHandler)();
+ XklDebug( 150, "listenerType: %x\n", _xklListenerType );
+ if( (*xklVTable->xklResumeListenHandler)() )
+ return 1;
+
+ _XklSelectInputMerging( _xklRootWindow,
+ SubstructureNotifyMask | PropertyChangeMask );
+ _XklEnsureVTableInited();
+ (*xklVTable->xklGetRealStateHandler)( &_xklCurState );
+ return 0;
}
Bool _XklLoadAllInfo( void )
diff --git a/libxklavier/xklavier.h b/libxklavier/xklavier.h
index 8c08cb0..b9c5348 100644
--- a/libxklavier/xklavier.h
+++ b/libxklavier/xklavier.h
@@ -28,6 +28,32 @@ extern "C"
XklStateChange;
/**
+ * Backend allows to toggls indicators on/off
+ */
+#define XKLF_CAN_TOGGLE_INDICATORS 0x01
+/**
+ * Backend allows to write ascii representation of the configuration
+ */
+#define XKLF_CAN_OUTPUT_CONFIG_AS_ASCII 0x02
+
+/**
+ * Backend allows to write binary representation of the configuration
+ */
+#define XKLF_CAN_OUTPUT_CONFIG_AS_BINARY 0x04
+
+/**
+ * Backend supports multiple layouts
+ */
+#define XKLF_MULTIPLE_LAYOUTS_SUPPORTED 0x08
+
+/**
+ * Backend requires manual configuration,
+ * some daemon should do
+ * XklStartListen( XKLL_MANAGE_LAYOUTS );
+ */
+#define XKLF_REQUIRES_MANUAL_LAYOUT_MANAGEMENT 0x10
+
+/**
* XKB state. Can be global or per-window
*/
typedef struct
@@ -59,6 +85,18 @@ extern "C"
*/
extern int XklTerm( void );
+/**
+ * What kind of backend if used
+ * @return some string id of the backend
+ */
+ extern const char *XklGetBackendName( void );
+
+/**
+ * Provides information regarding available backend features
+ * (combination of XKLF_* constants)
+ * @return ORed XKLF_* constants
+ */
+ extern int XklGetBackendFeatures( void );
/** @} */
/**
@@ -67,10 +105,28 @@ extern "C"
*/
/**
+ * The listener process should handle the per-window states
+ * and all the related activity
+ */
+#define XKLL_MANAGE_WINDOW_STATES 0x01
+
+/**
+ * Just track the state and pass it to the application above.
+ */
+#define XKLL_TRACK_KEYBOARD_STATE 0x02
+
+/**
+ * The listener process should help backend to maintain the configuration
+ * (manually switch layouts etc).
+ */
+#define XKLL_MANAGE_LAYOUTS 0x04
+
+/**
* Starts listening for XKB-related events
+ * @param what any combination of XKLL_* constants
* @return 0
*/
- extern int XklStartListen( void );
+ extern int XklStartListen( int what );
/**
* Stops listening for XKB-related events
@@ -92,19 +148,19 @@ extern "C"
/**
* Grabs some key
- * @param key is a keysym
+ * @param keycode is a keycode
* @param modifiers is a bitmask of modifiers
* @return True on success
*/
- extern Bool XklGrabKey( int key, unsigned modifiers );
+ extern Bool XklGrabKey( int keycode, unsigned modifiers );
/**
* Ungrabs some key
- * @param key is a keysym
+ * @param keycode is a keycode
* @param modifiers is a bitmask of modifiers
* @return True on success
*/
- extern Bool XklUngrabKey( int key, unsigned modifiers );
+ extern Bool XklUngrabKey( int keycode, unsigned modifiers );
/**
* Processes X events. Should be included into the main event cycle of an
@@ -450,12 +506,21 @@ extern "C"
*/
extern void XklSetDebugLevel( int level );
+/* Just to make doxygen happy - two block with/without @param format */
+#if defined(G_HAVE_GNUC_VARARGS)
/**
* Output (optionally) some debug info
* @param level is a level of the message
* @param format is a format (like in printf)
* @see _XklDebug
*/
+#else
+/**
+ * Output (optionally) some debug info
+ * @param level is a level of the message
+ * @see _XklDebug
+ */
+#endif
#ifdef G_HAVE_ISO_VARARGS
#define XklDebug( level, ... ) \
_XklDebug( __FILE__, __func__, level, __VA_ARGS__ )
diff --git a/libxklavier/xklavier_config.c b/libxklavier/xklavier_config.c
index e8b8dfb..dd109c8 100644
--- a/libxklavier/xklavier_config.c
+++ b/libxklavier/xklavier_config.c
@@ -1,5 +1,6 @@
#include <errno.h>
#include <string.h>
+#include <stdio.h>
#include <locale.h>
#include <sys/stat.h>
@@ -85,11 +86,11 @@ static Bool _XklReadConfigItem( xmlNodePtr iptr, XklConfigItemPtr pci )
if( lang != NULL )
{
int priority = _XklGetLanguagePriority( lang );
- if( !strcmp( nptr->name, "description" ) && ( priority > maxDescPriority ) ) // higher priority
+ if( !strcmp( nptr->name, "description" ) && ( priority > maxDescPriority ) ) /* higher priority */
{
descElement = nptr;
maxDescPriority = priority;
- } else if( !strcmp( nptr->name, "shortDescription" ) && ( priority > maxShortDescPriority ) ) // higher priority
+ } else if( !strcmp( nptr->name, "shortDescription" ) && ( priority > maxShortDescPriority ) ) /* higher priority */
{
shortDescElement = nptr;
maxShortDescPriority = priority;
@@ -105,16 +106,16 @@ static Bool _XklReadConfigItem( xmlNodePtr iptr, XklConfigItemPtr pci )
nptr = nptr->next;
}
- // if no language-specific description found - use the ones without lang
+ /* if no language-specific description found - use the ones without lang */
if( descElement == NULL )
descElement = ntDescElement;
if( shortDescElement == NULL )
shortDescElement = ntShortDescElement;
- //
- // Actually, here we should have some code to find the correct localized description...
- //
+ /**
+ * Actually, here we should have some code to find the correct localized description...
+ */
if( nameElement != NULL && nameElement->children != NULL )
strncat( pci->name, nameElement->children->content,
@@ -302,7 +303,7 @@ void _XklConfigRecSplitByComma( char ***array,
if( merged == NULL || merged[0] == '\0' )
return;
- // first count the elements
+ /* first count the elements */
while( ( npc = strchr( pc, ',' ) ) != NULL )
{
( *arraySize )++;
@@ -320,7 +321,7 @@ void _XklConfigRecSplitByComma( char ***array,
while( ( npc = strchr( pc, ',' ) ) != NULL )
{
int len = npc - pc;
- //*ppc = ( char * ) strndup( pc, len );
+ /* *ppc = ( char * ) strndup( pc, len ); */
*ppc = ( char * ) malloc( len + 1 );
if ( *ppc != NULL )
{
@@ -332,15 +333,34 @@ void _XklConfigRecSplitByComma( char ***array,
pc = npc + 1;
}
- //len = npc - pc;
+ /* len = npc - pc; */
len = strlen( pc );
- //*ppc = ( char * ) strndup( pc, len );
+ /* *ppc = ( char * ) strndup( pc, len ); */
*ppc = ( char * ) malloc( len + 1 );
if ( *ppc != NULL )
strcpy( *ppc, pc );
}
}
+char* _XklGetRulesSetName( const char defaultRuleset[] )
+{
+ static char rulesSetName[1024] = "";
+ if ( !rulesSetName[0] )
+ {
+ char* rf = NULL;
+ if( !XklGetNamesProp( xklVTable->baseConfigAtom, &rf, NULL ) || ( rf == NULL ) )
+ {
+ strncpy( rulesSetName, defaultRuleset, sizeof rulesSetName );
+ XklDebug( 100, "Using default rules set: [%s]\n", rulesSetName );
+ return rulesSetName;
+ }
+ strncpy( rulesSetName, rf, sizeof rulesSetName );
+ free( rf );
+ }
+ XklDebug( 100, "Rules set: [%s]\n", rulesSetName );
+ return rulesSetName;
+}
+
void XklConfigInit( void )
{
xmlXPathInit( );
@@ -532,17 +552,41 @@ Bool XklConfigLoadRegistry( void )
return (*xklVTable->xklConfigLoadRegistryHandler)();
}
-Bool XklMultipleLayoutsSupported( void )
-{
- _XklEnsureVTableInited();
- return (*xklVTable->xklConfigMultipleLayoutsSupportedHandler)();
-}
-
Bool XklConfigWriteFile( const char *fileName,
const XklConfigRecPtr data,
const Bool binary )
{
+ if( ( !binary &&
+ !( xklVTable->features & XKLF_CAN_OUTPUT_CONFIG_AS_ASCII ) ) ||
+ ( binary &&
+ !( xklVTable->features & XKLF_CAN_OUTPUT_CONFIG_AS_BINARY ) ) )
+ {
+ _xklLastErrorMsg = "Function not supported at backend";
+ return False;
+ }
_XklEnsureVTableInited();
return (*xklVTable->xklConfigWriteFileHandler)( fileName, data, binary );
}
+void XklConfigDump( FILE* file,
+ XklConfigRecPtr data )
+{
+ int i,j;
+ char**p;
+ fprintf( file, " model: [%s]\n", data->model );
+
+ fprintf( file, " layouts(%d):\n", data->numLayouts );
+ p = data->layouts;
+ for( i = data->numLayouts, j = 0; --i >= 0; )
+ fprintf( file, " %d: [%s]\n", j++, *p++ );
+
+ fprintf( file, " variants(%d):\n", data->numVariants );
+ p = data->variants;
+ for( i = data->numVariants, j = 0; --i >= 0; )
+ fprintf( file, " %d: [%s]\n", j++, *p++ );
+
+ fprintf( file, " options(%d):\n", data->numOptions );
+ p = data->options;
+ for( i = data->numOptions, j = 0; --i >= 0; )
+ fprintf( file, " %d: [%s]\n", j++, *p++ );
+}
diff --git a/libxklavier/xklavier_config.h b/libxklavier/xklavier_config.h
index 4441c54..7917d74 100644
--- a/libxklavier/xklavier_config.h
+++ b/libxklavier/xklavier_config.h
@@ -253,11 +253,6 @@ extern "C"
*/
/**
- * Determines whether multiple layouts (by Ivan Pascal) are supported.
- * @return True if so.
- */
- extern Bool XklMultipleLayoutsSupported( void );
-/**
* Activates some XKB configuration
* @param data is a valid XKB configuration
* description. Can be NULL
diff --git a/libxklavier/xklavier_config_i18n.c b/libxklavier/xklavier_config_i18n.c
index 4535659..fc20c14 100644
--- a/libxklavier/xklavier_config_i18n.c
+++ b/libxklavier/xklavier_config_i18n.c
@@ -31,9 +31,9 @@ static const char *_XklParseLC_ALL2LC_MESSAGES( const char *lcAll )
return lcAll;
lcMsgPos += 12;
lcMsgEnd = strchr( lcMsgPos, ';' );
- if( lcMsgEnd == NULL ) // LC_MESSAGES is the last piece of LC_ALL
+ if( lcMsgEnd == NULL ) /* LC_MESSAGES is the last piece of LC_ALL */
{
- return lcMsgPos; //safe to return!
+ return lcMsgPos; /* safe to return! */
}
len = lcMsgEnd - lcMsgPos;
if( len > sizeof( buf ) )
@@ -43,7 +43,7 @@ static const char *_XklParseLC_ALL2LC_MESSAGES( const char *lcAll )
return buf;
}
-// Taken from gnome-vfs
+/* Taken from gnome-vfs */
static Bool _XklGetCharset( const char **a )
{
static const char *charset = NULL;
@@ -54,7 +54,7 @@ static Bool _XklGetCharset( const char **a )
if( charset == NULL || charset[0] == '\0' )
{
-// taken from gnome-vfs
+/* taken from gnome-vfs */
#ifdef HAVE_LANGINFO_CODESET
charset = nl_langinfo( CODESET );
if( charset == NULL || charset[0] == '\0' )
@@ -208,7 +208,7 @@ void _XklI18NInit( )
}
XklDebug( 150, "Locale search order:\n" );
- XklDebug( 150, " 0: %s\n", localeSubStrings[0] ); // full locale - highest priority
+ XklDebug( 150, " 0: %s\n", localeSubStrings[0] ); /* full locale - highest priority */
XklDebug( 150, " 1: %s\n", localeSubStrings[1] );
XklDebug( 150, " 2: %s\n", localeSubStrings[2] );
}
diff --git a/libxklavier/xklavier_config_xkb.c b/libxklavier/xklavier_config_xkb.c
index 9306f36..25a9a73 100644
--- a/libxklavier/xklavier_config_xkb.c
+++ b/libxklavier/xklavier_config_xkb.c
@@ -21,7 +21,7 @@
#include <X11/extensions/XKM.h>
#endif
-// For "bad" X servers we hold our own copy
+/* For "bad" X servers we hold our own copy */
#define XML_CFG_FALLBACK_PATH ( DATA_DIR "/xfree86.xml" )
#define XKBCOMP ( XKB_BASE "/xkbcomp" )
@@ -37,34 +37,11 @@ static XkbComponentNamesRec componentNames;
static char *locale;
#endif
-static char* _XklGetRulesSetName( void )
-{
-#ifdef XKB_HEADERS_PRESENT
- static char rulesSetName[_XKB_RF_NAMES_PROP_MAXLEN] = "";
- if ( !rulesSetName[0] )
- {
- char* rf = NULL;
- if( !XklGetNamesProp( _xklAtoms[XKB_RF_NAMES_PROP_ATOM], &rf, NULL ) || ( rf == NULL ) )
- {
- strncpy( rulesSetName, XKB_DEFAULT_RULESET, sizeof rulesSetName );
- XklDebug( 100, "Using default rules set: [%s]\n", rulesSetName );
- return rulesSetName;
- }
- strncpy( rulesSetName, rf, sizeof rulesSetName );
- free( rf );
- }
- XklDebug( 100, "Rules set: [%s]\n", rulesSetName );
- return rulesSetName;
-#else
- return NULL;
-#endif
-}
-
#ifdef XKB_HEADERS_PRESENT
static XkbRF_RulesPtr _XklLoadRulesSet( void )
{
char fileName[MAXPATHLEN] = "";
- char* rf = _XklGetRulesSetName();
+ char* rf = _XklGetRulesSetName( XKB_DEFAULT_RULESET );
_xklRules = NULL;
if( rf == NULL )
@@ -110,7 +87,7 @@ Bool _XklXkbConfigLoadRegistry( void )
{
struct stat statBuf;
char fileName[MAXPATHLEN] = "";
- char* rf = _XklGetRulesSetName();
+ char* rf = _XklGetRulesSetName( XKB_DEFAULT_RULESET );
if ( rf == NULL )
return False;
@@ -318,7 +295,7 @@ static XkbDescPtr _XklConfigGetKeyboard( Bool activate )
}
#endif
-// check only client side support
+/* check only client side support */
Bool _XklXkbConfigMultipleLayoutsSupported( void )
{
enum { NON_SUPPORTED, SUPPORTED, UNCHECKED };
@@ -394,9 +371,9 @@ Bool _XklXkbConfigActivate( const XklConfigRecPtr data )
if( xkb != NULL )
{
if( XklSetNamesProp
- ( _xklAtoms[XKB_RF_NAMES_PROP_ATOM], _XklGetRulesSetName(), data ) )
- // We do not need to check the result of _XklGetRulesSetName -
- // because PrepareBeforeKbd did it for us
+ ( xklVTable->baseConfigAtom, _XklGetRulesSetName( XKB_DEFAULT_RULESET ), data ) )
+ /* We do not need to check the result of _XklGetRulesSetName -
+ because PrepareBeforeKbd did it for us */
rv = True;
else
_xklLastErrorMsg = "Could not set names property";
diff --git a/libxklavier/xklavier_config_xmm.c b/libxklavier/xklavier_config_xmm.c
index b8b696f..abceec0 100644
--- a/libxklavier/xklavier_config_xmm.c
+++ b/libxklavier/xklavier_config_xmm.c
@@ -25,23 +25,31 @@ void _XklXmmConfigInit( void )
Bool _XklXmmConfigLoadRegistry( void )
{
- return False;
-}
+ struct stat statBuf;
+ char fileName[MAXPATHLEN] = "";
+ char* rf = _XklGetRulesSetName( "" );
-// check only client side support
-Bool _XklXmmConfigMultipleLayoutsSupported( void )
-{
- return False;
-}
+ if ( rf == NULL || rf[0] == '\0' )
+ return False;
-Bool _XklXmmConfigActivate( const XklConfigRecPtr data )
-{
- return False;
+ snprintf( fileName, sizeof fileName, XMODMAP_BASE "/%s.xml", rf );
+
+ if( stat( fileName, &statBuf ) != 0 )
+ {
+ _xklLastErrorMsg = "No rules file found";
+ return False;
+ }
+
+ return XklConfigLoadRegistryFromFile( fileName );
}
-Bool _XklXmmConfigWriteFile( const char *fileName,
- const XklConfigRecPtr data,
- const Bool binary )
+Bool _XklXmmConfigActivate( const XklConfigRecPtr data )
{
- return False;
+ Bool rv;
+ rv = XklSetNamesProp( xklVTable->baseConfigAtom,
+ currentXmmRules,
+ data );
+ if( rv )
+ _XklXmmLockGroup( 0 );
+ return rv;
}
diff --git a/libxklavier/xklavier_evt.c b/libxklavier/xklavier_evt.c
index 1099673..2950424 100644
--- a/libxklavier/xklavier_evt.c
+++ b/libxklavier/xklavier_evt.c
@@ -33,27 +33,26 @@ int XklFilterEvents( XEvent * xev )
xev->xdestroywindow.window );
break;
case UnmapNotify:
- XklDebug( 200, "UnmapNotify\n" );
+ XklDebug( 200, "%s\n", _XklGetEventName( xev->type ) );
break;
case MapNotify:
- XklDebug( 200, "MapNotify\n" );
+ XklDebug( 200, "%s\n", _XklGetEventName( xev->type ) );
break;
case MappingNotify:
- XklDebug( 200, "MappingNotify\n" );
+ XklDebug( 200, "%s\n", _XklGetEventName( xev->type ) );
_XklFreeAllInfo( );
_XklLoadAllInfo( );
break;
case GravityNotify:
- XklDebug( 200, "GravityNotify\n" );
+ XklDebug( 200, "%s\n", _XklGetEventName( xev->type ) );
break;
case ReparentNotify:
- XklDebug( 200, "ReparentNotify\n" );
+ XklDebug( 200, "%s\n", _XklGetEventName( xev->type ) );
break; /* Ignore these events */
default:
{
- const char *name = _XklGetEventName( xev->type );
XklDebug( 200, "Unknown event %d [%s]\n", xev->type,
- ( name == NULL ? "??" : name ) );
+ _XklGetEventName( xev->type ) );
return 1;
}
}
@@ -71,6 +70,9 @@ void _XklFocusInEvHandler( XFocusChangeEvent * fev )
Window appWin;
XklState selectedWindowState;
+ if( !( _xklListenerType & XKLL_MANAGE_WINDOW_STATES ) )
+ return;
+
win = fev->window;
switch ( fev->mode )
@@ -129,7 +131,7 @@ void _XklFocusInEvHandler( XFocusChangeEvent * fev )
if( XklIsGroupPerApp() == !newWinTransparent )
{
- // We skip restoration only if we return to the same app window
+ /* We skip restoration only if we return to the same app window */
Bool doSkip = False;
if( _xklSkipOneRestore )
{
@@ -168,7 +170,8 @@ void _XklFocusInEvHandler( XFocusChangeEvent * fev )
}
}
- if( XklGetIndicatorsHandling( ) )
+ if( ( xklVTable->features & XKLF_CAN_TOGGLE_INDICATORS ) &&
+ XklGetIndicatorsHandling( ) )
{
XklDebug( 150,
"Restoring the indicators from %X to %X after gaining focus\n",
@@ -206,6 +209,9 @@ void _XklFocusInEvHandler( XFocusChangeEvent * fev )
*/
void _XklFocusOutEvHandler( XFocusChangeEvent * fev )
{
+ if( !( _xklListenerType & XKLL_MANAGE_WINDOW_STATES ) )
+ return;
+
if( fev->mode != NotifyNormal )
{
XklDebug( 200,
@@ -238,7 +244,10 @@ void _XklFocusOutEvHandler( XFocusChangeEvent * fev )
/**
* PropertyChange handler
- * Interested in WM_STATE property only
+ * Interested in :
+ * + for XKLL_MANAGE_WINDOW_STATES
+ * - WM_STATE property for all windows
+ * - Configuration property of the root window
*/
void _XklPropertyEvHandler( XPropertyEvent * pev )
{
@@ -257,49 +266,55 @@ void _XklPropertyEvHandler( XPropertyEvent * pev )
}
}
- if( pev->atom == _xklAtoms[WM_STATE] )
+ if( _xklListenerType & XKLL_MANAGE_WINDOW_STATES )
{
- Bool hasXklState = XklGetState( pev->window, NULL );
-
- if( pev->state == PropertyNewValue )
+ if( pev->atom == _xklAtoms[WM_STATE] )
{
- XklDebug( 160, "New value of WM_STATE on window " WINID_FORMAT "\n",
- pev->window );
- if( !hasXklState ) /* Is this event the first or not? */
+ Bool hasXklState = XklGetState( pev->window, NULL );
+
+ if( pev->state == PropertyNewValue )
{
- _XklAddAppWindow( pev->window, ( Window ) NULL, False,
- &_xklCurState );
+ XklDebug( 160, "New value of WM_STATE on window " WINID_FORMAT "\n",
+ pev->window );
+ if( !hasXklState ) /* Is this event the first or not? */
+ {
+ _XklAddAppWindow( pev->window, ( Window ) NULL, False,
+ &_xklCurState );
+ }
+ } else
+ { /* ev->xproperty.state == PropertyDelete, either client or WM can remove it, ICCCM 4.1.3.1 */
+ XklDebug( 160, "Something (%d) happened to WM_STATE of window 0x%x\n",
+ pev->state, pev->window );
+ _XklSelectInputMerging( pev->window, PropertyChangeMask );
+ if( hasXklState )
+ {
+ XklDelState( pev->window );
+ }
}
} else
- { /* ev->xproperty.state == PropertyDelete, either client or WM can remove it, ICCCM 4.1.3.1 */
- XklDebug( 160, "Something (%d) happened to WM_STATE of window 0x%x\n",
- pev->state, pev->window );
- _XklSelectInputMerging( pev->window, PropertyChangeMask );
- if( hasXklState )
+ if( pev->atom == xklVTable->baseConfigAtom
+ && pev->window == _xklRootWindow )
+ {
+ if( pev->state == PropertyNewValue )
{
- XklDelState( pev->window );
+ XklDebug( 160, "New value of *_NAMES_PROP_ATOM on root window\n" );
+ /* If root window got new *_NAMES_PROP_ATOM -
+ it most probably means new keyboard config is loaded by somebody */
+ _XklFreeAllInfo( );
+ _XklLoadAllInfo( );
}
}
- } else
- if( pev->atom == _xklAtoms[XKB_RF_NAMES_PROP_ATOM]
- && pev->window == _xklRootWindow )
- {
- if( pev->state == PropertyNewValue )
- {
- XklDebug( 160, "New value of XKB_RF_NAMES_PROP_ATOM on root window\n" );
- // If root window got new _XKB_RF_NAMES_PROP_ATOM -
- // it most probably means new xkb is loaded by somebody
- _XklFreeAllInfo( );
- _XklLoadAllInfo( );
- }
- }
+ } /* XKLL_MANAGE_WINDOW_STATES */
}
/**
- * * CreateNotify handler. Just interested in properties and focus events...
- * */
+ * CreateNotify handler. Just interested in properties and focus events...
+ */
void _XklCreateEvHandler( XCreateWindowEvent * cev )
{
+ if( !( _xklListenerType & XKLL_MANAGE_WINDOW_STATES ) )
+ return;
+
XklDebug( 200,
"Under-root window " WINID_FORMAT
"/%s (%d,%d,%d x %d) is created\n", cev->window,
@@ -339,7 +354,7 @@ void _XklErrHandler( Display * dpy, XErrorEvent * evt )
case BadWindow:
case BadAccess:
{
- // in most cases this means we are late:)
+ /* in most cases this means we are late:) */
XklDebug( 200, "ERROR: %p, " WINID_FORMAT ", %d, %d, %d\n",
dpy,
( unsigned long ) evt->resourceid,
diff --git a/libxklavier/xklavier_evt_xkb.c b/libxklavier/xklavier_evt_xkb.c
index 805b845..616f878 100644
--- a/libxklavier/xklavier_evt_xkb.c
+++ b/libxklavier/xklavier_evt_xkb.c
@@ -30,7 +30,7 @@ static void _XklStdXkbHandler( int grp, XklStateChange changeType, unsigned inds
}
if( !_XklGetAppWindow( focused, &focusedApp ) )
- focusedApp = _xklCurClient; //what else can I do
+ focusedApp = _xklCurClient; /* what else can I do */
XklDebug( 150, "Focused window: " WINID_FORMAT ", '%s'\n", focusedApp,
_XklGetDebugWindowTitle( focusedApp ) );
@@ -43,7 +43,8 @@ static void _XklStdXkbHandler( int grp, XklStateChange changeType, unsigned inds
{
_XklUpdateCurState( grp, inds,
"Updating the state from new focused window" );
- _XklAddAppWindow( focusedApp, ( Window ) NULL, False, &_xklCurState );
+ if( _xklListenerType & XKLL_MANAGE_WINDOW_STATES )
+ _XklAddAppWindow( focusedApp, ( Window ) NULL, False, &_xklCurState );
}
else
{
@@ -54,8 +55,8 @@ static void _XklStdXkbHandler( int grp, XklStateChange changeType, unsigned inds
XklDebug( 160, "CurClient:changed to " WINID_FORMAT ", '%s'\n",
_xklCurClient, _XklGetDebugWindowTitle( _xklCurClient ) );
}
- // if the window already has this this state - we are just restoring it!
- // (see the second parameter of stateCallback
+ /* if the window already has this this state - we are just restoring it!
+ (see the second parameter of stateCallback */
haveState = _XklGetAppState( _xklCurClient, &oldState );
if( setGroup || haveState )
@@ -68,7 +69,8 @@ static void _XklStdXkbHandler( int grp, XklStateChange changeType, unsigned inds
if( haveState )
_XklTryCallStateCallback( changeType, &oldState );
- _XklSaveAppState( _xklCurClient, &_xklCurState );
+ if( _xklListenerType & XKLL_MANAGE_WINDOW_STATES )
+ _XklSaveAppState( _xklCurClient, &_xklCurState );
}
#endif
@@ -86,8 +88,12 @@ int _XklXkbEventHandler( XEvent *xev )
if( xev->type != _xklXkbEventType )
return 0;
- XklDebug( 150, "Xkb event detected\n" );
+ if( !( _xklListenerType &
+ ( XKLL_MANAGE_WINDOW_STATES | XKLL_TRACK_KEYBOARD_STATE ) ) )
+ return 0;
+ XklDebug( 150, "Xkb event detected\n" );
+
switch ( kev->any.xkb_type )
{
case XkbStateNotify:
diff --git a/libxklavier/xklavier_evt_xmm.c b/libxklavier/xklavier_evt_xmm.c
index 4a30e79..1046757 100644
--- a/libxklavier/xklavier_evt_xmm.c
+++ b/libxklavier/xklavier_evt_xmm.c
@@ -4,18 +4,144 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xlibint.h>
+#include <X11/keysym.h>
#include "xklavier_private.h"
#include "xklavier_private_xmm.h"
+static int _XklXmmKeypressEventHandler( XKeyPressedEvent* kpe )
+{
+ if( _xklListenerType & XKLL_MANAGE_LAYOUTS )
+ {
+ XklDebug( 200, "Processing the KeyPress event\n" );
+ int currentShortcut = 0;
+ const XmmSwitchOptionPtr sop = _XklXmmFindSwitchOption( kpe->keycode,
+ kpe->state,
+ &currentShortcut );
+ if( sop != NULL )
+ {
+ XklDebug( 150, "It is THE shortcut\n" );
+ XklState state;
+ _XklXmmGetRealState( &state );
+ if( state.group != -1 )
+ {
+ int newGroup = ( state.group + sop->shortcutSteps[currentShortcut] ) %
+ currentXmmConfig.numLayouts;
+ XklDebug( 150, "Setting new xmm group %d\n", newGroup );
+ _XklXmmLockGroup( newGroup );
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int _XklXmmPropertyEventHandler( XPropertyEvent* kpe )
+{
+ XklDebug( 200, "Processing the PropertyNotify event: %d/%d\n",
+ kpe->atom, xmmStateAtom );
+ if( kpe->atom == xmmStateAtom )
+ {
+ if( _xklListenerType & XKLL_MANAGE_LAYOUTS )
+ {
+ XklState state;
+ _XklXmmGetRealState( &state );
+ XklDebug( 150, "Current group from the root window property %d\n", state.group );
+ _XklXmmUngrabShortcuts();
+ _XklXmmActualizeGroup( state.group );
+ _XklXmmGrabShortcuts();
+ return 1;
+ }
+ }
+ return 0;
+}
+
/**
- * XKB event handler
+ * XMM event handler
*/
int _XklXmmEventHandler( XEvent *xev )
{
+ switch( xev->type )
+ {
+ case KeyPress:
+ return _XklXmmKeypressEventHandler( (XKeyPressedEvent*)xev );
+ case PropertyNotify:
+ return _XklXmmPropertyEventHandler( (XPropertyEvent*)xev );
+ }
return 0;
}
-void _XklXmmSetIndicators( const XklState *windowState )
+/**
+ * We have to find which of Shift/Lock/Control/ModX masks
+ * belong to Caps/Num/Scroll lock
+ */
+static void _XklXmmInitXmmIndicatorsMap( int* pCapsLockMask,
+ int* pNumLockMask,
+ int* pScrollLockMask )
+{
+ XModifierKeymap *xmkm = NULL;
+ KeyCode *kcmap, nlkc, clkc, slkc;
+ int m, k, mask;
+
+ xmkm = XGetModifierMapping( _xklDpy );
+ if( xmkm )
+ {
+ clkc = XKeysymToKeycode( _xklDpy, XK_Num_Lock );
+ nlkc = XKeysymToKeycode( _xklDpy, XK_Caps_Lock );
+ slkc = XKeysymToKeycode( _xklDpy, XK_Scroll_Lock );
+
+ kcmap = xmkm->modifiermap;
+ mask = 1;
+ for( m = 8; --m >= 0; mask <<= 1 )
+ for( k = xmkm->max_keypermod; --k >= 0; kcmap++ )
+ {
+ if( *kcmap == clkc )
+ *pCapsLockMask = mask;
+ if( *kcmap == slkc )
+ *pScrollLockMask = mask;
+ if( *kcmap == nlkc )
+ *pNumLockMask = mask;
+ }
+ XFreeModifiermap( xmkm );
+ }
+}
+
+void _XklXmmGrabIgnoringIndicators( int keycode, int modifiers )
{
+ int CapsLockMask = 0, NumLockMask = 0, ScrollLockMask = 0;
+
+ _XklXmmInitXmmIndicatorsMap( &CapsLockMask, &NumLockMask, &ScrollLockMask );
+
+#define GRAB(mods) \
+ XklGrabKey( keycode, modifiers|(mods) )
+
+ GRAB( 0 );
+ GRAB( CapsLockMask );
+ GRAB( NumLockMask );
+ GRAB( ScrollLockMask );
+ GRAB( CapsLockMask | NumLockMask );
+ GRAB( CapsLockMask | ScrollLockMask );
+ GRAB( NumLockMask | ScrollLockMask );
+ GRAB( CapsLockMask | NumLockMask | ScrollLockMask );
+#undef GRAB
+}
+
+void _XklXmmUngrabIgnoringIndicators( int keycode, int modifiers )
+{
+ int CapsLockMask = 0, NumLockMask = 0, ScrollLockMask = 0;
+
+ _XklXmmInitXmmIndicatorsMap( &CapsLockMask, &NumLockMask, &ScrollLockMask );
+
+#define UNGRAB(mods) \
+ XklUngrabKey( keycode, modifiers|(mods) )
+
+ UNGRAB( 0 );
+ UNGRAB( CapsLockMask );
+ UNGRAB( NumLockMask );
+ UNGRAB( ScrollLockMask );
+ UNGRAB( CapsLockMask | NumLockMask );
+ UNGRAB( CapsLockMask | ScrollLockMask );
+ UNGRAB( NumLockMask | ScrollLockMask );
+ UNGRAB( CapsLockMask | NumLockMask | ScrollLockMask );
+#undef UNGRAB
}
diff --git a/libxklavier/xklavier_private.h b/libxklavier/xklavier_private.h
index a0af474..42f93c3 100644
--- a/libxklavier/xklavier_private.h
+++ b/libxklavier/xklavier_private.h
@@ -11,8 +11,6 @@ typedef void ( *XklConfigInitHandler )( void );
typedef Bool ( *XklConfigLoadRegistryHandler )( void );
-typedef Bool ( *XklConfigMultipleLayoutsSupportedHandler )( void );
-
typedef Bool ( *XklConfigWriteFileHandler )( const char *fileName,
const XklConfigRecPtr data,
const Bool binary );
@@ -25,6 +23,8 @@ typedef const char **( *XklGetGroupNamesHandler )( void );
typedef unsigned ( *XklGetNumGroupsHandler )( void );
+typedef void ( *XklGetRealStateHandler)( XklState * curState_return );
+
typedef Bool ( *XklLoadAllInfoHandler )( void );
typedef void ( *XklLockGroupHandler )( int group );
@@ -36,95 +36,132 @@ typedef void ( *XklSetIndicatorsHandler )( const XklState *windowState );
typedef struct
{
/**
+ * Backend name
+ */
+ const char *id;
+ /**
+ * Functions supported by the backend, combination of XKLF_* constants
+ */
+ int features;
+ /**
* Activates the configuration.
* xkb: create proper the XkbDescRec and send it to the server
- * TODO: xmodmap
+ * xmodmap: save the property, init layout #1
*/
XklConfigActivateHandler xklConfigActivateHandler;
/**
* Background-specific initialization.
* xkb: XkbInitAtoms - init internal xkb atoms table
- * TODO: xmodmap
+ * xmodmap: void.
*/
XklConfigInitHandler xklConfigInitHandler; /* private */
/**
* Loads the registry tree into DOM (using whatever path(s))
* The XklConfigFreeRegistry is static - no virtualization necessary.
* xkb: loads xml from XKB_BASE+"/rules/"+ruleset+".xml"
- * TODO: xmodmap
+ * xmodmap: loads xml from XMODMAP_BASE+"/"+ruleset+".xml"
*/
XklConfigLoadRegistryHandler xklConfigLoadRegistryHandler;
/**
- * Can the system combine layouts in one configuration - or not?
- * xkb: checks the simple rule with 2 layouts
- * xmodmap: return true
- */
- XklConfigMultipleLayoutsSupportedHandler xklConfigMultipleLayoutsSupportedHandler;
- /**
* Write the configuration into the file (binary/textual)
* xkb: write xkb or xkm file
- * TODO: xmodmap
+ * xmodmap: if text requested, just dump XklConfigRec to the
+ * file - not really useful. If binary - fail (not supported)
*/
XklConfigWriteFileHandler xklConfigWriteFileHandler;
/**
* Handles X events.
* xkb: XkbEvent handling
- * TODO: xmodmap: .... (scariest thing)
+ * xmodmap: keep track on the root window properties. What else can we do?
*/
XklEventHandler xklEventHandler;
/**
* Flushes the cached server config info.
* xkb: frees XkbDesc
- * TODO: xmodmap
+ * xmodmap: frees internal XklConfigRec
*/
XklFreeAllInfoHandler xklFreeAllInfoHandler; /* private */
/**
* Get the list of the group names
* xkb: return cached list of the group names
- * TODO: xmodmap
+ * xmodmap: return the list of layouts from the internal XklConfigRec
*/
XklGetGroupNamesHandler xklGetGroupNamesHandler;
/**
* Get the number of loaded groups
* xkb: return from the cached XkbDesc
- * TODO: xmodmap
+ * xmodmap: return number of layouts from internal XklConfigRec
*/
XklGetNumGroupsHandler xklGetNumGroupsHandler;
+
+ /**
+ * Gets the current stateCallback
+ * xkb: XkbGetState and XkbGetIndicatorState
+ * xmodmap: check the root window property (regarding the group)
+ */
+ XklGetRealStateHandler xklGetRealStateHandler;
+
/**
* Loads the configuration info from the server
* xkb: loads XkbDesc, names, indicators
- * TODO: xmodmap
+ * xmodmap: loads internal XklConfigRec from server
*/
XklLoadAllInfoHandler xklLoadAllInfoHandler; /* private */
/**
* Switches the keyboard to the group N
* xkb: simple one-liner to call the XKB function
- * TODO: xmodmap
+ * xmodmap: changes the root window property
+ * (listener invokes xmodmap with appropriate config file).
*/
XklLockGroupHandler xklLockGroupHandler;
/**
* Stop tracking the keyboard-related events
* xkb: XkbSelectEvents(..., 0)
- * TODO: xmodmap
+ * xmodmap: Ungrab the switching shortcut.
*/
XklPauseResumeListenHandler xklPauseListenHandler;
/**
* Start tracking the keyboard-related events
- * xkb: XkbSelectEvents + XkbSelectEventDetails + GetRealState
- * TODO: xmodmap
+ * xkb: XkbSelectEvents + XkbSelectEventDetails
+ * xmodmap: Grab the switching shortcut.
*/
XklPauseResumeListenHandler xklResumeListenHandler;
/**
* Set the indicators state from the XklState
* xkb: _XklSetIndicator for all indicators
- * TODO: xmodmap
+ * xmodmap: NULL. Not supported
*/
XklSetIndicatorsHandler xklSetIndicatorsHandler; /* private */
+
+ /* all data is private - no direct access */
+ /**
+ * The base configuration atom.
+ * xkb: _XKB_RF_NAMES_PROP_ATOM
+ * xmodmap: "_XMM_NAMES"
+ */
+ Atom baseConfigAtom;
+
+ /**
+ * The configuration backup atom
+ * xkb: "_XKB_RULES_NAMES_BACKUP"
+ * xmodmap: "_XMM_NAMES_BACKUP"
+ */
+ Atom backupConfigAtom;
+
+ /**
+ * Fallback for missing model
+ */
+ const char* defaultModel;
+
+ /**
+ * Fallback for missing layout
+ */
+ const char* defaultLayout;
+
} XklVTable;
extern void _XklEnsureVTableInited( void );
-extern void _XklGetRealState( XklState * curState_return );
extern void _XklAddAppWindow( Window win, Window parent, Bool force,
XklState * initState );
extern Bool _XklGetAppWindowBottomToTop( Window win, Window * appWin_return );
@@ -171,6 +208,11 @@ extern char *_XklLocaleFromUtf8( const char *utf8string );
extern int _XklGetLanguagePriority( const char *language );
+extern char* _XklGetRulesSetName( const char defaultRuleset[] );
+
+extern Bool _XklConfigGetFullFromServer( char **rulesFileOut,
+ XklConfigRecPtr data );
+
extern char *_XklConfigRecMergeByComma( const char **array,
const int arrayLength );
@@ -192,6 +234,9 @@ extern void _XklConfigRecSplitVariants( XklConfigRecPtr data,
extern void _XklConfigRecSplitOptions( XklConfigRecPtr data,
const char *merged );
+extern void XklConfigDump( FILE* file,
+ XklConfigRecPtr data );
+
extern const char *_XklGetEventName( int type );
extern Bool _XklIsTransparentAppWindow( Window appWin );
@@ -218,19 +263,12 @@ extern XErrorHandler _xklDefaultErrHandler;
extern char *_xklIndicatorNames[];
-#define WM_NAME 0
-#define WM_STATE 1
-#define XKLAVIER_STATE 2
-#define XKLAVIER_TRANSPARENT 3
-
-// XKB ones
-#define XKB_RF_NAMES_PROP_ATOM 4
-#define XKB_RF_NAMES_PROP_ATOM_BACKUP 5
-#define TOTAL_ATOMS 6
+enum { WM_NAME, WM_STATE, XKLAVIER_STATE, XKLAVIER_TRANSPARENT,
+ TOTAL_ATOMS };
#define XKLAVIER_STATE_PROP_LENGTH 2
-// taken from XFree86 maprules.c
+/* taken from XFree86 maprules.c */
#define _XKB_RF_NAMES_PROP_MAXLEN 1024
extern Atom _xklAtoms[];
@@ -245,6 +283,8 @@ extern int _xklSecondaryGroupsMask;
extern int _xklDebugLevel;
+extern int _xklListenerType;
+
extern Window _xklPrevAppWindow;
#define WINID_FORMAT "%lx"
@@ -255,4 +295,13 @@ extern void *_xklConfigCallbackData;
extern XklVTable *xklVTable;
+#ifdef __STRICT_ANSI__
+/* these are functions which are NOT in ANSI C.
+ Probably we should provide the implementation */
+extern int snprintf( char *s, size_t maxlen,
+ const char *format, ... );
+
+extern char *strdup( const char *s );
+#endif
+
#endif
diff --git a/libxklavier/xklavier_private_xkb.h b/libxklavier/xklavier_private_xkb.h
index 3906881..00ca966 100644
--- a/libxklavier/xklavier_private_xkb.h
+++ b/libxklavier/xklavier_private_xkb.h
@@ -18,6 +18,8 @@ extern XkbDescPtr _xklXkb;
extern void XklDumpXkbDesc( const char *filename, XkbDescPtr kbd );
+extern Bool _XklXkbConfigMultipleLayoutsSupported( void );
+
/* Start VTable methods */
extern Bool _XklXkbConfigActivate( const XklConfigRecPtr data );
@@ -26,8 +28,6 @@ extern void _XklXkbConfigInit( void );
extern Bool _XklXkbConfigLoadRegistry( void );
-extern Bool _XklXkbConfigMultipleLayoutsSupported( void );
-
extern Bool _XklXkbConfigWriteFile( const char *fileName,
const XklConfigRecPtr data,
const Bool binary );
@@ -40,6 +40,8 @@ extern const char **_XklXkbGetGroupNames( void );
extern unsigned _XklXkbGetNumGroups( void );
+extern void _XklXkbGetRealState( XklState * curState_return );
+
extern Bool _XklXkbLoadAllInfo( void );
extern void _XklXkbLockGroup( int group );
diff --git a/libxklavier/xklavier_private_xmm.h b/libxklavier/xklavier_private_xmm.h
index 0824f29..996a035 100644
--- a/libxklavier/xklavier_private_xmm.h
+++ b/libxklavier/xklavier_private_xmm.h
@@ -1,6 +1,48 @@
#ifndef __XKLAVIER_PRIVATE_XMM_H__
#define __XKLAVIER_PRIVATE_XMM_H__
+typedef struct _XmmShortcut
+{
+ int keysym;
+ int modifiers;
+} XmmShortcut, *XmmShortcutPtr;
+
+#define MAX_SHORTCUTS_PER_OPTION 4
+typedef struct _XmmSwitchOption
+{
+ const char* optionName;
+ int numShortcuts;
+ XmmShortcut shortcuts[MAX_SHORTCUTS_PER_OPTION];
+ int shortcutSteps[MAX_SHORTCUTS_PER_OPTION];
+} XmmSwitchOption, *XmmSwitchOptionPtr;
+
+extern char* currentXmmRules;
+
+extern XklConfigRec currentXmmConfig;
+
+extern Atom xmmStateAtom;
+
+/* in the ideal world this should be a hashmap */
+extern XmmSwitchOption allSwitchOptions[];
+
+extern void _XklXmmGrabIgnoringIndicators( int keycode, int modifiers );
+
+extern void _XklXmmUngrabIgnoringIndicators( int keycode, int modifiers );
+
+extern void _XklXmmGrabShortcuts( void );
+
+extern void _XklXmmUngrabShortcuts( void );
+
+extern const char* _XklXmmGetCurrentShortcutOptionName( void );
+
+extern const XmmSwitchOptionPtr _XklXmmGetCurrentShortcut( void );
+
+extern void _XklXmmActualizeGroup( int group );
+
+extern const XmmSwitchOptionPtr _XklXmmFindSwitchOption( unsigned keycode,
+ unsigned state,
+ int * currentShortcut_rv );
+
/* Start VTable methods */
extern Bool _XklXmmConfigActivate( const XklConfigRecPtr data );
@@ -9,12 +51,6 @@ extern void _XklXmmConfigInit( void );
extern Bool _XklXmmConfigLoadRegistry( void );
-extern Bool _XklXmmConfigMultipleLayoutsSupported( void );
-
-extern Bool _XklXmmConfigWriteFile( const char *fileName,
- const XklConfigRecPtr data,
- const Bool binary );
-
extern int _XklXmmEventHandler( XEvent * kev );
extern void _XklXmmFreeAllInfo( void );
@@ -23,6 +59,8 @@ extern const char **_XklXmmGetGroupNames( void );
extern unsigned _XklXmmGetNumGroups( void );
+extern void _XklXmmGetRealState( XklState * curState_return );
+
extern Bool _XklXmmLoadAllInfo( void );
extern void _XklXmmLockGroup( int group );
@@ -31,8 +69,6 @@ extern int _XklXmmPauseListen( void );
extern int _XklXmmResumeListen( void );
-extern void _XklXmmSetIndicators( const XklState *windowState );
-
/* End of VTable methods */
#endif
diff --git a/libxklavier/xklavier_props.c b/libxklavier/xklavier_props.c
index 99c12e0..7435ae2 100644
--- a/libxklavier/xklavier_props.c
+++ b/libxklavier/xklavier_props.c
@@ -13,12 +13,9 @@
#include "xklavier_config.h"
#include "xklavier_private.h"
-#define XKB_DEFAULT_MODEL "pc101"
-#define XKB_DEFAULT_LAYOUT "us"
-
void XklConfigRecInit( XklConfigRecPtr data )
{
- // clear the structure VarDefsPtr...
+ /* clear the structure VarDefsPtr... */
memset( ( void * ) data, 0, sizeof( XklConfigRec ) );
}
@@ -50,11 +47,11 @@ static Bool _XklGetDefaultNamesProp( char **rulesFileOut, XklConfigRecPtr data )
{
if ( rulesFileOut != NULL )
*rulesFileOut = strdup( XKB_DEFAULT_RULESET );
- data->model = strdup( XKB_DEFAULT_MODEL );
-// keeping Nvariants = Nlayouts
+ data->model = strdup( xklVTable->defaultModel );
+/* keeping Nvariants = Nlayouts */
data->numLayouts = data->numVariants = 1;
data->layouts = malloc( sizeof( char * ) );
- data->layouts[0] = strdup( XKB_DEFAULT_LAYOUT );
+ data->layouts[0] = strdup( xklVTable->defaultLayout );
data->variants = malloc( sizeof( char * ) );
data->variants[0] = strdup( "" );
data->numOptions = 0;
@@ -62,6 +59,17 @@ static Bool _XklGetDefaultNamesProp( char **rulesFileOut, XklConfigRecPtr data )
return True;
}
+Bool _XklConfigGetFullFromServer( char **rulesFileOut, XklConfigRecPtr data )
+{
+ Bool rv =
+ XklGetNamesProp( xklVTable->baseConfigAtom, rulesFileOut, data );
+
+ if( !rv )
+ rv = _XklGetDefaultNamesProp( rulesFileOut, data );
+
+ return rv;
+}
+
Bool XklConfigRecEquals( XklConfigRecPtr data1, XklConfigRecPtr data2 )
{
if ( data1 == data2 )
@@ -116,19 +124,13 @@ void XklConfigRecReset( XklConfigRecPtr data )
Bool XklConfigGetFromServer( XklConfigRecPtr data )
{
- Bool rv =
- XklGetNamesProp( _xklAtoms[XKB_RF_NAMES_PROP_ATOM], NULL, data );
-
- if( !rv )
- rv = _XklGetDefaultNamesProp( NULL, data );
-
- return rv;
+ return _XklConfigGetFullFromServer( NULL, data );
}
Bool XklConfigGetFromBackup( XklConfigRecPtr data )
{
Bool rv =
- XklGetNamesProp( _xklAtoms[XKB_RF_NAMES_PROP_ATOM_BACKUP], NULL, data );
+ XklGetNamesProp( xklVTable->backupConfigAtom, NULL, data );
return rv;
}
@@ -142,16 +144,14 @@ Bool XklBackupNamesProp( )
XklConfigRecInit( &data );
if( XklGetNamesProp
- ( _xklAtoms[XKB_RF_NAMES_PROP_ATOM_BACKUP], NULL, &data ) )
+ ( xklVTable->backupConfigAtom, NULL, &data ) )
{
XklConfigRecDestroy( &data );
return True;
}
- // "backup" property is not defined
+ /* "backup" property is not defined */
XklConfigRecReset( &data );
- cgp = XklGetNamesProp( _xklAtoms[XKB_RF_NAMES_PROP_ATOM], &rf, &data );
- if ( !cgp )
- cgp = _XklGetDefaultNamesProp( &rf, &data );
+ cgp = _XklConfigGetFullFromServer( &rf, &data );
if ( cgp )
{
@@ -171,7 +171,7 @@ Bool XklBackupNamesProp( )
for( i = data.numOptions; --i >= 0; )
XklDebug( 150, "%d: [%s]\n", i, data.options[i] );
#endif
- if( !XklSetNamesProp( _xklAtoms[XKB_RF_NAMES_PROP_ATOM_BACKUP], rf, &data ) )
+ if( !XklSetNamesProp( xklVTable->backupConfigAtom, rf, &data ) )
{
XklDebug( 150, "Could not backup the configuration" );
rv = False;
@@ -194,13 +194,13 @@ Bool XklRestoreNamesProp( )
XklConfigRec data;
XklConfigRecInit( &data );
- if( !XklGetNamesProp( _xklAtoms[XKB_RF_NAMES_PROP_ATOM_BACKUP], NULL, &data ) )
+ if( !XklGetNamesProp( xklVTable->backupConfigAtom, NULL, &data ) )
{
XklConfigRecDestroy( &data );
return False;
}
- if( !XklSetNamesProp( _xklAtoms[XKB_RF_NAMES_PROP_ATOM], rf, &data ) )
+ if( !XklSetNamesProp( xklVTable->baseConfigAtom, rf, &data ) )
{
XklDebug( 150, "Could not backup the configuration" );
rv = False;
@@ -218,7 +218,7 @@ Bool XklGetNamesProp( Atom rulesAtom,
char *propData = NULL, *out;
Status rtrn;
- // no such atom!
+ /* no such atom! */
if( rulesAtom == None ) /* property cannot exist */
{
_xklLastErrorMsg = "Could not find the atom";
@@ -230,17 +230,17 @@ Bool XklGetNamesProp( Atom rulesAtom,
_XKB_RF_NAMES_PROP_MAXLEN, False, XA_STRING,
&realPropType, &fmt, &nitems, &extraBytes,
( unsigned char ** ) ( void * ) &propData );
- // property not found!
+ /* property not found! */
if( rtrn != Success )
{
_xklLastErrorMsg = "Could not get the property";
return False;
}
- // set rules file to ""
+ /* set rules file to "" */
if( rulesFileOut )
*rulesFileOut = NULL;
- // has to be array of strings
+ /* has to be array of strings */
if( ( extraBytes > 0 ) || ( realPropType != XA_STRING ) || ( fmt != 8 ) )
{
if( propData )
@@ -255,13 +255,13 @@ Bool XklGetNamesProp( Atom rulesAtom,
return False;
}
- // rules file
+ /* rules file */
out = propData;
if( out && ( *out ) && rulesFileOut )
*rulesFileOut = strdup( out );
out += strlen( out ) + 1;
- // if user is interested in rules only - don't waste the time
+ /* if user is interested in rules only - don't waste the time */
if( !data )
{
XFree( propData );
@@ -298,7 +298,7 @@ Bool XklGetNamesProp( Atom rulesAtom,
( data->numLayouts - data->numVariants ) * sizeof( char * ) );
data->numVariants = data->numLayouts;
}
- // take variants from layouts like ru(winkeys)
+ /* take variants from layouts like ru(winkeys) */
theLayout = data->layouts;
theVariant = data->variants;
for( i = data->numLayouts; --i >= 0; theLayout++, theVariant++ )
@@ -313,7 +313,7 @@ Bool XklGetNamesProp( Atom rulesAtom,
{
int varlen = varend - varstart;
int laylen = varstart - *theLayout;
- // I am not sure - but I assume variants in layout have priority
+ /* I am not sure - but I assume variants in layout have priority */
char *var = *theVariant = ( *theVariant != NULL ) ?
realloc( *theVariant, varlen ) : malloc( varlen );
memcpy( var, varstart + 1, --varlen );
@@ -330,13 +330,13 @@ Bool XklGetNamesProp( Atom rulesAtom,
if( ( out - propData ) < nitems )
{
_XklConfigRecSplitOptions( data, out );
-// out += strlen( out ) + 1;
+/* out += strlen( out ) + 1; */
}
XFree( propData );
return True;
}
-// taken from XFree86 maprules.c
+/* taken from XFree86 maprules.c */
Bool XklSetNamesProp( Atom rulesAtom,
char *rulesFile, const XklConfigRecPtr data )
{
diff --git a/libxklavier/xklavier_util.c b/libxklavier/xklavier_util.c
index f88c8cf..6504b3b 100644
--- a/libxklavier/xklavier_util.c
+++ b/libxklavier/xklavier_util.c
@@ -65,6 +65,9 @@ void XklSaveState( Window win, XklState * state )
{
Window appWin;
+ if( !( _xklListenerType & XKLL_MANAGE_WINDOW_STATES ) )
+ return;
+
if( _XklGetAppWindow( win, &appWin ) )
_XklSaveAppState( appWin, state );
}
@@ -117,23 +120,23 @@ Bool _XklLoadSubtree( Window window, int level, XklState * initState )
child = children;
while( num )
{
- XklDebug( 150, "Looking at child " WINID_FORMAT " '%s'\n", *child,
- _XklGetDebugWindowTitle( *child ) );
if( _XklHasWmState( *child ) )
{
- XklDebug( 150, "It has WM_STATE so we'll add it\n" );
+ XklDebug( 160, "Window " WINID_FORMAT " '%s' has WM_STATE so we'll add it\n",
+ *child, _XklGetDebugWindowTitle( *child ) );
_XklAddAppWindow( *child, window, True, initState );
} else
{
- XklDebug( 150, "It does not have have WM_STATE so we'll not add it\n" );
+ XklDebug( 200, "Window " WINID_FORMAT " '%s' does not have have WM_STATE so we'll not add it\n",
+ *child, _XklGetDebugWindowTitle( *child ) );
if( level == 0 )
{
- XklDebug( 150, "But we are at level 0 so we'll spy on it\n" );
+ XklDebug( 200, "But we are at level 0 so we'll spy on it\n" );
_XklSelectInputMerging( *child,
FocusChangeMask | PropertyChangeMask );
} else
- XklDebug( 150, "And we are at level %d so we'll not spy on it\n",
+ XklDebug( 200, "And we are at level %d so we'll not spy on it\n",
level );
retval = _XklLoadSubtree( *child, level + 1, initState );
@@ -216,8 +219,8 @@ Status _XklStatusQueryTree( Display * display,
const char *_XklGetEventName( int type )
{
- // Not really good to use the fact of consecutivity
- // but X protocol is already standartized so...
+ /* Not really good to use the fact of consecutivity
+ but X protocol is already standartized so... */
static const char *evtNames[] = {
"KeyPress",
"KeyRelease",
@@ -253,7 +256,7 @@ const char *_XklGetEventName( int type )
};
type -= KeyPress;
if( type < 0 || type > ( sizeof( evtNames ) / sizeof( evtNames[0] ) ) )
- return NULL;
+ return "UNKNOWN";
return evtNames[type];
}
diff --git a/libxklavier/xklavier_xkb.c b/libxklavier/xklavier_xkb.c
index 6e78936..5b2ffe4 100644
--- a/libxklavier/xklavier_xkb.c
+++ b/libxklavier/xklavier_xkb.c
@@ -28,13 +28,14 @@ const char **_XklXkbGetGroupNames( void )
int _XklXkbPauseListen( )
{
XkbSelectEvents( _xklDpy, XkbUseCoreKbd, XkbAllEventsMask, 0 );
-// XkbSelectEventDetails( _xklDpy,
- // XkbUseCoreKbd,
- // XkbStateNotify,
- // 0,
- // 0 );
+/* XkbSelectEventDetails( _xklDpy,
+ XkbUseCoreKbd,
+ XkbStateNotify,
+ 0,
+ 0 );
- //!!_XklSelectInput( _xklRootWindow, 0 );
+ !!_XklSelectInput( _xklRootWindow, 0 );
+*/
return 0;
}
@@ -66,9 +67,6 @@ int _XklXkbResumeListen( )
XkbUseCoreKbd,
XkbNamesNotify,
XKB_NAMES_EVT_DTL_MASK, XKB_NAMES_EVT_DTL_MASK );
- _XklSelectInputMerging( _xklRootWindow,
- SubstructureNotifyMask | PropertyChangeMask );
- _XklGetRealState( &_xklCurState );
return 0;
}
@@ -184,7 +182,7 @@ void _XklXkbLockGroup( int group )
/**
* Updates current internal state from X state
*/
-void _XklGetRealState( XklState * curState_return )
+void _XklXkbGetRealState( XklState * curState_return )
{
XkbStateRec state;
@@ -197,7 +195,7 @@ void _XklGetRealState( XklState * curState_return )
&curState_return->indicators ) )
curState_return->indicators &= _xklXkb->indicators->phys_indicators;
else
- curState_return->indicators = 0;
+ curState_return->indicators = 0;
}
/*
@@ -228,7 +226,7 @@ Bool _XklSetIndicator( int indicatorNum, Bool set )
{
case XkbIM_NoExplicit | XkbIM_NoAutomatic:
{
- // Can do nothing. Just ignore the indicator
+ /* Can do nothing. Just ignore the indicator */
return True;
}
@@ -275,9 +273,9 @@ Bool _XklSetIndicator( int indicatorNum, Bool set )
}
/* The 'which_groups' field tells when this indicator turns on
- * * for the 'groups' field: base (0x1), latched (0x2), locked (0x4),
- * * or effective (0x8).
- * */
+ * for the 'groups' field: base (0x1), latched (0x2), locked (0x4),
+ * or effective (0x8).
+ */
if( map->groups )
{
int i;
@@ -298,13 +296,13 @@ Bool _XklSetIndicator( int indicatorNum, Bool set )
}
if( map->which_groups & ( XkbIM_UseLocked | XkbIM_UseEffective ) )
{
- // Important: Groups should be ignored here - because they are handled separately!
- // XklLockGroup( group );
+ /* Important: Groups should be ignored here - because they are handled separately! */
+ /* XklLockGroup( group ); */
} else if( map->which_groups & XkbIM_UseLatched )
XkbLatchGroup( _xklDpy, XkbUseCoreKbd, group );
else
{
- // Can do nothing. Just ignore the indicator
+ /* Can do nothing. Just ignore the indicator */
return True;
}
} else
@@ -364,15 +362,19 @@ int _XklXkbInit( void )
int opcode;
static XklVTable xklXkbVTable =
{
+ "XKB",
+ XKLF_CAN_TOGGLE_INDICATORS |
+ XKLF_CAN_OUTPUT_CONFIG_AS_ASCII |
+ XKLF_CAN_OUTPUT_CONFIG_AS_BINARY,
_XklXkbConfigActivate,
_XklXkbConfigInit,
_XklXkbConfigLoadRegistry,
- _XklXkbConfigMultipleLayoutsSupported,
_XklXkbConfigWriteFile,
_XklXkbEventHandler,
_XklXkbFreeAllInfo,
_XklXkbGetGroupNames,
_XklXkbGetNumGroups,
+ _XklXkbGetRealState,
_XklXkbLoadAllInfo,
_XklXkbLockGroup,
_XklXkbPauseListen,
@@ -394,14 +396,23 @@ int _XklXkbInit( void )
"xkbEvenType: %X, xkbError: %X, display: %p, root: " WINID_FORMAT
"\n", _xklXkbEventType, _xklXkbError, _xklDpy, _xklRootWindow );
- _xklAtoms[XKB_RF_NAMES_PROP_ATOM] =
+ xklXkbVTable.baseConfigAtom =
XInternAtom( _xklDpy, _XKB_RF_NAMES_PROP_ATOM, False );
- _xklAtoms[XKB_RF_NAMES_PROP_ATOM_BACKUP] =
+ xklXkbVTable.backupConfigAtom =
XInternAtom( _xklDpy, "_XKB_RULES_NAMES_BACKUP", False );
+ xklXkbVTable.defaultModel = "pc101";
+ xklXkbVTable.defaultLayout = "us";
+
xklVTable = &xklXkbVTable;
+
+ /* First, we have to assign xklVTable -
+ because this function uses it */
+
+ if( _XklXkbConfigMultipleLayoutsSupported() )
+ xklXkbVTable.features |= XKLF_MULTIPLE_LAYOUTS_SUPPORTED;
- return _XklLoadAllInfo( ) ? 0 : _xklLastErrorCode;
+ return 0;
#else
XklDebug( 160,
"NO XKB LIBS, display: %p, root: " WINID_FORMAT
diff --git a/libxklavier/xklavier_xmm.c b/libxklavier/xklavier_xmm.c
index d565732..2d68637 100755
--- a/libxklavier/xklavier_xmm.c
+++ b/libxklavier/xklavier_xmm.c
@@ -1,71 +1,266 @@
#include <time.h>
#include <stdlib.h>
+#include <string.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xlibint.h>
+#include <X11/keysym.h>
+
+#include "config.h"
#include "xklavier_private.h"
#include "xklavier_private_xmm.h"
+#define SHORTCUT_OPTION_PREFIX "grp:"
+
+char* currentXmmRules = NULL;
+
+XklConfigRec currentXmmConfig;
+
+Atom xmmStateAtom;
+
const char **_XklXmmGetGroupNames( void )
{
- return ( const char ** ) NULL;
+ return (const char **)currentXmmConfig.layouts;
}
-int _XklXmmPauseListen( )
+void _XklXmmGrabShortcuts( )
{
- return 0;
+ int i;
+ XmmShortcutPtr shortcut;
+ const XmmSwitchOptionPtr option = _XklXmmGetCurrentShortcut();
+
+ XklDebug( 150, "Found shortcut option: %p\n", option );
+ if( option == NULL )
+ return;
+
+ shortcut = option->shortcuts;
+ for( i = option->numShortcuts; --i >= 0; shortcut++ )
+ {
+ int keycode = XKeysymToKeycode( _xklDpy, shortcut->keysym );
+ _XklXmmGrabIgnoringIndicators( keycode,
+ shortcut->modifiers );
+ }
+}
+
+void _XklXmmUngrabShortcuts( )
+{
+ int i;
+ XmmShortcutPtr shortcut;
+ const XmmSwitchOptionPtr option = _XklXmmGetCurrentShortcut();
+
+ if( option == NULL )
+ return;
+
+ shortcut = option->shortcuts;
+ for( i = option->numShortcuts; --i >= 0; shortcut++ )
+ {
+ int keycode = XKeysymToKeycode( _xklDpy, shortcut->keysym );
+ _XklXmmUngrabIgnoringIndicators( keycode,
+ shortcut->modifiers );
+ }
+}
+
+const XmmSwitchOptionPtr _XklXmmGetCurrentShortcut()
+{
+ const char* optionName = _XklXmmGetCurrentShortcutOptionName();
+ XklDebug( 150, "Configured switch option: [%s]\n", optionName );
+ if( optionName == NULL )
+ return NULL;
+ XmmSwitchOptionPtr switchOption = allSwitchOptions;
+ while( switchOption->optionName != NULL )
+ {
+ if( !strcmp( switchOption->optionName, optionName ) )
+ return switchOption;
+ switchOption++;
+ }
+ return NULL;
+}
+
+const char* _XklXmmGetCurrentShortcutOptionName( )
+{
+ int i;
+ char** option = currentXmmConfig.options;
+ for( i = currentXmmConfig.numOptions; --i >= 0; option++ )
+ {
+ /* starts with "grp:" */
+ if( strstr( *option, SHORTCUT_OPTION_PREFIX ) != NULL )
+ {
+ return *option + sizeof SHORTCUT_OPTION_PREFIX - 1;
+ }
+ }
+ return NULL;
+}
+
+const XmmSwitchOptionPtr _XklXmmFindSwitchOption( unsigned keycode,
+ unsigned state,
+ int* currentShortcut_rv )
+{
+ const XmmSwitchOptionPtr rv = _XklXmmGetCurrentShortcut();
+ int i;
+
+ if( rv != NULL )
+ {
+ XmmShortcutPtr sc = rv->shortcuts;
+ for( i=rv->numShortcuts; --i>=0; sc++ )
+ {
+ if( ( XKeysymToKeycode( _xklDpy, sc->keysym ) == keycode ) &&
+ ( ( state & sc->modifiers ) == sc->modifiers ) )
+ {
+ return rv;
+ }
+ }
+ }
+ return NULL;
}
int _XklXmmResumeListen( )
{
+ if( _xklListenerType & XKLL_MANAGE_LAYOUTS )
+ _XklXmmGrabShortcuts();
return 0;
}
-unsigned _XklXmmGetNumGroups( void )
+int _XklXmmPauseListen( )
{
+ if( _xklListenerType & XKLL_MANAGE_LAYOUTS )
+ _XklXmmUngrabShortcuts();
return 0;
}
+unsigned _XklXmmGetNumGroups( void )
+{
+ return currentXmmConfig.numLayouts;
+}
+
void _XklXmmFreeAllInfo( )
{
+ if( currentXmmRules != NULL )
+ {
+ free( currentXmmRules );
+ currentXmmRules = NULL;
+ }
+ XklConfigRecReset( &currentXmmConfig );
}
Bool _XklXmmLoadAllInfo( )
{
- return False;
+ return _XklConfigGetFullFromServer( &currentXmmRules, &currentXmmConfig );
+}
+
+void _XklXmmGetRealState( XklState * state )
+{
+ unsigned char *propval = NULL;
+ Atom actualType;
+ int actualFormat;
+ unsigned long bytesRemaining;
+ unsigned long actualItems;
+ int result;
+
+ memset( state, 0, sizeof( *state ) );
+
+ result = XGetWindowProperty( _xklDpy, _xklRootWindow, xmmStateAtom, 0L, 1L,
+ False, XA_INTEGER, &actualType, &actualFormat,
+ &actualItems, &bytesRemaining,
+ &propval );
+
+ if( Success != result )
+ {
+ XklDebug( 160, "Could not get the xmodmap current group: %d\n", result );
+ return;
+ }
+
+ if( actualFormat != 32 ||
+ actualItems != 1 )
+ {
+ XklDebug( 160, "Could not get the xmodmap current group\n" );
+ return;
+ }
+
+ state->group = *(CARD32*)propval;
+ XFree( propval );
+ state->indicators = 0;
+}
+
+void _XklXmmActualizeGroup( int group )
+{
+ char cmd[1024];
+ int res;
+ const char* layoutName = NULL;
+
+ if( currentXmmConfig.numLayouts < group )
+ return;
+
+ layoutName = currentXmmConfig.layouts[group];
+
+ snprintf( cmd, sizeof cmd,
+ "xmodmap %s/xmodmap.%s",
+ XMODMAP_BASE, layoutName );
+
+ res = system( cmd );
+ if( res > 0 )
+ {
+ XklDebug( 0, "xmodmap error %d\n", res );
+ } else if( res < 0 )
+ {
+ XklDebug( 0, "Could not execute xmodmap: %d\n", res );
+ }
+ XSync( _xklDpy, False );
}
void _XklXmmLockGroup( int group )
{
+ CARD32 propval;
+
+ if( currentXmmConfig.numLayouts < group )
+ return;
+
+ /* updating the status property */
+ propval = group;
+ XChangeProperty( _xklDpy, _xklRootWindow, xmmStateAtom,
+ XA_INTEGER, 32, PropModeReplace,
+ (unsigned char*)&propval, 1 );
+ XSync( _xklDpy, False );
}
int _XklXmmInit( void )
{
static XklVTable xklXmmVTable =
{
+ "xmodmap",
+ XKLF_MULTIPLE_LAYOUTS_SUPPORTED |
+ XKLF_REQUIRES_MANUAL_LAYOUT_MANAGEMENT,
_XklXmmConfigActivate,
_XklXmmConfigInit,
_XklXmmConfigLoadRegistry,
- _XklXmmConfigMultipleLayoutsSupported,
- _XklXmmConfigWriteFile,
+ NULL,
_XklXmmEventHandler,
_XklXmmFreeAllInfo,
_XklXmmGetGroupNames,
_XklXmmGetNumGroups,
+ _XklXmmGetRealState,
_XklXmmLoadAllInfo,
_XklXmmLockGroup,
_XklXmmPauseListen,
_XklXmmResumeListen,
- _XklXmmSetIndicators,
+ NULL,
};
+ xklXmmVTable.baseConfigAtom =
+ XInternAtom( _xklDpy, "_XMM_NAMES", False );
+ xklXmmVTable.backupConfigAtom =
+ XInternAtom( _xklDpy, "_XMM_NAMES_BACKUP", False );
+
+ xmmStateAtom =
+ XInternAtom( _xklDpy, "_XMM_STATE", False );
+
+ xklXmmVTable.defaultModel = "generic";
+ xklXmmVTable.defaultLayout = "us";
+
xklVTable = &xklXmmVTable;
- XklDebug( 160,
- "Xmodmap support activated, display: %p, root: " WINID_FORMAT
- "\n", _xklDpy, _xklRootWindow );
- return -1;
+ XklDebug( 0, "XMM backend inited\n" );
+ return 0;
}
diff --git a/libxklavier/xklavier_xmm_opts.c b/libxklavier/xklavier_xmm_opts.c
new file mode 100644
index 0000000..d082482
--- /dev/null
+++ b/libxklavier/xklavier_xmm_opts.c
@@ -0,0 +1,104 @@
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xlibint.h>
+#include <X11/keysym.h>
+
+#include "config.h"
+
+#include "xklavier_private.h"
+#include "xklavier_private_xmm.h"
+
+#define SHORTCUT_OPTION_PREFIX "grp:"
+
+XmmSwitchOption allSwitchOptions[] =
+{
+ {
+ "ralt_toggle", 1,
+ { { XK_Alt_R, 0 } }, { 1 }
+ },
+ {
+ "lalt_toggle", 1,
+ { { XK_Alt_L, 0 } }, { 1 }
+ },
+ {
+ "caps_toggle", 1,
+ { { XK_Caps_Lock, 0 } }, { 1 }
+ },
+ {
+ "shift_caps_toggle", 1,
+ { { XK_Caps_Lock, ShiftMask } }, { 1 }
+ },
+ {
+ "shifts_toggle", 2,
+ { { XK_Shift_R, ShiftMask },
+ { XK_Shift_L, ShiftMask } }, { 1, -1 }
+ },
+ {
+ "alts_toggle", 2,
+ { { XK_Alt_R, Mod1Mask },
+ { XK_Alt_L, Mod1Mask } }, { 1, -1 }
+ },
+ {
+ "ctrls_toggle", 2,
+ { { XK_Control_R, ControlMask },
+ { XK_Control_L, ControlMask } }, { 1, -1 }
+ },
+ {
+ "ctrl_shift_toggle", 4,
+ { { XK_Control_R, ShiftMask },
+ { XK_Control_L, ShiftMask },
+ { XK_Shift_R, ControlMask },
+ { XK_Shift_L, ControlMask } }, { 1, -1, 1, -1 }
+ },
+ {
+ "ctrl_alt_toggle", 4,
+ { { XK_Control_R, Mod1Mask },
+ { XK_Control_L, Mod1Mask },
+ { XK_Alt_R, ControlMask },
+ { XK_Alt_L, ControlMask } }, { 1, -1, 1, -1 }
+ },
+ {
+ "alt_shift_toggle", 4,
+ { { XK_Shift_R, Mod1Mask },
+ { XK_Shift_L, Mod1Mask },
+ { XK_Alt_R, ShiftMask },
+ { XK_Alt_L, ShiftMask } }, { 1, -1, 1, -1 }
+ },
+ {
+ "menu_toggle", 1,
+ { { XK_Menu, 0 } }, { 1 }
+ },
+ {
+ "lwin_toggle", 1,
+ { { XK_Super_L, 0 } }, { 1 }
+ },
+ {
+ "rwin_toggle", 1,
+ { { XK_Super_R, 0 } }, { 1 }
+ },
+ {
+ "lshift_toggle", 1,
+ { { XK_Shift_L, 0 } }, { 1 }
+ },
+ {
+ "rshift_toggle", 1,
+ { { XK_Shift_R, 0 } }, { 1 }
+ },
+ {
+ "lctrl_toggle", 1,
+ { { XK_Control_L, 0 } }, { 1 }
+ },
+ {
+ "rctrl_toggle", 1,
+ { { XK_Control_R, 0 } }, { 1 }
+ },
+ {
+ NULL, 1,
+ { { 0, 0 } }, { 1 }
+ }
+};
diff --git a/tests/test_config.c b/tests/test_config.c
index ad2c4f0..cf01482 100644
--- a/tests/test_config.c
+++ b/tests/test_config.c
@@ -1,12 +1,22 @@
#include <config.h>
#include <stdio.h>
#include <unistd.h>
+#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <libxklavier/xklavier.h>
#include <libxklavier/xklavier_config.h>
+#ifdef __STRICT_ANSI__
+/* these are functions which are NOT in ANSI C.
+ Probably we should provide the implementation */
+extern char *strdup( const char *s );
+#endif
+
+extern void XklConfigDump( FILE* file,
+ XklConfigRecPtr data );
+
enum { ACTION_NONE, ACTION_GET, ACTION_SET, ACTION_WRITE };
static void printUsage()
@@ -21,28 +31,6 @@ static void printUsage()
printf( " -h - Show this help\n" );
}
-static void dump( XklConfigRecPtr ptr )
-{
- int i,j;
- char**p;
- XklDebug( 0, " model: [%s]\n", ptr->model );
-
- XklDebug( 0, " layouts(%d):\n", ptr->numLayouts );
- p = ptr->layouts;
- for( i = ptr->numLayouts, j = 0; --i >= 0; )
- XklDebug( 0, " %d: [%s]\n", j++, *p++ );
-
- XklDebug( 0, " variants(%d):\n", ptr->numVariants );
- p = ptr->variants;
- for( i = ptr->numVariants, j = 0; --i >= 0; )
- XklDebug( 0, " %d: [%s]\n", j++, *p++ );
-
- XklDebug( 0, " options(%d):\n", ptr->numOptions );
- p = ptr->options;
- for( i = ptr->numOptions, j = 0; --i >= 0; )
- XklDebug( 0, " %d: [%s]\n", j++, *p++ );
-}
-
int main( int argc, char * const argv[] )
{
int c, i;
@@ -50,7 +38,7 @@ int main( int argc, char * const argv[] )
const char* model = NULL;
const char* layouts = NULL;
const char* options = NULL;
- int debugLevel = 0;
+ int debugLevel = -1;
int binary = 0;
Display *dpy;
@@ -109,13 +97,14 @@ int main( int argc, char * const argv[] )
if ( !XklInit( dpy ) )
{
XklConfigRec currentConfig, r2;
- XklSetDebugLevel( debugLevel );
+ if( debugLevel != -1 )
+ XklSetDebugLevel( debugLevel );
XklDebug( 0, "Xklavier initialized\n" );
XklConfigInit();
XklConfigLoadRegistry();
XklDebug( 0, "Xklavier registry loaded\n" );
- XklDebug( 0, "Multiple layouts are %ssupported\n",
- XklMultipleLayoutsSupported() ? "" : "not " );
+ XklDebug( 0, "Bakend: [%s]\n", XklGetBackendName() );
+ XklDebug( 0, "Supported features: 0x0%X\n", XklGetBackendFeatures() );
XklConfigRecInit( &currentConfig );
XklConfigGetFromServer( &currentConfig );
@@ -124,14 +113,14 @@ int main( int argc, char * const argv[] )
{
case ACTION_GET:
XklDebug( 0, "Got config from the server\n" );
- dump( &currentConfig );
+ XklConfigDump( stdout, &currentConfig );
XklConfigRecInit( &r2 );
if ( XklConfigGetFromBackup( &r2 ) )
{
XklDebug( 0, "Got config from the backup\n" );
- dump( &r2 );
+ XklConfigDump( stdout, &r2 );
}
if ( XklConfigActivate( &r2 ) )
@@ -191,7 +180,7 @@ int main( int argc, char * const argv[] )
}
XklDebug( 0, "New config:\n" );
- dump( &currentConfig );
+ XklConfigDump( stdout, &currentConfig );
if ( XklConfigActivate( &currentConfig ) )
XklDebug( 0, "Set the config\n" );
else
@@ -215,7 +204,7 @@ int main( int argc, char * const argv[] )
XklTerm();
} else
{
- fprintf( stderr, "Could not init Xklavier\n" );
+ fprintf( stderr, "Could not init Xklavier: %s\n", XklGetLastError() );
exit(2);
}
printf( "closing display: %p\n", dpy );
diff --git a/tests/test_monitor.c b/tests/test_monitor.c
index 8808b62..515c328 100644
--- a/tests/test_monitor.c
+++ b/tests/test_monitor.c
@@ -1,52 +1,41 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <getopt.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/XKBlib.h>
#include <libxklavier/xklavier.h>
#include <libxklavier/xklavier_config.h>
+extern void XklConfigDump( FILE* file,
+ XklConfigRecPtr data );
+
static void printUsage()
{
- printf( "Usage: test_monitor (-h)|(-d <debugLevel>)\n" );
+ printf( "Usage: test_monitor (-l1)(-l2)(-l3)(-h)(-d <debugLevel>)\n" );
printf( "Options:\n" );
printf( " -d - Set the debug level (by default, 0)\n" );
printf( " -h - Show this help\n" );
-}
-
-void dump( XklConfigRecPtr ptr )
-{
- int i,j;
- char**p;
- XklDebug( 0, " model: [%s]\n", ptr->model );
-
- XklDebug( 0, " layouts(%d):\n", ptr->numLayouts );
- p = ptr->layouts;
- for( i = ptr->numLayouts, j = 0; --i >= 0; )
- XklDebug( 0, " %d: [%s]\n", j++, *p++ );
-
- XklDebug( 0, " variants(%d):\n", ptr->numVariants );
- p = ptr->variants;
- for( i = ptr->numVariants, j = 0; --i >= 0; )
- XklDebug( 0, " %d: [%s]\n", j++, *p++ );
-
- XklDebug( 0, " options(%d):\n", ptr->numOptions );
- p = ptr->options;
- for( i = ptr->numOptions, j = 0; --i >= 0; )
- XklDebug( 0, " %d: [%s]\n", j++, *p++ );
+ printf( " -l1 - listen to manage layouts\n" );
+ printf( " -l2 - listen to manage window states\n" );
+ printf( " -l3 - listen to track the keyboard state\n" );
}
int main( int argc, char * argv[] )
{
int c;
- int debugLevel = 0;
+ int debugLevel = -1;
XkbEvent ev;
Display* dpy;
+ int listenerType = 0, lt;
+ int listenerTypes[] = { XKLL_MANAGE_LAYOUTS,
+ XKLL_MANAGE_WINDOW_STATES,
+ XKLL_TRACK_KEYBOARD_STATE };
while (1)
{
- c = getopt( argc, argv, "hd:" );
+ c = getopt( argc, argv, "hd:l:" );
if ( c == -1 )
break;
switch (c)
@@ -57,6 +46,11 @@ int main( int argc, char * argv[] )
case 'd':
debugLevel = atoi( optarg );
break;
+ case 'l':
+ lt = optarg[0] - '1';
+ if( lt >= 0 && lt < sizeof(listenerTypes)/sizeof(listenerTypes[0]) )
+ listenerType |= listenerTypes[lt];
+ break;
default:
fprintf( stderr, "?? getopt returned character code 0%o ??\n", c );
printUsage();
@@ -71,10 +65,11 @@ int main( int argc, char * argv[] )
exit(1);
}
printf( "opened display: %p\n", dpy );
- if ( !XklInit( dpy ) )
+ if( !XklInit( dpy ) )
{
XklConfigRec currentConfig;
- XklSetDebugLevel( debugLevel );
+ if( debugLevel != -1 )
+ XklSetDebugLevel( debugLevel );
XklDebug( 0, "Xklavier initialized\n" );
XklConfigInit();
XklConfigLoadRegistry();
@@ -83,7 +78,8 @@ int main( int argc, char * argv[] )
XklConfigRecInit( &currentConfig );
XklConfigGetFromServer( &currentConfig );
- XklStartListen();
+ XklDebug( 0, "Now, listening...\n" );
+ XklStartListen( listenerType );
while (1)
{
@@ -103,7 +99,7 @@ int main( int argc, char * argv[] )
XklTerm();
} else
{
- fprintf( stderr, "Could not init Xklavier\n" );
+ fprintf( stderr, "Could not init Xklavier: %s\n", XklGetLastError() );
exit(2);
}
printf( "closing display: %p\n", dpy );