pax_global_header00006660000000000000000000000064130553312370014514gustar00rootroot0000000000000052 comment=04ae06724d914c7d4fec6a2723edf9c6320ec502 keybinder-keybinder-3.0-v0.3.2/000077500000000000000000000000001305533123700161305ustar00rootroot00000000000000keybinder-keybinder-3.0-v0.3.2/.gitignore000066400000000000000000000005351305533123700201230ustar00rootroot00000000000000/ChangeLog /INSTALL /Makefile /Makefile.in /aclocal.m4 /autom4te.cache/ /config.guess /config.log /config.status /config.sub /configure /depcomp /install-sh /libkeybinder/Makefile /libkeybinder/Makefile.in /libkeybinder/*.pc /libtool /ltmain.sh /lua-keybinder/Makefile /lua-keybinder/Makefile.in /m4/*.m4 /missing /*.tar.gz .deps/ .libs/ *.la *.lo keybinder-keybinder-3.0-v0.3.2/AUTHORS000066400000000000000000000002521305533123700171770ustar00rootroot00000000000000Alex Graveley Nigel Tao Raphaël Slinckx Sebastian Pölsterl Ulrik Sverdrup keybinder-keybinder-3.0-v0.3.2/COPYING000066400000000000000000000022411305533123700171620ustar00rootroot00000000000000/* * Copyright (C) 2008 Alex Graveley * Copyright (C) 2010 Ulrik Sverdrup * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ keybinder-keybinder-3.0-v0.3.2/ChangeLog.pre-git000066400000000000000000000161201305533123700212500ustar00rootroot000000000000002009-04-13 Sebastian Pölsterl * deskbar/handlers/evolution/Makefile.am * deskbar/handlers/gdmclient/Makefile.am * deskbar/osutils/Makefile.am * deskbar/core/_userdirs/Makefile.am * deskbar/core/keybinder/Makefile.am * deskbar/ui/iconentry/Makefile.am: Fixed bug #578803: deskbar-applet incorrectly installs to pythondir rather than pyexecdir 2009-01-15 Sebastian Pölsterl * deskbar/core/keybinder/eggaccelerators.c: Fixed bug #567422: Add missing include to eggaccelerators.c (patch by Magnus Boman) 2009-01-05 Sebastian Pölsterl * configure.ac: Post release version bump to 2.25.5 2008-11-04 Sebastian Pölsterl * deskbar/core/keybinder/eggaccelerators.h * deskbar/core/keybinder/tomboykeybinder.c * deskbar/core/keybinder/eggaccelerators.c * deskbar/core/keybinder/tomboykeybinder.h * deskbar/ui/iconentry/ephy-icon-entry.h * deskbar/ui/iconentry/ephy-icon-entry.c: Cleanup GTK+ includes 2007-10-27 Sebastian Pölsterl * deskbar/core/keybinder/_keybinder.override: * deskbar/core/Keybinder.py: Fixed: Doesn't unbind keybinding when it changes. Python binding of tomboy_keybinder_bind returns boolean value now 2006-11-21 Rodrigo Moya * deskbar/keybinder/tomboykeybinder.c: added missing header files to pass code check tests. 2006-01-21 Raphael Slinckx * deskbar/DeskbarApplet.py: * deskbar/Keybinder.py: Repair the keybinder 2006-01-21 Raphael Slinckx * TODO: * configure.ac: * deskbar/BrowserMatch.py: * deskbar/DeskbarApplet.py: * deskbar/DeskbarAppletPreferences.py: * deskbar/DeskbarHistory.py: * deskbar/Handler.py: * deskbar/Indexer.py: * deskbar/Keybinder.py: * deskbar/Makefile.am: * deskbar/Match.py: * deskbar/ModuleContext.py: * deskbar/ModuleList.py: * deskbar/ModuleLoader.py: * deskbar/Utils.py: * deskbar/Watcher.py: * deskbar/__init__.py: * deskbar/about.py: * deskbar/applet.py: * deskbar/applet_keybinder.py: * deskbar/defs.py: * deskbar/deskbar-applet.py: * deskbar/deskbarentry.py: * deskbar/filewatcher.py: * deskbar/handler.py: * deskbar/handler_utils.py: * deskbar/handlers/beagle-live.py: * deskbar/handlers/beagle.py: * deskbar/handlers/debug-async_handler.py: * deskbar/handlers/debug-requirements.py: * deskbar/handlers/debug-signal_handler.py: * deskbar/handlers/email_address.py: * deskbar/handlers/epiphany.py: * deskbar/handlers/evolution.py: * deskbar/handlers/files.py: * deskbar/handlers/galago.py: * deskbar/handlers/galeon.py: * deskbar/handlers/google-live.py: * deskbar/handlers/gtkbookmarks.py: * deskbar/handlers/mozilla.py: * deskbar/handlers/pathprograms.py: * deskbar/handlers/programs.py: * deskbar/handlers/volumes.py: * deskbar/handlers/web_address.py: * deskbar/handlers_browsers.py: * deskbar/history.py: * deskbar/indexer.py: * deskbar/locale_utils.py: * deskbar/module_list.py: * deskbar/preferences.py: * deskbar/ui/.cvsignore: * deskbar/ui/About.py: * deskbar/ui/DeskbarEntry.py: * deskbar/ui/DeskbarPreferencesUI.py: * deskbar/ui/Makefile.am: * deskbar/ui/ModuleListView.py: Big refactoring for inclusion of the cuemiac branch 2005-11-25 Nigel Tao * data/prefs-dialog.glade: * deskbar/applet.py: * deskbar/applet_keybinder.py: * deskbar/module_list.py: * deskbar/preferences.py: Tidied up the preferences dialog. Added keybinding UI. Rephrased some things to be consistent with the Epiphany web browser. For example, "Handlers" became "Extensions". Fixed warning when no extension is selected. "Enabled" checkbox now comes before the extension icon. Removed the word "Applet". 2005-10-18 Raphael Slinckx * deskbar/keybinder/_keybinder.override: Remove a bit of the GIL sprinkling, still seems to work. 2005-10-18 Raphael Slinckx * deskbar/deskbar-applet: * deskbar/keybinder/_keybinder.override: Mess around with The Big Sucking Python Lock, hopefully fixes all the problems in the world, universe, and everything 2005-10-11 Raphael Slinckx * AUTHORS: * deskbar/about.py: Add Mikkel * deskbar/applet_keybinder.py: * deskbar/deskbarentry.py: * deskbar/handler.py: * deskbar/handlers/galago.py: * deskbar/handlers/mozilla.py: * deskbar/handlers/programs.py: * deskbar/indexer.py: * deskbar/locale_utils.py: Fix problems found with pylint, add icon_size instead of -1 for more py-2.3 fixes, and fix an error in locale detection. 2005-10-07 Raphael Slinckx * deskbar/__init__.py: Revert to 16 pixels icon size, some problems with non-even values seems to appear * deskbar/applet.py: Fixes the Gnome-WARNING due to gnome.ui being loaded after gnomeapplet * deskbar/applet_keybinder.py: Use a default global keybinding for uninstalled setup * deskbar/deskbarentry.py: Force the image widget to be the icon size, to avoid flickering of entry length * deskbar/handlers/Makefile.am: Add networkplaces.py handler * deskbar/indexer.py: bug #318241, partial word matches not cleared 2005-10-07 Nigel Tao * deskbar/applet_keybinder.py: * deskbar/keybinder/_keybinder.override: unbind(keystring) now only takes 1 argument. (Python) exceptions in the callback will now be printed to stderr. Binding collisions now throw exceptions. Removing non-existant bindings also throw exceptions. Plugged some memory leaks. I reverted (removed) the "g_free(keystring)" calls added in Raphael's commits, since I don't think we own the reference to the char *. See: 1) http://www.python.org/doc/2.4.2/ext/parseTuple.html and 2) function pygobject_connect in pygobject.c in the pygtk source for example code. 2005-10-07 Nigel Tao * deskbar/applet_keybinder.py: Fixed crasher when gconf entry for "/apps/deskbar/keybinder" is None. 2005-10-06 Raphael Slinckx * data/deskbar-applet.schemas.in: Add a new pref, the global shortcut key * deskbar/Makefile.am: * deskbar/__init__.py: * deskbar/applet.py: * deskbar/deskbar-applet: Add a way to focus the applet with a global key shortcut. The gconf default is F3 * deskbar/handler_utils.py: Fix a little bug when the term is exactly matching a file * deskbar/keybinder/_keybinder.override: * deskbar/keybinder/_keybindermodule.c: (init_keybinder): Add unbind, and fix some leaks in the python wrapper 2005-10-07 Nigel Tao * configure.ac: * deskbar/Makefile.am: * deskbar/keybinder/.cvsignore: * deskbar/keybinder/Makefile.am: * deskbar/keybinder/__init__.py: * deskbar/keybinder/_keybinder.defs: * deskbar/keybinder/_keybinder.override: * deskbar/keybinder/_keybindermodule.c: * deskbar/keybinder/eggaccelerators.c: * deskbar/keybinder/eggaccelerators.h: * deskbar/keybinder/gen-defs.sh: * deskbar/keybinder/tomboykeybinder.c: * deskbar/keybinder/tomboykeybinder.h: First draft of Tomboy's keybinding code (and Python wrapper). Removed portstem.py from deskbar/Makefile.am. keybinder-keybinder-3.0-v0.3.2/Makefile.am000066400000000000000000000007321305533123700201660ustar00rootroot00000000000000SUBDIRS = libkeybinder docs EXTRA_DIST = \ examples/Makefile \ examples/README \ examples/example.py \ examples/example.lua \ examples/example_gi.lua \ examples/lkeybinder.c \ examples/lminigtk.c \ examples/keybinder.vapi \ examples/vexample.vala \ examples/main.c DISTCLEANFILES = \ intltool-extract \ intltool-merge \ intltool-update \ gnome-doc-utils.make ACLOCAL_AMFLAGS = -I m4 DISTCHECK_CONFIGURE_FLAGS = --enable-introspection --enable-gtk-doc keybinder-keybinder-3.0-v0.3.2/NEWS000066400000000000000000000106441305533123700166340ustar00rootroot00000000000000 keybinder-3.0 v0.3.2 -------------------- * Fix ``keybinder_bind`` and others to not crash on non-X11 displays. It simply returns FALSE, failing to bind the key. * Add new API: ``gboolean keybinder_supported()`` Return TRUE if on key bindings are implemented for this configuration. (Right now: only TRUE if gtk says there's an X11 display) * Fix deprecated directives in build system keybinder-3.0 v0.3.1 -------------------- * Use ``XkbFreeKeyboard`` to fix memory leak (by Dmitry Eremin-Solenikov) * Fix deprecated directives in build system (by Dmitry Eremin-Solenikov) keybinder and keybinder-3.0 v0.3.0 ----------------------------------- Released Sunday, 17 June 2012 * Patch Makefile.am to use ACLOCAL_AMFLAGS=-I m4 (by Luca Falavigna) * Add two functions to fix gobject-introspection (gir) bindings: ``keybinder_bind_full(keystring, callback, user_data, notify)`` Uses GDestroyNotify for notification of callback unregistration. This function is compatible with introspected bindings unlike ``keybinder_bind``. Exported as ``keybinder_bind`` (``bind``) to bindings. ``keybinder_unbind_all(keystring)`` unregister all callbacks for the specified keystring. ``keybinder_unbind``'s signature cannot be supported by introspection bindings, and unbinding all matches the common use case (especially from bindings). Exported as ``keybinder_unbind`` (``unbind``) to bindings. * Build a gobject-introspection ``.typelib`` file for libkeybinder * Add a reference manual for libkeybinder using gtk-doc * Branch the library into two simultaneously installable libraries + ``keybinder`` is like the old version, using Gtk+ 2, package name ``keybinder`` (pkgconfig) and ``Keybinder-0.0`` (gir) + ``keybinder-3.0`` is a new version, using Gtk+ 3, package name ``keybinder-3.0`` (pkgconfig) and ``Keybinder-3.0`` (gir) + ``keybinder-3.0`` removes ``python-keybinder`` because pygtk will never be compatible with Gtk+ 3. Instead gir bindings have to be used. + These libraries will possibly have separate releases in the future but their first release is simultaneous, it is now. + ``keybinder-3.0`` is distributed under X11 license, since the GPL parts have been removed (python-keybinder and ax_lua). The old branch ``keybinder`` is still GPL! keybinder v0.2.2 ---------------- Released Sunday, 20 May 2010 * Add pkg-config file contributed by Jérôme Guelfucci * Add Vala example and .vapi file to examples/ * Make lua-keybinder installable (this is experimental), using ax_lua.m4 keybinder v0.2.1 ---------------- Released Monday, 26 April 2010 * Release key grabs if binding fails partially. keybinder v0.2.0 ---------------- Released Saturday, 24 April 2010 * Split into libkeybinder library and python-keybinder so that the same module can be used from Python or C. The Python bindings are now optional. * Add examples/ directory with C, Python and Lua examples (including experimental Lua bindings). keybinder v0.1.1 ---------------- Released Wednesday, 21 April 2010 * Workaround GTK+ Bug 616401 https://bugzilla.gnome.org/show_bug.cgi?id=616401 * Don't bind anything when mapping virtual modifiers fail (Kupfer bug :lp:`566945`) keybinder v0.1.0 ---------------- Released Tuesday, 6 April 2010 * Depend on GTK+ 2.20 * Remove egg* code keybinder v0.0.9 ---------------- Released Tuesday, 6 April 2010 * Replace some egg* code with GTK+ functionality. * Take great pains to understand "Consumed Modifiers", as in: + When pressing *Ctrl+Shift+1* to make *Ctrl+!*, Shift is a consumed modifier. So when receiving a binding specification like ``exclam``, we have to dig deep into XKB to find out which hardware modifiers are needed to create the bang (!) character. With this, it is now possible to bind any composed character. * Keybindings now work in alternative layouts as well, you just have to press the same hardware keys as in the primary layout. For example a keybinding *Ctrl+W* will still be available on the same physical keys after switching to a secondary Greek layout. * Remove keybinder.is_modifier from the module * Use -Wall keybinder v0.0.4 ---------------- Released 22 November 2009 * Remove bogus dependencies from configure checks (gnome-doc-utils and gnomeapplet) * Enable ``AM_SILENT_RULES`` * Fix language errors in documentation .. -*- encoding: UTF-8 -*- .. vim: ft=rst tw=72 keybinder-keybinder-3.0-v0.3.2/README000077700000000000000000000000001305533123700204722README.rstustar00rootroot00000000000000keybinder-keybinder-3.0-v0.3.2/README.rst000066400000000000000000000030441305533123700176200ustar00rootroot00000000000000libkeybinder ============ **keybinder** is a library for registering global keyboard shortcuts. Keybinder works with GTK-based applications using the X Window System. The library contains ``keybinder-3.0`` * A C library, ``libkeybinder`` * Gobject-Introspection (gir) generated bindings Compile and Installation Notes ------------------------------ The package ``keybinder`` compiles against GTK+ 2 while the package ``keybinder-3.0`` compiles against GTK+ 3. The two packages can be installed in parallel. NOTE: the old “``keybinder``” is in the branch ``keybinder-legacy`` on github. ``keybinder-3.0`` is the active development. Both packages support generating gobject-introspection (gir) bindings, even if these bindings are more relevant for the future, hence the GTK+ 3 package. For ``keybinder-3.0``, the gir bindings are strongly recommended over any other language bindings. If you want to compile with reduced library linking, configure using:: CC="cc -Wl,--as-needed" ./configure Build Requirements ------------------ * GTK+ 3.0 (``keybinder-3.0``) * gobject-introspection * gtk-doc 1.14 History ------- This library originates in `Tomboy`_ and has been widely reused without having a separate release. This package has taken the python bindings from the `Deskbar Applet`_ project, and broken it out to a standalone project. The library was subsequently rewritten in major parts. .. _Tomboy: http://projects.gnome.org/tomboy/ .. _`Deskbar Applet`: http://projects.gnome.org/deskbar-applet/ .. vim: ft=rst tw=72 keybinder-keybinder-3.0-v0.3.2/acinclude.m4000066400000000000000000000017071305533123700203260ustar00rootroot00000000000000dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR) dnl dnl example dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir) dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local AC_DEFUN([AS_AC_EXPAND], [ EXP_VAR=[$1] FROM_VAR=[$2] dnl first expand prefix and exec_prefix if necessary prefix_save=$prefix exec_prefix_save=$exec_prefix dnl if no prefix given, then use /usr/local, the default prefix if test "x$prefix" = "xNONE"; then prefix=$ac_default_prefix fi dnl if no exec_prefix given, then use prefix if test "x$exec_prefix" = "xNONE"; then exec_prefix=$prefix fi full_var="$FROM_VAR" dnl loop until it doesn't change anymore while true; do new_full_var="`eval echo $full_var`" if test "x$new_full_var"="x$full_var"; then break; fi full_var=$new_full_var done dnl clean up full_var=$new_full_var AC_SUBST([$1], "$full_var") dnl restore prefix and exec_prefix prefix=$prefix_save exec_prefix=$exec_prefix_save ]) keybinder-keybinder-3.0-v0.3.2/autogen.sh000077500000000000000000000016751305533123700201420ustar00rootroot00000000000000#!/bin/sh # Run this to generate all the initial makefiles, etc. srcdir=`dirname $0` test -z "$srcdir" && srcdir=. touch ChangeLog ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I m4" REQUIRED_AUTOCONF_VERSION=2.62 REQUIRED_AUTOMAKE_VERSION=1.9.2 REQUIRED_MACROS= (test -f $srcdir/configure.ac \ && test -f $srcdir/autogen.sh) || { echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" echo " top-level $PKG_NAME directory" exit 1 } DIE=0 gnome_autogen= gnome_datadir= ifs_save="$IFS"; IFS=":" for dir in $PATH ; do test -z "$dir" && dir=. if test -f $dir/gnome-autogen.sh ; then gnome_autogen="$dir/gnome-autogen.sh" gnome_datadir=`echo $dir | sed -e 's,/bin$,/share,'` break fi done IFS="$ifs_save" if test -z "$gnome_autogen" ; then echo "You need to install the gnome-common module and make" echo "sure the gnome-autogen.sh script is in your \$PATH." exit 1 fi GNOME_DATADIR="$gnome_datadir" . $gnome_autogen keybinder-keybinder-3.0-v0.3.2/configure.ac000066400000000000000000000066101305533123700204210ustar00rootroot00000000000000AC_INIT(keybinder-3.0, 0.3.2, []) AC_CONFIG_SRCDIR(libkeybinder/bind.c) AC_CONFIG_MACRO_DIR([m4]) AC_PREREQ(2.62) AM_INIT_AUTOMAKE([-Wno-portability]) # Libtool version # For any change: increment revision # If interfaces are added/changed/removed: increment current, reset revision # If library changed but is backwards-compatible: increment age # If library changed backwards-incompatibly: reset age m4_define([keybinder_lt_current], [0]) m4_define([keybinder_lt_revision], [0]) m4_define([keybinder_lt_age], [0]) LT_CURRENT=keybinder_lt_current LT_REVISION=keybinder_lt_revision LT_AGE=keybinder_lt_age AC_SUBST(LT_CURRENT) AC_SUBST(LT_REVISION) AC_SUBST(LT_AGE) AM_MAINTAINER_MODE AM_DISABLE_STATIC AM_PROG_LIBTOOL AC_SUBST(ACLOCAL_AMFLAGS, "$ACLOCAL_FLAGS -I m4") AC_PROG_CC dnl **************************************************************************** dnl * Enable Automake 1.11 silent rules dnl **************************************************************************** m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) dnl **************************************************************************** dnl * Pkg-Config dnl **************************************************************************** AC_CHECK_PROG(HAVE_PKGCONFIG, pkg-config, yes, no) if test "x$HAVE_PKGCONFIG" = "xno"; then AC_MSG_ERROR(you need to have pkgconfig installed !) fi dnl **************************************************************************** dnl * Write the values of various paths in defs.py dnl **************************************************************************** AC_SUBST(VERSION) PACKAGE=$PACKAGE_NAME PACKAGE_TARNAME=$PACKAGE_NAME AC_SUBST(PACKAGE) AC_SUBST(PACKAGE_TARNAME) AS_AC_EXPAND(DATADIR, $datarootdir) AC_SUBST(DATADIR) AS_AC_EXPAND(LIBDIR, $libdir) AC_SUBST(LIBDIR) dnl **************************************************************************** dnl * GTK dnl **************************************************************************** gtk_version="gtk+-3.0" PKG_CHECK_MODULES(GTK, [gtk+-3.0 >= 3.0]) AC_SUBST(GTK_CFLAGS) AC_SUBST(GTK_LIBS) dnl ** dnl * Required gtk package (for keybinder.pc) dnl ** AS_AC_EXPAND(GTKPACKAGEDEP, $gtk_version) AC_SUBST(GTKPACKAGEDEP) dnl * gobject-introspection GOBJECT_INTROSPECTION_CHECK([0.6.7]) dnl *********************************** dnl * Require XKB dnl *********************************** X_LIBS="`$PKG_CONFIG --libs x11 xext xrender`" X_CFLAGS="`$PKG_CONFIG --cflags x11 xext xrender`" old_cflags="$CFLAGS" CFLAGS="$CFLAGS $X_CFLAGS" LIBS="$X_LIBS $LIBS" AC_CHECK_FUNC(XkbQueryExtension, [], AC_MSG_ERROR(Could not find XKB)) CFLAGS="$old_cflags" X_LDFLAGS="$X_LIBS" AC_SUBST(X_CFLAGS) AC_SUBST(X_LDFLAGS) dnl *** dnl * GTK DOC dnl *** GTK_DOC_CHECK([1.14], [--flavour no-tmpl]) dnl **************************************************************************** dnl * -------------------------------------------------------------------------- dnl **************************************************************************** AC_OUTPUT([ Makefile libkeybinder/Makefile libkeybinder/$PACKAGE_NAME.pc docs/Makefile docs/version.info ]) echo echo $PACKAGE v$VERSION echo echo Prefix............... : $prefix echo GTK version ......... : $gtk_version echo libkeybinder ........ : yes echo gobject-introspection : $found_introspection echo gtk-doc ............. : $enable_gtk_doc echo echo "Now type make to compile" echo "Then su to root and type: make install" echo keybinder-keybinder-3.0-v0.3.2/docs/000077500000000000000000000000001305533123700170605ustar00rootroot00000000000000keybinder-keybinder-3.0-v0.3.2/docs/Makefile.am000066400000000000000000000067711305533123700211270ustar00rootroot00000000000000## Process this file with automake to produce Makefile.in # We require automake 1.6 at least. AUTOMAKE_OPTIONS = 1.6 # This is a blank Makefile.am for using gtk-doc. # Copy this to your project's API docs directory and modify the variables to # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples # of using the various options. # The name of the module, e.g. 'glib'. DOC_MODULE = keybinder # Uncomment for versioned docs and specify the version of the module, e.g. '2'. DOC_MODULE_VERSION=3.0 # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml # Directories containing the source code, relative to $(srcdir). # gtk-doc will search all .c and .h files beneath these paths # for inline comments documenting functions and macros. # e.g. DOC_SOURCE_DIR=../../../gtk ../../../gdk DOC_SOURCE_DIR= ../libkeybinder # Extra options to pass to gtkdoc-scangobj. Not normally needed. SCANGOBJ_OPTIONS= # Extra options to supply to gtkdoc-scan. # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS= --rebuild-sections --rebuild-types # Extra options to supply to gtkdoc-mkdb. # e.g. MKDB_OPTIONS=--xml-mode --output-format=xml MKDB_OPTIONS=--xml-mode --output-format=xml # Extra options to supply to gtkdoc-mktmpl # e.g. MKTMPL_OPTIONS=--only-section-tmpl MKTMPL_OPTIONS= # Extra options to supply to gtkdoc-mkhtml MKHTML_OPTIONS= # Extra options to supply to gtkdoc-fixref. Not normally needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS= # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c HFILE_GLOB= CFILE_GLOB= # Extra header to include when scanning, which are not under DOC_SOURCE_DIR # e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h EXTRA_HFILES= # Header files or dirs to ignore when scanning. Use base file/dir names # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code IGNORE_HFILES= # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES= # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml content_files= version.info # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml expand_content_files= # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget # signals and properties. # e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) GTKDOC_CFLAGS= GTKDOC_LIBS= # This includes the standard gtk-doc make rules, copied by gtkdocize. include $(top_srcdir)/gtk-doc.make # Other files to distribute # e.g. EXTRA_DIST += version.xml.in EXTRA_DIST += version.info.in # Files not to distribute # for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types # for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt #DISTCLEANFILES += # Comment this out if you want 'make check' to test you doc status # and run some sanity checks if ENABLE_GTK_DOC TESTS_ENVIRONMENT = cd $(srcdir) && \ DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \ SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir) #TESTS = $(GTKDOC_CHECK) endif -include $(top_srcdir)/git.mk keybinder-keybinder-3.0-v0.3.2/docs/keybinder-docs.sgml000066400000000000000000000024251305533123700226510ustar00rootroot00000000000000 ]> libkeybinder-3.0 Reference Manual libkeybinder Object Hierarchy API Index Index of deprecated API keybinder-keybinder-3.0-v0.3.2/docs/keybinder-overrides.txt000066400000000000000000000000001305533123700235630ustar00rootroot00000000000000keybinder-keybinder-3.0-v0.3.2/docs/version.info.in000066400000000000000000000000471305533123700220300ustar00rootroot00000000000000Package: @PACKAGE@ Version: @VERSION@ keybinder-keybinder-3.0-v0.3.2/examples/000077500000000000000000000000001305533123700177465ustar00rootroot00000000000000keybinder-keybinder-3.0-v0.3.2/examples/.gitignore000066400000000000000000000000251305533123700217330ustar00rootroot00000000000000*.so /main /vexample keybinder-keybinder-3.0-v0.3.2/examples/Makefile000066400000000000000000000016061305533123700214110ustar00rootroot00000000000000GTKPKG = gtk+-3.0 KEYBPKG = keybinder-3.0 GTK_CFLAGS = $(shell pkg-config --cflags $(GTKPKG)) GTK_LDFLAGS = $(shell pkg-config --libs $(GTKPKG)) LUA_CFLAGS = $(shell pkg-config --cflags lua5.1) LUA_LDFLAGS = $(shell pkg-config --libs lua5.1) KEYB_FLAGS = $(shell pkg-config --cflags --libs $(KEYBPKG)) CFLAGS ?= -g -O2 VALAC = valac all: main lua vala lua: minigtk.so keybinder.so # Example C program with libkeybinder main: main.c $(CC) $(KEYB_FLAGS) $(CFLAGS) $< -o $@ # Lua "minigtk" library keybinder.so: lkeybinder.c $(CC) $(KEYB_FLAGS) $(CFLAGS) \ $(LUA_CFLAGS) $(LUA_LDFLAGS) $< -shared -o $@ minigtk.so: lminigtk.c $(CC) $(GTK_CFLAGS) $(GTK_LDFLAGS) \ $(LUA_CFLAGS) $(LUA_LDFLAGS) $< -shared -o $@ vala: vexample vexample: vexample.vala keybinder.vapi $(VALAC) --pkg $(GTKPKG) --pkg keybinder --vapidir=. $< clean: rm -f *.so *.lo main vexample .PHONY: clean all lua vala keybinder-keybinder-3.0-v0.3.2/examples/README000066400000000000000000000013751305533123700206340ustar00rootroot00000000000000Examples for libkeybinder ========================= The examples require that keybinder is already built and installed, otherwise the applications won't find their libraries or modules. main.c contains a minimal C program using libkeybinder. Run it using:: make main ./main example.py contains a minimal Python program using keybinder. Run it using:: ./example.py example.lua contains a minimal Lua program using keybinder. Run it using:: make lua ./example.lua example_gi.lua contains a minimal Lua program using keybinder via gobject-introspection and `lgi `__. Run it using:: ./example_gi.lua vexample.vala contains a minimal Vala program using keybinder. Run it using:: make vala ./vexample keybinder-keybinder-3.0-v0.3.2/examples/example.lua000077500000000000000000000007561305533123700221170ustar00rootroot00000000000000#!/usr/bin/env lua -- example.lua -- -- Created in 2010 by Ulrik Sverdrup -- This work is placed in the public domain. require "minigtk" require "keybinder" function callback(keystring, user_data) print("In callback", keystring, keybinder.get_current_event_time()) print("Userdata: ", user_data) minigtk.main_quit() end minigtk.init() keybinder.bind("A", callback, {1,2,3}) print("Press A to activate keybinding and quit"); minigtk.main() keybinder-keybinder-3.0-v0.3.2/examples/example.py000077500000000000000000000012051305533123700217540ustar00rootroot00000000000000#!/usr/bin/env python """ example.py Created in 2010 by Ulrik Sverdrup This work is placed in the public domain. """ import gi gi.require_version('Gtk', '3.0') gi.require_version('Keybinder', '3.0') from gi.repository import Gtk from gi.repository import Keybinder def callback(keystr, user_data): print "Handling", keystr, user_data print "Event time:", Keybinder.get_current_event_time() Gtk.main_quit() if __name__ == '__main__': keystr = "A" Keybinder.init() Keybinder.bind(keystr, callback, "Keystring %s (user data)" % keystr) print "Press", keystr, "to handle keybinding and quit" Gtk.main() keybinder-keybinder-3.0-v0.3.2/examples/example_gi.lua000077500000000000000000000011711305533123700225660ustar00rootroot00000000000000#!/usr/bin/env lua -- example_gi.lua -- -- Created in 2011 by Ulrik Sverdrup -- This work is placed in the public domain. -- -- requires lgi http://gitorious.org/lgi local lgi = require 'lgi' local Gtk = lgi.require('Gtk', '3.0') local Keybinder = lgi.require('Keybinder', '3.0') local function callback(keystring) print("In callback for", keystring) print("Event time:", Keybinder.get_current_event_time()) Keybinder.unbind(keystring) Gtk.main_quit() end Gtk.init() Keybinder.init() Keybinder.bind("A", callback) print("Press A to activate keybinding and quit"); Gtk.main() keybinder-keybinder-3.0-v0.3.2/examples/keybinder.vapi000066400000000000000000000006331305533123700226050ustar00rootroot00000000000000 [CCode (cprefix = "KEYBINDER", lower_case_cprefix = "keybinder_", cheader_filename="keybinder.h")] namespace Keybinder { [CCode (has_target=false)] public delegate void Handler (string keystring, void *udata); public void init(); public bool bind (string keystring, Handler hander, void *udata); public void unbind (string keystring, Handler handler); public uint32 get_current_event_time (); } keybinder-keybinder-3.0-v0.3.2/examples/lkeybinder.c000066400000000000000000000061541305533123700222500ustar00rootroot00000000000000/* lkeybinder.c * Created in 2010 by Ulrik Sverdrup * * This file is placed in the public domain. */ #include #include #include #define LUA_LIB #include #include /* @lkeybinder_reg_key is a "ref" into the registry where we store * a mapping from keystring to callback function in a table. */ static int lkeybinder_reg_key; static void lkeybinder_check_init () { static int did_init; if (!did_init) { keybinder_init(); did_init = true; } } /* Callback closure with upvalues: * 1 Lua callback function * 2 Keystring * 3 User data */ static int lkeybinder_closure (lua_State *L) { /* Call callback f(keystring, user_data) */ lua_pushvalue(L, lua_upvalueindex(1)); lua_pushvalue(L, lua_upvalueindex(2)); lua_pushvalue(L, lua_upvalueindex(3)); lua_call(L, 2, 0); return 0; } static void lkeybinder_handler (const char *keystring, void *user_data) { lua_State *L = user_data; /* get table */ lua_rawgeti(L, LUA_REGISTRYINDEX, lkeybinder_reg_key); lua_pushstring(L, keystring); lua_rawget(L, -2); /* call callback closure */ if (lua_pcall(L, 0, 0, 0)) { fprintf(stderr, "Error in callback:\n\t%s\n", lua_tostring(L, -1)); lua_pop(L, 1); } lua_pop(L, 1); } /* lkeybinder library function 'bind' */ static int lkeybinder_bind (lua_State *L) { int success; int table_index; const char *keystr = luaL_checkstring(L, 1); luaL_checktype(L, 2, LUA_TFUNCTION); /* argument 3 is nil/none or user data */ lua_settop(L, 3); lkeybinder_check_init(); /* get RefTable */ lua_rawgeti(L, LUA_REGISTRYINDEX, lkeybinder_reg_key); table_index = lua_gettop(L); lua_pushstring(L, keystr); lua_rawget(L, table_index); if (!lua_isnil(L, -1)) { success = false; } else { success = keybinder_bind(keystr, lkeybinder_handler, L); if (success) { lua_pushstring(L, keystr); /* Create a closure with three upvalues * RefTable[keystr] = */ lua_pushvalue(L, 2); lua_pushstring(L, keystr); lua_pushvalue(L, 3); lua_pushcclosure(L, lkeybinder_closure, 3); lua_rawset(L, table_index); } } lua_pushboolean(L, success); return 1; } /* lkeybinder library function 'unbind' */ static int lkeybinder_unbind (lua_State *L) { const char *keystr = luaL_checkstring(L, 1); keybinder_unbind(keystr, lkeybinder_handler); /* RefTable[keystring] = nil */ lua_rawgeti(L, LUA_REGISTRYINDEX, lkeybinder_reg_key); lua_pushstring(L, keystr); lua_pushnil(L); lua_rawset(L, -3); return 0; } /* lkeybinder library function 'get_current_event_time' */ static int lkeybinder_current_event_time (lua_State *L) { lua_pushnumber(L, keybinder_get_current_event_time()); return 1; } static const luaL_reg keybinderlib[] = { {"bind", lkeybinder_bind}, {"unbind", lkeybinder_unbind}, {"get_current_event_time", lkeybinder_current_event_time}, {NULL, NULL} }; LUALIB_API int luaopen_keybinder (lua_State *L) { luaL_register(L, "keybinder", keybinderlib); lua_newtable(L); lkeybinder_reg_key = luaL_ref(L, LUA_REGISTRYINDEX); return 1; } keybinder-keybinder-3.0-v0.3.2/examples/lminigtk.c000066400000000000000000000012751305533123700217350ustar00rootroot00000000000000/* lminigtk.c * Created in 2010 by Ulrik Sverdrup * * This work is placed in the public domain. */ #include #define LUA_LIB #include #include static int init (lua_State *L) { int argc = 0; char **argv = NULL; lua_pushnumber(L, gtk_init_check(&argc, &argv)); return 1; } static int main (lua_State *L) { gtk_main(); return 0; } static int main_quit (lua_State *L) { gtk_main_quit(); return 0; } static const luaL_reg minigtk[] = { {"init", init}, {"main", main}, {"main_quit", main_quit}, {NULL, NULL} }; LUALIB_API int luaopen_minigtk (lua_State *L) { luaL_register(L, "minigtk", minigtk); return 1; } keybinder-keybinder-3.0-v0.3.2/examples/main.c000066400000000000000000000011561305533123700210410ustar00rootroot00000000000000/* main.c * Created in 2010 by Ulrik Sverdrup * * This work is placed in the public domain. */ #include #include #include #define EXAMPLE_KEY "A" void handler (const char *keystring, void *user_data) { printf("Handle %s (%p)!\n", keystring, user_data); keybinder_unbind(keystring, handler); gtk_main_quit(); } int main (int argc, char *argv[]) { gtk_init(&argc, &argv); keybinder_init(); keybinder_bind(EXAMPLE_KEY, handler, NULL); printf("Press " EXAMPLE_KEY " to activate keybinding and quit\n"); gtk_main(); return 0; } keybinder-keybinder-3.0-v0.3.2/examples/vexample.vala000066400000000000000000000012261305533123700224350ustar00rootroot00000000000000/* vexample.vala * Created in 2010 by Ulrik Sverdrup * * This work is placed in the public domain. */ const string EXAMPLE_KEY = "A"; public void callback (string keystring, void *udata) { string s = (string) udata; print("Handling key %s. User data: %p, %s\n", keystring, udata, s); print("Event time: %u\n", Keybinder.get_current_event_time()); Keybinder.unbind(keystring, callback); Gtk.main_quit(); } int main(string[] args) { Gtk.init(ref args); Keybinder.init(); Keybinder.bind(EXAMPLE_KEY, callback, "user data"); print("Press %s to activate keybinding and quit\n", EXAMPLE_KEY); Gtk.main(); return 0; } keybinder-keybinder-3.0-v0.3.2/libkeybinder/000077500000000000000000000000001305533123700205735ustar00rootroot00000000000000keybinder-keybinder-3.0-v0.3.2/libkeybinder/Makefile.am000066400000000000000000000026031305533123700226300ustar00rootroot00000000000000AM_CPPFLAGS = $(GTK_CFLAGS) AM_CFLAGS = -Wall -Wextra -ansi LIBKEYBINDER_VERSION = $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) # C library libkeybinder # keybinderdir = $(libdir) keybinder_LTLIBRARIES = libkeybinder-3.0.la libkeybinder_3_0_la_SOURCES = bind.c libkeybinder_3_0_la_LDFLAGS = $(GTK_LIBS) -version-info $(LIBKEYBINDER_VERSION) keybinder_includedir = $(pkgincludedir) keybinder_include_HEADERS = keybinder.h pkgconffile = $(PACKAGE).pc pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = $(pkgconffile) EXTRA_DIST = $(pkgconffile).in DISTCLEANFILES = $(pkgconffile) CLEANFILES = # gobject-introspection for keybinder -include $(INTROSPECTION_MAKEFILE) INTROSPECTION_GIRS = INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir) if HAVE_INTROSPECTION introspection_sources = $(libkeybinder_3_0_la_SOURCES) $(keybinder_include_HEADERS) Keybinder-3.0.gir: libkeybinder-3.0.la Keybinder_3_0_gir_INCLUDES = GObject-2.0 Keybinder_3_0_gir_CFLAGS = $(INCLUDES) Keybinder_3_0_gir_LIBS = libkeybinder-3.0.la Keybinder_3_0_gir_FILES = $(introspection_sources) Keybinder_3_0_gir_SCANNERFLAGS = --warn-all INTROSPECTION_GIRS += Keybinder-3.0.gir girdir = $(datadir)/gir-1.0 gir_DATA = $(INTROSPECTION_GIRS) typelibdir = $(libdir)/girepository-1.0 typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) CLEANFILES += $(gir_DATA) $(typelib_DATA) endif keybinder-keybinder-3.0-v0.3.2/libkeybinder/bind.c000066400000000000000000000445011305533123700216570ustar00rootroot00000000000000/* bind.c * Copyright (C) 2008 Alex Graveley * Copyright (C) 2010 Ulrik Sverdrup * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include "keybinder.h" /* Uncomment the next line to print a debug trace. */ /* #define DEBUG */ #ifdef DEBUG # define TRACE(x) x #else # define TRACE(x) do {} while (FALSE); #endif #define MODIFIERS_ERROR ((GdkModifierType)(-1)) #define MODIFIERS_NONE 0 /* Group to use: Which of configured keyboard Layouts * Since grabbing a key blocks its use, we can't grab the corresponding * (physical) keys for alternative layouts. * * Because of this, we interpret all keys relative to the default * keyboard layout. * * For example, if you bind "w", the physical W key will respond to * the bound key, even if you switch to a keyboard layout where the W key * types a different letter. */ #define WE_ONLY_USE_ONE_GROUP 0 struct Binding { KeybinderHandler handler; void *user_data; char *keystring; GDestroyNotify notify; /* GDK "distilled" values */ guint keyval; GdkModifierType modifiers; }; static GSList *bindings = NULL; static guint32 last_event_time = 0; static gboolean processing_event = FALSE; static gboolean detected_xkb_extension = FALSE; static gboolean use_xkb_extension = FALSE; /* Return the modifier mask that needs to be pressed to produce key in the * given group (keyboard layout) and level ("shift level"). */ static GdkModifierType FinallyGetModifiersForKeycode (XkbDescPtr xkb, KeyCode key, guint group, guint level) { int nKeyGroups; int effectiveGroup; XkbKeyTypeRec *type; int k; nKeyGroups = XkbKeyNumGroups(xkb, key); if ((!XkbKeycodeInRange(xkb, key)) || (nKeyGroups == 0)) { return MODIFIERS_ERROR; } /* Taken from GDK's MyEnhancedXkbTranslateKeyCode */ /* find the offset of the effective group */ effectiveGroup = group; if (effectiveGroup >= nKeyGroups) { unsigned groupInfo = XkbKeyGroupInfo(xkb,key); switch (XkbOutOfRangeGroupAction(groupInfo)) { default: effectiveGroup %= nKeyGroups; break; case XkbClampIntoRange: effectiveGroup = nKeyGroups-1; break; case XkbRedirectIntoRange: effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo); if (effectiveGroup >= nKeyGroups) effectiveGroup = 0; break; } } type = XkbKeyKeyType(xkb, key, effectiveGroup); for (k = 0; k < type->map_count; k++) { if (type->map[k].active && type->map[k].level == level) { if (type->preserve) { return (type->map[k].mods.mask & ~type->preserve[k].mask); } else { return type->map[k].mods.mask; } } } return MODIFIERS_NONE; } /* Grab or ungrab the keycode+modifiers combination, first plainly, and then * including each ignorable modifier in turn. */ static gboolean grab_ungrab_with_ignorable_modifiers (GdkWindow *rootwin, guint keycode, guint modifiers, gboolean grab) { guint i; gboolean success = FALSE; /* Ignorable modifiers */ guint mod_masks [] = { 0, /* modifier only */ GDK_MOD2_MASK, GDK_LOCK_MASK, GDK_MOD2_MASK | GDK_LOCK_MASK, }; gdk_error_trap_push (); for (i = 0; i < G_N_ELEMENTS (mod_masks); i++) { if (grab) { XGrabKey (GDK_WINDOW_XDISPLAY (rootwin), keycode, modifiers | mod_masks [i], GDK_WINDOW_XID (rootwin), False, GrabModeAsync, GrabModeAsync); } else { XUngrabKey (GDK_WINDOW_XDISPLAY (rootwin), keycode, modifiers | mod_masks [i], GDK_WINDOW_XID (rootwin)); } } gdk_flush(); if (gdk_error_trap_pop()) { TRACE (g_print ("Failed grab/ungrab!\n")); if (grab) { /* On error, immediately release keys again */ grab_ungrab_with_ignorable_modifiers(rootwin, keycode, modifiers, FALSE); } } else { success = TRUE; } return success; } /* Grab or ungrab then keyval and modifiers combination, grabbing all key * combinations yielding the same key values. * Includes ignorable modifiers using grab_ungrab_with_ignorable_modifiers. */ static gboolean grab_ungrab (GdkWindow *rootwin, guint keyval, guint modifiers, gboolean grab) { int k; GdkKeymap *map; GdkKeymapKey *keys; gint n_keys; GdkModifierType add_modifiers = 0; XkbDescPtr xmap = NULL; gboolean success = FALSE; if (!keybinder_supported()) { return FALSE; } if (use_xkb_extension) { xmap = XkbGetMap(GDK_WINDOW_XDISPLAY(rootwin), XkbAllClientInfoMask, XkbUseCoreKbd); } map = gdk_keymap_get_default(); gdk_keymap_get_entries_for_keyval(map, keyval, &keys, &n_keys); if (n_keys == 0) return FALSE; for (k = 0; k < n_keys; k++) { /* NOTE: We only bind for the first group, * so regardless of current keyboard layout, it will * grab the key from the default Layout. */ if (keys[k].group != WE_ONLY_USE_ONE_GROUP) { continue; } TRACE (g_print("grab/ungrab keycode: %d, lev: %d, grp: %d, ", keys[k].keycode, keys[k].level, keys[k].group)); if (use_xkb_extension) { add_modifiers = FinallyGetModifiersForKeycode(xmap, keys[k].keycode, keys[k].group, keys[k].level); } else if (keys[k].level > 0) { /* skip shifted/modified keys in non-xkb mode * this might mean the key can't be bound at all */ continue; } if (add_modifiers == MODIFIERS_ERROR) { continue; } TRACE (g_print("modifiers: 0x%x (consumed: 0x%x)\n", add_modifiers | modifiers, add_modifiers)); if (grab_ungrab_with_ignorable_modifiers(rootwin, keys[k].keycode, add_modifiers | modifiers, grab)) { success = TRUE; } else { /* When grabbing, break on error */ if (grab && !success) { break; } } } g_free(keys); if (xmap) { XkbFreeKeyboard(xmap, 0, TRUE); } return success; } static gboolean keyvalues_equal (guint kv1, guint kv2) { return kv1 == kv2; } /* Compare modifier set equality, * while accepting overloaded modifiers (MOD1 and META together) */ static gboolean modifiers_equal (GdkModifierType mf1, GdkModifierType mf2) { GdkModifierType ignored = 0; /* Accept MOD1 + META as MOD1 */ if (mf1 & mf2 & GDK_MOD1_MASK) { ignored |= GDK_META_MASK; } /* Accept SUPER + HYPER as SUPER */ if (mf1 & mf2 & GDK_SUPER_MASK) { ignored |= GDK_HYPER_MASK; } if ((mf1 & ~ignored) == (mf2 & ~ignored)) { return TRUE; } return FALSE; } static gboolean do_grab_key (struct Binding *binding) { gboolean success; GdkWindow *rootwin = gdk_get_default_root_window (); GdkKeymap *keymap = gdk_keymap_get_default (); GdkModifierType modifiers; guint keysym = 0; if (keymap == NULL || rootwin == NULL) return FALSE; gtk_accelerator_parse(binding->keystring, &keysym, &modifiers); if (keysym == 0) return FALSE; binding->keyval = keysym; binding->modifiers = modifiers; TRACE (g_print ("Grabbing keyval: %d, vmodifiers: 0x%x, name: %s\n", keysym, modifiers, binding->keystring)); /* Map virtual modifiers to non-virtual modifiers */ gdk_keymap_map_virtual_modifiers(keymap, &modifiers); if (modifiers == binding->modifiers && (GDK_SUPER_MASK | GDK_HYPER_MASK | GDK_META_MASK) & modifiers) { g_warning ("Failed to map virtual modifiers"); return FALSE; } success = grab_ungrab (rootwin, keysym, modifiers, TRUE /* grab */); if (!success) { g_warning ("Binding '%s' failed!", binding->keystring); } return success; } static gboolean do_ungrab_key (struct Binding *binding) { GdkKeymap *keymap = gdk_keymap_get_default (); GdkWindow *rootwin = gdk_get_default_root_window (); GdkModifierType modifiers; if (keymap == NULL || rootwin == NULL) return FALSE; TRACE (g_print ("Ungrabbing keyval: %d, vmodifiers: 0x%x, name: %s\n", binding->keyval, binding->modifiers, binding->keystring)); /* Map virtual modifiers to non-virtual modifiers */ modifiers = binding->modifiers; gdk_keymap_map_virtual_modifiers(keymap, &modifiers); grab_ungrab (rootwin, binding->keyval, modifiers, FALSE /* ungrab */); return TRUE; } static GdkFilterReturn filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) { XEvent *xevent = (XEvent *) gdk_xevent; GdkKeymap *keymap = gdk_keymap_get_default(); guint keyval; GdkModifierType consumed, modifiers; guint mod_mask = gtk_accelerator_get_default_mod_mask(); GSList *iter; (void) event; (void) data; switch (xevent->type) { case KeyPress: modifiers = xevent->xkey.state; TRACE (g_print ("Got KeyPress keycode: %d, modifiers: 0x%x\n", xevent->xkey.keycode, xevent->xkey.state)); if (use_xkb_extension) { gdk_keymap_translate_keyboard_state( keymap, xevent->xkey.keycode, modifiers, /* See top comment why we don't use this here: XkbGroupForCoreState (xevent->xkey.state) */ WE_ONLY_USE_ONE_GROUP, &keyval, NULL, NULL, &consumed); } else { consumed = 0; keyval = XLookupKeysym(&xevent->xkey, 0); } /* Map non-virtual to virtual modifiers */ modifiers &= ~consumed; gdk_keymap_add_virtual_modifiers(keymap, &modifiers); modifiers &= mod_mask; TRACE (g_print ("Translated keyval: %d, vmodifiers: 0x%x, name: %s\n", keyval, modifiers, gtk_accelerator_name(keyval, modifiers))); /* * Set the last event time for use when showing * windows to avoid anti-focus-stealing code. */ processing_event = TRUE; last_event_time = xevent->xkey.time; iter = bindings; while (iter != NULL) { /* NOTE: ``iter`` might be removed from the list * in the callback. */ struct Binding *binding = iter->data; iter = iter->next; if (keyvalues_equal(binding->keyval, keyval) && modifiers_equal(binding->modifiers, modifiers)) { TRACE (g_print ("Calling handler for '%s'...\n", binding->keystring)); (binding->handler) (binding->keystring, binding->user_data); } } processing_event = FALSE; break; case KeyRelease: TRACE (g_print ("Got KeyRelease! \n")); break; } return GDK_FILTER_CONTINUE; } static void keymap_changed (GdkKeymap *map) { GSList *iter; (void) map; TRACE (g_print ("Keymap changed! Regrabbing keys...")); for (iter = bindings; iter != NULL; iter = iter->next) { struct Binding *binding = iter->data; do_ungrab_key (binding); } for (iter = bindings; iter != NULL; iter = iter->next) { struct Binding *binding = iter->data; do_grab_key (binding); } } /** * keybinder_init: * * Initialize the keybinder library. * * This function must be called after initializing GTK, before calling any * other function in the library. Can only be called once. */ void keybinder_init () { GdkKeymap *keymap = gdk_keymap_get_default (); GdkWindow *rootwin = gdk_get_default_root_window (); Display *disp; int xkb_opcode; int xkb_event_base; int xkb_error_base; int majver = XkbMajorVersion; int minver = XkbMinorVersion; if (!keybinder_supported()) { return; } if (!(disp = XOpenDisplay(NULL))) { g_warning("keybinder_init: Unable to open display"); return; } detected_xkb_extension = XkbQueryExtension(disp, &xkb_opcode, &xkb_event_base, &xkb_error_base, &majver, &minver); use_xkb_extension = detected_xkb_extension; TRACE(g_print("XKB: %d, version: %d, %d\n", use_xkb_extension, majver, minver)); gdk_window_add_filter (rootwin, filter_func, NULL); /* Workaround: Make sure modmap is up to date * There is possibly a bug in GTK+ where virtual modifiers are not * mapped because the modmap is not updated. The following function * updates it. */ (void) gdk_keymap_have_bidi_layouts(keymap); g_signal_connect (keymap, "keys_changed", G_CALLBACK (keymap_changed), NULL); } /** * keybinder_set_use_cooked_accelerators: * @use_cooked: if %FALSE disable cooked accelerators * * "Cooked" accelerators use symbols produced by using modifiers such * as shift or altgr, for example if "!" is produced by "Shift+1". * * If cooked accelerators are enabled, use "<Ctrl>exclam" to bind * "Ctrl+!" If disabled, use "<Ctrl><Shift>1" to bind * "Ctrl+Shift+1". These two examples are not equal on all keymaps. * * The cooked accelerator keyvalue and modifiers are provided by the * function gdk_keymap_translate_keyboard_state() * * Cooked accelerators are useful if you receive keystrokes from GTK to bind, * but raw accelerators can be useful if you or the user inputs accelerators as * text. * * Default: Enabled. Should be set before binding anything. */ void keybinder_set_use_cooked_accelerators (gboolean use_cooked) { use_xkb_extension = use_cooked && detected_xkb_extension; } /** * keybinder_bind: (skip) * @keystring: an accelerator description (gtk_accelerator_parse() format) * @handler: callback function * @user_data: data to pass to @handler * * Grab a key combination globally and register a callback to be called each * time the key combination is pressed. * * This function is excluded from introspected bindings and is replaced by * keybinder_bind_full. * * Returns: %TRUE if the accelerator could be grabbed */ gboolean keybinder_bind (const char *keystring, KeybinderHandler handler, void *user_data) { return keybinder_bind_full(keystring, handler, user_data, NULL); } /** * keybinder_bind_full: (rename-to keybinder_bind) * @keystring: an accelerator description (gtk_accelerator_parse() format) * @handler: (scope notified): callback function * @user_data: (closure) (allow-none): data to pass to @handler * @notify: (allow-none): called when @handler is unregistered * * Grab a key combination globally and register a callback to be called each * time the key combination is pressed. * * Since: 0.3.0 * * Returns: %TRUE if the accelerator could be grabbed */ gboolean keybinder_bind_full (const char *keystring, KeybinderHandler handler, void *user_data, GDestroyNotify notify) { struct Binding *binding; gboolean success; binding = g_new0 (struct Binding, 1); binding->keystring = g_strdup (keystring); binding->handler = handler; binding->user_data = user_data; binding->notify = notify; /* Sets the binding's keycode and modifiers */ success = do_grab_key (binding); if (success) { bindings = g_slist_prepend (bindings, binding); } else { g_free (binding->keystring); g_free (binding); } return success; } /** * keybinder_unbind: (skip) * @keystring: an accelerator description (gtk_accelerator_parse() format) * @handler: callback function * * Unregister a previously bound callback for this keystring. * * NOTE: multiple callbacks per keystring are not properly supported. You * might as well use keybinder_unbind_all(). * * This function is excluded from introspected bindings and is replaced by * keybinder_unbind_all(). */ void keybinder_unbind (const char *keystring, KeybinderHandler handler) { GSList *iter; for (iter = bindings; iter != NULL; iter = iter->next) { struct Binding *binding = iter->data; if (strcmp (keystring, binding->keystring) != 0 || handler != binding->handler) continue; do_ungrab_key (binding); bindings = g_slist_remove (bindings, binding); TRACE (g_print("unbind, notify: %p\n", binding->notify)); if (binding->notify) { binding->notify(binding->user_data); } g_free (binding->keystring); g_free (binding); break; } } /** * keybinder_unbind_all: (rename-to keybinder_unbind) * @keystring: an accelerator description (gtk_accelerator_parse() format) * * Unregister all previously bound callbacks for this keystring. * * Since: 0.3.0 */ void keybinder_unbind_all (const char *keystring) { GSList *iter = bindings; for (iter = bindings; iter != NULL; iter = iter->next) { struct Binding *binding = iter->data; if (strcmp (keystring, binding->keystring) != 0) continue; do_ungrab_key (binding); bindings = g_slist_remove (bindings, binding); TRACE (g_print("unbind_all, notify: %p\n", binding->notify)); if (binding->notify) { binding->notify(binding->user_data); } g_free (binding->keystring); g_free (binding); /* re-start scan from head of new list */ iter = bindings; if (!iter) break; } } /** * keybinder_get_current_event_time: * * Returns: the current event timestamp */ guint32 keybinder_get_current_event_time (void) { if (processing_event) return last_event_time; else return GDK_CURRENT_TIME; } /** * keybinder_supported: * * Returns: TRUE if keybindings are supported */ gboolean keybinder_supported (void) { return GDK_IS_X11_DISPLAY(gdk_display_get_default()); } keybinder-keybinder-3.0-v0.3.2/libkeybinder/keybinder-3.0.pc.in000066400000000000000000000004141305533123700237750ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@/@PACKAGE@ Name: @PACKAGE@ Description: Register global keyboard shortcuts Requires: @GTKPACKAGEDEP@ Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lkeybinder-3.0 Cflags: -I${includedir} keybinder-keybinder-3.0-v0.3.2/libkeybinder/keybinder.h000066400000000000000000000040141305533123700227170ustar00rootroot00000000000000/* bind.h * Copyright (C) 2008 Alex Graveley * Copyright (C) 2010 Ulrik Sverdrup * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __KEY_BINDER_H__ #define __KEY_BINDER_H__ #include G_BEGIN_DECLS typedef void (* KeybinderHandler) (const char *keystring, void *user_data); void keybinder_init (void); void keybinder_set_use_cooked_accelerators (gboolean use_cooked); gboolean keybinder_bind (const char *keystring, KeybinderHandler handler, void *user_data); gboolean keybinder_bind_full (const char *keystring, KeybinderHandler handler, void *user_data, GDestroyNotify notify); void keybinder_unbind (const char *keystring, KeybinderHandler handler); void keybinder_unbind_all (const char *keystring); guint32 keybinder_get_current_event_time (void); gboolean keybinder_supported (void); G_END_DECLS #endif /* __KEY_BINDER_H__ */ keybinder-keybinder-3.0-v0.3.2/m4/000077500000000000000000000000001305533123700164505ustar00rootroot00000000000000keybinder-keybinder-3.0-v0.3.2/m4/introspection.m4000066400000000000000000000066141305533123700216210ustar00rootroot00000000000000dnl -*- mode: autoconf -*- dnl Copyright 2009 Johan Dahlin dnl dnl This file is free software; the author(s) gives unlimited dnl permission to copy and/or distribute it, with or without dnl modifications, as long as this notice is preserved. dnl # serial 1 m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL], [ AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first AC_BEFORE([LT_INIT],[$0])dnl setup libtool first dnl enable/disable introspection m4_if([$2], [require], [dnl enable_introspection=yes ],[dnl AC_ARG_ENABLE(introspection, AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]], [Enable introspection for this build]),, [enable_introspection=auto]) ])dnl AC_MSG_CHECKING([for gobject-introspection]) dnl presence/version checking AS_CASE([$enable_introspection], [no], [dnl found_introspection="no (disabled, use --enable-introspection to enable)" ],dnl [yes],[dnl PKG_CHECK_EXISTS([gobject-introspection-1.0],, AC_MSG_ERROR([gobject-introspection-1.0 is not installed])) PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME])) ],dnl [auto],[dnl PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no) ],dnl [dnl AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@]) ])dnl AC_MSG_RESULT([$found_introspection]) INTROSPECTION_SCANNER= INTROSPECTION_COMPILER= INTROSPECTION_GENERATE= INTROSPECTION_GIRDIR= INTROSPECTION_TYPELIBDIR= if test "x$found_introspection" = "xyes"; then INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection fi AC_SUBST(INTROSPECTION_SCANNER) AC_SUBST(INTROSPECTION_COMPILER) AC_SUBST(INTROSPECTION_GENERATE) AC_SUBST(INTROSPECTION_GIRDIR) AC_SUBST(INTROSPECTION_TYPELIBDIR) AC_SUBST(INTROSPECTION_CFLAGS) AC_SUBST(INTROSPECTION_LIBS) AC_SUBST(INTROSPECTION_MAKEFILE) AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes") ]) dnl Usage: dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version]) AC_DEFUN([GOBJECT_INTROSPECTION_CHECK], [ _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1]) ]) dnl Usage: dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version]) AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE], [ _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require]) ])