diff options
-rw-r--r-- | AUTHORS | 0 | ||||
-rw-r--r-- | ChangeLog | 0 | ||||
-rw-r--r-- | Makefile.am | 9 | ||||
-rw-r--r-- | NEWS | 0 | ||||
-rw-r--r-- | README | 0 | ||||
-rwxr-xr-x | autogen.sh | 3 | ||||
-rw-r--r-- | configure.ac | 130 | ||||
-rw-r--r-- | doc/Doxyfile.in | 183 | ||||
-rw-r--r-- | doc/Makefile.am | 14 | ||||
-rw-r--r-- | fakekey/Makefile.am | 5 | ||||
-rw-r--r-- | fakekey/fakekey.h | 131 | ||||
-rw-r--r-- | libfakekey.pc.in | 10 | ||||
-rw-r--r-- | src/Makefile.am | 10 | ||||
-rw-r--r-- | src/libfakekey.c | 409 | ||||
-rw-r--r-- | tests/Makefile.am | 5 | ||||
-rw-r--r-- | tests/fakekey-test.c | 38 |
16 files changed, 947 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/ChangeLog diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..44de5fe --- /dev/null +++ b/Makefile.am @@ -0,0 +1,9 @@ +SUBDIRS=fakekey src tests doc + +EXTRA_DIST = fakekey.pc.in + +pkgconfigdir=$(libdir)/pkgconfig +pkgconfig_DATA = libfakekey.pc + + + diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..b1376df --- /dev/null +++ b/autogen.sh @@ -0,0 +1,3 @@ +#! /bin/sh +autoreconf -v --install || exit 1 +./configure --enable-maintainer-mode "$@" diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..b07a732 --- /dev/null +++ b/configure.ac @@ -0,0 +1,130 @@ +>AC_PREREQ(2.53) +AC_INIT([libfakekey], 0.1, [mallum@openedhand.com]) +AC_CONFIG_SRCDIR([src/libfakekey.c]) + +AM_INIT_AUTOMAKE() +AM_CONFIG_HEADER([config.h]) +AC_CONFIG_AUX_DIR(.) + +# Checks for programs. +AC_PROG_CC +AC_PROG_LIBTOOL +AC_HEADER_STDC + +dnl ------ libtool versioning ----------------------------------------------- + +LT_CURRENT=0 +LT_REVISION=1 +AC_SUBST(LT_CURRENT) +AC_SUBST(LT_REVISION) +LT_AGE=0 + +LT_VERSION_INFO="$LT_CURRENT:$LT_REVISION:$LT_AGE" +AC_SUBST(LT_VERSION_INFO) + +LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE` +AC_SUBST(LT_CURRENT_MINUS_AGE) + +dnl ------ Check for X Stuff ------------------------------------------------ + +PKG_CHECK_MODULES(X11, x11, [have_libx11pc="yes"], [have_libx11pc="no"]) + +if test $have_libx11pc = yes; then + PKG_CHECK_MODULES(XLIBS, x11 xtst) + + FAKEKEY_LIBS="$XLIBS_LIBS" + FAKEKEY_CFLAGS="$XLIBS_CFLAGS" + +else + +AC_PATH_XTRA + +ALL_X_LIBS="$X_LIBS -lX11" + +AC_CHECK_LIB(Xtst, XTestQueryExtension, XTEST_LIBS=-lXtst have_xtest="yes" , have_xtest="no", $ALL_X_LIBS) + +if test "x$have_xtest" = "xno"; then + AC_MSG_ERROR([Cannot find XTest extension library]) + exit 1 +fi + +FAKEKEY_CFLAGS="$XLIBS_CLAGS" +FAKEKEY_LIBS="$ALL_X_LIBS $XTEST_LIBS" + +fi + +dnl ------ Debug ----------------------------------------------------------- + +AC_ARG_ENABLE(debug, + [ --enable-debug enable debug ( verbose ) build], + enable_debug=$enableval, enable_debug=no ) + +if test x$enable_debug != xno; then + FAKEKEY_CFLAGS="$FAKEKEY_CFLAGS -DDEBUG" +fi + +dnl ------ Doxygen docs ---------------------------------------------------- + +AC_ARG_ENABLE(doxygen-docs, + [ --enable-doxygen-docs build DOXYGEN API documentation (requires Doxygen)], + enable_doxygen_docs=$enableval,enable_doxygen_docs=no) + +if test x$enable_doxygen_docs = xyes ; then + + AC_PATH_PROG(DOXYGEN, doxygen, no) + + AC_MSG_CHECKING([whether to build Doxygen documentation]) + + if test x$DOXYGEN = xno ; then + have_doxygen=no + else + have_doxygen=yes + fi + + if test x$have_doxygen = xno; then + AC_MSG_ERROR([Building Doxygen docs explicitly required, but Doxygen not found]) + fi + + AC_MSG_RESULT(yes) + +fi + +AM_CONDITIONAL(HAVE_DOXYGEN, test x$enable_doxygen_docs = xyes) + + +dnl ------ GCC flags -------------------------------------------------------- + +if test "x$GCC" = "xyes"; then + GCC_WARNINGS="-g -Wall -fno-strict-aliasing" + FAKEKEY_CFLAGS="$GCC_WARNINGS $FAKEKEY_CFLAGS" +fi + +dnl ------------------------------------------------------------------------- + +AC_SUBST(FAKEKEY_CFLAGS) +AC_SUBST(FAKEKEY_LIBS) + + +AC_OUTPUT([ +Makefile +libfakekey.pc +fakekey/Makefile +src/Makefile +doc/Doxyfile +doc/Makefile +tests/Makefile + +]) + +dnl ========================================================================== +echo " + LibFakeKey $VERSION + ====================== + + prefix: ${prefix} + source code location: ${srcdir} + + Building with Debug: ${enable_debug} + Building with API Documentation: ${enable_doxygen_docs} + +" diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in new file mode 100644 index 0000000..3b0adec --- /dev/null +++ b/doc/Doxyfile.in @@ -0,0 +1,183 @@ +# Doxyfile 0.1 + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = libfakekey +PROJECT_NUMBER = @VERSION@ +OUTPUT_DIRECTORY = @top_srcdir@/doc +OUTPUT_LANGUAGE = English +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +INTERNAL_DOCS = NO +STRIP_CODE_COMMENTS = YES +CASE_SENSE_NAMES = YES +SHORT_NAMES = NO +HIDE_SCOPE_NAMES = NO +VERBATIM_HEADERS = YES +SHOW_INCLUDE_FILES = YES +JAVADOC_AUTOBRIEF = YES +INHERIT_DOCS = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 8 +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +ALIASES = +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +OPTIMIZE_OUTPUT_FOR_C = YES +SHOW_USED_FILES = YES +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_FORMAT = +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = @top_srcdir@/fakekey +FILE_PATTERNS = *.h +RECURSIVE = YES +#EXCLUDE = test + +# 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. + +EXCLUDE_PATTERNS = Makefile.* ChangeLog CHANGES CHANGES.* README \ + README.* *.png AUTHORS DESIGN DESIGN.* *.desktop \ + DESKTOP* COMMENTS HOWTO magic NOTES TODO THANKS + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = YES +MAN_OUTPUT = man +MAN_EXTENSION = .mb +MAN_LINKS = YES +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +PERL_PATH = +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +TEMPLATE_RELATIONS = YES +HIDE_UNDOC_RELATIONS = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +GRAPHICAL_HIERARCHY = YES +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 640 +MAX_DOT_GRAPH_HEIGHT = 1024 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO +CGI_NAME = +CGI_URL = +DOC_URL = +DOC_ABSPATH = +BIN_ABSPATH = +EXT_DOC_PATHS = diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..8b643e4 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,14 @@ +EXTRA_DIST = Doxyfile.in + +all: stamp-doxygen + +stamp-doxygen: +if HAVE_DOXYGEN + doxygen Doxyfile + touch stamp-doxygen +endif + +clean: clean-local +clean-local: + -rm -Rf html + -rm -f stamp-doxygen
\ No newline at end of file diff --git a/fakekey/Makefile.am b/fakekey/Makefile.am new file mode 100644 index 0000000..e1a772a --- /dev/null +++ b/fakekey/Makefile.am @@ -0,0 +1,5 @@ +fakekeyincludedir=$(includedir)/fakekey + +fakekey_headers=fakekey.h + +fakekeyinclude_HEADERS = $(fakekey_headers) diff --git a/fakekey/fakekey.h b/fakekey/fakekey.h new file mode 100644 index 0000000..da83223 --- /dev/null +++ b/fakekey/fakekey.h @@ -0,0 +1,131 @@ +#ifndef _HAVE_LIBFAKEKEY_H +#define _HAVE_LIBFAKEKEY_H + +#include <stdio.h> +#include <stdlib.h> +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/Xlibint.h> +#include <X11/Xutil.h> +#include <X11/cursorfont.h> +#include <X11/keysymdef.h> +#include <X11/keysym.h> +#include <X11/extensions/XTest.h> +#include <X11/Xos.h> +#include <X11/Xproto.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup FakeKey FakeKey - + * @brief yada yada yada + * + * + * Always remember to release held keys + * @{ + */ + + +/** + * @typedef FakeKey + * + * Opaque structure used for all operations. + */ +typedef struct FakeKey FakeKey; + +/** + * @typedef FakeKeyModifier + * + * enumerated types for #mb_pixbuf_img_transform + */ +typedef enum +{ + FAKEKEYMOD_SHIFT = (1<<1), + FAKEKEYMOD_CONTROL = (1<<2), + FAKEKEYMOD_ALT = (1<<3), + FAKEKEYMOD_META = (1<<4) + +} FakeKeyModifier; + +/** + * Initiates FakeKey. + * + * @param xdpy X Display connection. + * + * @return new #FakeKey reference on success, NULL on fail. + */ +FakeKey* +fakekey_init(Display *xdpy); + + +/** + * Sends a Keypress to the server for the supplied UTF8 character. + * + * @param fk #FakeKey refernce from #fakekey_init + * @param utf8_char_in Pointer to a single UTF8 Character data. + * @param len_bytes Lenth in bytes of character, or -1 in ends with 0 + * @param modifiers OR'd list of #FakeKeyModifier modifiers keys + * to press with the key. + * + * + * @return + */ +int +fakekey_press(FakeKey *fk, + unsigned char *utf8_char_in, + int len_bytes, + int modifiers); + +/** + * Repreats a press of the currently held key ( from #fakekey_press ) + * + * @param fk #FakeKey refernce from #fakekey_init + */ +void +fakekey_repeat(FakeKey *fk); + + +/** + * Releases the currently held key ( from #fakekey_press ) + * + * @param fk #FakeKey refernce from #fakekey_init + */ +void +fakekey_release(FakeKey *fk); + +/** + * Resyncs the internal list of keysyms with the server. + * Should be called if a MappingNotify event is recieved. + * + * @param fk #FakeKey refernce from #fakekey_init + * + * @return + */ +int +fakekey_reload_keysyms(FakeKey *fk); + +/** + * + * + * @param fk #FakeKey refernce from #fakekey_init + * @param keycode X Keycode to send + * @param is_press Is this a press ( or release ) + * @param modifiers + * + * @return + */ +int +fakekey_send_keyevent(FakeKey *fk, + KeyCode keycode, + Bool is_press, + int modifiers); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* _HAVE_LIBFAKEKEY_H */ diff --git a/libfakekey.pc.in b/libfakekey.pc.in new file mode 100644 index 0000000..ae778d1 --- /dev/null +++ b/libfakekey.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libfakekey +Description: X Virtual Keyboard Library +Version: @VERSION@ +Libs: -L${libdir} @FAKEKEY_LIBS@ +Cflags: -I${includedir} diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..443befa --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,10 @@ +source_c = libfakekey.c + +AM_CFLAGS = @FAKEKEY_CFLAGS@ + +libfakekey_la_SOURCES = $(source_c) + +lib_LTLIBRARIES = libfakekey.la + +libfakekey_la_LDFLAGS = -version-info @LT_VERSION_INFO@ +libfakekey_la_LIBADD = $(FAKEKEY_LIBS) diff --git a/src/libfakekey.c b/src/libfakekey.c new file mode 100644 index 0000000..307b4fb --- /dev/null +++ b/src/libfakekey.c @@ -0,0 +1,409 @@ +/* + * libFakeKey + * + * A simple library for converting utf8 chars into 'fake' keypresses. + * + * Uses ideas from Fontconfig, libvirtkeys.c, keysym2ucs.c and dasher. + * + * Authored By Matthew Allum <amllum@openedhand.com> + * + * Copyright (C) 2004 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include <fakekey/fakekey.h> + +#if (DEBUG) +#define FK_DBG(x, a...) \ + fprintf(stderr, __FILE__ ":%d,%s() " x "\n", __LINE__, __func__, ##a) +#else +#define FK_DBG(x, a...) do {} while (0) +#endif + +#define N_MODIFIER_INDEXES (Mod5MapIndex + 1) + +typedef unsigned int FkChar32; + +struct FakeKey +{ + Display *xdpy; + int min_keycode, max_keycode; + int n_keysyms_per_keycode; + KeySym *keysyms; + int held_keycode; + int held_state_flags; + KeyCode modifier_table[N_MODIFIER_INDEXES]; + int shift_mod_index, alt_mod_index, meta_mod_index; +}; + + +/* utf8_to_ucs4() Borrowed from fontconfig + * + * Converts the next Unicode char from src into dst and returns the + * number of bytes containing the char. src nust be at least len bytes + * long. + */ +static int +utf8_to_ucs4 (const unsigned char *src_orig, + FkChar32 *dst, + int len) +{ + const unsigned char *src = src_orig; + unsigned char s; + int extra; + FkChar32 result; + + if (len == 0) + return 0; + + s = *src++; + len--; + + if (!(s & 0x80)) + { + result = s; + extra = 0; + } + else if (!(s & 0x40)) + { + return -1; + } + else if (!(s & 0x20)) + { + result = s & 0x1f; + extra = 1; + } + else if (!(s & 0x10)) + { + result = s & 0xf; + extra = 2; + } + else if (!(s & 0x08)) + { + result = s & 0x07; + extra = 3; + } + else if (!(s & 0x04)) + { + result = s & 0x03; + extra = 4; + } + else if ( ! (s & 0x02)) + { + result = s & 0x01; + extra = 5; + } + else + { + return -1; + } + if (extra > len) + return -1; + + while (extra--) + { + result <<= 6; + s = *src++; + + if ((s & 0xc0) != 0x80) + return -1; + + result |= s & 0x3f; + } + *dst = result; + return src - src_orig; +} + +FakeKey* +fakekey_init(Display *xdpy) +{ + FakeKey *fk = NULL; + int event, error, major, minor; + XModifierKeymap *modifiers; + int mod_index; + int mod_key; + KeyCode *kp; + + if (xdpy == NULL) return NULL; + + if (!XTestQueryExtension(xdpy, &event, &error, &major, &minor)) + { + return NULL; + } + + fk = malloc(sizeof(FakeKey)); + memset(fk,0,sizeof(FakeKey)); + + fk->xdpy = xdpy; + + /* Find keycode limits */ + + XDisplayKeycodes(fk->xdpy, &fk->min_keycode, &fk->max_keycode); + + /* Get the mapping */ + + /* TODO: Below needs to be kept in sync with anything else + * that may change the keyboard mapping. + * + * case MappingNotify: + * XRefreshKeyboardMapping(&ev.xmapping); + * + */ + + fk->keysyms = XGetKeyboardMapping(fk->xdpy, + fk->min_keycode, + fk->max_keycode - fk->min_keycode + 1, + &fk->n_keysyms_per_keycode); + + + modifiers = XGetModifierMapping(fk->xdpy); + + kp = modifiers->modifiermap; + + for (mod_index = 0; mod_index < 8; mod_index++) + { + fk->modifier_table[mod_index] = 0; + + for (mod_key = 0; mod_key < modifiers->max_keypermod; mod_key++) + { + int keycode = kp[mod_index * modifiers->max_keypermod + mod_key]; + + if (keycode != 0) + { + fk->modifier_table[mod_index] = keycode; + break; + } + } + } + + for (mod_index = Mod1MapIndex; mod_index <= Mod5MapIndex; mod_index++) + { + if (fk->modifier_table[mod_index]) + { + KeySym ks = XKeycodeToKeysym(fk->xdpy, + fk->modifier_table[mod_index], 0); + + /* + * Note: ControlMapIndex is already defined by xlib + * ShiftMapIndex + */ + + printf("checking ks\n"); + + switch (ks) + { + case XK_Meta_R: + case XK_Meta_L: + fk->meta_mod_index = mod_index; + break; + + case XK_Alt_R: + case XK_Alt_L: + fk->alt_mod_index = mod_index; + break; + + case XK_Shift_R: + case XK_Shift_L: + printf("got shift\n"); + fk->shift_mod_index = mod_index; + break; + } + } + } + + if (modifiers) + XFreeModifiermap(modifiers); + + printf("index is %i %i\n", + fk->meta_mod_index, fk->modifier_table[ShiftMapIndex]); + + return fk; +} + +int +fakekey_reload_keysyms(FakeKey *fk) +{ + if (fk->keysyms) + XFree(fk->keysyms); + + fk->keysyms = XGetKeyboardMapping(fk->xdpy, + fk->min_keycode, + fk->max_keycode - fk->min_keycode + 1, + &fk->n_keysyms_per_keycode); + return 1; +} + +int +fakekey_send_keyevent(FakeKey *fk, + KeyCode keycode, + Bool is_press, + int flags) +{ + if (flags) + { + if (flags & FAKEKEYMOD_SHIFT) + XTestFakeKeyEvent(fk->xdpy, fk->modifier_table[ShiftMapIndex], + is_press, CurrentTime); + + if (flags & FAKEKEYMOD_CONTROL) + XTestFakeKeyEvent(fk->xdpy, fk->modifier_table[ControlMapIndex], + is_press, CurrentTime); + + if (flags & FAKEKEYMOD_ALT) + XTestFakeKeyEvent(fk->xdpy, fk->modifier_table[fk->alt_mod_index], + is_press, CurrentTime); + + XSync(fk->xdpy, True); + } + + XTestFakeKeyEvent(fk->xdpy, keycode, is_press, CurrentTime); + + XSync(fk->xdpy, True); +} + +int +fakekey_press(FakeKey *fk, + unsigned char *utf8_char_in, + int len_bytes, + int flags) +{ + static int modifiedkey; + FkChar32 ucs4_out; + KeyCode code = 0; + + if (fk->held_keycode) /* key is already held down */ + return 0; + + /* TODO: check for Return key here and other chars */ + + if (len_bytes < 0) + { + unsigned char *p = utf8_char_in; + while (*p != '\0') len_bytes++; + } + + if (utf8_to_ucs4 (utf8_char_in, &ucs4_out, len_bytes) < 1) + { + printf("failed\n"); + return 0; + } + + /* first check for Latin-1 characters (1:1 mapping) + if ((keysym >= 0x0020 && keysym <= 0x007e) || + (keysym >= 0x00a0 && keysym <= 0x00ff)) + return keysym; + */ + + if (ucs4_out > 0x00ff) /* < 0xff assume Latin-1 1:1 mapping */ + ucs4_out = ucs4_out | 0x01000000; /* This gives us the magic X keysym */ + + if ((code = XKeysymToKeycode(fk->xdpy, ucs4_out)) != 0) + { + printf("using fast code\n"); + + /* we already have a keycode for this keysym */ + /* Does it need a shift key though ? */ + if (XKeycodeToKeysym(fk->xdpy, code, 0) != ucs4_out) + { + printf("does not equal code\n"); + /* TODO: Assumes 1st modifier is shifted ? */ + if (XKeycodeToKeysym(fk->xdpy, code, 1) == ucs4_out) + flags |= FAKEKEYMOD_SHIFT; /* can get at it via shift */ + else + code = 0; /* urg, some other modifier do it the heavy way */ + } + } + + if (!code) + { + int index; + + printf("using slow remapping code\n"); + + /* Change one of the last 10 keysyms to our converted utf8, + * remapping the x keyboard on the fly. + * + * This make assumption the last 10 arn't already used. + * TODO: probably safer to check for this. + */ + + modifiedkey = (modifiedkey+1) % 10; + + /* Point at the end of keysyms, modifier 0 */ + + index = (fk->max_keycode - fk->min_keycode - modifiedkey - 1) * fk->n_keysyms_per_keycode; + + fk->keysyms[index] = ucs4_out; + + XChangeKeyboardMapping(fk->xdpy, + fk->min_keycode, + fk->n_keysyms_per_keycode, + fk->keysyms, + (fk->max_keycode-fk->min_keycode)); + + XSync(fk->xdpy, True); + + /* From dasher src; + * There's no way whatsoever that this could ever possibly + * be guaranteed to work (ever), but it does. + * + * code = fk->max_keycode - modifiedkey - 1; + * + * below instead is probably safer. + */ + + code = XKeysymToKeycode(fk->xdpy, ucs4_out); + } + + if (code != 0) + { + fakekey_send_keyevent(fk, code, True, flags); + + fk->held_state_flags = flags; + fk->held_keycode = code; + + return 1; + } + + fk->held_state_flags = 0; + fk->held_keycode = 0; + + return 0; +} + +void +fakekey_repeat(FakeKey *fk) +{ + if (!fk->held_keycode) + return; + + fakekey_send_keyevent(fk, fk->held_keycode, True, fk->held_state_flags); +} + +void +fakekey_release(FakeKey *fk) +{ + if (!fk->held_keycode) + return; + + fakekey_send_keyevent(fk, fk->held_keycode, False, fk->held_state_flags); + + fk->held_state_flags = 0; + fk->held_keycode = 0; +} + diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..67ed38b --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,5 @@ +INCLUDES=-I${top_srcdir}/src -I${top_srcdir} $(FAKEKEY_CFLAGS) + +noinst_PROGRAMS=fakekey-test + +fakekey_test_LDADD=../src/libfakekey.la
\ No newline at end of file diff --git a/tests/fakekey-test.c b/tests/fakekey-test.c new file mode 100644 index 0000000..9d807b6 --- /dev/null +++ b/tests/fakekey-test.c @@ -0,0 +1,38 @@ +#include "fakekey/fakekey.h" + +int +main(int argc, char **argv) +{ + Display *dpy; + FakeKey *fk; + int i; + unsigned char str[] = "hello HELLO worldly world", *p = NULL; + unsigned char str2[] = "\303\270"; + + if ((dpy = XOpenDisplay(NULL)) == NULL) + { + fprintf(stderr,"Failed to open display\n"); + exit(1); + } + + fk = fakekey_init(dpy); + + p = str; + + /* + for (i=0; i<10; i++) + { + fakekey_press(fk, str2, 2, 0); + fakekey_release(fk); + } + */ + + while (*p != '\0') + { + fakekey_press(fk, p, 1, 0); + fakekey_release(fk); + p++; + } + + +} |